[llvm] b751da4 - [InstCombine] Handle integer extension in `select` patterns using the condition as value

Markus Böck via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 20 13:25:25 PDT 2022


Author: Markus Böck
Date: 2022-09-20T22:25:13+02:00
New Revision: b751da43b2bdccda78f30ac8411b6396c0be6874

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

LOG: [InstCombine] Handle integer extension in `select` patterns using the condition as value

These patterns were previously only implemented for i1 type but can be extended for any integer type by also handling zext and sext operands.

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

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index fc1a43535e35..a0631381f12f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2662,6 +2662,51 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
   if (Instruction *I = canonicalizeScalarSelectOfVecs(SI, *this))
     return I;
 
+  // If the type of select is not an integer type or if the condition and
+  // the selection type are not both scalar nor both vector types, there is no
+  // point in attempting to match these patterns.
+  if (!isa<Constant>(CondVal) && SelType->isIntOrIntVectorTy() &&
+      CondVal->getType()->isVectorTy() == SelType->isVectorTy()) {
+    auto *One = ConstantInt::get(SelType, 1);
+    auto *Zero = ConstantInt::get(SelType, 0);
+    auto *AllOnes = ConstantInt::get(SelType, -1, /*isSigned*/ true);
+
+    // select a, a, b -> select a, 1, b
+    // select a, zext(a), b -> select a, 1, b
+    if (match(TrueVal, m_ZExtOrSelf(m_Specific(CondVal))))
+      return replaceOperand(SI, 1, One);
+
+    // select a, sext(a), b -> select a, -1, b
+    if (match(TrueVal, m_SExt(m_Specific(CondVal))))
+      return replaceOperand(SI, 1, AllOnes);
+
+    // select a, b, a -> select a, b, 0
+    // select a, b, zext(a) -> select a, b, 0
+    // select a, b, sext(a) -> select a, b, 0
+    if (match(FalseVal, m_ZExtOrSExtOrSelf(m_Specific(CondVal))))
+      return replaceOperand(SI, 2, Zero);
+
+    Value *NotCond;
+
+    // select a, !a, b -> select !a, b, 0
+    // select a, sext(!a), b -> select !a, b, 0
+    // select a, zext(!a), b -> select !a, b, 0
+    if (match(TrueVal, m_ZExtOrSExtOrSelf(m_CombineAnd(
+                           m_Value(NotCond), m_Not(m_Specific(CondVal))))))
+      return SelectInst::Create(NotCond, FalseVal, Zero);
+
+    // select a, b, !a -> select !a, 1, b
+    // select a, b, zext(!a) -> select !a, 1, b
+    if (match(FalseVal, m_ZExtOrSelf(m_CombineAnd(m_Value(NotCond),
+                                                  m_Not(m_Specific(CondVal))))))
+      return SelectInst::Create(NotCond, One, TrueVal);
+
+    // select a, b, sext(!a) -> select !a, -1, b
+    if (match(FalseVal, m_SExt(m_CombineAnd(m_Value(NotCond),
+                                            m_Not(m_Specific(CondVal))))))
+      return SelectInst::Create(NotCond, AllOnes, TrueVal);
+  }
+
   // Avoid potential infinite loops by checking for non-constant condition.
   // TODO: Can we assert instead by improving canonicalizeSelectToShuffle()?
   //       Scalar select must have simplified?
@@ -2711,20 +2756,6 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
       return SelectInst::Create(NotCond, One, TrueVal);
     }
 
-    // select a, a, b -> select a, true, b
-    if (CondVal == TrueVal)
-      return replaceOperand(SI, 1, One);
-    // select a, b, a -> select a, b, false
-    if (CondVal == FalseVal)
-      return replaceOperand(SI, 2, Zero);
-
-    // select a, !a, b -> select !a, b, false
-    if (match(TrueVal, m_Not(m_Specific(CondVal))))
-      return SelectInst::Create(TrueVal, FalseVal, Zero);
-    // select a, b, !a -> select !a, true, b
-    if (match(FalseVal, m_Not(m_Specific(CondVal))))
-      return SelectInst::Create(FalseVal, One, TrueVal);
-
     Value *A, *B;
 
     // DeMorgan in select form: !a && !b --> !(a || b)

