[llvm] ddfee07 - [InstSimplify] Fold and/or using implied conditions

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri May 13 06:09:23 PDT 2022


Author: Nikita Popov
Date: 2022-05-13T15:09:14+02:00
New Revision: ddfee075199db7bd4285bb5b2c739630c5ff9706

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

LOG: [InstSimplify] Fold and/or using implied conditions

This adds two conjugated folds:

 * A | B -> B if A implies B (https://alive2.llvm.org/ce/z/R6GU4j)
 * A & B -> A if A implies B (https://alive2.llvm.org/ce/z/EGMqyy)

If A and B are icmps themselves, we will usually fold this through
other logic already (though the tests show a couple additional cases
we previously missed). However, isImpliedCond() also supports A
being of the form X & Y, which allows us to handle cases like
(X & Y) | B where X implies B. This addresses the regression from
D125398.

Something that notably doesn't work yet is the (X | Y) & B case.
This is due to an asymmetry in the isImpliedCondition()
implementation that will have to be addressed separately.

Differential Revision: https://reviews.llvm.org/D125530

Added: 
    

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/and-icmps-same-ops.ll
    llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll
    llvm/test/Transforms/InstSimplify/or-icmps-same-ops.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 99289721e90f5..1b16df02d04c8 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2219,6 +2219,15 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
       match(Op1, m_c_Xor(m_Specific(Or), m_Specific(Y))))
     return Constant::getNullValue(Op0->getType());
 
+  if (Op0->getType()->isIntOrIntVectorTy(1)) {
+    // Op0&Op1 -> Op0 where Op0 implies Op1
+    if (isImpliedCondition(Op0, Op1, Q.DL).getValueOr(false))
+      return Op0;
+    // Op0&Op1 -> Op1 where Op1 implies Op0
+    if (isImpliedCondition(Op1, Op0, Q.DL).getValueOr(false))
+      return Op1;
+  }
+
   return nullptr;
 }
 
@@ -2451,6 +2460,15 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
     if (Value *V = ThreadBinOpOverPHI(Instruction::Or, Op0, Op1, Q, MaxRecurse))
       return V;
 
+  if (Op0->getType()->isIntOrIntVectorTy(1)) {
+    // Op0|Op1 -> Op1 where Op0 implies Op1
+    if (isImpliedCondition(Op0, Op1, Q.DL).getValueOr(false))
+      return Op1;
+    // Op0|Op1 -> Op0 where Op1 implies Op0
+    if (isImpliedCondition(Op1, Op0, Q.DL).getValueOr(false))
+      return Op0;
+  }
+
   return nullptr;
 }
 

diff  --git a/llvm/test/Transforms/InstSimplify/and-icmps-same-ops.ll b/llvm/test/Transforms/InstSimplify/and-icmps-same-ops.ll
index 860732fb53e90..25b8b78c7db07 100644
--- a/llvm/test/Transforms/InstSimplify/and-icmps-same-ops.ll
+++ b/llvm/test/Transforms/InstSimplify/and-icmps-same-ops.ll
@@ -1214,9 +1214,7 @@ define <2 x i1> @ult_ule_vec(<2 x i8> %a, <2 x i8> %b) {
 define i1 @ult_uge_swap(i8 %a, i8 %b) {
 ; CHECK-LABEL: @ult_uge_swap(
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i8 [[B]], [[A]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
-; CHECK-NEXT:    ret i1 [[AND]]
+; CHECK-NEXT:    ret i1 [[CMP1]]
 ;
   %cmp1 = icmp ult i8 %a, %b
   %cmp2 = icmp uge i8 %b, %a

diff  --git a/llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll b/llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll
index 1bdc75e6b265b..52a2594a8b7f1 100644
--- a/llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll
+++ b/llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll
@@ -3,11 +3,8 @@
 
 define i1 @or_implied(i8 %x, i1 %c) {
 ; CHECK-LABEL: @or_implied(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 0
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 [[X]], 1
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[C:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[AND]], [[CMP2]]
-; CHECK-NEXT:    ret i1 [[OR]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 [[X:%.*]], 1
+; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp = icmp eq i8 %x, 0
   %cmp2 = icmp ne i8 %x, 1
@@ -18,11 +15,8 @@ define i1 @or_implied(i8 %x, i1 %c) {
 
 define i1 @or_implied_comm1(i8 %x, i1 %c) {
 ; CHECK-LABEL: @or_implied_comm1(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 0
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 [[X]], 1
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[C:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP2]], [[AND]]
-; CHECK-NEXT:    ret i1 [[OR]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 [[X:%.*]], 1
+; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp = icmp eq i8 %x, 0
   %cmp2 = icmp ne i8 %x, 1
@@ -33,11 +27,8 @@ define i1 @or_implied_comm1(i8 %x, i1 %c) {
 
 define i1 @or_implied_comm2(i8 %x, i1 %c) {
 ; CHECK-LABEL: @or_implied_comm2(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 0
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 [[X]], 1
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C:%.*]], [[CMP]]
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[AND]], [[CMP2]]
-; CHECK-NEXT:    ret i1 [[OR]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 [[X:%.*]], 1
+; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp = icmp eq i8 %x, 0
   %cmp2 = icmp ne i8 %x, 1
@@ -48,11 +39,8 @@ define i1 @or_implied_comm2(i8 %x, i1 %c) {
 
 define i1 @or_implied_comm3(i8 %x, i1 %c) {
 ; CHECK-LABEL: @or_implied_comm3(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 0
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 [[X]], 1
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C:%.*]], [[CMP]]
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP2]], [[AND]]
-; CHECK-NEXT:    ret i1 [[OR]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 [[X:%.*]], 1
+; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp = icmp eq i8 %x, 0
   %cmp2 = icmp ne i8 %x, 1

diff  --git a/llvm/test/Transforms/InstSimplify/or-icmps-same-ops.ll b/llvm/test/Transforms/InstSimplify/or-icmps-same-ops.ll
index 0878a521f9010..3dfef79c450c4 100644
--- a/llvm/test/Transforms/InstSimplify/or-icmps-same-ops.ll
+++ b/llvm/test/Transforms/InstSimplify/or-icmps-same-ops.ll
@@ -1213,10 +1213,8 @@ define <2 x i1> @ult_ule_vec(<2 x i8> %a, <2 x i8> %b) {
 
 define i1 @ult_ne_swap(i8 %a, i8 %b) {
 ; CHECK-LABEL: @ult_ne_swap(
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 [[B]], [[A]]
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
-; CHECK-NEXT:    ret i1 [[OR]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp ult i8 %a, %b
   %cmp2 = icmp ne i8 %b, %a
@@ -1226,10 +1224,8 @@ define i1 @ult_ne_swap(i8 %a, i8 %b) {
 
 define i1 @ult_ule_swap(i8 %a, i8 %b) {
 ; CHECK-LABEL: @ult_ule_swap(
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i8 [[B]], [[A]]
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
-; CHECK-NEXT:    ret i1 [[OR]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i8 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp ult i8 %a, %b
   %cmp2 = icmp uge i8 %b, %a


        


More information about the llvm-commits mailing list