[llvm] 982cbed - [InstCombine] Fold logical and/or of range icmps with nowrap flags

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 29 05:42:49 PDT 2022


Author: Nikita Popov
Date: 2022-04-29T14:42:42+02:00
New Revision: 982cbed81920b474d41b63760cbde68680b15966

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

LOG: [InstCombine] Fold logical and/or of range icmps with nowrap flags

This is an edge-case where we don't convert to bitwise and/or based
on implies poison reasoning, so explicitly try to perform the fold
in logical form. The transform itself is poison-safe, as both icmps
are based on the same value and any nowrap flags are discarded as
part of the fold (https://alive2.llvm.org/ce/z/aCwC8b for the used
example).

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/lib/Transforms/InstCombine/InstCombineInternal.h
    llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
    llvm/test/Transforms/InstCombine/and-or-icmps.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 98a0c80f6740..aef9ae1df2eb 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1128,8 +1128,10 @@ static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
 /// Fold (icmp Pred1 V1, C1) & (icmp Pred2 V2, C2)
 /// or   (icmp Pred1 V1, C1) | (icmp Pred2 V2, C2)
 /// into a single comparison using range-based reasoning.
-static Value *foldAndOrOfICmpsUsingRanges(ICmpInst *ICmp1, ICmpInst *ICmp2,
-                                          IRBuilderBase &Builder, bool IsAnd) {
+/// NOTE: This is also used for logical and/or, must be poison-safe!
+Value *InstCombinerImpl::foldAndOrOfICmpsUsingRanges(ICmpInst *ICmp1,
+                                                     ICmpInst *ICmp2,
+                                                     bool IsAnd) {
   ICmpInst::Predicate Pred1, Pred2;
   Value *V1, *V2;
   const APInt *C1, *C2;
@@ -2513,7 +2515,7 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
     }
   }
 
-  return foldAndOrOfICmpsUsingRanges(LHS, RHS, Builder, IsAnd);
+  return foldAndOrOfICmpsUsingRanges(LHS, RHS, IsAnd);
 }
 
 // FIXME: We use commutative matchers (m_c_*) for some, but not all, matches

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 3e5fc3e32771..7637cb4a40ee 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -350,6 +350,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
 
   Value *foldEqOfParts(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd);
 
+  Value *foldAndOrOfICmpsUsingRanges(ICmpInst *ICmp1, ICmpInst *ICmp2,
+                                     bool IsAnd);
+
   /// Optimize (fcmp)&(fcmp) or (fcmp)|(fcmp).
   /// NOTE: Unlike most of instcombine, this returns a Value which should
   /// already be inserted into the function.

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index c2414744ad38..e1f9c099d79f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2805,6 +2805,12 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
 
           if (auto *V = foldEqOfParts(ICmp0, ICmp1, IsAnd))
             return replaceInstUsesWith(SI, V);
+
+          // This pattern would usually be converted into a bitwise and/or based
+          // on "implies poison" reasoning. However, this may fail if adds with
+          // nowrap flags are involved.
+          if (auto *V = foldAndOrOfICmpsUsingRanges(ICmp0, ICmp1, IsAnd))
+            return replaceInstUsesWith(SI, V);
         }
       }
     }

diff  --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
index 5aa6ec5854c2..ad6bf63d584c 100644
--- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll
+++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
@@ -1249,12 +1249,10 @@ define i1 @and_two_ranges_to_mask_and_range_no_add_on_one_range(i16 %x) {
 ; converted into a bitwise or.
 define i1 @is_ascii_alphabetic(i32 %char) {
 ; CHECK-LABEL: @is_ascii_alphabetic(
-; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i32 [[CHAR:%.*]], -65
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[ADD1]], 26
-; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i32 [[CHAR]], -97
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[ADD2]], 26
-; CHECK-NEXT:    [[LOGICAL:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]]
-; CHECK-NEXT:    ret i1 [[LOGICAL]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[CHAR:%.*]], -33
+; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[TMP1]], -65
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 26
+; CHECK-NEXT:    ret i1 [[TMP3]]
 ;
   %add1 = add nsw i32 %char, -65
   %cmp1 = icmp ult i32 %add1, 26
@@ -1266,12 +1264,10 @@ define i1 @is_ascii_alphabetic(i32 %char) {
 
 define i1 @is_ascii_alphabetic_inverted(i32 %char) {
 ; CHECK-LABEL: @is_ascii_alphabetic_inverted(
-; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i32 [[CHAR:%.*]], -91
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[ADD1]], -26
-; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i32 [[CHAR]], -123
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[ADD2]], -26
-; CHECK-NEXT:    [[LOGICAL:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 false
-; CHECK-NEXT:    ret i1 [[LOGICAL]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[CHAR:%.*]], -33
+; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[TMP1]], -91
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i32 [[TMP2]], -26
+; CHECK-NEXT:    ret i1 [[TMP3]]
 ;
   %add1 = add nsw i32 %char, -91
   %cmp1 = icmp ult i32 %add1, -26


        


More information about the llvm-commits mailing list