diff  --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 0558138b8491..8620fd0bc7ce 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -3213,8 +3213,7 @@ declare i32 @llvm.cttz.i32(i32, i1 immarg)
 
 define i32 @select_cond_zext_cond(i1 %cond, i32 %b) {
 ; CHECK-LABEL: @select_cond_zext_cond(
-; CHECK-NEXT:    [[ZEXT:%.*]] = zext i1 [[COND:%.*]] to i32
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND]], i32 [[ZEXT]], i32 [[B:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i32 1, i32 [[B:%.*]]
 ; CHECK-NEXT:    ret i32 [[SEL]]
 ;
   %zext = zext i1 %cond to i32
@@ -3224,8 +3223,7 @@ define i32 @select_cond_zext_cond(i1 %cond, i32 %b) {
 
 define <2 x i32> @select_cond_zext_cond_vec(<2 x i1> %cond, <2 x i32> %b) {
 ; CHECK-LABEL: @select_cond_zext_cond_vec(
-; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i1> [[COND:%.*]] to <2 x i32>
-; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[ZEXT]], <2 x i32> [[B:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i32> <i32 1, i32 1>, <2 x i32> [[B:%.*]]
 ; CHECK-NEXT:    ret <2 x i32> [[SEL]]
 ;
   %zext = zext <2 x i1> %cond to <2 x i32>
@@ -3235,8 +3233,7 @@ define <2 x i32> @select_cond_zext_cond_vec(<2 x i1> %cond, <2 x i32> %b) {
 
 define i32 @select_cond_sext_cond(i1 %cond, i32 %b) {
 ; CHECK-LABEL: @select_cond_sext_cond(
-; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[COND:%.*]] to i32
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND]], i32 [[SEXT]], i32 [[B:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i32 -1, i32 [[B:%.*]]
 ; CHECK-NEXT:    ret i32 [[SEL]]
 ;
   %sext = sext i1 %cond to i32
@@ -3246,8 +3243,7 @@ define i32 @select_cond_sext_cond(i1 %cond, i32 %b) {
 
 define <2 x i32> @select_cond_sext_cond_vec(<2 x i1> %cond, <2 x i32> %b) {
 ; CHECK-LABEL: @select_cond_sext_cond_vec(
-; CHECK-NEXT:    [[SEXT:%.*]] = sext <2 x i1> [[COND:%.*]] to <2 x i32>
-; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[SEXT]], <2 x i32> [[B:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i32> <i32 -1, i32 -1>, <2 x i32> [[B:%.*]]
 ; CHECK-NEXT:    ret <2 x i32> [[SEL]]
 ;
   %sext = sext <2 x i1> %cond to <2 x i32>
@@ -3257,8 +3253,7 @@ define <2 x i32> @select_cond_sext_cond_vec(<2 x i1> %cond, <2 x i32> %b) {
 
 define i32 @select_cond_val_zext_cond(i1 %cond, i32 %b) {
 ; CHECK-LABEL: @select_cond_val_zext_cond(
-; CHECK-NEXT:    [[ZEXT:%.*]] = zext i1 [[COND:%.*]] to i32
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND]], i32 [[B:%.*]], i32 [[ZEXT]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i32 [[B:%.*]], i32 0
 ; CHECK-NEXT:    ret i32 [[SEL]]
 ;
   %zext = zext i1 %cond to i32
@@ -3268,8 +3263,7 @@ define i32 @select_cond_val_zext_cond(i1 %cond, i32 %b) {
 
 define <2 x i32> @select_cond_val_zext_cond_vec(<2 x i1> %cond, <2 x i32> %b) {
 ; CHECK-LABEL: @select_cond_val_zext_cond_vec(
-; CHECK-NEXT:    [[ZEXT:%.*]] = zext <2 x i1> [[COND:%.*]] to <2 x i32>
-; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[B:%.*]], <2 x i32> [[ZEXT]]
+; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i32> [[B:%.*]], <2 x i32> zeroinitializer
 ; CHECK-NEXT:    ret <2 x i32> [[SEL]]
 ;
   %zext = zext <2 x i1> %cond to <2 x i32>
@@ -3279,8 +3273,7 @@ define <2 x i32> @select_cond_val_zext_cond_vec(<2 x i1> %cond, <2 x i32> %b) {
 
 define i32 @select_cond_val_sext_cond(i1 %cond, i32 %b) {
 ; CHECK-LABEL: @select_cond_val_sext_cond(
-; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[COND:%.*]] to i32
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND]], i32 [[B:%.*]], i32 [[SEXT]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i32 [[B:%.*]], i32 0
 ; CHECK-NEXT:    ret i32 [[SEL]]
 ;
   %sext = sext i1 %cond to i32
@@ -3290,9 +3283,7 @@ define i32 @select_cond_val_sext_cond(i1 %cond, i32 %b) {
 
 define i32 @select_cond_zext_not_cond_val(i1 %cond, i32 %b) {
 ; CHECK-LABEL: @select_cond_zext_not_cond_val(
-; CHECK-NEXT:    [[NOT_COND:%.*]] = xor i1 [[COND:%.*]], true
-; CHECK-NEXT:    [[ZEXT:%.*]] = zext i1 [[NOT_COND]] to i32
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND]], i32 [[ZEXT]], i32 [[B:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i32 0, i32 [[B:%.*]]
 ; CHECK-NEXT:    ret i32 [[SEL]]
 ;
   %not_cond = xor i1 %cond, true
@@ -3303,9 +3294,7 @@ define i32 @select_cond_zext_not_cond_val(i1 %cond, i32 %b) {
 
 define i32 @select_cond_sext_not_cond_val(i1 %cond, i32 %b) {
 ; CHECK-LABEL: @select_cond_sext_not_cond_val(
-; CHECK-NEXT:    [[NOT_COND:%.*]] = xor i1 [[COND:%.*]], true
-; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[NOT_COND]] to i32
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND]], i32 [[SEXT]], i32 [[B:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i32 0, i32 [[B:%.*]]
 ; CHECK-NEXT:    ret i32 [[SEL]]
 ;
   %not_cond = xor i1 %cond, true
@@ -3317,9 +3306,7 @@ define i32 @select_cond_sext_not_cond_val(i1 %cond, i32 %b) {
 
 define i32 @select_cond_val_zext_not_cond(i1 %cond, i32 %b) {
 ; CHECK-LABEL: @select_cond_val_zext_not_cond(
-; CHECK-NEXT:    [[NOT_COND:%.*]] = xor i1 [[COND:%.*]], true
-; CHECK-NEXT:    [[ZEXT:%.*]] = zext i1 [[NOT_COND]] to i32
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND]], i32 [[B:%.*]], i32 [[ZEXT]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i32 [[B:%.*]], i32 1
 ; CHECK-NEXT:    ret i32 [[SEL]]
 ;
   %not_cond = xor i1 %cond, true
@@ -3330,9 +3317,7 @@ define i32 @select_cond_val_zext_not_cond(i1 %cond, i32 %b) {
 
 define i32 @select_cond_val_sext_not_cond(i1 %cond, i32 %b) {
 ; CHECK-LABEL: @select_cond_val_sext_not_cond(
-; CHECK-NEXT:    [[NOT_COND:%.*]] = xor i1 [[COND:%.*]], true
-; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[NOT_COND]] to i32
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND]], i32 [[B:%.*]], i32 [[SEXT]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i32 [[B:%.*]], i32 -1
 ; CHECK-NEXT:    ret i32 [[SEL]]
 ;
   %not_cond = xor i1 %cond, true
@@ -3343,11 +3328,7 @@ define i32 @select_cond_val_sext_not_cond(i1 %cond, i32 %b) {
 
 define i32 @select_cond_not_cond_cond1(i1 %cond) {
 ; CHECK-LABEL: @select_cond_not_cond_cond1(
-; CHECK-NEXT:    [[Z:%.*]] = zext i1 [[COND:%.*]] to i32
-; CHECK-NEXT:    [[NOT_COND:%.*]] = xor i1 [[COND]], true
-; CHECK-NEXT:    [[S:%.*]] = sext i1 [[NOT_COND]] to i32
-; CHECK-NEXT:    [[V:%.*]] = select i1 [[COND]], i32 [[S]], i32 [[Z]]
-; CHECK-NEXT:    ret i32 [[V]]
+; CHECK-NEXT:    ret i32 0
 ;
   %z = zext i1 %cond to i32
   %not_cond = xor i1 %cond, true
@@ -3358,11 +3339,7 @@ define i32 @select_cond_not_cond_cond1(i1 %cond) {
 
 define i32 @select_cond_not_cond_cond2(i1 %cond) {
 ; CHECK-LABEL: @select_cond_not_cond_cond2(
-; CHECK-NEXT:    [[Z:%.*]] = sext i1 [[COND:%.*]] to i32
-; CHECK-NEXT:    [[NOT_COND:%.*]] = xor i1 [[COND]], true
-; CHECK-NEXT:    [[S:%.*]] = zext i1 [[NOT_COND]] to i32
-; CHECK-NEXT:    [[V:%.*]] = select i1 [[COND]], i32 [[S]], i32 [[Z]]
-; CHECK-NEXT:    ret i32 [[V]]
+; CHECK-NEXT:    ret i32 0
 ;
   %z = sext i1 %cond to i32
   %not_cond = xor i1 %cond, true


        


More information about the llvm-commits mailing list