Index: lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp =================================================================== --- lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp +++ lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp @@ -1465,6 +1465,7 @@ Value *ExitMainLoopAt = nullptr; const SCEVConstant *MinusOneS = cast(SE.getConstant(IVTy, -1, true /* isSigned */)); + const Loop *L = LI.getLoopFor(MainLoopStructure.Header); if (NeedsPreLoop) { const SCEV *ExitPreLoopAtSCEV = nullptr; @@ -1481,7 +1482,8 @@ ExitPreLoopAtSCEV = SE.getAddExpr(*SR.HighLimit, MinusOneS); } - if (!isSafeToExpandAt(ExitPreLoopAtSCEV, InsertPt, SE)) { + if (!isSafeToExpandAt(ExitPreLoopAtSCEV, InsertPt, SE) || + !SE.isAvailableAtLoopEntry(ExitPreLoopAtSCEV, L)) { DEBUG(dbgs() << "irce: could not prove that it is safe to expand the" << " preloop exit limit " << *ExitPreLoopAtSCEV << " at block " << InsertPt->getParent()->getName() << "\n"); @@ -1507,7 +1509,8 @@ ExitMainLoopAtSCEV = SE.getAddExpr(*SR.LowLimit, MinusOneS); } - if (!isSafeToExpandAt(ExitMainLoopAtSCEV, InsertPt, SE)) { + if (!isSafeToExpandAt(ExitMainLoopAtSCEV, InsertPt, SE) || + !SE.isAvailableAtLoopEntry(ExitMainLoopAtSCEV, L)) { DEBUG(dbgs() << "irce: could not prove that it is safe to expand the" << " main loop exit limit " << *ExitMainLoopAtSCEV << " at block " << InsertPt->getParent()->getName() << "\n"); Index: test/Transforms/IRCE/bad_expander.ll =================================================================== --- test/Transforms/IRCE/bad_expander.ll +++ test/Transforms/IRCE/bad_expander.ll @@ -9,6 +9,8 @@ ; CHECK-NOT: irce: in function test_01: constrained Loop ; CHECK-NOT: irce: in function test_02: constrained Loop ; CHECK-LABEL: irce: in function test_03: constrained Loop +; CHECK-NOT: irce: in function test_04: constrained Loop +; CHECK-NOT: irce: in function test_05: constrained Loop define void @test_01() { @@ -136,5 +138,70 @@ br i1 %tmp7, label %loop, label %exit } +define void @test_04(i64* %p1, i64* %p2, i1 %maybe_exit) { + +; CHECK-LABEL: test_04 +; CHECK-NOT: preloop +; CHECK-NOT: postloop +; CHECK-NOT: br i1 false +; CHECK-NOT: br i1 true + +entry: + %num = load i64, i64* %p1, align 4, !range !2 + %denom = load i64, i64* %p2, align 4, !range !2 + br label %loop + +exit: ; preds = %guarded, %loop + ret void + +loop: ; preds = %guarded, %entry + %iv = phi i64 [ 0, %entry ], [ %iv.next, %guarded ] + %iv.next = add nuw nsw i64 %iv, 1 + br i1 %maybe_exit, label %range_check, label %exit + +range_check: + %rem_result = srem i64 %num, %denom + %rc = icmp slt i64 %iv.next, %rem_result + br i1 %rc, label %guarded, label %exit + +guarded: + %gep = getelementptr i64, i64* %p1, i64 %iv.next + %loaded = load i64, i64* %gep, align 4 + %tmp7 = icmp slt i64 %iv.next, 1000 + br i1 %tmp7, label %loop, label %exit +} + +define void @test_05(i64* %p1, i1 %maybe_exit) { + +; CHECK-LABEL: test_05 +; CHECK-NOT: preloop +; CHECK-NOT: postloop +; CHECK-NOT: br i1 false +; CHECK-NOT: br i1 true + +entry: + br label %loop + +exit: ; preds = %guarded, %loop + ret void + +loop: ; preds = %guarded, %entry + %iv = phi i64 [ 0, %entry ], [ %iv.next, %guarded ] + %iv.next = add nuw nsw i64 %iv, 1 + br i1 %maybe_exit, label %range_check, label %exit + +range_check: + %load_result = load i64, i64* %p1, align 4, !range !1 + %rc = icmp slt i64 %iv.next, %load_result + br i1 %rc, label %guarded, label %exit + +guarded: + %gep = getelementptr i64, i64* %p1, i64 %iv.next + %loaded = load i64, i64* %gep, align 4 + %tmp7 = icmp slt i64 %iv.next, 1000 + br i1 %tmp7, label %loop, label %exit +} + !0 = !{i64 0, i64 100} !1 = !{i64 1, i64 100} +!2 = !{i64 -100, i64 100}