diff --git a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp --- a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp +++ b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp @@ -866,7 +866,7 @@ const SCEV *IndVarStart = SE.getAddExpr(StartNext, Addend); const SCEV *Step = SE.getSCEV(StepCI); - ConstantInt *One = ConstantInt::get(IndVarTy, 1); + const SCEV *FixedRightSCEV = nullptr; if (IsIncreasing) { bool DecreasedRightValueByOne = false; if (StepCI->isOne()) { @@ -928,10 +928,9 @@ if (LatchBrExitIdx == 0) { // We need to increase the right value unless we have already decreased // it virtually when we replaced EQ with SGT. - if (!DecreasedRightValueByOne) { - IRBuilder<> B(Preheader->getTerminator()); - RightValue = B.CreateAdd(RightValue, One); - } + if (!DecreasedRightValueByOne) + FixedRightSCEV = + SE.getAddExpr(RightSCEV, SE.getOne(RightSCEV->getType())); } else { assert(!DecreasedRightValueByOne && "Right value can be decreased only for LatchBrExitIdx == 0!"); @@ -995,10 +994,9 @@ if (LatchBrExitIdx == 0) { // We need to decrease the right value unless we have already increased // it virtually when we replaced EQ with SLT. - if (!IncreasedRightValueByOne) { - IRBuilder<> B(Preheader->getTerminator()); - RightValue = B.CreateSub(RightValue, One); - } + if (!IncreasedRightValueByOne) + FixedRightSCEV = + SE.getMinusSCEV(RightSCEV, SE.getOne(RightSCEV->getType())); } else { assert(!IncreasedRightValueByOne && "Right value can be increased only for LatchBrExitIdx == 0!"); @@ -1012,9 +1010,14 @@ assert(!L.contains(LatchExit) && "expected an exit block!"); const DataLayout &DL = Preheader->getModule()->getDataLayout(); - Value *IndVarStartV = - SCEVExpander(SE, DL, "irce") - .expandCodeFor(IndVarStart, IndVarTy, Preheader->getTerminator()); + SCEVExpander Expander(SE, DL, "irce"); + Instruction *Ins = Preheader->getTerminator(); + + if (FixedRightSCEV) + RightValue = + Expander.expandCodeFor(FixedRightSCEV, FixedRightSCEV->getType(), Ins); + + Value *IndVarStartV = Expander.expandCodeFor(IndVarStart, IndVarTy, Ins); IndVarStartV->setName("indvar.start"); LoopStructure Result; diff --git a/llvm/test/Transforms/IRCE/non-loop-invariant-rhs-instr.ll b/llvm/test/Transforms/IRCE/non-loop-invariant-rhs-instr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/IRCE/non-loop-invariant-rhs-instr.ll @@ -0,0 +1,39 @@ +; RUN: opt -irce-print-changed-loops -S -verify-loop-info -irce -verify < %s 2>&1 | FileCheck %s + +; this test must compile successfully +; CHECK: constrained Loop +define i32 @test(i32 %A, i64 %Len, i32 *%array) { + +preheader: + %tripcheck = icmp sgt i64 %Len, 2 + br i1 %tripcheck, label %loop, label %zero + +loop: + %indvar = phi i64 [ 1, %preheader ], [ %indvar.next, %latch ] + %0 = icmp ult i64 %indvar, %Len + br i1 %0, label %guarded, label %deopt + +guarded: + %addr = getelementptr inbounds i32, i32* %array, i64 %indvar + %res = load i32, i32* %addr + %cmp = icmp eq i32 %res, 0 + br i1 %cmp, label %zero, label %latch + +latch: + %indvar.next = add nuw nsw i64 %indvar, 2 + %res2 = mul i32 %res, 3 +; NOTE: this is loop invariant value, but not loop invariant instruction! + %1 = zext i32 %A to i64 + %cmp2 = icmp ugt i64 %indvar.next, %1 + br i1 %cmp2, label %loopexit, label %loop + +loopexit: + ret i32 %res2 + +zero: + ret i32 0 + +deopt: + ret i32 1 + +}