diff options
| author | Warren Ristow <warren.ristow@sony.com> | 2019-05-08 18:50:07 +0000 | 
|---|---|---|
| committer | Warren Ristow <warren.ristow@sony.com> | 2019-05-08 18:50:07 +0000 | 
| commit | d27b0c624722c113953c4d46379c8c6a72814e8c (patch) | |
| tree | 5b557d1dc720e2b0841264edf94f8a0ebbed8736 /llvm/lib/Analysis | |
| parent | 1558731607cb2aef361d02be9973d4e374475254 (diff) | |
| download | bcm5719-llvm-d27b0c624722c113953c4d46379c8c6a72814e8c.tar.gz bcm5719-llvm-d27b0c624722c113953c4d46379c8c6a72814e8c.zip  | |
[SCEV] Suppress hoisting insertion point of binops when unsafe
InsertBinop tries to move insertion-points out of loops for expressions
that are loop-invariant. This patch adds a new parameter, IsSafeToHost,
to guard that hoisting. This allows callers to suppress that hoisting
for unsafe situations, such as divisions that may have a zero
denominator.
This fixes PR38697.
Differential Revision: https://reviews.llvm.org/D55232
llvm-svn: 360280
Diffstat (limited to 'llvm/lib/Analysis')
| -rw-r--r-- | llvm/lib/Analysis/ScalarEvolutionExpander.cpp | 45 | 
1 files changed, 27 insertions, 18 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolutionExpander.cpp b/llvm/lib/Analysis/ScalarEvolutionExpander.cpp index fc5d865fa83..0c77d814242 100644 --- a/llvm/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/llvm/lib/Analysis/ScalarEvolutionExpander.cpp @@ -166,9 +166,10 @@ Value *SCEVExpander::InsertNoopCastOfTo(Value *V, Type *Ty) {  }  /// InsertBinop - Insert the specified binary operator, doing a small amount -/// of work to avoid inserting an obviously redundant operation. +/// of work to avoid inserting an obviously redundant operation, and hoisting +/// to an outer loop when the opportunity is there and it is safe.  Value *SCEVExpander::InsertBinop(Instruction::BinaryOps Opcode, -                                 Value *LHS, Value *RHS) { +                                 Value *LHS, Value *RHS, bool IsSafeToHoist) {    // Fold a binop with constant operands.    if (Constant *CLHS = dyn_cast<Constant>(LHS))      if (Constant *CRHS = dyn_cast<Constant>(RHS)) @@ -210,14 +211,16 @@ Value *SCEVExpander::InsertBinop(Instruction::BinaryOps Opcode,    DebugLoc Loc = Builder.GetInsertPoint()->getDebugLoc();    SCEVInsertPointGuard Guard(Builder, this); -  // Move the insertion point out of as many loops as we can. -  while (const Loop *L = SE.LI.getLoopFor(Builder.GetInsertBlock())) { -    if (!L->isLoopInvariant(LHS) || !L->isLoopInvariant(RHS)) break; -    BasicBlock *Preheader = L->getLoopPreheader(); -    if (!Preheader) break; +  if (IsSafeToHoist) { +    // Move the insertion point out of as many loops as we can. +    while (const Loop *L = SE.LI.getLoopFor(Builder.GetInsertBlock())) { +      if (!L->isLoopInvariant(LHS) || !L->isLoopInvariant(RHS)) break; +      BasicBlock *Preheader = L->getLoopPreheader(); +      if (!Preheader) break; -    // Ok, move up a level. -    Builder.SetInsertPoint(Preheader->getTerminator()); +      // Ok, move up a level. +      Builder.SetInsertPoint(Preheader->getTerminator()); +    }    }    // If we haven't found this binop, insert it. @@ -734,7 +737,7 @@ Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) {        // Instead of doing a negate and add, just do a subtract.        Value *W = expandCodeFor(SE.getNegativeSCEV(Op), Ty);        Sum = InsertNoopCastOfTo(Sum, Ty); -      Sum = InsertBinop(Instruction::Sub, Sum, W); +      Sum = InsertBinop(Instruction::Sub, Sum, W, /*IsSafeToHoist*/ true);        ++I;      } else {        // A simple add. @@ -742,7 +745,7 @@ Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) {        Sum = InsertNoopCastOfTo(Sum, Ty);        // Canonicalize a constant to the RHS.        if (isa<Constant>(Sum)) std::swap(Sum, W); -      Sum = InsertBinop(Instruction::Add, Sum, W); +      Sum = InsertBinop(Instruction::Add, Sum, W, /*IsSafeToHoist*/ true);        ++I;      }    } @@ -794,9 +797,11 @@ Value *SCEVExpander::visitMulExpr(const SCEVMulExpr *S) {      if (Exponent & 1)        Result = P;      for (uint64_t BinExp = 2; BinExp <= Exponent; BinExp <<= 1) { -      P = InsertBinop(Instruction::Mul, P, P); +      P = InsertBinop(Instruction::Mul, P, P, /*IsSafeToHoist*/ true);        if (Exponent & BinExp) -        Result = Result ? InsertBinop(Instruction::Mul, Result, P) : P; +        Result = Result ? InsertBinop(Instruction::Mul, Result, P, +                                      /*IsSafeToHoist*/ true) +                        : P;      }      I = E; @@ -811,7 +816,8 @@ Value *SCEVExpander::visitMulExpr(const SCEVMulExpr *S) {      } else if (I->second->isAllOnesValue()) {        // Instead of doing a multiply by negative one, just do a negate.        Prod = InsertNoopCastOfTo(Prod, Ty); -      Prod = InsertBinop(Instruction::Sub, Constant::getNullValue(Ty), Prod); +      Prod = InsertBinop(Instruction::Sub, Constant::getNullValue(Ty), Prod, +                         /*IsSafeToHoist*/ true);        ++I;      } else {        // A simple mul. @@ -824,9 +830,10 @@ Value *SCEVExpander::visitMulExpr(const SCEVMulExpr *S) {          // Canonicalize Prod*(1<<C) to Prod<<C.          assert(!Ty->isVectorTy() && "vector types are not SCEVable");          Prod = InsertBinop(Instruction::Shl, Prod, -                           ConstantInt::get(Ty, RHS->logBase2())); +                           ConstantInt::get(Ty, RHS->logBase2()), +                           /*IsSafeToHoist*/ true);        } else { -        Prod = InsertBinop(Instruction::Mul, Prod, W); +        Prod = InsertBinop(Instruction::Mul, Prod, W, /*IsSafeToHoist*/ true);        }      }    } @@ -842,11 +849,13 @@ Value *SCEVExpander::visitUDivExpr(const SCEVUDivExpr *S) {      const APInt &RHS = SC->getAPInt();      if (RHS.isPowerOf2())        return InsertBinop(Instruction::LShr, LHS, -                         ConstantInt::get(Ty, RHS.logBase2())); +                         ConstantInt::get(Ty, RHS.logBase2()), +                         /*IsSafeToHoist*/ true);    }    Value *RHS = expandCodeFor(S->getRHS(), Ty); -  return InsertBinop(Instruction::UDiv, LHS, RHS); +  return InsertBinop(Instruction::UDiv, LHS, RHS, +                     /*IsSafeToHoist*/ SE.isKnownNonZero(S->getRHS()));  }  /// Move parts of Base into Rest to leave Base with the minimal  | 

