Skip to content

Commit f51d873

Browse files
authored
[InstSimplify] Simplify 'x u>= 1' to true when x is known non-zero (#145204)
1 parent fa0b84f commit f51d873

File tree

2 files changed

+127
-4
lines changed

2 files changed

+127
-4
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2981,7 +2981,7 @@ static Value *simplifyICmpWithZero(CmpPredicate Pred, Value *LHS, Value *RHS,
29812981
}
29822982

29832983
static Value *simplifyICmpWithConstant(CmpPredicate Pred, Value *LHS,
2984-
Value *RHS, const InstrInfoQuery &IIQ) {
2984+
Value *RHS, const SimplifyQuery &Q) {
29852985
Type *ITy = getCompareTy(RHS); // The return type.
29862986

29872987
Value *X;
@@ -3007,7 +3007,7 @@ static Value *simplifyICmpWithConstant(CmpPredicate Pred, Value *LHS,
30073007
return ConstantInt::getTrue(ITy);
30083008

30093009
ConstantRange LHS_CR =
3010-
computeConstantRange(LHS, CmpInst::isSigned(Pred), IIQ.UseInstrInfo);
3010+
computeConstantRange(LHS, CmpInst::isSigned(Pred), Q.IIQ.UseInstrInfo);
30113011
if (!LHS_CR.isFullSet()) {
30123012
if (RHS_CR.contains(LHS_CR))
30133013
return ConstantInt::getTrue(ITy);
@@ -3018,13 +3018,16 @@ static Value *simplifyICmpWithConstant(CmpPredicate Pred, Value *LHS,
30183018
// (mul nuw/nsw X, MulC) != C --> true (if C is not a multiple of MulC)
30193019
// (mul nuw/nsw X, MulC) == C --> false (if C is not a multiple of MulC)
30203020
const APInt *MulC;
3021-
if (IIQ.UseInstrInfo && ICmpInst::isEquality(Pred) &&
3021+
if (Q.IIQ.UseInstrInfo && ICmpInst::isEquality(Pred) &&
30223022
((match(LHS, m_NUWMul(m_Value(), m_APIntAllowPoison(MulC))) &&
30233023
*MulC != 0 && C->urem(*MulC) != 0) ||
30243024
(match(LHS, m_NSWMul(m_Value(), m_APIntAllowPoison(MulC))) &&
30253025
*MulC != 0 && C->srem(*MulC) != 0)))
30263026
return ConstantInt::get(ITy, Pred == ICmpInst::ICMP_NE);
30273027

3028+
if (Pred == ICmpInst::ICMP_UGE && C->isOne() && isKnownNonZero(LHS, Q))
3029+
return ConstantInt::getTrue(ITy);
3030+
30283031
return nullptr;
30293032
}
30303033

@@ -3776,7 +3779,7 @@ static Value *simplifyICmpInst(CmpPredicate Pred, Value *LHS, Value *RHS,
37763779
if (Value *V = simplifyICmpWithZero(Pred, LHS, RHS, Q))
37773780
return V;
37783781

3779-
if (Value *V = simplifyICmpWithConstant(Pred, LHS, RHS, Q.IIQ))
3782+
if (Value *V = simplifyICmpWithConstant(Pred, LHS, RHS, Q))
37803783
return V;
37813784

37823785
// If both operands have range metadata, use the metadata
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
3+
4+
define i32 @known_non_zero_by_or(i32 %x, i32 %y) {
5+
; CHECK-LABEL: define i32 @known_non_zero_by_or(
6+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
7+
; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
8+
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
9+
; CHECK: [[IF_THEN]]:
10+
; CHECK-NEXT: [[VAL:%.*]] = or i32 [[X]], [[Y]]
11+
; CHECK-NEXT: ret i32 [[VAL]]
12+
; CHECK: [[IF_ELSE]]:
13+
; CHECK-NEXT: ret i32 0
14+
;
15+
%cond = icmp ne i32 %x, 0
16+
br i1 %cond, label %if.then, label %if.else
17+
18+
if.then:
19+
%val = or i32 %x, %y
20+
%max = call i32 @llvm.umax.i32(i32 %val, i32 1)
21+
ret i32 %max
22+
23+
if.else:
24+
ret i32 0
25+
}
26+
27+
define i32 @known_non_zero_by_mul(i32 %x) {
28+
; CHECK-LABEL: define i32 @known_non_zero_by_mul(
29+
; CHECK-SAME: i32 [[X:%.*]]) {
30+
; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
31+
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
32+
; CHECK: [[IF_THEN]]:
33+
; CHECK-NEXT: [[NONZERO1:%.*]] = mul nuw i32 [[X]], 3
34+
; CHECK-NEXT: ret i32 [[NONZERO1]]
35+
; CHECK: [[IF_ELSE]]:
36+
; CHECK-NEXT: ret i32 0
37+
;
38+
%cond = icmp ne i32 %x, 0
39+
br i1 %cond, label %if.then, label %if.else
40+
41+
if.then:
42+
%nonzero = mul nuw i32 %x, 3
43+
%max = call i32 @llvm.umax.i32(i32 %nonzero, i32 1)
44+
ret i32 %max
45+
46+
if.else:
47+
ret i32 0
48+
}
49+
50+
define i32 @known_non_zero_commute(i32 %x, i32 %y) {
51+
; CHECK-LABEL: define i32 @known_non_zero_commute(
52+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
53+
; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
54+
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
55+
; CHECK: [[IF_THEN]]:
56+
; CHECK-NEXT: [[VAL:%.*]] = or i32 [[X]], [[Y]]
57+
; CHECK-NEXT: ret i32 [[VAL]]
58+
; CHECK: [[IF_ELSE]]:
59+
; CHECK-NEXT: ret i32 0
60+
;
61+
%cond = icmp ne i32 %x, 0
62+
br i1 %cond, label %if.then, label %if.else
63+
64+
if.then:
65+
%val = or i32 %x, %y
66+
%max = call i32 @llvm.umax.i32(i32 1, i32 %val)
67+
ret i32 %max
68+
69+
if.else:
70+
ret i32 0
71+
}
72+
73+
; Negative
74+
define i32 @umax_ge_2(i32 %x, i32 %y) {
75+
; CHECK-LABEL: define i32 @umax_ge_2(
76+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
77+
; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
78+
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
79+
; CHECK: [[IF_THEN]]:
80+
; CHECK-NEXT: [[VAL:%.*]] = or i32 [[X]], [[Y]]
81+
; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[VAL]], i32 2)
82+
; CHECK-NEXT: ret i32 [[MAX]]
83+
; CHECK: [[IF_ELSE]]:
84+
; CHECK-NEXT: ret i32 0
85+
;
86+
%cond = icmp ne i32 %x, 0
87+
br i1 %cond, label %if.then, label %if.else
88+
89+
if.then:
90+
%val = or i32 %x, %y
91+
%max = call i32 @llvm.umax.i32(i32 %val, i32 2)
92+
ret i32 %max
93+
94+
if.else:
95+
ret i32 0
96+
}
97+
98+
define i32 @unknown_by_and(i32 %x, i32 %y) {
99+
; CHECK-LABEL: define i32 @unknown_by_and(
100+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
101+
; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
102+
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
103+
; CHECK: [[IF_THEN]]:
104+
; CHECK-NEXT: [[VAL:%.*]] = and i32 [[X]], [[Y]]
105+
; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[VAL]], i32 1)
106+
; CHECK-NEXT: ret i32 [[MAX]]
107+
; CHECK: [[IF_ELSE]]:
108+
; CHECK-NEXT: ret i32 0
109+
;
110+
%cond = icmp ne i32 %x, 0
111+
br i1 %cond, label %if.then, label %if.else
112+
113+
if.then:
114+
%val = and i32 %x, %y
115+
%max = call i32 @llvm.umax.i32(i32 %val, i32 1)
116+
ret i32 %max
117+
118+
if.else:
119+
ret i32 0
120+
}

0 commit comments

Comments
 (0)