[llvm] 18170d0 - [ConstraintElim] Extend AND implication logic to support OR as well. (#76044)

via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 20 09:13:46 PST 2023


Author: Florian Hahn
Date: 2023-12-20T18:13:41+01:00
New Revision: 18170d0f281c2cae5252c501cbcd174783de78b7

URL: https://github.com/llvm/llvm-project/commit/18170d0f281c2cae5252c501cbcd174783de78b7
DIFF: https://github.com/llvm/llvm-project/commit/18170d0f281c2cae5252c501cbcd174783de78b7.diff

LOG: [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.

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
    llvm/test/Transforms/ConstraintElimination/and-implied-by-operands.ll
    llvm/test/Transforms/ConstraintElimination/gep-arithmetic-signed-predicates.ll
    llvm/test/Transforms/ConstraintElimination/geps-precondition-overflow-check.ll
    llvm/test/Transforms/ConstraintElimination/or-implied-by-operands.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index f208ca2f5634bf..98cfadddee8efb 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1365,29 +1365,34 @@ removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info,
     ReproducerCondStack.pop_back();
 }
 
-/// Check if either the first condition of an AND is implied by the second or
-/// vice versa.
-static bool
-checkAndOpImpliedByOther(FactOrCheck &CB, ConstraintInfo &Info,
-                         Module *ReproducerModule,
-                         SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
-                         SmallVectorImpl<StackEntry> &DFSInStack) {
+/// Check if either the first condition of an AND or OR is implied by the
+/// (negated in case of OR) second condition or vice versa.
+static bool checkOrAndOpImpliedByOther(
+    FactOrCheck &CB, ConstraintInfo &Info, Module *ReproducerModule,
+    SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
+    SmallVectorImpl<StackEntry> &DFSInStack) {
 
   CmpInst::Predicate Pred;
   Value *A, *B;
-  Instruction *And = CB.getContextInst();
+  Instruction *JoinOp = CB.getContextInst();
   CmpInst *CmpToCheck = cast<CmpInst>(CB.getInstructionToSimplify());
-  unsigned OtherOpIdx = And->getOperand(0) == CmpToCheck ? 1 : 0;
+  unsigned OtherOpIdx = JoinOp->getOperand(0) == CmpToCheck ? 1 : 0;
 
   // Don't try to simplify the first condition of a select by the second, as
   // this may make the select more poisonous than the original one.
   // TODO: check if the first operand may be poison.
-  if (OtherOpIdx != 0 && isa<SelectInst>(And))
+  if (OtherOpIdx != 0 && isa<SelectInst>(JoinOp))
     return false;
 
-  if (!match(And->getOperand(OtherOpIdx), m_ICmp(Pred, m_Value(A), m_Value(B))))
+  if (!match(JoinOp->getOperand(OtherOpIdx),
+             m_ICmp(Pred, m_Value(A), m_Value(B))))
     return false;
 
+  // For OR, check if the negated condition implies CmpToCheck.
+  bool IsOr = match(JoinOp, m_LogicalOr());
+  if (IsOr)
+    Pred = CmpInst::getInversePredicate(Pred);
+
   // Optimistically add fact from first condition.
   unsigned OldSize = DFSInStack.size();
   Info.addFact(Pred, A, B, CB.NumIn, CB.NumOut, DFSInStack);
@@ -1400,8 +1405,15 @@ checkAndOpImpliedByOther(FactOrCheck &CB, ConstraintInfo &Info,
           checkCondition(CmpToCheck->getPredicate(), CmpToCheck->getOperand(0),
                          CmpToCheck->getOperand(1), CmpToCheck, Info, CB.NumIn,
                          CB.NumOut, CB.getContextInst())) {
-    And->setOperand(1 - OtherOpIdx,
-                    ConstantInt::getBool(And->getType(), *ImpliedCondition));
+    if (IsOr && isa<SelectInst>(JoinOp)) {
+      JoinOp->setOperand(
+          OtherOpIdx == 0 ? 2 : 0,
+          ConstantInt::getBool(JoinOp->getType(), *ImpliedCondition));
+    } else
+      JoinOp->setOperand(
+          1 - OtherOpIdx,
+          ConstantInt::getBool(JoinOp->getType(), *ImpliedCondition));
+
     Changed = true;
   }
 
@@ -1622,10 +1634,10 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
             Cmp, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
             ReproducerModule.get(), ReproducerCondStack, S.DT, ToRemove);
         if (!Simplified &&
-            match(CB.getContextInst(), m_LogicalAnd(m_Value(), m_Value()))) {
+            match(CB.getContextInst(), m_LogicalOp(m_Value(), m_Value()))) {
           Simplified =
-              checkAndOpImpliedByOther(CB, Info, ReproducerModule.get(),
-                                       ReproducerCondStack, DFSInStack);
+              checkOrAndOpImpliedByOther(CB, Info, ReproducerModule.get(),
+                                         ReproducerCondStack, DFSInStack);
         }
         Changed |= Simplified;
       }

diff  --git a/llvm/test/Transforms/ConstraintElimination/and-implied-by-operands.ll b/llvm/test/Transforms/ConstraintElimination/and-implied-by-operands.ll
index 3d2a480195abc3..2de7592d5ccc7a 100644
--- a/llvm/test/Transforms/ConstraintElimination/and-implied-by-operands.ll
+++ b/llvm/test/Transforms/ConstraintElimination/and-implied-by-operands.ll
@@ -398,7 +398,7 @@ define i1 @test_or_used_in_false_branch(i8 %x) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[X:%.*]], 10
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ule i8 [[X]], 5
-; CHECK-NEXT:    [[AND:%.*]] = or i1 [[C_1]], [[T_1]]
+; CHECK-NEXT:    [[AND:%.*]] = or i1 [[C_1]], false
 ; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
 ; CHECK-NEXT:    ret i1 [[T_1]]
