[llvm] 4c6f95b - Revert "[IRCE] Parse range checks in the form of 'LHS - RHS vs Limit'"
Aleksandr Popov via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 10 05:01:18 PDT 2023
Author: Aleksandr Popov
Date: 2023-07-10T13:59:22+02:00
New Revision: 4c6f95be29c6ce0f89663a5103c58ee63d76cda3
URL: https://github.com/llvm/llvm-project/commit/4c6f95be29c6ce0f89663a5103c58ee63d76cda3
DIFF: https://github.com/llvm/llvm-project/commit/4c6f95be29c6ce0f89663a5103c58ee63d76cda3.diff
LOG: Revert "[IRCE] Parse range checks in the form of 'LHS - RHS vs Limit'"
This reverts commit e16c5c092205f68825466c25a1dd30783c4820f3.
Revert due to Buildbot failure https://lab.llvm.org/buildbot/#/builders/193
Added:
Modified:
llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
llvm/test/Transforms/IRCE/iv-plus-offset-range-check.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
index 5ab688235c72a9..5f9bad37e7ab73 100644
--- a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
@@ -119,16 +119,6 @@ static cl::opt<bool> AllowNarrowLatchCondition(
cl::desc("If set to true, IRCE may eliminate wide range checks in loops "
"with narrow latch condition."));
-static cl::opt<unsigned> MaxTypeSizeForOverflowCheck(
- "irce-max-type-size-for-overflow-check", cl::Hidden, cl::init(32),
- cl::desc(
- "Maximum size of range check type for which can be produced runtime "
- "overflow check of its limit's computation"));
-
-static cl::opt<bool>
- PrintScaledBoundaryRangeChecks("irce-print-scaled-boundary-range-checks",
- cl::Hidden, cl::init(false));
-
static const char *ClonedLoopTag = "irce.loop.clone";
#define DEBUG_TYPE "irce"
@@ -166,10 +156,6 @@ class InductiveRangeCheck {
const SCEVAddRecExpr *&Index,
const SCEV *&End);
- static bool reassociateSubLHS(Loop *L, Value *VariantLHS, Value *InvariantRHS,
- ICmpInst::Predicate Pred, ScalarEvolution &SE,
- const SCEVAddRecExpr *&Index, const SCEV *&End);
-
public:
const SCEV *getBegin() const { return Begin; }
const SCEV *getStep() const { return Step; }
@@ -295,10 +281,6 @@ bool InductiveRangeCheck::parseRangeCheckICmp(Loop *L, ICmpInst *ICI,
if (parseIvAgaisntLimit(L, LHS, RHS, Pred, SE, Index, End))
return true;
- if (reassociateSubLHS(L, LHS, RHS, Pred, SE, Index, End))
- return true;
-
- // TODO: support ReassociateAddLHS
return false;
}
@@ -364,126 +346,6 @@ bool InductiveRangeCheck::parseIvAgaisntLimit(Loop *L, Value *LHS, Value *RHS,
llvm_unreachable("default clause returns!");
}
-// Try to parse range check in the form of "IV - Offset vs Limit" or "Offset -
-// IV vs Limit"
-bool InductiveRangeCheck::reassociateSubLHS(
- Loop *L, Value *VariantLHS, Value *InvariantRHS, ICmpInst::Predicate Pred,
- ScalarEvolution &SE, const SCEVAddRecExpr *&Index, const SCEV *&End) {
- Value *LHS, *RHS;
- if (!match(VariantLHS, m_Sub(m_Value(LHS), m_Value(RHS))))
- return false;
-
- const SCEV *IV = SE.getSCEV(LHS);
- const SCEV *Offset = SE.getSCEV(RHS);
- const SCEV *Limit = SE.getSCEV(InvariantRHS);
-
- bool OffsetSubtracted = false;
- if (SE.isLoopInvariant(IV, L))
- // "Offset - IV vs Limit"
- std::swap(IV, Offset);
- else if (SE.isLoopInvariant(Offset, L))
- // "IV - Offset vs Limit"
- OffsetSubtracted = true;
- else
- return false;
-
- const auto *AddRec = dyn_cast<SCEVAddRecExpr>(IV);
- if (!AddRec)
- return false;
-
- // In order to turn "IV - Offset < Limit" into "IV < Limit + Offset", we need
- // to be able to freely move values from left side of inequality to right side
- // (just as in normal linear arithmetics). Overflows make things much more
- // complicated, so we want to avoid this.
- //
- // Let's prove that the initial subtraction doesn't overflow with all IV's
- // values from the safe range constructed for that check.
- //
- // [Case 1] IV - Offset < Limit
- // It doesn't overflow if:
- // SINT_MIN <= IV - Offset <= SINT_MAX
- // In terms of scaled SINT we need to prove:
- // SINT_MIN + Offset <= IV <= SINT_MAX + Offset
- // Safe range will be constructed:
- // 0 <= IV < Limit + Offset
- // It means that 'IV - Offset' doesn't underflow, because:
- // SINT_MIN + Offset < 0 <= IV
- // and doesn't overflow:
- // IV < Limit + Offset <= SINT_MAX + Offset
- //
- // [Case 2] Offset - IV > Limit
- // It doesn't overflow if:
- // SINT_MIN <= Offset - IV <= SINT_MAX
- // In terms of scaled SINT we need to prove:
- // -SINT_MIN >= IV - Offset >= -SINT_MAX
- // Offset - SINT_MIN >= IV >= Offset - SINT_MAX
- // Safe range will be constructed:
- // 0 <= IV < Offset - Limit
- // It means that 'Offset - IV' doesn't underflow, because
- // Offset - SINT_MAX < 0 <= IV
- // and doesn't overflow:
- // IV < Offset - Limit <= Offset - SINT_MIN
- //
- // For the computed upper boundary of the IV's range (Offset +/- Limit) we
- // don't know exactly whether it overflows or not. So if we can't prove this
- // fact at compile time, we scale boundary computations to a wider type with
- // the intention to add runtime overflow check.
-
- auto getExprScaledIfOverflow = [&](Instruction::BinaryOps BinOp,
- const SCEV *LHS,
- const SCEV *RHS) -> const SCEV * {
- const SCEV *(ScalarEvolution::*Operation)(const SCEV *, const SCEV *,
- SCEV::NoWrapFlags, unsigned);
- switch (BinOp) {
- default:
- llvm_unreachable("Unsupported binary op");
- case Instruction::Add:
- Operation = &ScalarEvolution::getAddExpr;
- break;
- case Instruction::Sub:
- Operation = &ScalarEvolution::getMinusSCEV;
- break;
- }
-
- if (SE.willNotOverflow(BinOp, ICmpInst::isSigned(Pred), LHS, RHS,
- cast<Instruction>(VariantLHS)))
- return (SE.*Operation)(LHS, RHS, SCEV::FlagAnyWrap, 0);
-
- // We couldn't prove that the expression does not overflow.
- // Than scale it to a wider type to check overflow at runtime.
- auto *Ty = cast<IntegerType>(LHS->getType());
- if (Ty->getBitWidth() > MaxTypeSizeForOverflowCheck)
- return nullptr;
-
- auto WideTy = IntegerType::get(Ty->getContext(), Ty->getBitWidth() * 2);
- return (SE.*Operation)(SE.getSignExtendExpr(LHS, WideTy),
- SE.getSignExtendExpr(RHS, WideTy), SCEV::FlagAnyWrap,
- 0);
- };
-
- if (OffsetSubtracted)
- // "IV - Offset < Limit" -> "IV" < Offset + Limit
- Limit = getExprScaledIfOverflow(Instruction::BinaryOps::Add, Offset, Limit);
- else {
- // "Offset - IV > Limit" -> "IV" < Offset - Limit
- Limit = getExprScaledIfOverflow(Instruction::BinaryOps::Sub, Offset, Limit);
- Pred = ICmpInst::getSwappedPredicate(Pred);
- }
-
- if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE) {
- // "Expr <= Limit" -> "Expr < Limit + 1"
- if (Pred == ICmpInst::ICMP_SLE && Limit)
- Limit = getExprScaledIfOverflow(Instruction::BinaryOps::Add, Limit,
- SE.getOne(Limit->getType()));
- if (Limit) {
- Index = AddRec;
- End = Limit;
- return true;
- }
- }
- return false;
-}
-
void InductiveRangeCheck::extractRangeChecksFromCond(
Loop *L, ScalarEvolution &SE, Use &ConditionUse,
SmallVectorImpl<InductiveRangeCheck> &Checks,
@@ -1731,34 +1593,11 @@ InductiveRangeCheck::computeSafeIterationSpace(ScalarEvolution &SE,
// if latch check is more narrow.
auto *IVType = dyn_cast<IntegerType>(IndVar->getType());
auto *RCType = dyn_cast<IntegerType>(getBegin()->getType());
- auto *EndType = dyn_cast<IntegerType>(getEnd()->getType());
// Do not work with pointer types.
if (!IVType || !RCType)
return std::nullopt;
if (IVType->getBitWidth() > RCType->getBitWidth())
return std::nullopt;
-
- auto PrintRangeCheck = [&](raw_ostream &OS) {
- auto L = IndVar->getLoop();
- OS << "irce: in function ";
- OS << L->getHeader()->getParent()->getName();
- OS << ", in ";
- L->print(OS);
- OS << "there is range check with scaled boundary:\n";
- print(OS);
- };
-
- if (EndType->getBitWidth() > RCType->getBitWidth()) {
- assert(EndType->getBitWidth() == RCType->getBitWidth() * 2);
- if (PrintScaledBoundaryRangeChecks)
- PrintRangeCheck(errs());
- // End is computed with extended type but will be truncated to a narrow one
- // type of range check. Therefore we need a check that the result will not
- // overflow in terms of narrow type.
- // TODO: Support runtime overflow check for End
- return std::nullopt;
- }
-
// IndVar is of the form "A + B * I" (where "I" is the canonical induction
// variable, that may or may not exist as a real llvm::Value in the loop) and
// this inductive range check is a range check on the "C + D * I" ("C" is
diff --git a/llvm/test/Transforms/IRCE/iv-plus-offset-range-check.ll b/llvm/test/Transforms/IRCE/iv-plus-offset-range-check.ll
index f1d645fa1138e5..fbab857a2f0556 100644
--- a/llvm/test/Transforms/IRCE/iv-plus-offset-range-check.ll
+++ b/llvm/test/Transforms/IRCE/iv-plus-offset-range-check.ll
@@ -1,24 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
-; RUN: opt -verify-loop-info -passes=irce -irce-print-scaled-boundary-range-checks -S < %s 2>&1 | FileCheck %s
-
-
-; CHECK: irce: in function test1, in Loop at depth 1 containing: %loop<header><exiting>,%inbounds<latch><exiting>
-; CHECK-NEXT: there is range check with scaled boundary:
-; CHECK-NEXT: InductiveRangeCheck:
-; CHECK-NEXT: Begin: 0 Step: 1 End: (-1 + (sext i8 %n to i16))<nsw>
-; CHECK-NEXT: CheckUse: br i1 %check, label %inbounds, label %out_of_bounds Operand: 0
-;
-; CHECK-NEXT: irce: in function test4, in Loop at depth 1 containing: %loop<header><exiting>,%inbounds<latch><exiting>
-; CHECK-NEXT: there is range check with scaled boundary:
-; CHECK-NEXT: InductiveRangeCheck:
-; CHECK-NEXT: Begin: 0 Step: 1 End: (-2 + (sext i8 %n to i16))<nsw>
-; CHECK-NEXT: CheckUse: br i1 %check, label %inbounds, label %out_of_bounds Operand: 0
-;
-; CHECK-NEXT: irce: in function test_overflow_check_runtime, in Loop at depth 1 containing: %loop<header><exiting>,%inbounds<latch><exiting>
-; CHECK-NEXT: there is range check with scaled boundary:
-; CHECK-NEXT: InductiveRangeCheck:
-; CHECK-NEXT: Begin: 0 Step: 1 End: (3 + (zext i8 %n to i16))<nuw><nsw>
-; CHECK-NEXT: CheckUse: br i1 %check, label %inbounds, label %out_of_bounds Operand: 0
+; RUN: opt -verify-loop-info -passes=irce -S < %s 2>&1 | FileCheck %s
; IV = 0; IV <s limit; IV += 1;
; Check(N - IV >= 2)
@@ -85,64 +66,25 @@ define i8 @test1a(i8 %limit, ptr %p) {
; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
; CHECK: loop.preheader:
-; CHECK-NEXT: [[TMP0:%.*]] = add nsw i8 [[N]], -1
-; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP0]], i8 0)
-; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[SMIN]], 1
-; CHECK-NEXT: [[TMP2:%.*]] = mul i8 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: [[SMIN2:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP2]])
-; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN2]], i8 0)
-; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
-; CHECK-NEXT: br i1 [[TMP3]], label [[LOOP_PREHEADER4:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
-; CHECK: loop.preheader4:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER4]] ]
+; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
; CHECK-NEXT: [[CHECK:%.*]] = icmp sge i8 [[SUB]], 2
-; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]]
+; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
; CHECK: inbounds:
; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
-; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
-; CHECK-NEXT: br i1 [[TMP4]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
-; CHECK: main.exit.selector:
-; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
-; CHECK-NEXT: [[IDX_LCSSA3:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
-; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
-; CHECK-NEXT: br i1 [[TMP5]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
-; CHECK: main.pseudo.exit:
-; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
-; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
-; CHECK-NEXT: br label [[POSTLOOP:%.*]]
-; CHECK: exit.loopexit.loopexit:
-; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
-; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
+; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK: exit.loopexit:
-; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA3]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
; CHECK-NEXT: ret i8 [[RES]]
-; CHECK: out_of_bounds.loopexit:
-; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
-; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
-; CHECK: out_of_bounds.loopexit5:
-; CHECK-NEXT: [[IDX_LCSSA_PH6:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
-; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
; CHECK: out_of_bounds:
-; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH6]], [[OUT_OF_BOUNDS_LOOPEXIT5]] ]
+; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
-; CHECK: postloop:
-; CHECK-NEXT: br label [[LOOP_POSTLOOP]]
-; CHECK: loop.postloop:
-; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
-; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]
-; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sge i8 [[SUB_POSTLOOP]], 2
-; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
-; CHECK: inbounds.postloop:
-; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
-; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
-; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP1:![0-9]+]], !irce.loop.clone [[META6:![0-9]+]]
;
entry:
%n = load i8, ptr %p, !range !0
@@ -396,7 +338,7 @@ define i8 @test3a(i8 %limit, ptr %p) {
; CHECK: inbounds.postloop:
; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
-; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP7:![0-9]+]], !irce.loop.clone [[META6]]
+; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP1:![0-9]+]], !irce.loop.clone !6
;
entry:
%n = load i8, ptr %p, !range !0
@@ -487,69 +429,25 @@ define i8 @test4a(i8 %limit, ptr %p) {
; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
; CHECK: loop.preheader:
-; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -2
-; CHECK-NEXT: [[TMP1:%.*]] = add nuw i8 [[N]], 127
-; CHECK-NEXT: [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 0)
-; CHECK-NEXT: [[TMP2:%.*]] = sub i8 [[TMP0]], [[SMAX]]
-; CHECK-NEXT: [[TMP3:%.*]] = add nsw i8 [[N]], -2
-; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP3]], i8 0)
-; CHECK-NEXT: [[SMAX2:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 -1)
-; CHECK-NEXT: [[TMP4:%.*]] = add nsw i8 [[SMAX2]], 1
-; CHECK-NEXT: [[TMP5:%.*]] = mul i8 [[TMP2]], [[TMP4]]
-; CHECK-NEXT: [[SMIN3:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP5]])
-; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN3]], i8 0)
-; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
-; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP_PREHEADER6:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
-; CHECK: loop.preheader6:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER6]] ]
+; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
; CHECK-NEXT: [[CHECK:%.*]] = icmp sgt i8 [[SUB]], 2
-; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT7:%.*]]
+; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
; CHECK: inbounds:
; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
-; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
-; CHECK-NEXT: br i1 [[TMP7]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
-; CHECK: main.exit.selector:
-; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
-; CHECK-NEXT: [[IDX_LCSSA5:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
-; CHECK-NEXT: [[TMP8:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
-; CHECK-NEXT: br i1 [[TMP8]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
-; CHECK: main.pseudo.exit:
-; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
-; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
-; CHECK-NEXT: br label [[POSTLOOP:%.*]]
-; CHECK: exit.loopexit.loopexit:
-; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
-; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
+; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK: exit.loopexit:
-; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA5]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
; CHECK-NEXT: ret i8 [[RES]]
-; CHECK: out_of_bounds.loopexit:
-; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
-; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
-; CHECK: out_of_bounds.loopexit7:
-; CHECK-NEXT: [[IDX_LCSSA_PH8:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
-; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
; CHECK: out_of_bounds:
-; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH8]], [[OUT_OF_BOUNDS_LOOPEXIT7]] ]
+; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
-; CHECK: postloop:
-; CHECK-NEXT: br label [[LOOP_POSTLOOP]]
-; CHECK: loop.postloop:
-; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
-; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]
-; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sgt i8 [[SUB_POSTLOOP]], 2
-; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
-; CHECK: inbounds.postloop:
-; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
-; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
-; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP8:![0-9]+]], !irce.loop.clone [[META6]]
;
entry:
%n = load i8, ptr %p, !range !0
@@ -754,7 +652,7 @@ define i8 @test6(i8 %limit, i8 %n) {
; CHECK: inbounds.postloop:
; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
-; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP9:![0-9]+]], !irce.loop.clone [[META6]]
+; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP7:![0-9]+]], !irce.loop.clone !6
;
entry:
%precheck = icmp sgt i8 %limit, 0
@@ -845,7 +743,7 @@ define i8 @test6a(i8 %limit, ptr %p) {
; CHECK: inbounds.postloop:
; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
-; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP10:![0-9]+]], !irce.loop.clone [[META6]]
+; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP8:![0-9]+]], !irce.loop.clone !6
;
entry:
%n = load i8, ptr %p, !range !0
@@ -871,158 +769,4 @@ out_of_bounds:
ret i8 %idx;
}
-; IV = 0; IV <s limit; IV += 1;
-; Check(N - IV > -2)
-;
-; IRCE is allowed.
-; IRCE will reassociate this range check to the 'IV < N + 2',
-; since N < 126 no-overflow fact is provable at compile time.
-define i8 @test_overflow_check_compile_time(i8 %limit, ptr %p) {
-; CHECK-LABEL: define i8 @test_overflow_check_compile_time
-; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG11:![0-9]+]]
-; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
-; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
-; CHECK: loop.preheader:
-; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i8 [[N]], 2
-; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP0]])
-; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 0)
-; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
-; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PREHEADER3:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
-; CHECK: loop.preheader3:
-; CHECK-NEXT: br label [[LOOP:%.*]]
-; CHECK: loop:
-; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER3]] ]
-; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
-; CHECK-NEXT: [[CHECK:%.*]] = icmp sgt i8 [[SUB]], -2
-; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT4:%.*]]
-; CHECK: inbounds:
-; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
-; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
-; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
-; CHECK: main.exit.selector:
-; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
-; CHECK-NEXT: [[IDX_LCSSA2:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
-; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
-; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
-; CHECK: main.pseudo.exit:
-; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
-; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
-; CHECK-NEXT: br label [[POSTLOOP:%.*]]
-; CHECK: exit.loopexit.loopexit:
-; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
-; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
-; CHECK: exit.loopexit:
-; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA2]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
-; CHECK-NEXT: br label [[EXIT]]
-; CHECK: exit:
-; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
-; CHECK-NEXT: ret i8 [[RES]]
-; CHECK: out_of_bounds.loopexit:
-; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
-; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
-; CHECK: out_of_bounds.loopexit4:
-; CHECK-NEXT: [[IDX_LCSSA_PH5:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
-; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
-; CHECK: out_of_bounds:
-; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH5]], [[OUT_OF_BOUNDS_LOOPEXIT4]] ]
-; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
-; CHECK: postloop:
-; CHECK-NEXT: br label [[LOOP_POSTLOOP]]
-; CHECK: loop.postloop:
-; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
-; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]
-; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sgt i8 [[SUB_POSTLOOP]], -2
-; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
-; CHECK: inbounds.postloop:
-; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
-; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
-; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP12:![0-9]+]], !irce.loop.clone [[META6]]
-;
-entry:
- %n = load i8, ptr %p, !range !1
- %precheck = icmp sgt i8 %limit, 0
- br i1 %precheck, label %loop, label %exit
-
-loop:
- %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
- %sub = sub i8 %n, %idx
- %check = icmp sgt i8 %sub, -2
- br i1 %check, label %inbounds, label %out_of_bounds
-
-inbounds:
- %idx.next = add nuw i8 %idx, 1
- %cmp = icmp slt i8 %idx.next, %limit
- br i1 %cmp, label %loop, label %exit
-
-exit:
- %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
- ret i8 %res
-
-out_of_bounds:
- ret i8 %idx;
-}
-
-; IV = 0; IV <s limit; IV += 1;
-; Check(N - IV >= -2)
-;
-; TODO: IRCE is allowed.
-; IRCE will reassociate this range check to the 'IV < (N + 2) + 1',
-; since N < 126 no-overflow fact is NOT provable at compile time and
-; runtime overflow check is required.
-define i8 @test_overflow_check_runtime(i8 %limit, ptr %p) {
-; CHECK-LABEL: define i8 @test_overflow_check_runtime
-; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG11]]
-; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
-; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
-; CHECK: loop.preheader:
-; CHECK-NEXT: br label [[LOOP:%.*]]
-; CHECK: loop:
-; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
-; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
-; CHECK-NEXT: [[CHECK:%.*]] = icmp sge i8 [[SUB]], -2
-; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
-; CHECK: inbounds:
-; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
-; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
-; CHECK: exit.loopexit:
-; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
-; CHECK-NEXT: br label [[EXIT]]
-; CHECK: exit:
-; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
-; CHECK-NEXT: ret i8 [[RES]]
-; CHECK: out_of_bounds:
-; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
-; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
-;
-entry:
- %n = load i8, ptr %p, !range !1
- %precheck = icmp sgt i8 %limit, 0
- br i1 %precheck, label %loop, label %exit
-
-loop:
- %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
- %sub = sub i8 %n, %idx
- %check = icmp sge i8 %sub, -2
- br i1 %check, label %inbounds, label %out_of_bounds
-
-inbounds:
- %idx.next = add nuw i8 %idx, 1
- %cmp = icmp slt i8 %idx.next, %limit
- br i1 %cmp, label %loop, label %exit
-
-exit:
- %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
- ret i8 %res
-
-out_of_bounds:
- ret i8 %idx;
-}
-
!0 = !{i8 0, i8 127}
-!1 = !{i8 0, i8 126}
More information about the llvm-commits
mailing list