[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