@@ -424,7 +424,7 @@ define i1 @test_or_used_in_false_branch2(i8 %x) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ugt i8 [[X]], 5
-; CHECK-NEXT:    [[AND:%.*]] = or i1 [[C_1]], [[T_1]]
+; CHECK-NEXT:    [[AND:%.*]] = or i1 false, [[T_1]]
 ; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
 ; CHECK-NEXT:    ret i1 [[T_1]]

diff  --git a/llvm/test/Transforms/ConstraintElimination/gep-arithmetic-signed-predicates.ll b/llvm/test/Transforms/ConstraintElimination/gep-arithmetic-signed-predicates.ll
index 96ff98b00538ef..52094914f6962d 100644
--- a/llvm/test/Transforms/ConstraintElimination/gep-arithmetic-signed-predicates.ll
+++ b/llvm/test/Transforms/ConstraintElimination/gep-arithmetic-signed-predicates.ll
@@ -617,7 +617,7 @@ define i4 @ptr_N_signed_positive_assume(ptr %src, ptr %lower, ptr %upper, i16 %N
 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[STEP]]
 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]]
 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]]
-; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
+; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 true, [[CMP_STEP_END]]
 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret i4 3

diff  --git a/llvm/test/Transforms/ConstraintElimination/geps-precondition-overflow-check.ll b/llvm/test/Transforms/ConstraintElimination/geps-precondition-overflow-check.ll
index 834db0418b4d46..08b25c6065aace 100644
--- a/llvm/test/Transforms/ConstraintElimination/geps-precondition-overflow-check.ll
+++ b/llvm/test/Transforms/ConstraintElimination/geps-precondition-overflow-check.ll
@@ -152,7 +152,7 @@ define i1 @overflow_check_3_or(ptr %dst) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[DST_5:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 5
 ; CHECK-NEXT:    [[DST_5_UGE:%.*]] = icmp uge ptr [[DST_5]], [[DST]]
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[DST_5_UGE]], [[DST_5_UGE]]
+; CHECK-NEXT:    [[OR:%.*]] = or i1 false, [[DST_5_UGE]]
 ; CHECK-NEXT:    br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
 ; CHECK-NEXT:    [[DST_4:%.*]] = getelementptr i32, ptr [[DST]], i64 4

diff  --git a/llvm/test/Transforms/ConstraintElimination/or-implied-by-operands.ll b/llvm/test/Transforms/ConstraintElimination/or-implied-by-operands.ll
index 61e6e250f6dd99..fea6f2d8a5dc4e 100644
--- a/llvm/test/Transforms/ConstraintElimination/or-implied-by-operands.ll
+++ b/llvm/test/Transforms/ConstraintElimination/or-implied-by-operands.ll
@@ -6,7 +6,7 @@ define i1 @test_second_or_condition_implied_by_first(i8 %x) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[X:%.*]], 10
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ugt i8 [[X]], 5
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_1]], [[T_1]]
+; CHECK-NEXT:    [[OR:%.*]] = or i1 true, [[T_1]]
 ; CHECK-NEXT:    br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
 ; CHECK-NEXT:    ret i1 false
@@ -31,7 +31,7 @@ define i1 @test_first_or_condition_implied_by_second_ops(i8 %x) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[X:%.*]], 10
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ugt i8 [[X]], 5
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[T_1]], [[C_1]]
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[T_1]], true
 ; CHECK-NEXT:    br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
 ; CHECK-NEXT:    ret i1 false
@@ -105,7 +105,7 @@ define i1 @test_same_cond_for_or(i8 %x) {
 ; CHECK-LABEL: @test_same_cond_for_or(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_1]], [[C_1]]
+; CHECK-NEXT:    [[OR:%.*]] = or i1 false, [[C_1]]
 ; CHECK-NEXT:    br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
 ; CHECK-NEXT:    ret i1 false
@@ -152,7 +152,7 @@ define i1 @test_second_or_condition_not_implied_by_first(i8 %x) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp ugt i8 [[X]], 5
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_2]], [[C_1]]
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_2]], false
 ; CHECK-NEXT:    br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
 ; CHECK-NEXT:    ret i1 false
@@ -245,7 +245,7 @@ define i1 @test_or_used_in_false_branch(i8 %x) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[X:%.*]], 10
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ule i8 [[X]], 5
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_1]], [[T_1]]
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_1]], false
 ; CHECK-NEXT:    br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
 ; CHECK-NEXT:    ret i1 [[T_1]]
@@ -271,7 +271,7 @@ define i1 @test_or_used_in_false_branch2(i8 %x) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ugt i8 [[X]], 5
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_1]], [[T_1]]
+; CHECK-NEXT:    [[OR:%.*]] = or i1 false, [[T_1]]
 ; CHECK-NEXT:    br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
 ; CHECK-NEXT:    ret i1 [[T_1]]


        


More information about the llvm-commits mailing list