Skip to content

Commit 982cbed

Browse files
committed
[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).
1 parent 3c2a74a commit 982cbed

File tree

4 files changed

+22
-15
lines changed

4 files changed

+22
-15
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,8 +1128,10 @@ static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
11281128
/// Fold (icmp Pred1 V1, C1) & (icmp Pred2 V2, C2)
11291129
/// or (icmp Pred1 V1, C1) | (icmp Pred2 V2, C2)
11301130
/// into a single comparison using range-based reasoning.
1131-
static Value *foldAndOrOfICmpsUsingRanges(ICmpInst *ICmp1, ICmpInst *ICmp2,
1132-
IRBuilderBase &Builder, bool IsAnd) {
1131+
/// NOTE: This is also used for logical and/or, must be poison-safe!
1132+
Value *InstCombinerImpl::foldAndOrOfICmpsUsingRanges(ICmpInst *ICmp1,
1133+
ICmpInst *ICmp2,
1134+
bool IsAnd) {
11331135
ICmpInst::Predicate Pred1, Pred2;
11341136
Value *V1, *V2;
11351137
const APInt *C1, *C2;
@@ -2513,7 +2515,7 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
25132515
}
25142516
}
25152517

2516-
return foldAndOrOfICmpsUsingRanges(LHS, RHS, Builder, IsAnd);
2518+
return foldAndOrOfICmpsUsingRanges(LHS, RHS, IsAnd);
25172519
}
25182520

25192521
// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
350350

351351
Value *foldEqOfParts(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd);
352352

353+
Value *foldAndOrOfICmpsUsingRanges(ICmpInst *ICmp1, ICmpInst *ICmp2,
354+
bool IsAnd);
355+
353356
/// Optimize (fcmp)&(fcmp) or (fcmp)|(fcmp).
354357
/// NOTE: Unlike most of instcombine, this returns a Value which should
355358
/// already be inserted into the function.

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2805,6 +2805,12 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
28052805

28062806
if (auto *V = foldEqOfParts(ICmp0, ICmp1, IsAnd))
28072807
return replaceInstUsesWith(SI, V);
2808+
2809+
// This pattern would usually be converted into a bitwise and/or based
2810+
// on "implies poison" reasoning. However, this may fail if adds with
2811+
// nowrap flags are involved.
2812+
if (auto *V = foldAndOrOfICmpsUsingRanges(ICmp0, ICmp1, IsAnd))
2813+
return replaceInstUsesWith(SI, V);
28082814
}
28092815
}
28102816
}

llvm/test/Transforms/InstCombine/and-or-icmps.ll

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,12 +1249,10 @@ define i1 @and_two_ranges_to_mask_and_range_no_add_on_one_range(i16 %x) {
12491249
; converted into a bitwise or.
12501250
define i1 @is_ascii_alphabetic(i32 %char) {
12511251
; CHECK-LABEL: @is_ascii_alphabetic(
1252-
; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[CHAR:%.*]], -65
1253-
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[ADD1]], 26
1254-
; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[CHAR]], -97
1255-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[ADD2]], 26
1256-
; CHECK-NEXT: [[LOGICAL:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]]
1257-
; CHECK-NEXT: ret i1 [[LOGICAL]]
1252+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[CHAR:%.*]], -33
1253+
; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], -65
1254+
; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 26
1255+
; CHECK-NEXT: ret i1 [[TMP3]]
12581256
;
12591257
%add1 = add nsw i32 %char, -65
12601258
%cmp1 = icmp ult i32 %add1, 26
@@ -1266,12 +1264,10 @@ define i1 @is_ascii_alphabetic(i32 %char) {
12661264

12671265
define i1 @is_ascii_alphabetic_inverted(i32 %char) {
12681266
; CHECK-LABEL: @is_ascii_alphabetic_inverted(
1269-
; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[CHAR:%.*]], -91
1270-
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[ADD1]], -26
1271-
; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[CHAR]], -123
1272-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[ADD2]], -26
1273-
; CHECK-NEXT: [[LOGICAL:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 false
1274-
; CHECK-NEXT: ret i1 [[LOGICAL]]
1267+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[CHAR:%.*]], -33
1268+
; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], -91
1269+
; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[TMP2]], -26
1270+
; CHECK-NEXT: ret i1 [[TMP3]]
12751271
;
12761272
%add1 = add nsw i32 %char, -91
12771273
%cmp1 = icmp ult i32 %add1, -26

0 commit comments

Comments
 (0)