Skip to content

Commit 18170d0

Browse files
authored
[ConstraintElim] Extend AND implication logic to support OR as well. (#76044)
Extend the logic check if an operand of an AND is implied by the other to also support OR. This is done by checking if !op1 implies op2 or vice versa.
1 parent 2c257cf commit 18170d0

File tree

5 files changed

+38
-26
lines changed

5 files changed

+38
-26
lines changed

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,29 +1365,34 @@ removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info,
13651365
ReproducerCondStack.pop_back();
13661366
}
13671367

1368-
/// Check if either the first condition of an AND is implied by the second or
1369-
/// vice versa.
1370-
static bool
1371-
checkAndOpImpliedByOther(FactOrCheck &CB, ConstraintInfo &Info,
1372-
Module *ReproducerModule,
1373-
SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
1374-
SmallVectorImpl<StackEntry> &DFSInStack) {
1368+
/// Check if either the first condition of an AND or OR is implied by the
1369+
/// (negated in case of OR) second condition or vice versa.
1370+
static bool checkOrAndOpImpliedByOther(
1371+
FactOrCheck &CB, ConstraintInfo &Info, Module *ReproducerModule,
1372+
SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
1373+
SmallVectorImpl<StackEntry> &DFSInStack) {
13751374

13761375
CmpInst::Predicate Pred;
13771376
Value *A, *B;
1378-
Instruction *And = CB.getContextInst();
1377+
Instruction *JoinOp = CB.getContextInst();
13791378
CmpInst *CmpToCheck = cast<CmpInst>(CB.getInstructionToSimplify());
1380-
unsigned OtherOpIdx = And->getOperand(0) == CmpToCheck ? 1 : 0;
1379+
unsigned OtherOpIdx = JoinOp->getOperand(0) == CmpToCheck ? 1 : 0;
13811380

13821381
// Don't try to simplify the first condition of a select by the second, as
13831382
// this may make the select more poisonous than the original one.
13841383
// TODO: check if the first operand may be poison.
1385-
if (OtherOpIdx != 0 && isa<SelectInst>(And))
1384+
if (OtherOpIdx != 0 && isa<SelectInst>(JoinOp))
13861385
return false;
13871386

1388-
if (!match(And->getOperand(OtherOpIdx), m_ICmp(Pred, m_Value(A), m_Value(B))))
1387+
if (!match(JoinOp->getOperand(OtherOpIdx),
1388+
m_ICmp(Pred, m_Value(A), m_Value(B))))
13891389
return false;
13901390

1391+
// For OR, check if the negated condition implies CmpToCheck.
1392+
bool IsOr = match(JoinOp, m_LogicalOr());
1393+
if (IsOr)
1394+
Pred = CmpInst::getInversePredicate(Pred);
1395+
13911396
// Optimistically add fact from first condition.
13921397
unsigned OldSize = DFSInStack.size();
13931398
Info.addFact(Pred, A, B, CB.NumIn, CB.NumOut, DFSInStack);
@@ -1400,8 +1405,15 @@ checkAndOpImpliedByOther(FactOrCheck &CB, ConstraintInfo &Info,
14001405
checkCondition(CmpToCheck->getPredicate(), CmpToCheck->getOperand(0),
14011406
CmpToCheck->getOperand(1), CmpToCheck, Info, CB.NumIn,
14021407
CB.NumOut, CB.getContextInst())) {
1403-
And->setOperand(1 - OtherOpIdx,
1404-
ConstantInt::getBool(And->getType(), *ImpliedCondition));
1408+
if (IsOr && isa<SelectInst>(JoinOp)) {
1409+
JoinOp->setOperand(
1410+
OtherOpIdx == 0 ? 2 : 0,
1411+
ConstantInt::getBool(JoinOp->getType(), *ImpliedCondition));
1412+
} else
1413+
JoinOp->setOperand(
1414+
1 - OtherOpIdx,
1415+
ConstantInt::getBool(JoinOp->getType(), *ImpliedCondition));
1416+
14051417
Changed = true;
14061418
}
14071419

@@ -1622,10 +1634,10 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
16221634
Cmp, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
16231635
ReproducerModule.get(), ReproducerCondStack, S.DT, ToRemove);
16241636
if (!Simplified &&
1625-
match(CB.getContextInst(), m_LogicalAnd(m_Value(), m_Value()))) {
1637+
match(CB.getContextInst(), m_LogicalOp(m_Value(), m_Value()))) {
16261638
Simplified =
1627-
checkAndOpImpliedByOther(CB, Info, ReproducerModule.get(),
1628-
ReproducerCondStack, DFSInStack);
1639+
checkOrAndOpImpliedByOther(CB, Info, ReproducerModule.get(),
1640+
ReproducerCondStack, DFSInStack);
16291641
}
16301642
Changed |= Simplified;
16311643
}

