Skip to content

[llvm][ConstraintElimination]Insert ConditionFact into loop header in case of monotonic induction variables #112080

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 76 additions & 4 deletions llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,12 @@ struct State {
LoopInfo &LI;
ScalarEvolution &SE;
SmallVector<FactOrCheck, 64> WorkList;
bool AddInductionInfoIntoHeader = false;

State(DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE)
: DT(DT), LI(LI), SE(SE) {}
State(DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE,
bool AddInductionInfoIntoHeader = false)
: DT(DT), LI(LI), SE(SE),
AddInductionInfoIntoHeader(AddInductionInfoIntoHeader) {}

/// Process block \p BB and add known facts to work-list.
void addInfoFor(BasicBlock &BB);
Expand All @@ -197,6 +200,8 @@ struct State {
/// controlling the loop header.
void addInfoForInductions(BasicBlock &BB);

void addConditionFactsIntoLoopHeader(BasicBlock &BB);

/// Returns true if we can add a known condition from BB to its successor
/// block Succ.
bool canAddSuccessor(BasicBlock &BB, BasicBlock *Succ) const {
Expand Down Expand Up @@ -900,7 +905,62 @@ static void dumpConstraint(ArrayRef<int64_t> C,
}
#endif

// For monotonically decreasing/increasing variables in the loop,
// this will insert ConditionFact PN >= StartingValue or PN <= StartingValue
// associated with the loop header, where PN is the corresponding PHi node.
void State::addConditionFactsIntoLoopHeader(BasicBlock &BB) {
auto *L = LI.getLoopFor(&BB);
if (!L || L->getHeader() != &BB)
return;
DomTreeNode *DTN = DT.getNode(&BB);
for (PHINode &PN : L->getHeader()->phis()) {
if (PN.getNumIncomingValues() != 2 || PN.getParent() != &BB ||
!SE.isSCEVable(PN.getType()))
continue;
auto *AR = dyn_cast_or_null<SCEVAddRecExpr>(SE.getSCEV(&PN));
BasicBlock *LoopPred = L->getLoopPredecessor();
if (!AR || AR->getLoop() != L || !LoopPred)
return;
const SCEV *StartSCEV = AR->getStart();
Value *StartValue = nullptr;
if (auto *C = dyn_cast<SCEVConstant>(StartSCEV)) {
StartValue = C->getValue();
} else {
StartValue = PN.getIncomingValueForBlock(LoopPred);
assert(SE.getSCEV(StartValue) == StartSCEV && "inconsistent start value");
}
auto IncUnsigned = SE.getMonotonicPredicateType(AR, CmpInst::ICMP_UGT);
auto IncSigned = SE.getMonotonicPredicateType(AR, CmpInst::ICMP_SGT);

// Monotonically Increasing
bool MonotonicallyIncreasingUnsigned =
IncUnsigned && *IncUnsigned == ScalarEvolution::MonotonicallyIncreasing;
bool MonotonicallyIncreasingSigned =
IncSigned && *IncSigned == ScalarEvolution::MonotonicallyIncreasing;
if (MonotonicallyIncreasingUnsigned)
WorkList.push_back(FactOrCheck::getConditionFact(DTN, CmpInst::ICMP_UGE,
&PN, StartValue));
if (MonotonicallyIncreasingSigned)
WorkList.push_back(FactOrCheck::getConditionFact(DTN, CmpInst::ICMP_SGE,
&PN, StartValue));

// Monotonically Decreasing
bool MonotonicallyDecreasingUnsigned =
IncUnsigned && *IncUnsigned == ScalarEvolution::MonotonicallyDecreasing;
bool MonotonicallyDecreasingSigned =
IncSigned && *IncSigned == ScalarEvolution::MonotonicallyDecreasing;
if (MonotonicallyDecreasingUnsigned)
WorkList.push_back(FactOrCheck::getConditionFact(DTN, CmpInst::ICMP_ULE,
&PN, StartValue));
if (MonotonicallyDecreasingSigned)
WorkList.push_back(FactOrCheck::getConditionFact(DTN, CmpInst::ICMP_SLE,
&PN, StartValue));
}
}

void State::addInfoForInductions(BasicBlock &BB) {
if (AddInductionInfoIntoHeader)
addConditionFactsIntoLoopHeader(BB);
auto *L = LI.getLoopFor(&BB);
if (!L || L->getHeader() != &BB)
return;
Expand Down Expand Up @@ -1358,7 +1418,7 @@ static std::optional<bool> checkCondition(CmpInst::Predicate Pred, Value *A,
LLVM_DEBUG(dbgs() << "Checking " << *CheckInst << "\n");

auto R = Info.getConstraintForSolving(Pred, A, B);
if (R.empty() || !R.isValid(Info)){
if (R.empty() || !R.isValid(Info)) {
LLVM_DEBUG(dbgs() << " failed to decompose condition\n");
return std::nullopt;
}
Expand Down Expand Up @@ -1671,6 +1731,16 @@ tryToSimplifyOverflowMath(IntrinsicInst *II, ConstraintInfo &Info,
return Changed;
}

static unsigned int getNumConditionalBranches(Function &F) {
unsigned int NumCondBranches = 0;
for (BasicBlock &BB : F) {
BranchInst *BranchInstr = dyn_cast_or_null<BranchInst>(BB.getTerminator());
if (BranchInstr && BranchInstr->isConditional())
NumCondBranches++;
}
return NumCondBranches;
}

static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
ScalarEvolution &SE,
OptimizationRemarkEmitter &ORE) {
Expand All @@ -1680,7 +1750,9 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
for (Value &Arg : F.args())
FunctionArgs.push_back(&Arg);
ConstraintInfo Info(F.getDataLayout(), FunctionArgs);
State S(DT, LI, SE);
unsigned int NumCondBranches = getNumConditionalBranches(F);
State S(DT, LI, SE,
/* AddInductionInfoIntoHeader= */ NumCondBranches < MaxRows / 5);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not aware of the existing MaxRows mechanism during my earlier review, so that seems to be already enough to avoid compile-time explosion.

Doing a whole walk over the function to count conditional branches feels somewhat heavy and we potentially get an amount of facts in the number of Phi instructions (which isn't necessarily correlated to number of condjumps). Anyway just trying to make a case that maybe we should just do the simpler thing and rely on MaxRows limiting things without adding extra conditions here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I added this condition is to avoid regression in some edge cases (see analysis by @dtcxzyw). If we add extra constrains in loop headers and reach MaxRows limit, some constraints are dropped that are not otherwise. I am happy to remove it if we are OK with those regressions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It just feels like a lot of trouble (or rather a lot of memory read) to go through the whole function just to count the number of conditional branches... So I am wondering if there is ways to limit this without having an extra pass over the whole function...

std::unique_ptr<Module> ReproducerModule(
DumpReproducers ? new Module(F.getName(), F.getContext()) : nullptr);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,8 @@ define void @test_monotonic_ptr_iv_inc_1_eq_to_uge(ptr %start, i16 %len) {
; CHECK-NEXT: [[AND_0:%.*]] = and i1 [[LEN_NEG]], [[C]]
; CHECK-NEXT: br i1 [[AND_0]], label [[FOR_BODY:%.*]], label [[EXIT:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
; CHECK: loop.latch:
; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
Expand Down
47 changes: 47 additions & 0 deletions llvm/test/Transforms/ConstraintElimination/loop-removal.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -passes=constraint-elimination -S | FileCheck %s

define i32 @foo() {
; CHECK-LABEL: define i32 @foo() {
; CHECK-NEXT: init:
; CHECK-NEXT: br label %[[OUTER_LOOP_CONTROL:.*]]
; CHECK: outer.loop.control:
; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[INIT:%.*]] ], [ [[X_OUTER:%.*]], %[[OUTER_LOOP_INC:.*]] ]
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[X_0]], 10
; CHECK-NEXT: br i1 [[TMP0]], label %[[INNER_LOOP_CONTROL:.*]], label %[[EXIT:.*]]
; CHECK: inner.loop.control:
; CHECK-NEXT: [[X_1:%.*]] = phi i32 [ [[X_0]], %[[OUTER_LOOP_CONTROL]] ], [ [[X_INNER:%.*]], %[[INNER_LOOP_BODY:.*]] ]
; CHECK-NEXT: br i1 false, label %[[INNER_LOOP_BODY]], label %[[OUTER_LOOP_INC]]
; CHECK: inner.loop.body:
; CHECK-NEXT: [[X_INNER]] = add nsw i32 [[X_1]], -1
; CHECK-NEXT: br label %[[INNER_LOOP_CONTROL]]
; CHECK: outer.loop.inc:
; CHECK-NEXT: [[X_OUTER]] = add nsw i32 [[X_1]], 2
; CHECK-NEXT: br label %[[OUTER_LOOP_CONTROL]]
; CHECK: exit:
; CHECK-NEXT: ret i32 [[X_0]]
;
init:
br label %outer.loop.control

outer.loop.control: ; preds = %init, %outer.loop.inc
%x.0 = phi i32 [ 0, %init ], [ %x.outer, %outer.loop.inc ]
%0 = icmp slt i32 %x.0, 10
br i1 %0, label %inner.loop.control, label %exit

inner.loop.control: ; preds = %outer.loop.control, %inner.loop.body
%x.1 = phi i32 [ %x.0, %outer.loop.control ], [ %x.inner, %inner.loop.body ]
%1 = icmp sgt i32 %x.1, 20
br i1 %1, label %inner.loop.body, label %outer.loop.inc

inner.loop.body: ; preds = %inner.loop.control
%x.inner = add nsw i32 %x.1, -1
br label %inner.loop.control

outer.loop.inc: ; preds = %inner.loop.control
%x.outer = add nsw i32 %x.1, 2
br label %outer.loop.control

exit: ; preds = %1
ret i32 %x.0
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ define void @loop_iv_cond_variable_bound(i32 %n) {
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i32 [[IV]], [[N:%.*]]
; CHECK-NEXT: call void @use(i1 [[T_1]])
; CHECK-NEXT: [[T_2:%.*]] = icmp sge i32 [[IV]], 0
; CHECK-NEXT: call void @use(i1 [[T_2]])
; CHECK-NEXT: [[T_3:%.*]] = icmp sge i32 [[IV]], -1
; CHECK-NEXT: call void @use(i1 [[T_3]])
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[C_1:%.*]] = icmp ult i32 [[IV]], [[N]]
; CHECK-NEXT: call void @use(i1 [[C_1]])
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[IV]], 1
Expand Down Expand Up @@ -58,10 +56,8 @@ define void @loop_iv_cond_constant_bound() {
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i32 [[IV]], 2
; CHECK-NEXT: call void @use(i1 [[T_1]])
; CHECK-NEXT: [[T_2:%.*]] = icmp sge i32 [[IV]], 0
; CHECK-NEXT: call void @use(i1 [[T_2]])
; CHECK-NEXT: [[T_3:%.*]] = icmp sge i32 [[IV]], -1
; CHECK-NEXT: call void @use(i1 [[T_3]])
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[C_1:%.*]] = icmp ult i32 [[IV]], 2
; CHECK-NEXT: call void @use(i1 [[C_1]])
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[IV]], 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ define void @checks_in_loops_removable(ptr %ptr, ptr %lower, ptr %upper, i8 %n)
; CHECK: loop.header:
; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 0, [[PRE_2]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV]]
; CHECK-NEXT: [[CMP_PTR_IV_LOWER:%.*]] = icmp ugt ptr [[LOWER]], [[PTR_IV]]
; CHECK-NEXT: [[CMP_PTR_IV_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[PTR_IV]]
; CHECK-NEXT: [[OR:%.*]] = or i1 false, [[CMP_PTR_IV_UPPER]]
; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_LATCH]]
Expand Down Expand Up @@ -86,7 +85,6 @@ define void @some_checks_in_loops_removable(ptr %ptr, ptr %lower, ptr %upper, i8
; CHECK: loop.header:
; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 0, [[PRE_2]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV]]
; CHECK-NEXT: [[CMP_PTR_IV_LOWER:%.*]] = icmp ugt ptr [[LOWER]], [[PTR_IV]]
; CHECK-NEXT: [[CMP_PTR_IV_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[PTR_IV]]
; CHECK-NEXT: [[OR:%.*]] = or i1 false, [[CMP_PTR_IV_UPPER]]
; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_BODY:%.*]]
Expand Down Expand Up @@ -163,7 +161,6 @@ define void @no_checks_in_loops_removable(ptr %ptr, ptr %lower, ptr %upper, i8 %
; CHECK: loop.header:
; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 0, [[PRE_1]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV]]
; CHECK-NEXT: [[CMP_PTR_IV_LOWER:%.*]] = icmp ugt ptr [[LOWER]], [[PTR_IV]]
; CHECK-NEXT: [[CMP_PTR_IV_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[PTR_IV]]
; CHECK-NEXT: [[OR:%.*]] = or i1 false, [[CMP_PTR_IV_UPPER]]
; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_BODY:%.*]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,11 @@ define void @loop_phi_pos_start_value(i32 %y, i1 %c, i32 %n) {
; CHECK: loop.latch:
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: call void @use(i1 false)
; CHECK-NEXT: [[T_2:%.*]] = icmp sge i32 [[X]], 10
; CHECK-NEXT: call void @use(i1 [[T_2]])
; CHECK-NEXT: [[C_2:%.*]] = icmp sle i32 [[X]], 9
; CHECK-NEXT: call void @use(i1 [[C_2]])
; CHECK-NEXT: [[C_3:%.*]] = icmp sgt i32 [[X]], 9
; CHECK-NEXT: call void @use(i1 [[C_3]])
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[C_5:%.*]] = icmp sge i32 [[X]], 9
; CHECK-NEXT: call void @use(i1 [[C_5]])
; CHECK-NEXT: call void @use(i1 false)
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[X_NEXT]] = add nsw i32 [[X]], 1
; CHECK-NEXT: br label [[LOOP_HEADER]]
; CHECK: exit:
Expand Down Expand Up @@ -75,8 +71,7 @@ define void @loop_phi_neg_start_value(i32 %y, i1 %c, i32 %n) {
; CHECK: loop.latch:
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: call void @use(i1 false)
; CHECK-NEXT: [[T_2:%.*]] = icmp sge i32 [[X]], -10
; CHECK-NEXT: call void @use(i1 [[T_2]])
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[C_2:%.*]] = icmp sle i32 [[X]], 9
; CHECK-NEXT: call void @use(i1 [[C_2]])
; CHECK-NEXT: [[C_3:%.*]] = icmp sgt i32 [[X]], 9
Expand Down Expand Up @@ -299,10 +294,8 @@ define void @loop_iv_cond_variable_bound(i32 %n) {
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i32 [[IV]], [[N:%.*]]
; CHECK-NEXT: call void @use(i1 [[T_1]])
; CHECK-NEXT: [[T_2:%.*]] = icmp sge i32 [[IV]], 0
; CHECK-NEXT: call void @use(i1 [[T_2]])
; CHECK-NEXT: [[T_3:%.*]] = icmp sge i32 [[IV]], -1
; CHECK-NEXT: call void @use(i1 [[T_3]])
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[C_1:%.*]] = icmp ult i32 [[IV]], [[N]]
; CHECK-NEXT: call void @use(i1 [[C_1]])
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[IV]], 1
Expand Down Expand Up @@ -364,10 +357,8 @@ define void @loop_iv_cond_constant_bound() {
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i32 [[IV]], 2
; CHECK-NEXT: call void @use(i1 [[T_1]])
; CHECK-NEXT: [[T_2:%.*]] = icmp sge i32 [[IV]], 0
; CHECK-NEXT: call void @use(i1 [[T_2]])
; CHECK-NEXT: [[T_3:%.*]] = icmp sge i32 [[IV]], -1
; CHECK-NEXT: call void @use(i1 [[T_3]])
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[C_1:%.*]] = icmp ult i32 [[IV]], 2
; CHECK-NEXT: call void @use(i1 [[C_1]])
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[IV]], 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ define void @test2_with_ne(ptr %src, ptr %lower, ptr %upper, i8 %N) {
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_BODY:%.*]]
; CHECK: loop.body:
; CHECK-NEXT: [[SRC_IV:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[IV]]
; CHECK-NEXT: [[CMP_IV_START:%.*]] = icmp ult ptr [[SRC_IV]], [[LOWER]]
; CHECK-NEXT: [[CMP_IV_END:%.*]] = icmp uge ptr [[SRC_IV]], [[UPPER]]
; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_IV_END]]
; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP_BB]], label [[LOOP_BODY_1:%.*]]
Expand Down Expand Up @@ -304,7 +303,6 @@ define void @test3(ptr %src, ptr %lower, ptr %upper, i8 %N) {
; CHECK-NEXT: br i1 [[EC]], label [[LOOP_BODY:%.*]], label [[EXIT:%.*]]
; CHECK: loop.body:
; CHECK-NEXT: [[SRC_IV:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[IV]]
; CHECK-NEXT: [[CMP_IV_START:%.*]] = icmp ult ptr [[SRC_IV]], [[LOWER]]
; CHECK-NEXT: [[CMP_IV_END:%.*]] = icmp uge ptr [[SRC_IV]], [[UPPER]]
; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_IV_END]]
; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP_BB]], label [[LOOP_BODY_1:%.*]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ define void @loop_pointer_iv(ptr %start, ptr %end, ptr %upper) {
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT: [[C_2:%.*]] = icmp ule ptr [[IV]], [[END]]
; CHECK-NEXT: call void @use(i1 [[C_2]])
; CHECK-NEXT: [[T_2:%.*]] = icmp uge ptr [[IV]], [[START]]
; CHECK-NEXT: call void @use(i1 [[T_2]])
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[C_1:%.*]] = icmp ule ptr [[IV]], [[END]]
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT]]
; CHECK: loop.latch:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ define void @test_iv_nuw_nsw_1_uge_start(i8 %len.n, i8 %a) {
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
; CHECK: loop.header:
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ -1, [[LOOP_PH:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[IV]], 1
; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
; CHECK-NEXT: br i1 false, label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_LATCH]], label [[EXIT]]
Expand Down Expand Up @@ -90,8 +89,7 @@ define void @test_iv_nuw_nsw_2_uge_start(i8 %len.n, i8 %a) {
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
; CHECK: loop.header:
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START]], [[LOOP_PH:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[IV]], 1
; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
; CHECK-NEXT: br i1 false, label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_LATCH]], label [[EXIT]]
Expand Down Expand Up @@ -131,8 +129,7 @@ define void @test_iv_nsw_nuw_1_ult_end(i8 %len.n, i8 %a) {
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
; CHECK: loop.header:
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ -2, [[LOOP_PH:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[IV]], 1
; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
; CHECK-NEXT: br i1 false, label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_LATCH]], label [[EXIT]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_chain_of_2_ex
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
; CHECK: loop.next:
; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
; CHECK: loop.latch:
; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
Expand Down Expand Up @@ -94,9 +93,8 @@ define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_chain_of_3_ex
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
; CHECK: loop.next:
; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
; CHECK: loop.latch:
; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
Expand Down Expand Up @@ -163,9 +161,8 @@ define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_chain_of_2_ex
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
; CHECK: loop.next:
; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
; CHECK: loop.latch:
; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
Expand Down Expand Up @@ -227,9 +224,8 @@ define void @test_header_not_exiting(ptr %start, i16 %len, i16 %x) {
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
; CHECK: loop.next:
; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
; CHECK: loop.latch:
; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
Expand Down
Loading
Loading