[llvm] 9a53793 - [InstCombine] Fold two select patterns into and-or

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 28 13:08:01 PDT 2022


Author: chenglin.bi
Date: 2022-03-28T16:07:55-04:00
New Revision: 9a53793ab803a839908411868700982923939015

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

LOG: [InstCombine] Fold two select patterns into and-or

select (~a | c), a, b -> and a, (or c, b) https://alive2.llvm.org/ce/z/bnDobs
select (~c & b), a, b -> and b, (or a, c) https://alive2.llvm.org/ce/z/k2jJHJ

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

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
    llvm/test/Transforms/InstCombine/select-and-or.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 9bef9549da045..06c2de65e834a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2570,6 +2570,20 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
         match(TrueVal, m_Specific(B)) && match(FalseVal, m_Zero()))
       return replaceOperand(SI, 0, A);
 
+    Value *C;
+    // select (~a | c), a, b -> and a, (or c, freeze(b))
+    if (match(CondVal, m_c_Or(m_Not(m_Specific(TrueVal)), m_Value(C))) &&
+        CondVal->hasOneUse()) {
+      FalseVal = Builder.CreateFreeze(FalseVal);
+      return BinaryOperator::CreateAnd(TrueVal, Builder.CreateOr(C, FalseVal));
+    }
+    // select (~c & b), a, b -> and b, (or freeze(a), c)
+    if (match(CondVal, m_c_And(m_Not(m_Value(C)), m_Specific(FalseVal))) &&
+        CondVal->hasOneUse()) {
+      TrueVal = Builder.CreateFreeze(TrueVal);
+      return BinaryOperator::CreateAnd(FalseVal, Builder.CreateOr(C, TrueVal));
+    }
+
     if (!SelType->isVectorTy()) {
       if (Value *S = simplifyWithOpReplaced(TrueVal, CondVal, One, SQ,
                                             /* AllowRefinement */ true))

diff  --git a/llvm/test/Transforms/InstCombine/select-and-or.ll b/llvm/test/Transforms/InstCombine/select-and-or.ll
index 8f492b1f20fdb..16fbb8a6dab11 100644
--- a/llvm/test/Transforms/InstCombine/select-and-or.ll
+++ b/llvm/test/Transforms/InstCombine/select-and-or.ll
@@ -3,6 +3,7 @@
 
 declare void @use(i1)
 declare i1 @gen_i1()
+declare <2 x i1> @gen_v2i1()
 
 ; Should not be converted to "and", which has 
diff erent poison semantics.
 define i1 @logical_and(i1 %a, i1 %b) {
@@ -452,9 +453,9 @@ define i1 @demorgan_select_infloop2(i1 %L) {
 
 define i1 @and_or1(i1 %a, i1 %b, i1 %c) {
 ; CHECK-LABEL: @and_or1(
-; CHECK-NEXT:    [[NOTA:%.*]] = xor i1 [[A:%.*]], true
-; CHECK-NEXT:    [[COND:%.*]] = or i1 [[NOTA]], [[C:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND]], i1 [[A]], i1 [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = freeze i1 [[B:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or i1 [[TMP1]], [[C:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP2]], [[A:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %nota = xor i1 %a, true
@@ -465,9 +466,9 @@ define i1 @and_or1(i1 %a, i1 %b, i1 %c) {
 
 define i1 @and_or2(i1 %a, i1 %b, i1 %c) {
 ; CHECK-LABEL: @and_or2(
-; CHECK-NEXT:    [[NOTC:%.*]] = xor i1 [[C:%.*]], true
-; CHECK-NEXT:    [[COND:%.*]] = and i1 [[NOTC]], [[B:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = freeze i1 [[A:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or i1 [[TMP1]], [[C:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP2]], [[B:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %notc = xor i1 %c, true
@@ -478,9 +479,8 @@ define i1 @and_or2(i1 %a, i1 %b, i1 %c) {
 
 define i1 @and_or1_bundef(i1 %a, i1 noundef %b, i1 %c) {
 ; CHECK-LABEL: @and_or1_bundef(
-; CHECK-NEXT:    [[NOTA:%.*]] = xor i1 [[A:%.*]], true
-; CHECK-NEXT:    [[COND:%.*]] = or i1 [[NOTA]], [[C:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND]], i1 [[A]], i1 [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = or i1 [[C:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP1]], [[A:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %nota = xor i1 %a, true
@@ -491,9 +491,8 @@ define i1 @and_or1_bundef(i1 %a, i1 noundef %b, i1 %c) {
 
 define i1 @and_or2_aundef(i1 noundef %a, i1 %b, i1 %c) {
 ; CHECK-LABEL: @and_or2_aundef(
-; CHECK-NEXT:    [[NOTC:%.*]] = xor i1 [[C:%.*]], true
-; CHECK-NEXT:    [[COND:%.*]] = and i1 [[NOTC]], [[B:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = or i1 [[C:%.*]], [[A:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP1]], [[B:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %notc = xor i1 %c, true
@@ -535,9 +534,9 @@ define i1 @no_and_or2_aundef(i1 noundef %a, i1 %b, i1 %c) {
 define i1 @and_or1_op1not(i1 %a, i1 %b) {
 ; CHECK-LABEL: @and_or1_op1not(
 ; CHECK-NEXT:    [[C:%.*]] = call i1 @gen_i1()
-; CHECK-NEXT:    [[NOTA:%.*]] = xor i1 [[A:%.*]], true
-; CHECK-NEXT:    [[COND:%.*]] = or i1 [[C]], [[NOTA]]
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND]], i1 [[A]], i1 [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = freeze i1 [[B:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or i1 [[C]], [[TMP1]]
+; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP2]], [[A:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %c = call i1 @gen_i1()
@@ -547,6 +546,21 @@ define i1 @and_or1_op1not(i1 %a, i1 %b) {
   ret i1 %r
 }
 
+define i1 @and_or2_op1not(i1 %a, i1 %c) {
+; CHECK-LABEL: @and_or2_op1not(
+; CHECK-NEXT:    [[B:%.*]] = call i1 @gen_i1()
+; CHECK-NEXT:    [[TMP1:%.*]] = freeze i1 [[A:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or i1 [[TMP1]], [[C:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = and i1 [[B]], [[TMP2]]
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %b = call i1 @gen_i1()
+  %notc = xor i1 %c, true
+  %cond = and i1 %b, %notc
+  %r = select i1 %cond, i1 %a, i1 %b
+  ret i1 %r
+}
+
 define i1 @neg_and_or1(i1 %a, i1 %b, i1 %c, i1 %d) {
 ; CHECK-LABEL: @neg_and_or1(
 ; CHECK-NEXT:    [[NOTA:%.*]] = xor i1 [[A:%.*]], true
@@ -572,3 +586,18 @@ define i1 @neg_and_or2(i1 %a, i1 %b, i1 %c, i1 %d) {
   %r = select i1 %cond, i1 %a, i1 %d
   ret i1 %r
 }
+
+define <2 x i1> @and_or1_op1not_vec(<2 x i1> %a, <2 x i1> %b) {
+; CHECK-LABEL: @and_or1_op1not_vec(
+; CHECK-NEXT:    [[C:%.*]] = call <2 x i1> @gen_v2i1()
+; CHECK-NEXT:    [[TMP1:%.*]] = freeze <2 x i1> [[B:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or <2 x i1> [[C]], [[TMP1]]
+; CHECK-NEXT:    [[R:%.*]] = and <2 x i1> [[TMP2]], [[A:%.*]]
+; CHECK-NEXT:    ret <2 x i1> [[R]]
+;
+  %c = call <2 x i1> @gen_v2i1()
+  %nota = xor <2 x i1> %a, <i1 true, i1 true>
+  %cond = or <2 x i1> %c, %nota
+  %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
+  ret <2 x i1> %r
+}


        


More information about the llvm-commits mailing list