llvm/test/Transforms/ConstraintElimination/and-implied-by-operands.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ define i1 @test_or_used_in_false_branch(i8 %x) {
398398
; CHECK-NEXT: entry:
399399
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[X:%.*]], 10
400400
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i8 [[X]], 5
401-
; CHECK-NEXT: [[AND:%.*]] = or i1 [[C_1]], [[T_1]]
401+
; CHECK-NEXT: [[AND:%.*]] = or i1 [[C_1]], false
402402
; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
403403
; CHECK: then:
404404
; CHECK-NEXT: ret i1 [[T_1]]
@@ -424,7 +424,7 @@ define i1 @test_or_used_in_false_branch2(i8 %x) {
424424
; CHECK-NEXT: entry:
425425
; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
426426
; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[X]], 5
427-
; CHECK-NEXT: [[AND:%.*]] = or i1 [[C_1]], [[T_1]]
427+
; CHECK-NEXT: [[AND:%.*]] = or i1 false, [[T_1]]
428428
; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
429429
; CHECK: then:
430430
; CHECK-NEXT: ret i1 [[T_1]]

llvm/test/Transforms/ConstraintElimination/gep-arithmetic-signed-predicates.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ define i4 @ptr_N_signed_positive_assume(ptr %src, ptr %lower, ptr %upper, i16 %N
617617
; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[STEP]]
618618
; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]]
619619
; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]]
620-
; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
620+
; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 true, [[CMP_STEP_END]]
621621
; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
622622
; CHECK: exit:
623623
; CHECK-NEXT: ret i4 3

llvm/test/Transforms/ConstraintElimination/geps-precondition-overflow-check.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ define i1 @overflow_check_3_or(ptr %dst) {
152152
; CHECK-NEXT: entry:
153153
; CHECK-NEXT: [[DST_5:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 5
154154
; CHECK-NEXT: [[DST_5_UGE:%.*]] = icmp uge ptr [[DST_5]], [[DST]]
155-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[DST_5_UGE]], [[DST_5_UGE]]
155+
; CHECK-NEXT: [[OR:%.*]] = or i1 false, [[DST_5_UGE]]
156156
; CHECK-NEXT: br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
157157
; CHECK: then:
158158
; CHECK-NEXT: [[DST_4:%.*]] = getelementptr i32, ptr [[DST]], i64 4

llvm/test/Transforms/ConstraintElimination/or-implied-by-operands.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ define i1 @test_second_or_condition_implied_by_first(i8 %x) {
66
; CHECK-NEXT: entry:
77
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[X:%.*]], 10
88
; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[X]], 5
9-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_1]], [[T_1]]
9+
; CHECK-NEXT: [[OR:%.*]] = or i1 true, [[T_1]]
1010
; CHECK-NEXT: br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
1111
; CHECK: then:
1212
; CHECK-NEXT: ret i1 false
@@ -31,7 +31,7 @@ define i1 @test_first_or_condition_implied_by_second_ops(i8 %x) {
3131
; CHECK-NEXT: entry:
3232
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[X:%.*]], 10
3333
; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[X]], 5
34-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[T_1]], [[C_1]]
34+
; CHECK-NEXT: [[OR:%.*]] = or i1 [[T_1]], true
3535
; CHECK-NEXT: br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
3636
; CHECK: then:
3737
; CHECK-NEXT: ret i1 false
@@ -105,7 +105,7 @@ define i1 @test_same_cond_for_or(i8 %x) {
105105
; CHECK-LABEL: @test_same_cond_for_or(
106106
; CHECK-NEXT: entry:
107107
; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
108-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_1]], [[C_1]]
108+
; CHECK-NEXT: [[OR:%.*]] = or i1 false, [[C_1]]
109109
; CHECK-NEXT: br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
110110
; CHECK: then:
111111
; CHECK-NEXT: ret i1 false
@@ -152,7 +152,7 @@ define i1 @test_second_or_condition_not_implied_by_first(i8 %x) {
152152
; CHECK-NEXT: entry:
153153
; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
154154
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i8 [[X]], 5
155-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_2]], [[C_1]]
155+
; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_2]], false
156156
; CHECK-NEXT: br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
157157
; CHECK: then:
158158
; CHECK-NEXT: ret i1 false
@@ -245,7 +245,7 @@ define i1 @test_or_used_in_false_branch(i8 %x) {
245245
; CHECK-NEXT: entry:
246246
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[X:%.*]], 10
247247
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i8 [[X]], 5
248-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_1]], [[T_1]]
248+
; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_1]], false
249249
; CHECK-NEXT: br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
250250
; CHECK: then:
251251
; CHECK-NEXT: ret i1 [[T_1]]
@@ -271,7 +271,7 @@ define i1 @test_or_used_in_false_branch2(i8 %x) {
271271
; CHECK-NEXT: entry:
272272
; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
273273
; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[X]], 5
274-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_1]], [[T_1]]
274+
; CHECK-NEXT: [[OR:%.*]] = or i1 false, [[T_1]]
275275
; CHECK-NEXT: br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
276276
; CHECK: then:
277277
; CHECK-NEXT: ret i1 [[T_1]]

0 commit comments

Comments
 (0)