Skip to content

Commit 492c471

Browse files
committed
[InstCombine] Handle logical op in simplifyRangeCheck() (PR59484)
We need to freeze to avoid propagating a potentially poison upper bound (https://alive2.llvm.org/ce/z/MsD38k). This resolves the existing TODO in the code. Fixes llvm#59484.
1 parent 88c5b96 commit 492c471

File tree

4 files changed

+39
-43
lines changed

4 files changed

+39
-43
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ static Value *foldLogOpOfMaskedICmps(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
662662
/// If \p Inverted is true then the check is for the inverted range, e.g.
663663
/// (icmp slt x, 0) | (icmp sgt x, n) --> icmp ugt x, n
664664
Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1,
665-
bool Inverted) {
665+
bool Inverted, bool IsLogical) {
666666
// Check the lower range comparison, e.g. x >= 0
667667
// InstCombine already ensured that if there is a constant it's on the RHS.
668668
ConstantInt *RangeStart = dyn_cast<ConstantInt>(Cmp0->getOperand(1));
@@ -709,6 +709,8 @@ Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1,
709709
if (Inverted)
710710
NewPred = ICmpInst::getInversePredicate(NewPred);
711711

712+
if (IsLogical)
713+
RangeEnd = Builder.CreateFreeze(RangeEnd);
712714
return Builder.CreateICmp(NewPred, Input, RangeEnd);
713715
}
714716

@@ -2672,19 +2674,18 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
26722674
if (Value *V = foldIsPowerOf2OrZero(RHS, LHS, IsAnd, Builder))
26732675
return V;
26742676

2675-
// TODO: One of these directions is fine with logical and/or, the other could
2676-
// be supported by inserting freeze.
2677-
if (!IsLogical) {
2678-
// E.g. (icmp slt x, 0) | (icmp sgt x, n) --> icmp ugt x, n
2679-
// E.g. (icmp sge x, 0) & (icmp slt x, n) --> icmp ult x, n
2680-
if (Value *V = simplifyRangeCheck(LHS, RHS, /*Inverted=*/!IsAnd))
2681-
return V;
2677+
// E.g. (icmp slt x, 0) | (icmp sgt x, n) --> icmp ugt x, n
2678+
// E.g. (icmp sge x, 0) & (icmp slt x, n) --> icmp ult x, n
2679+
if (Value *V = simplifyRangeCheck(LHS, RHS, /*Inverted=*/!IsAnd, IsLogical))
2680+
return V;
26822681

2683-
// E.g. (icmp sgt x, n) | (icmp slt x, 0) --> icmp ugt x, n
2684-
// E.g. (icmp slt x, n) & (icmp sge x, 0) --> icmp ult x, n
2685-
if (Value *V = simplifyRangeCheck(RHS, LHS, /*Inverted=*/!IsAnd))
2686-
return V;
2687-
}
2682+
// E.g. (icmp sgt x, n) | (icmp slt x, 0) --> icmp ugt x, n
2683+
// E.g. (icmp slt x, n) & (icmp sge x, 0) --> icmp ult x, n
2684+
// We can treat logical like bitwise here, because poison from both x and n
2685+
// propagates in the original pattern.
2686+
if (Value *V = simplifyRangeCheck(RHS, LHS, /*Inverted=*/!IsAnd,
2687+
/*IsLogical*/ false))
2688+
return V;
26882689

26892690
// TODO: Add conjugated or fold, check whether it is safe for logical and/or.
26902691
if (IsAnd && !IsLogical)

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
103103
Instruction *visitUDiv(BinaryOperator &I);
104104
Instruction *visitSDiv(BinaryOperator &I);
105105
Instruction *visitFDiv(BinaryOperator &I);
106-
Value *simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, bool Inverted);
106+
Value *simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, bool Inverted,
107+
bool IsLogical);
107108
Instruction *visitAnd(BinaryOperator &I);
108109
Instruction *visitOr(BinaryOperator &I);
109110
bool sinkNotIntoOtherHandOfAndOrOr(BinaryOperator &I);

