Skip to content

Commit 27c7f10

Browse files
rkirslingAnthony Tran
authored andcommitted
[InstCombine] KnownBits::isNonNegative should recognize b - a after a <= b (llvm#145105)
Alive2: https://alive2.llvm.org/ce/z/an9npN Fixes llvm#142283.
1 parent e35fc14 commit 27c7f10

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,11 @@ static void computeKnownBitsAddSub(bool Add, const Value *Op0, const Value *Op1,
362362

363363
computeKnownBits(Op0, DemandedElts, Known2, Q, Depth + 1);
364364
KnownOut = KnownBits::computeForAddSub(Add, NSW, NUW, Known2, KnownOut);
365+
366+
if (!Add && NSW && !KnownOut.isNonNegative() &&
367+
isImpliedByDomCondition(ICmpInst::ICMP_SLE, Op1, Op0, Q.CxtI, Q.DL)
368+
.value_or(false))
369+
KnownOut.makeNonNegative();
365370
}
366371

367372
static void computeKnownBitsMul(const Value *Op0, const Value *Op1, bool NSW,
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3+
declare void @subroutine(i16)
4+
5+
define void @test_as_arg(i8 %a, i8 %b) {
6+
; CHECK-LABEL: define void @test_as_arg(
7+
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
8+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[A]], [[B]]
9+
; CHECK-NEXT: br i1 [[CMP]], label %[[COND_END:.*]], label %[[COND_FALSE:.*]]
10+
; CHECK: [[COND_FALSE]]:
11+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 [[B]], [[A]]
12+
; CHECK-NEXT: [[CONV:%.*]] = zext nneg i8 [[SUB]] to i16
13+
; CHECK-NEXT: call void @subroutine(i16 [[CONV]])
14+
; CHECK-NEXT: br label %[[COND_END]]
15+
; CHECK: [[COND_END]]:
16+
; CHECK-NEXT: ret void
17+
;
18+
%cmp = icmp sgt i8 %a, %b
19+
br i1 %cmp, label %cond.end, label %cond.false
20+
21+
cond.false:
22+
%sub = sub nsw i8 %b, %a
23+
%conv = sext i8 %sub to i16
24+
call void @subroutine(i16 %conv)
25+
br label %cond.end
26+
27+
cond.end:
28+
ret void
29+
}
30+
31+
define i16 @test_as_retval(i8 %a, i8 %b) {
32+
; CHECK-LABEL: define i16 @test_as_retval(
33+
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
34+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[A]], [[B]]
35+
; CHECK-NEXT: br i1 [[CMP]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]
36+
; CHECK: [[COND_TRUE]]:
37+
; CHECK-NEXT: ret i16 0
38+
; CHECK: [[COND_FALSE]]:
39+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 [[B]], [[A]]
40+
; CHECK-NEXT: [[CONV:%.*]] = zext nneg i8 [[SUB]] to i16
41+
; CHECK-NEXT: ret i16 [[CONV]]
42+
;
43+
%cmp = icmp sgt i8 %a, %b
44+
br i1 %cmp, label %cond.true, label %cond.false
45+
46+
cond.true:
47+
ret i16 0
48+
49+
cond.false:
50+
%sub = sub nsw i8 %b, %a
51+
%conv = sext i8 %sub to i16
52+
ret i16 %conv
53+
}
54+
55+
define void @test_as_arg_wrong_icmp(i8 %a, i8 %b) {
56+
; CHECK-LABEL: define void @test_as_arg_wrong_icmp(
57+
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
58+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[A]], [[B]]
59+
; CHECK-NEXT: br i1 [[CMP]], label %[[COND_END:.*]], label %[[COND_FALSE:.*]]
60+
; CHECK: [[COND_FALSE]]:
61+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 [[B]], [[A]]
62+
; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[SUB]] to i16
63+
; CHECK-NEXT: call void @subroutine(i16 [[CONV]])
64+
; CHECK-NEXT: br label %[[COND_END]]
65+
; CHECK: [[COND_END]]:
66+
; CHECK-NEXT: ret void
67+
;
68+
%cmp = icmp slt i8 %a, %b
69+
br i1 %cmp, label %cond.end, label %cond.false
70+
71+
cond.false:
72+
%sub = sub nsw i8 %b, %a
73+
%conv = sext i8 %sub to i16
74+
call void @subroutine(i16 %conv)
75+
br label %cond.end
76+
77+
cond.end:
78+
ret void
79+
}
80+
81+
define void @test_as_arg_missing_nsw(i8 %a, i8 %b) {
82+
; CHECK-LABEL: define void @test_as_arg_missing_nsw(
83+
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
84+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[A]], [[B]]
85+
; CHECK-NEXT: br i1 [[CMP]], label %[[COND_END:.*]], label %[[COND_FALSE:.*]]
86+
; CHECK: [[COND_FALSE]]:
87+
; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[B]], [[A]]
88+
; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[SUB]] to i16
89+
; CHECK-NEXT: call void @subroutine(i16 [[CONV]])
90+
; CHECK-NEXT: br label %[[COND_END]]
91+
; CHECK: [[COND_END]]:
92+
; CHECK-NEXT: ret void
93+
;
94+
%cmp = icmp sgt i8 %a, %b
95+
br i1 %cmp, label %cond.end, label %cond.false
96+
97+
cond.false:
98+
%sub = sub i8 %b, %a
99+
%conv = sext i8 %sub to i16
100+
call void @subroutine(i16 %conv)
101+
br label %cond.end
102+
103+
cond.end:
104+
ret void
105+
}
106+
107+
define i16 @test_as_retval_wrong_icmp(i8 %a, i8 %b) {
108+
; CHECK-LABEL: define i16 @test_as_retval_wrong_icmp(
109+
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
110+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[A]], [[B]]
111+
; CHECK-NEXT: br i1 [[CMP]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]
112+
; CHECK: [[COND_TRUE]]:
113+
; CHECK-NEXT: ret i16 0
114+
; CHECK: [[COND_FALSE]]:
115+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 [[B]], [[A]]
116+
; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[SUB]] to i16
117+
; CHECK-NEXT: ret i16 [[CONV]]
118+
;
119+
%cmp = icmp slt i8 %a, %b
120+
br i1 %cmp, label %cond.true, label %cond.false
121+
122+
cond.true:
123+
ret i16 0
124+
125+
cond.false:
126+
%sub = sub nsw i8 %b, %a
127+
%conv = sext i8 %sub to i16
128+
ret i16 %conv
129+
}
130+
131+
define i16 @test_as_retval_missing_nsw(i8 %a, i8 %b) {
132+
; CHECK-LABEL: define i16 @test_as_retval_missing_nsw(
133+
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
134+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[A]], [[B]]
135+
; CHECK-NEXT: br i1 [[CMP]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]
136+
; CHECK: [[COND_TRUE]]:
137+
; CHECK-NEXT: ret i16 0
138+
; CHECK: [[COND_FALSE]]:
139+
; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[B]], [[A]]
140+
; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[SUB]] to i16
141+
; CHECK-NEXT: ret i16 [[CONV]]
142+
;
143+
%cmp = icmp sgt i8 %a, %b
144+
br i1 %cmp, label %cond.true, label %cond.false
145+
146+
cond.true:
147+
ret i16 0
148+
149+
cond.false:
150+
%sub = sub i8 %b, %a
151+
%conv = sext i8 %sub to i16
152+
ret i16 %conv
153+
}

0 commit comments

Comments
 (0)