[llvm] 2bf6123 - [InstCombine] fold icmp of sext bool based on limited range

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue May 31 09:45:17 PDT 2022


Author: Sanjay Patel
Date: 2022-05-31T12:37:56-04:00
New Revision: 2bf6123f22c65995dec60e02944b459424532d9b

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

LOG: [InstCombine] fold icmp of sext bool based on limited range

X <=u (sext i1 Y) --> (X == 0) | Y

https://alive2.llvm.org/ce/z/W_tZzo

This is the conjugate/sibling pattern suggested with D126171
for a sign-extended bool value.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/test/Transforms/InstCombine/icmp-range.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 1df61f0624bc..6e61c5f7e2d9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5656,12 +5656,16 @@ static Instruction *foldICmpUsingBoolRange(ICmpInst &I,
   ICmpInst::Predicate Pred;
 
   // X must be 0 and bool must be true for "ULT":
-  // X <u (zext i1 Y) --> (X == 0) && Y
+  // X <u (zext i1 Y) --> (X == 0) & Y
   if (match(&I, m_c_ICmp(Pred, m_Value(X), m_OneUse(m_ZExt(m_Value(Y))))) &&
       Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULT)
     return BinaryOperator::CreateAnd(Builder.CreateIsNull(X), Y);
 
-  // TODO: Handle the related pattern with UGE/sext.
+  // X must be 0 or bool must be true for "ULE":
+  // X <=u (sext i1 Y) --> (X == 0) | Y
+  if (match(&I, m_c_ICmp(Pred, m_Value(X), m_OneUse(m_SExt(m_Value(Y))))) &&
+      Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
+    return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
   return nullptr;
 }

diff  --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll
index b8d8310cfc74..df00200626b5 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -403,8 +403,8 @@ define i1 @and_ugt_sub(i8 %b, i8 %x, i8 %y) {
 
 define i1 @uge_sext(i1 %b, i8 %x) {
 ; CHECK-LABEL: @uge_sext(
-; CHECK-NEXT:    [[S:%.*]] = sext i1 [[B:%.*]] to i8
-; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[S]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
+; CHECK-NEXT:    [[R:%.*]] = or i1 [[TMP1]], [[B:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %s = sext i1 %b to i8
@@ -415,8 +415,8 @@ define i1 @uge_sext(i1 %b, i8 %x) {
 define <2 x i1> @ule_sext(<2 x i1> %b, <2 x i8> %p) {
 ; CHECK-LABEL: @ule_sext(
 ; CHECK-NEXT:    [[X:%.*]] = mul <2 x i8> [[P:%.*]], [[P]]
-; CHECK-NEXT:    [[S:%.*]] = sext <2 x i1> [[B:%.*]] to <2 x i8>
-; CHECK-NEXT:    [[R:%.*]] = icmp ule <2 x i8> [[X]], [[S]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i8> [[X]], zeroinitializer
+; CHECK-NEXT:    [[R:%.*]] = or <2 x i1> [[TMP1]], [[B:%.*]]
 ; CHECK-NEXT:    ret <2 x i1> [[R]]
 ;
   %x = mul <2 x i8> %p, %p ; thwart complexity-based canonicalization
@@ -425,6 +425,8 @@ define <2 x i1> @ule_sext(<2 x i1> %b, <2 x i8> %p) {
   ret <2 x i1> %r
 }
 
+; negative test - need ule/uge
+
 define i1 @ugt_sext(i1 %b, i8 %x) {
 ; CHECK-LABEL: @ugt_sext(
 ; CHECK-NEXT:    [[S:%.*]] = sext i1 [[B:%.*]] to i8
@@ -436,6 +438,8 @@ define i1 @ugt_sext(i1 %b, i8 %x) {
   ret i1 %r
 }
 
+; negative test - need ule/uge
+
 define i1 @ult_sext(i1 %b, i8 %p) {
 ; CHECK-LABEL: @ult_sext(
 ; CHECK-NEXT:    [[X:%.*]] = mul i8 [[P:%.*]], [[P]]
@@ -449,6 +453,8 @@ define i1 @ult_sext(i1 %b, i8 %p) {
   ret i1 %r
 }
 
+; negative test - extra use
+
 define i1 @uge_sext_use(i1 %b, i8 %x) {
 ; CHECK-LABEL: @uge_sext_use(
 ; CHECK-NEXT:    [[S:%.*]] = sext i1 [[B:%.*]] to i8
@@ -462,6 +468,8 @@ define i1 @uge_sext_use(i1 %b, i8 %x) {
   ret i1 %r
 }
 
+; negative test - must be sext of i1
+
 define i1 @ule_sext_not_i1(i2 %b, i8 %x) {
 ; CHECK-LABEL: @ule_sext_not_i1(
 ; CHECK-NEXT:    [[S:%.*]] = sext i2 [[B:%.*]] to i8
@@ -473,11 +481,12 @@ define i1 @ule_sext_not_i1(i2 %b, i8 %x) {
   ret i1 %r
 }
 
+; sub is eliminated
+
 define i1 @sub_ule_sext(i1 %b, i8 %x, i8 %y) {
 ; CHECK-LABEL: @sub_ule_sext(
-; CHECK-NEXT:    [[S:%.*]] = sext i1 [[B:%.*]] to i8
-; CHECK-NEXT:    [[D:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[D]], [[S]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = or i1 [[TMP1]], [[B:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %s = sext i1 %b to i8
@@ -489,8 +498,8 @@ define i1 @sub_ule_sext(i1 %b, i8 %x, i8 %y) {
 define i1 @sext_ule_sext(i1 %b, i8 %p) {
 ; CHECK-LABEL: @sext_ule_sext(
 ; CHECK-NEXT:    [[X:%.*]] = mul i8 [[P:%.*]], [[P]]
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i1 [[B:%.*]] to i8
-; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[X]], [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT:    [[R:%.*]] = or i1 [[TMP1]], [[B:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %x = mul i8 %p, %p ; thwart complexity-based canonicalization
@@ -500,12 +509,14 @@ define i1 @sext_ule_sext(i1 %b, i8 %p) {
   ret i1 %r
 }
 
+; match and fold even if both sides are sexts (from 
diff erent source types)
+
 define i1 @sext_uge_sext(i1 %b, i4 %x) {
 ; CHECK-LABEL: @sext_uge_sext(
 ; CHECK-NEXT:    [[SX:%.*]] = sext i4 [[X:%.*]] to i8
 ; CHECK-NEXT:    call void @use(i8 [[SX]])
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i1 [[B:%.*]] to i4
-; CHECK-NEXT:    [[R:%.*]] = icmp uge i4 [[TMP1]], [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i4 [[X]], 0
+; CHECK-NEXT:    [[R:%.*]] = or i1 [[TMP1]], [[B:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %s = sext i1 %b to i8
@@ -515,6 +526,8 @@ define i1 @sext_uge_sext(i1 %b, i4 %x) {
   ret i1 %r
 }
 
+; negative test - must be sext of i1
+
 define i1 @sub_ule_sext_not_i1(i2 %b, i8 %x, i8 %y) {
 ; CHECK-LABEL: @sub_ule_sext_not_i1(
 ; CHECK-NEXT:    [[S:%.*]] = sext i2 [[B:%.*]] to i8
@@ -528,6 +541,8 @@ define i1 @sub_ule_sext_not_i1(i2 %b, i8 %x, i8 %y) {
   ret i1 %r
 }
 
+; negative test - extra use (but we could try harder to fold this)
+
 define i1 @sub_ule_sext_use1(i1 %b, i8 %x, i8 %y) {
 ; CHECK-LABEL: @sub_ule_sext_use1(
 ; CHECK-NEXT:    [[S:%.*]] = sext i1 [[B:%.*]] to i8
@@ -545,10 +560,10 @@ define i1 @sub_ule_sext_use1(i1 %b, i8 %x, i8 %y) {
 
 define <2 x i1> @sext_uge_sub_use2(<2 x i1> %b, <2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @sext_uge_sub_use2(
-; CHECK-NEXT:    [[S:%.*]] = sext <2 x i1> [[B:%.*]] to <2 x i8>
 ; CHECK-NEXT:    [[D:%.*]] = sub <2 x i8> [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    call void @use_vec(<2 x i8> [[D]])
-; CHECK-NEXT:    [[R:%.*]] = icmp ule <2 x i8> [[D]], [[S]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i8> [[X]], [[Y]]
+; CHECK-NEXT:    [[R:%.*]] = or <2 x i1> [[TMP1]], [[B:%.*]]
 ; CHECK-NEXT:    ret <2 x i1> [[R]]
 ;
   %s = sext <2 x i1> %b to <2 x i8>


        


More information about the llvm-commits mailing list