llvm/test/Transforms/InstCombine/pr49688.ll

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
define i1 @f(i32 %i1) {
66
; CHECK-LABEL: @f(
77
; CHECK-NEXT: entry:
8-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I1:%.*]], 0
9-
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 7, [[I1]]
10-
; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[SHR]], [[I1]]
11-
; CHECK-NEXT: [[I2:%.*]] = select i1 [[CMP]], i1 true, i1 [[CMP4]]
12-
; CHECK-NEXT: ret i1 [[I2]]
8+
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 7, [[I1:%.*]]
9+
; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[SHR]]
10+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[I1]]
11+
; CHECK-NEXT: ret i1 [[TMP1]]
1312
;
1413
entry:
1514
%cmp = icmp slt i32 %i1, 0
@@ -22,11 +21,10 @@ entry:
2221
; %cmp should not vanish
2322
define i32 @f2(i32 signext %g, i32 zeroext %h) {
2423
; CHECK-LABEL: @f2(
25-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[G:%.*]], 0
2624
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 7, [[H:%.*]]
27-
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[SHR]], [[G]]
28-
; CHECK-NEXT: [[DOT0:%.*]] = select i1 [[CMP]], i1 true, i1 [[CMP1]]
29-
; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[DOT0]] to i32
25+
; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[SHR]]
26+
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[TMP1]], [[G:%.*]]
27+
; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[TMP2]] to i32
3028
; CHECK-NEXT: ret i32 [[LOR_EXT]]
3129
;
3230
%cmp = icmp slt i32 %g, 0

llvm/test/Transforms/InstCombine/range-check.ll

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@ define i1 @test_and1(i32 %x, i32 %n) {
1919

2020
define i1 @test_and1_logical(i32 %x, i32 %n) {
2121
; CHECK-LABEL: @test_and1_logical(
22-
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
23-
; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -1
24-
; CHECK-NEXT: [[B:%.*]] = icmp sgt i32 [[NN]], [[X]]
25-
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 [[B]], i1 false
26-
; CHECK-NEXT: ret i1 [[C]]
22+
; CHECK-NEXT: [[N_FR:%.*]] = freeze i32 [[N:%.*]]
23+
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N_FR]], 2147483647
24+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[NN]], [[X:%.*]]
25+
; CHECK-NEXT: ret i1 [[TMP1]]
2726
;
2827
%nn = and i32 %n, 2147483647
2928
%a = icmp sge i32 %x, 0
@@ -47,11 +46,10 @@ define i1 @test_and2(i32 %x, i32 %n) {
4746

4847
define i1 @test_and2_logical(i32 %x, i32 %n) {
4948
; CHECK-LABEL: @test_and2_logical(
50-
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
51-
; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -1
52-
; CHECK-NEXT: [[B:%.*]] = icmp sge i32 [[NN]], [[X]]
53-
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 [[B]], i1 false
54-
; CHECK-NEXT: ret i1 [[C]]
49+
; CHECK-NEXT: [[N_FR:%.*]] = freeze i32 [[N:%.*]]
50+
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N_FR]], 2147483647
51+
; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 [[NN]], [[X:%.*]]
52+
; CHECK-NEXT: ret i1 [[TMP1]]
5553
;
5654
%nn = and i32 %n, 2147483647
5755
%a = icmp sgt i32 %x, -1
@@ -127,11 +125,10 @@ define i1 @test_or1(i32 %x, i32 %n) {
127125

128126
define i1 @test_or1_logical(i32 %x, i32 %n) {
129127
; CHECK-LABEL: @test_or1_logical(
130-
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
131-
; CHECK-NEXT: [[A:%.*]] = icmp slt i32 [[X:%.*]], 0
132-
; CHECK-NEXT: [[B:%.*]] = icmp sle i32 [[NN]], [[X]]
133-
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 true, i1 [[B]]
134-
; CHECK-NEXT: ret i1 [[C]]
128+
; CHECK-NEXT: [[N_FR:%.*]] = freeze i32 [[N:%.*]]
129+
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N_FR]], 2147483647
130+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[NN]], [[X:%.*]]
131+
; CHECK-NEXT: ret i1 [[TMP1]]
135132
;
136133
%nn = and i32 %n, 2147483647
137134
%a = icmp slt i32 %x, 0
@@ -155,11 +152,10 @@ define i1 @test_or2(i32 %x, i32 %n) {
155152

156153
define i1 @test_or2_logical(i32 %x, i32 %n) {
157154
; CHECK-LABEL: @test_or2_logical(
158-
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
159-
; CHECK-NEXT: [[A:%.*]] = icmp slt i32 [[X:%.*]], 0
160-
; CHECK-NEXT: [[B:%.*]] = icmp slt i32 [[NN]], [[X]]
161-
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 true, i1 [[B]]
162-
; CHECK-NEXT: ret i1 [[C]]
155+
; CHECK-NEXT: [[N_FR:%.*]] = freeze i32 [[N:%.*]]
156+
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N_FR]], 2147483647
157+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[NN]], [[X:%.*]]
158+
; CHECK-NEXT: ret i1 [[TMP1]]
163159
;
164160
%nn = and i32 %n, 2147483647
165161
%a = icmp sle i32 %x, -1

0 commit comments

Comments
 (0)