diff options
| -rw-r--r-- | llvm/include/llvm/Analysis/ScalarEvolution.h | 3 | ||||
| -rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 21 | ||||
| -rw-r--r-- | llvm/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll | 42 | 
3 files changed, 64 insertions, 2 deletions
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h index 8f87b58fe73..c213ade5e8e 100644 --- a/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -837,7 +837,8 @@ namespace llvm {      ///      bool SimplifyICmpOperands(ICmpInst::Predicate &Pred,                                const SCEV *&LHS, -                              const SCEV *&RHS); +                              const SCEV *&RHS, +                              unsigned Depth = 0);      /// getLoopDisposition - Return the "disposition" of the given SCEV with      /// respect to the given loop. diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 8781441fd43..c45cc8d0f8c 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -5605,9 +5605,14 @@ static bool HasSameValue(const SCEV *A, const SCEV *B) {  /// predicate Pred. Return true iff any changes were made.  ///  bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred, -                                           const SCEV *&LHS, const SCEV *&RHS) { +                                           const SCEV *&LHS, const SCEV *&RHS, +                                           unsigned Depth) {    bool Changed = false; +  // If we hit the max recursion limit bail out. +  if (Depth >= 3) +    return false; +    // Canonicalize a constant to the right side.    if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(LHS)) {      // Check for both operands constant. @@ -5645,6 +5650,15 @@ bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred,      default: llvm_unreachable("Unexpected ICmpInst::Predicate value!");      case ICmpInst::ICMP_EQ:      case ICmpInst::ICMP_NE: +      // Fold ((-1) * %a) + %b == 0 (equivalent to %b-%a == 0) into %a == %b. +      if (!RA) +        if (const SCEVAddExpr *AE = dyn_cast<SCEVAddExpr>(LHS)) +          if (const SCEVMulExpr *ME = dyn_cast<SCEVMulExpr>(AE->getOperand(0))) +            if (ME->getOperand(0)->isAllOnesValue()) { +              RHS = AE->getOperand(1); +              LHS = ME->getOperand(1); +              Changed = true; +            }        break;      case ICmpInst::ICMP_UGE:        if ((RA - 1).isMinValue()) { @@ -5846,6 +5860,11 @@ bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred,    // TODO: More simplifications are possible here. +  // Recursively simplify until we either hit a recursion limit or nothing +  // changes. +  if (Changed) +    return SimplifyICmpOperands(Pred, LHS, RHS, Depth+1); +    return Changed;  trivially_true: diff --git a/llvm/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll b/llvm/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll new file mode 100644 index 00000000000..c58a3af62fc --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll @@ -0,0 +1,42 @@ +; RUN: opt -S -indvars < %s | FileCheck %s + +define void @test1(float* nocapture %autoc, float* nocapture %data, float %d, i32 %data_len, i32 %sample) nounwind { +entry: +  %sub = sub i32 %data_len, %sample +  %cmp4 = icmp eq i32 %data_len, %sample +  br i1 %cmp4, label %for.end, label %for.body + +for.body:                                         ; preds = %entry, %for.body +  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] +  %0 = trunc i64 %indvars.iv to i32 +  %add = add i32 %0, %sample +  %idxprom = zext i32 %add to i64 +  %arrayidx = getelementptr inbounds float* %data, i64 %idxprom +  %1 = load float* %arrayidx, align 4 +  %mul = fmul float %1, %d +  %arrayidx2 = getelementptr inbounds float* %autoc, i64 %indvars.iv +  %2 = load float* %arrayidx2, align 4 +  %add3 = fadd float %2, %mul +  store float %add3, float* %arrayidx2, align 4 +  %indvars.iv.next = add i64 %indvars.iv, 1 +  %3 = trunc i64 %indvars.iv.next to i32 +  %cmp = icmp ult i32 %3, %sub +  br i1 %cmp, label %for.body, label %for.end + +for.end:                                          ; preds = %for.body, %entry +  ret void + +; CHECK: @test1 + +; First check that we move the sub into the preheader, it doesn't have to be +; executed if %cmp4 == false +; CHECK: for.body.preheader: +; CHECK: sub i32 %data_len, %sample +; CHECK: br label %for.body + +; Second, check that we turn the IV test into an eq. +; CHECK: %lftr.wideiv = trunc i64 %indvars.iv.next to i32 +; CHECK: %exitcond = icmp ne i32 %lftr.wideiv, %0 +; CHECK: br i1 %exitcond, label %for.body, label %for.end.loopexit +} +  | 

