[llvm] r274228 - [InstCombine] extend matchSelectFromAndOr() to work with i1 scalar types

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 30 07:18:19 PDT 2016


Author: spatel
Date: Thu Jun 30 09:18:18 2016
New Revision: 274228

URL: http://llvm.org/viewvc/llvm-project?rev=274228&view=rev
Log:
[InstCombine] extend matchSelectFromAndOr() to work with i1 scalar types

If the incoming types are i1, then we don't have to pattern match any sext ops.

Differential Revision: http://reviews.llvm.org/D21740


Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/trunk/test/Transforms/InstCombine/logical-select.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp?rev=274228&r1=274227&r2=274228&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp Thu Jun 30 09:18:18 2016
@@ -1590,10 +1590,32 @@ Instruction *InstCombiner::MatchBSwap(Bi
   return LastInst;
 }
 
-/// We have an expression of the form (A & C) | (B & D). If A is (Cond?-1:0)
-/// and B is ~(Cond?-1,0), then simplify this expression to "Cond ? C : D".
+/// We have an expression of the form (A & C) | (B & D). If A is a scalar or
+/// vector composed of all-zeros or all-ones values and is the bitwise 'not' of
+/// B, it can be used as the condition operand of a select instruction.
+static Value *getSelectCondition(Value *A, Value *B) {
+  // If these are scalars or vectors of i1, A can be used directly.
+  Type *Ty = A->getType();
+  if (match(A, m_Not(m_Specific(B))) && Ty->getScalarType()->isIntegerTy(1))
+    return A;
+
+  // If A and B are sign-extended, look through the sexts to find the booleans.
+  Value *Cond;
+  if (match(A, m_SExt(m_Value(Cond))) &&
+      Cond->getType()->getScalarType()->isIntegerTy(1) &&
+      match(B, m_CombineOr(m_Not(m_SExt(m_Specific(Cond))),
+                           m_SExt(m_Not(m_Specific(Cond))))))
+    return Cond;
+
+  // TODO: Try more matches that only apply to non-splat constant vectors.
+
+  return nullptr;
+}
+
+/// We have an expression of the form (A & C) | (B & D). Try to simplify this
+/// to "A' ? C : D", where A' is a boolean or vector of booleans.
 static Value *matchSelectFromAndOr(Value *A, Value *C, Value *B, Value *D,
-                                         InstCombiner::BuilderTy &Builder) {
+                                   InstCombiner::BuilderTy &Builder) {
   // The potential condition of the select may be bitcasted. In that case, look
   // through its bitcast and the corresponding bitcast of the 'not' condition.
   Type *OrigType = A->getType();
@@ -1604,13 +1626,7 @@ static Value *matchSelectFromAndOr(Value
     B = SrcB;
   }
 
-  // The condition must be a value of -1/0, and B must be the 'not' of that
-  // condition.
-  Value *Cond;
-  if (match(A, m_SExt(m_Value(Cond))) &&
-      Cond->getType()->getScalarType()->isIntegerTy(1) &&
-      match(B, m_CombineOr(m_Not(m_SExt(m_Specific(Cond))),
-                           m_SExt(m_Not(m_Specific(Cond)))))) {
+  if (Value *Cond = getSelectCondition(A, B)) {
     // ((bc Cond) & C) | ((bc ~Cond) & D) --> bc (select Cond, (bc C), (bc D))
     // The bitcasts will either all exist or all not exist. The builder will
     // not create unnecessary casts if the types already match.

Modified: llvm/trunk/test/Transforms/InstCombine/logical-select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/logical-select.ll?rev=274228&r1=274227&r2=274228&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/logical-select.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/logical-select.ll Thu Jun 30 09:18:18 2016
@@ -262,15 +262,10 @@ define <2 x i64> @bitcast_select_swap7(<
   ret <2 x i64> %or
 }
 
-; FIXME: Missed conversions to select below here.
-
 define i1 @bools(i1 %a, i1 %b, i1 %c) {
 ; CHECK-LABEL: @bools(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i1 %c, true
-; CHECK-NEXT:    [[AND1:%.*]] = and i1 [[NOT]], %a
-; CHECK-NEXT:    [[AND2:%.*]] = and i1 %c, %b
-; CHECK-NEXT:    [[OR:%.*]] = or i1 [[AND1]], [[AND2]]
-; CHECK-NEXT:    ret i1 [[OR]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 %c, i1 %b, i1 %a
+; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %not = xor i1 %c, -1
   %and1 = and i1 %not, %a
@@ -281,11 +276,8 @@ define i1 @bools(i1 %a, i1 %b, i1 %c) {
 
 define <4 x i1> @vec_of_bools(<4 x i1> %a, <4 x i1> %b, <4 x i1> %c) {
 ; CHECK-LABEL: @vec_of_bools(
-; CHECK-NEXT:    [[NOT:%.*]] = xor <4 x i1> %c, <i1 true, i1 true, i1 true, i1 true>
-; CHECK-NEXT:    [[AND1:%.*]] = and <4 x i1> [[NOT]], %a
-; CHECK-NEXT:    [[AND2:%.*]] = and <4 x i1> %b, %c
-; CHECK-NEXT:    [[OR:%.*]] = or <4 x i1> [[AND2]], [[AND1]]
-; CHECK-NEXT:    ret <4 x i1> [[OR]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select <4 x i1> %c, <4 x i1> %b, <4 x i1> %a
+; CHECK-NEXT:    ret <4 x i1> [[TMP1]]
 ;
   %not = xor <4 x i1> %c, <i1 true, i1 true, i1 true, i1 true>
   %and1 = and <4 x i1> %not, %a
@@ -296,13 +288,11 @@ define <4 x i1> @vec_of_bools(<4 x i1> %
 
 define i4 @vec_of_casted_bools(i4 %a, i4 %b, <4 x i1> %c) {
 ; CHECK-LABEL: @vec_of_casted_bools(
-; CHECK-NEXT:    [[NOT:%.*]] = xor <4 x i1> %c, <i1 true, i1 true, i1 true, i1 true>
-; CHECK-NEXT:    [[BC1:%.*]] = bitcast <4 x i1> [[NOT]] to i4
-; CHECK-NEXT:    [[BC2:%.*]] = bitcast <4 x i1> %c to i4
-; CHECK-NEXT:    [[AND1:%.*]] = and i4 [[BC1]], %a
-; CHECK-NEXT:    [[AND2:%.*]] = and i4 [[BC2]], %b
-; CHECK-NEXT:    [[OR:%.*]] = or i4 [[AND1]], [[AND2]]
-; CHECK-NEXT:    ret i4 [[OR]]
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i4 %a to <4 x i1>
+; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i4 %b to <4 x i1>
+; CHECK-NEXT:    [[TMP3:%.*]] = select <4 x i1> %c, <4 x i1> [[TMP2]], <4 x i1> [[TMP1]]
+; CHECK-NEXT:    [[TMP4:%.*]] = bitcast <4 x i1> [[TMP3]] to i4
+; CHECK-NEXT:    ret i4 [[TMP4]]
 ;
   %not = xor <4 x i1> %c, <i1 true, i1 true, i1 true, i1 true>
   %bc1 = bitcast <4 x i1> %not to i4
@@ -313,6 +303,7 @@ define i4 @vec_of_casted_bools(i4 %a, i4
   ret i4 %or
 }
 
+; FIXME: Missed conversions to select below here.
 ; Inverted 'and' constants mean this is a select.
 
 define <4 x i32> @vec_sel_consts(<4 x i32> %a, <4 x i32> %b) {




More information about the llvm-commits mailing list