Skip to content

Commit 349dc34

Browse files
authored
[ConstraintElim] Fix poison check before adding intrinsic facts (#136291)
1 parent 01e0296 commit 349dc34

File tree

2 files changed

+162
-28
lines changed

2 files changed

+162
-28
lines changed

llvm/test/Transforms/ConstraintElimination/abs.ll

+97-28
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
22
; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
33

4-
define i1 @abs_int_min_is_not_poison(i32 %arg) {
4+
define i1 @abs_int_min_is_not_poison(i32 noundef %arg) {
55
; CHECK-LABEL: define i1 @abs_int_min_is_not_poison(
6-
; CHECK-SAME: i32 [[ARG:%.*]]) {
6+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
77
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 false)
88
; CHECK-NEXT: ret i1 true
99
;
@@ -12,9 +12,9 @@ define i1 @abs_int_min_is_not_poison(i32 %arg) {
1212
ret i1 %cmp
1313
}
1414

15-
define i1 @abs_int_min_is_poison(i32 %arg) {
15+
define i1 @abs_int_min_is_poison(i32 noundef %arg) {
1616
; CHECK-LABEL: define i1 @abs_int_min_is_poison(
17-
; CHECK-SAME: i32 [[ARG:%.*]]) {
17+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
1818
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true)
1919
; CHECK-NEXT: ret i1 true
2020
;
@@ -23,9 +23,22 @@ define i1 @abs_int_min_is_poison(i32 %arg) {
2323
ret i1 %cmp
2424
}
2525

26-
define i1 @abs_plus_one(i32 %arg) {
27-
; CHECK-LABEL: define i1 @abs_plus_one(
28-
; CHECK-SAME: i32 [[ARG:%.*]]) {
26+
define i1 @abs_plus_one_min_is_not_poison(i32 noundef %arg) {
27+
; CHECK-LABEL: define i1 @abs_plus_one_min_is_not_poison(
28+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
29+
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 false)
30+
; CHECK-NEXT: [[ABS_PLUS_ONE:%.*]] = add nsw i32 [[ABS]], 1
31+
; CHECK-NEXT: ret i1 true
32+
;
33+
%abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 false)
34+
%abs_plus_one = add nsw i32 %abs, 1
35+
%cmp = icmp sge i32 %abs_plus_one, %arg
36+
ret i1 %cmp
37+
}
38+
39+
define i1 @abs_plus_one_min_is_poison(i32 noundef %arg) {
40+
; CHECK-LABEL: define i1 @abs_plus_one_min_is_poison(
41+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
2942
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true)
3043
; CHECK-NEXT: [[ABS_PLUS_ONE:%.*]] = add nsw i32 [[ABS]], 1
3144
; CHECK-NEXT: ret i1 true
@@ -36,9 +49,23 @@ define i1 @abs_plus_one(i32 %arg) {
3649
ret i1 %cmp
3750
}
3851

39-
define i1 @arg_minus_one_strict_less(i32 %arg) {
40-
; CHECK-LABEL: define i1 @arg_minus_one_strict_less(
41-
; CHECK-SAME: i32 [[ARG:%.*]]) {
52+
define i1 @arg_minus_one_strict_less_min_is_not_poison(i32 noundef %arg) {
53+
; CHECK-LABEL: define i1 @arg_minus_one_strict_less_min_is_not_poison(
54+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
55+
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 false)
56+
; CHECK-NEXT: [[ARG_MINUS_ONE:%.*]] = add nsw i32 [[ARG]], -1
57+
; CHECK-NEXT: ret i1 true
58+
;
59+
%abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 false)
60+
%arg_minus_one = add nsw i32 %arg, -1
61+
%cmp = icmp slt i32 %arg_minus_one, %abs
62+
ret i1 %cmp
63+
}
64+
65+
66+
define i1 @arg_minus_one_strict_less_min_is_poison(i32 noundef %arg) {
67+
; CHECK-LABEL: define i1 @arg_minus_one_strict_less_min_is_poison(
68+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
4269
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true)
4370
; CHECK-NEXT: [[ARG_MINUS_ONE:%.*]] = add nsw i32 [[ARG]], -1
4471
; CHECK-NEXT: ret i1 true
@@ -49,9 +76,22 @@ define i1 @arg_minus_one_strict_less(i32 %arg) {
4976
ret i1 %cmp
5077
}
5178

52-
define i1 @arg_minus_one_strict_greater(i32 %arg) {
53-
; CHECK-LABEL: define i1 @arg_minus_one_strict_greater(
54-
; CHECK-SAME: i32 [[ARG:%.*]]) {
79+
define i1 @arg_minus_one_strict_greater_min_is_not_poison(i32 noundef %arg) {
80+
; CHECK-LABEL: define i1 @arg_minus_one_strict_greater_min_is_not_poison(
81+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
82+
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 false)
83+
; CHECK-NEXT: [[ARG_MINUS_ONE:%.*]] = add nsw i32 [[ARG]], -1
84+
; CHECK-NEXT: ret i1 false
85+
;
86+
%abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 false)
87+
%arg_minus_one = add nsw i32 %arg, -1
88+
%cmp = icmp sgt i32 %arg_minus_one, %abs
89+
ret i1 %cmp
90+
}
91+
92+
define i1 @arg_minus_one_strict_greater_min_is_poison(i32 noundef %arg) {
93+
; CHECK-LABEL: define i1 @arg_minus_one_strict_greater_min_is_poison(
94+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
5595
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true)
5696
; CHECK-NEXT: [[ARG_MINUS_ONE:%.*]] = add nsw i32 [[ARG]], -1
5797
; CHECK-NEXT: ret i1 false
@@ -62,9 +102,26 @@ define i1 @arg_minus_one_strict_greater(i32 %arg) {
62102
ret i1 %cmp
63103
}
64104

65-
define i1 @abs_plus_one_unsigned_greater_or_equal_nonnegative_arg(i32 %arg) {
66-
; CHECK-LABEL: define i1 @abs_plus_one_unsigned_greater_or_equal_nonnegative_arg(
67-
; CHECK-SAME: i32 [[ARG:%.*]]) {
105+
define i1 @abs_plus_one_unsigned_greater_or_equal_nonnegative_arg_min_is_not_poison(i32 noundef %arg) {
106+
; CHECK-LABEL: define i1 @abs_plus_one_unsigned_greater_or_equal_nonnegative_arg_min_is_not_poison(
107+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
108+
; CHECK-NEXT: [[CMP_ARG_NONNEGATIVE:%.*]] = icmp sge i32 [[ARG]], 0
109+
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ARG_NONNEGATIVE]])
110+
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 false)
111+
; CHECK-NEXT: [[ABS_PLUS_ONE:%.*]] = add nuw i32 [[ABS]], 1
112+
; CHECK-NEXT: ret i1 true
113+
;
114+
%cmp_arg_nonnegative = icmp sge i32 %arg, 0
115+
call void @llvm.assume(i1 %cmp_arg_nonnegative)
116+
%abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 false)
117+
%abs_plus_one = add nuw i32 %abs, 1
118+
%cmp = icmp uge i32 %abs_plus_one, %arg
119+
ret i1 %cmp
120+
}
121+
122+
define i1 @abs_plus_one_unsigned_greater_or_equal_nonnegative_arg_min_is_poison(i32 noundef %arg) {
123+
; CHECK-LABEL: define i1 @abs_plus_one_unsigned_greater_or_equal_nonnegative_arg_min_is_poison(
124+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
68125
; CHECK-NEXT: [[CMP_ARG_NONNEGATIVE:%.*]] = icmp sge i32 [[ARG]], 0
69126
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ARG_NONNEGATIVE]])
70127
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true)
@@ -79,15 +136,15 @@ define i1 @abs_plus_one_unsigned_greater_or_equal_nonnegative_arg(i32 %arg) {
79136
ret i1 %cmp
80137
}
81138

82-
define i1 @abs_plus_one_unsigned_greater_or_equal_cannot_be_simplified(i32 %arg) {
139+
define i1 @abs_plus_one_unsigned_greater_or_equal_cannot_be_simplified(i32 noundef %arg) {
83140
; CHECK-LABEL: define i1 @abs_plus_one_unsigned_greater_or_equal_cannot_be_simplified(
84-
; CHECK-SAME: i32 [[ARG:%.*]]) {
85-
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true)
141+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
142+
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 false)
86143
; CHECK-NEXT: [[ABS_PLUS_ONE:%.*]] = add nuw i32 [[ABS]], 1
87144
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[ABS_PLUS_ONE]], [[ARG]]
88145
; CHECK-NEXT: ret i1 [[CMP]]
89146
;
90-
%abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 true)
147+
%abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 false)
91148
%abs_plus_one = add nuw i32 %abs, 1
92149
%cmp = icmp uge i32 %abs_plus_one, %arg
93150
ret i1 %cmp
@@ -114,9 +171,9 @@ define i1 @abs_constant_positive_arg() {
114171
ret i1 %cmp
115172
}
116173

117-
define i1 @abs_is_nonnegative_except_for_int_min_if_int_min_is_not_poison(i32 %arg) {
174+
define i1 @abs_is_nonnegative_except_for_int_min_if_int_min_is_not_poison(i32 noundef %arg) {
118175
; CHECK-LABEL: define i1 @abs_is_nonnegative_except_for_int_min_if_int_min_is_not_poison(
119-
; CHECK-SAME: i32 [[ARG:%.*]]) {
176+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
120177
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 false)
121178
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[ABS]], 0
122179
; CHECK-NEXT: ret i1 [[CMP]]
@@ -126,21 +183,33 @@ define i1 @abs_is_nonnegative_except_for_int_min_if_int_min_is_not_poison(i32 %a
126183
ret i1 %cmp
127184
}
128185

129-
define i1 @abs_is_not_strictly_positive(i32 %arg) {
186+
define i1 @abs_is_not_strictly_positive(i32 noundef %arg) {
130187
; CHECK-LABEL: define i1 @abs_is_not_strictly_positive(
131-
; CHECK-SAME: i32 [[ARG:%.*]]) {
132-
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true)
188+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
189+
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 false)
133190
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ABS]], 0
134191
; CHECK-NEXT: ret i1 [[CMP]]
135192
;
136-
%abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 true)
193+
%abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 false)
137194
%cmp = icmp sgt i32 %abs, 0
138195
ret i1 %cmp
139196
}
140197

141-
define i1 @abs_is_nonnegative_int_min_is_poison(i32 %arg) {
198+
define i1 @abs_is_nonnegative_int_min_is_not_poison(i32 noundef %arg) {
199+
; CHECK-LABEL: define i1 @abs_is_nonnegative_int_min_is_not_poison(
200+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
201+
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 false)
202+
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[ABS]], 0
203+
; CHECK-NEXT: ret i1 [[CMP]]
204+
;
205+
%abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 false)
206+
%cmp = icmp sge i32 %abs, 0
207+
ret i1 %cmp
208+
}
209+
210+
define i1 @abs_is_nonnegative_int_min_is_poison(i32 noundef %arg) {
142211
; CHECK-LABEL: define i1 @abs_is_nonnegative_int_min_is_poison(
143-
; CHECK-SAME: i32 [[ARG:%.*]]) {
212+
; CHECK-SAME: i32 noundef [[ARG:%.*]]) {
144213
; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true)
145214
; CHECK-NEXT: ret i1 true
146215
;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3+
4+
declare i64 @llvm.uadd.sat.i64(i64, i64)
5+
declare i64 @llvm.usub.sat.i64(i64, i64)
6+
7+
define i1 @uadd_sat_uge(i64 noundef %a, i64 noundef %b) {
8+
; CHECK-LABEL: define i1 @uadd_sat_uge(
9+
; CHECK-SAME: i64 noundef [[A:%.*]], i64 noundef [[B:%.*]]) {
10+
; CHECK-NEXT: [[ADD_SAT:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[A]], i64 [[B]])
11+
; CHECK-NEXT: [[CMP1:%.*]] = icmp uge i64 [[ADD_SAT]], [[A]]
12+
; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i64 [[ADD_SAT]], [[B]]
13+
; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP1]], [[CMP2]]
14+
; CHECK-NEXT: ret i1 [[CMP]]
15+
;
16+
%add.sat = call i64 @llvm.uadd.sat.i64(i64 %a, i64 %b)
17+
%cmp1 = icmp uge i64 %add.sat, %a
18+
%cmp2 = icmp uge i64 %add.sat, %b
19+
%cmp = and i1 %cmp1, %cmp2
20+
ret i1 %cmp
21+
}
22+
23+
define i1 @usub_sat_ule_lhs(i64 noundef %a, i64 noundef %b) {
24+
; CHECK-LABEL: define i1 @usub_sat_ule_lhs(
25+
; CHECK-SAME: i64 noundef [[A:%.*]], i64 noundef [[B:%.*]]) {
26+
; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
27+
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[SUB_SAT]], [[A]]
28+
; CHECK-NEXT: ret i1 [[CMP]]
29+
;
30+
%sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b)
31+
%cmp = icmp ule i64 %sub.sat, %a
32+
ret i1 %cmp
33+
}
34+
35+
; Negative test
36+
define i1 @usub_sat_not_ule_rhs(i64 noundef %a, i64 noundef %b) {
37+
; CHECK-LABEL: define i1 @usub_sat_not_ule_rhs(
38+
; CHECK-SAME: i64 noundef [[A:%.*]], i64 noundef [[B:%.*]]) {
39+
; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
40+
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[SUB_SAT]], [[B]]
41+
; CHECK-NEXT: ret i1 [[CMP]]
42+
;
43+
%sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b)
44+
%cmp = icmp ule i64 %sub.sat, %b
45+
ret i1 %cmp
46+
}
47+
48+
define i1 @pr135603(i64 %conv6, i64 %str.coerce, ptr %conv) {
49+
; CHECK-LABEL: define i1 @pr135603(
50+
; CHECK-SAME: i64 [[CONV6:%.*]], i64 [[STR_COERCE:%.*]], ptr [[CONV:%.*]]) {
51+
; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[CONV]], align 4
52+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], -1
53+
; CHECK-NEXT: [[CONV2:%.*]] = zext nneg i32 [[A]] to i64
54+
; CHECK-NEXT: [[ADD:%.*]] = add i64 [[STR_COERCE]], [[CONV6]]
55+
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[CONV2]], i64 [[ADD]])
56+
; CHECK-NEXT: ret i1 [[CMP]]
57+
;
58+
%a = load i32, ptr %conv, align 4
59+
%cmp = icmp sgt i32 %a, -1
60+
%conv2 = zext nneg i32 %a to i64
61+
%add = add i64 %str.coerce, %conv6
62+
%spec.select = call i64 @llvm.usub.sat.i64(i64 %conv2, i64 %add)
63+
ret i1 %cmp
64+
}
65+

0 commit comments

Comments
 (0)