1 ; RUN: opt < %s -ipsccp -S | FileCheck %s
4 define internal i1 @f.trunc(i32 %x) {
5 ; CHECK-LABEL: define internal i1 @f.trunc(i32 %x) {
6 ; CHECK-NEXT: %t.1 = trunc i32 %x to i16
7 ; CHECK-NEXT: %c.2 = icmp sgt i16 %t.1, 299
8 ; CHECK-NEXT: %c.4 = icmp slt i16 %t.1, 101
9 ; CHECK-NEXT: %res.1 = add i1 false, %c.2
10 ; CHECK-NEXT: %res.2 = add i1 %res.1, false
11 ; CHECK-NEXT: %res.3 = add i1 %res.2, %c.4
12 ; CHECK-NEXT: %t.2 = trunc i32 %x to i8
13 ; CHECK-NEXT: %c.5 = icmp sgt i8 %t.2, 44
14 ; CHECK-NEXT: %c.6 = icmp sgt i8 %t.2, 43
15 ; CHECK-NEXT: %c.7 = icmp slt i8 %t.2, 100
16 ; CHECK-NEXT: %c.8 = icmp slt i8 %t.2, 101
17 ; CHECK-NEXT: %res.4 = add i1 %res.3, %c.5
18 ; CHECK-NEXT: %res.5 = add i1 %res.4, %c.6
19 ; CHECK-NEXT: %res.6 = add i1 %res.5, %c.7
20 ; CHECK-NEXT: %res.7 = add i1 %res.6, %c.8
21 ; CHECK-NEXT: ret i1 %res.7
23 %t.1 = trunc i32 %x to i16
24 %c.1 = icmp sgt i16 %t.1, 300
25 %c.2 = icmp sgt i16 %t.1, 299
26 %c.3 = icmp slt i16 %t.1, 100
27 %c.4 = icmp slt i16 %t.1, 101
28 %res.1 = add i1 %c.1, %c.2
29 %res.2 = add i1 %res.1, %c.3
30 %res.3 = add i1 %res.2, %c.4
31 %t.2 = trunc i32 %x to i8
32 %c.5 = icmp sgt i8 %t.2, 300
33 %c.6 = icmp sgt i8 %t.2, 299
34 %c.7 = icmp slt i8 %t.2, 100
35 %c.8 = icmp slt i8 %t.2, 101
36 %res.4 = add i1 %res.3, %c.5
37 %res.5 = add i1 %res.4, %c.6
38 %res.6 = add i1 %res.5, %c.7
39 %res.7 = add i1 %res.6, %c.8
43 define i1 @caller1() {
44 ; CHECK-LABEL: define i1 @caller1() {
45 ; CHECK-NEXT: %call.1 = tail call i1 @f.trunc(i32 100)
46 ; CHECK-NEXT: %call.2 = tail call i1 @f.trunc(i32 300)
47 ; CHECK-NEXT: %res = and i1 %call.1, %call.2
48 ; CHECK-NEXT: ret i1 %res
50 %call.1 = tail call i1 @f.trunc(i32 100)
51 %call.2 = tail call i1 @f.trunc(i32 300)
52 %res = and i1 %call.1, %call.2
58 define internal i1 @f.zext(i32 %x, i32 %y) {
59 ; CHECK-LABEL: define internal i1 @f.zext(i32 %x, i32 %y) {
60 ; CHECK-NEXT: %t.1 = zext i32 %x to i64
61 ; CHECK-NEXT: %c.2 = icmp sgt i64 %t.1, 299
62 ; CHECK-NEXT: %c.4 = icmp slt i64 %t.1, 101
63 ; CHECK-NEXT: %res.1 = add i1 false, %c.2
64 ; CHECK-NEXT: %res.2 = add i1 %res.1, false
65 ; CHECK-NEXT: %res.3 = add i1 %res.2, %c.4
66 ; CHECK-NEXT: %t.2 = zext i32 %y to i64
67 ; CHECK-NEXT: %c.5 = icmp sgt i64 %t.2, 300
68 ; CHECK-NEXT: %c.6 = icmp sgt i64 %t.2, 299
69 ; CHECK-NEXT: %c.8 = icmp slt i64 %t.2, 1
70 ; CHECK-NEXT: %res.4 = add i1 %res.3, %c.5
71 ; CHECK-NEXT: %res.5 = add i1 %res.4, %c.6
72 ; CHECK-NEXT: %res.6 = add i1 %res.5, false
73 ; CHECK-NEXT: %res.7 = add i1 %res.6, %c.8
74 ; CHECK-NEXT: ret i1 %res.7
76 %t.1 = zext i32 %x to i64
77 %c.1 = icmp sgt i64 %t.1, 300
78 %c.2 = icmp sgt i64 %t.1, 299
79 %c.3 = icmp slt i64 %t.1, 100
80 %c.4 = icmp slt i64 %t.1, 101
81 %res.1 = add i1 %c.1, %c.2
82 %res.2 = add i1 %res.1, %c.3
83 %res.3 = add i1 %res.2, %c.4
84 %t.2 = zext i32 %y to i64
85 %c.5 = icmp sgt i64 %t.2, 300
86 %c.6 = icmp sgt i64 %t.2, 299
87 %c.7 = icmp slt i64 %t.2, 0
88 %c.8 = icmp slt i64 %t.2, 1
89 %res.4 = add i1 %res.3, %c.5
90 %res.5 = add i1 %res.4, %c.6
91 %res.6 = add i1 %res.5, %c.7
92 %res.7 = add i1 %res.6, %c.8
96 define i1 @caller.zext() {
97 ; CHECK-LABEL: define i1 @caller.zext() {
98 ; CHECK-NEXT: %call.1 = tail call i1 @f.zext(i32 100, i32 -120)
99 ; CHECK-NEXT: %call.2 = tail call i1 @f.zext(i32 300, i32 900)
100 ; CHECK-NEXT: %res = and i1 %call.1, %call.2
101 ; CHECK-NEXT: ret i1 %res
103 %call.1 = tail call i1 @f.zext(i32 100, i32 -120)
104 %call.2 = tail call i1 @f.zext(i32 300, i32 900)
105 %res = and i1 %call.1, %call.2
110 define internal i1 @f.sext(i32 %x, i32 %y) {
111 ; CHECK-LABEL: define internal i1 @f.sext(i32 %x, i32 %y) {
112 ; CHECK-NEXT: [[T_1:%.*]] = zext i32 %x to i64
113 ; CHECK-NEXT: %c.2 = icmp sgt i64 [[T_1]], 299
114 ; CHECK-NEXT: %c.4 = icmp slt i64 [[T_1]], 101
115 ; CHECK-NEXT: %res.1 = add i1 false, %c.2
116 ; CHECK-NEXT: %res.2 = add i1 %res.1, false
117 ; CHECK-NEXT: %res.3 = add i1 %res.2, %c.4
118 ; CHECK-NEXT: %t.2 = sext i32 %y to i64
119 ; CHECK-NEXT: %c.6 = icmp sgt i64 %t.2, 899
120 ; CHECK-NEXT: %c.8 = icmp slt i64 %t.2, -119
121 ; CHECK-NEXT: %res.4 = add i1 %res.3, false
122 ; CHECK-NEXT: %res.5 = add i1 %res.4, %c.6
123 ; CHECK-NEXT: %res.6 = add i1 %res.5, false
124 ; CHECK-NEXT: %res.7 = add i1 %res.6, %c.8
125 ; CHECK-NEXT: ret i1 %res.7
127 %t.1 = sext i32 %x to i64
128 %c.1 = icmp sgt i64 %t.1, 300
129 %c.2 = icmp sgt i64 %t.1, 299
130 %c.3 = icmp slt i64 %t.1, 100
131 %c.4 = icmp slt i64 %t.1, 101
132 %res.1 = add i1 %c.1, %c.2
133 %res.2 = add i1 %res.1, %c.3
134 %res.3 = add i1 %res.2, %c.4
135 %t.2 = sext i32 %y to i64
136 %c.5 = icmp sgt i64 %t.2, 900
137 %c.6 = icmp sgt i64 %t.2, 899
138 %c.7 = icmp slt i64 %t.2, -120
139 %c.8 = icmp slt i64 %t.2, -119
140 %res.4 = add i1 %res.3, %c.5
141 %res.5 = add i1 %res.4, %c.6
142 %res.6 = add i1 %res.5, %c.7
143 %res.7 = add i1 %res.6, %c.8
147 define i1 @caller.sext() {
148 ; CHECK-LABEL: define i1 @caller.sext() {
149 ; CHECK-NEXT: %call.1 = tail call i1 @f.sext(i32 100, i32 -120)
150 ; CHECK-NEXT: %call.2 = tail call i1 @f.sext(i32 300, i32 900)
151 ; CHECK-NEXT: %res = and i1 %call.1, %call.2
152 ; CHECK-NEXT: ret i1 %res
154 %call.1 = tail call i1 @f.sext(i32 100, i32 -120)
155 %call.2 = tail call i1 @f.sext(i32 300, i32 900)
156 %res = and i1 %call.1, %call.2
160 ; There's nothing we can do besides going to the full range or overdefined.
161 define internal i1 @f.fptosi(i32 %x) {
162 ; CHECK-LABEL: define internal i1 @f.fptosi(i32 %x) {
163 ; CHECK-NEXT: %to.double = sitofp i32 %x to double
164 ; CHECK-NEXT: %add = fadd double 0.000000e+00, %to.double
165 ; CHECK-NEXT: %to.i32 = fptosi double %add to i32
166 ; CHECK-NEXT: %c.1 = icmp sgt i32 %to.i32, 300
167 ; CHECK-NEXT: %c.2 = icmp sgt i32 %to.i32, 299
168 ; CHECK-NEXT: %c.3 = icmp slt i32 %to.i32, 100
169 ; CHECK-NEXT: %c.4 = icmp slt i32 %to.i32, 101
170 ; CHECK-NEXT: %res.1 = add i1 %c.1, %c.2
171 ; CHECK-NEXT: %res.2 = add i1 %res.1, %c.3
172 ; CHECK-NEXT: %res.3 = add i1 %res.2, %c.4
173 ; CHECK-NEXT: ret i1 %res.3
175 %to.double = sitofp i32 %x to double
176 %add = fadd double 0.000000e+00, %to.double
177 %to.i32 = fptosi double %add to i32
178 %c.1 = icmp sgt i32 %to.i32, 300
179 %c.2 = icmp sgt i32 %to.i32, 299
180 %c.3 = icmp slt i32 %to.i32, 100
181 %c.4 = icmp slt i32 %to.i32, 101
182 %res.1 = add i1 %c.1, %c.2
183 %res.2 = add i1 %res.1, %c.3
184 %res.3 = add i1 %res.2, %c.4
188 define i1 @caller.fptosi() {
189 ; CHECK-LABEL: define i1 @caller.fptosi() {
190 ; CHECK-NEXT: %call.1 = tail call i1 @f.fptosi(i32 100)
191 ; CHECK-NEXT: %call.2 = tail call i1 @f.fptosi(i32 300)
192 ; CHECK-NEXT: %res = and i1 %call.1, %call.2
193 ; CHECK-NEXT: ret i1 %res
195 %call.1 = tail call i1 @f.fptosi(i32 100)
196 %call.2 = tail call i1 @f.fptosi(i32 300)
197 %res = and i1 %call.1, %call.2
201 ; There's nothing we can do besides going to the full range or overdefined.
202 define internal i1 @f.fpext(i16 %x) {
203 ; CHECK-LABEL: define internal i1 @f.fpext(i16 %x) {
204 ; CHECK-NEXT: %to.float = sitofp i16 %x to float
205 ; CHECK-NEXT: %to.double = fpext float %to.float to double
206 ; CHECK-NEXT: %to.i64 = fptoui float %to.float to i64
207 ; CHECK-NEXT: %c.1 = icmp sgt i64 %to.i64, 300
208 ; CHECK-NEXT: %c.2 = icmp sgt i64 %to.i64, 299
209 ; CHECK-NEXT: %c.3 = icmp slt i64 %to.i64, 100
210 ; CHECK-NEXT: %c.4 = icmp slt i64 %to.i64, 101
211 ; CHECK-NEXT: %res.1 = add i1 %c.1, %c.2
212 ; CHECK-NEXT: %res.2 = add i1 %res.1, %c.3
213 ; CHECK-NEXT: %res.3 = add i1 %res.2, %c.4
214 ; CHECK-NEXT: ret i1 %res.3
216 %to.float = sitofp i16 %x to float
217 %to.double = fpext float %to.float to double
218 %to.i64= fptoui float %to.float to i64
219 %c.1 = icmp sgt i64 %to.i64, 300
220 %c.2 = icmp sgt i64 %to.i64, 299
221 %c.3 = icmp slt i64 %to.i64, 100
222 %c.4 = icmp slt i64 %to.i64, 101
223 %res.1 = add i1 %c.1, %c.2
224 %res.2 = add i1 %res.1, %c.3
225 %res.3 = add i1 %res.2, %c.4
229 ; There's nothing we can do besides going to the full range or overdefined.
230 define i1 @caller.fpext() {
231 ; CHECK-LABEL: define i1 @caller.fpext() {
232 ; CHECK-NEXT: %call.1 = tail call i1 @f.fpext(i16 100)
233 ; CHECK-NEXT: %call.2 = tail call i1 @f.fpext(i16 300)
234 ; CHECK-NEXT: %res = and i1 %call.1, %call.2
235 ; CHECK-NEXT: ret i1 %res
237 %call.1 = tail call i1 @f.fpext(i16 100)
238 %call.2 = tail call i1 @f.fpext(i16 300)
239 %res = and i1 %call.1, %call.2
243 ; There's nothing we can do besides going to the full range or overdefined.
244 define internal i1 @f.inttoptr.ptrtoint(i64 %x) {
245 ; CHECK-LABEL: define internal i1 @f.inttoptr.ptrtoint(i64 %x) {
246 ; CHECK-NEXT: %to.ptr = inttoptr i64 %x to i8*
247 ; CHECK-NEXT: %to.i64 = ptrtoint i8* %to.ptr to i64
248 ; CHECK-NEXT: %c.1 = icmp sgt i64 %to.i64, 300
249 ; CHECK-NEXT: %c.2 = icmp sgt i64 %to.i64, 299
250 ; CHECK-NEXT: %c.3 = icmp slt i64 %to.i64, 100
251 ; CHECK-NEXT: %c.4 = icmp slt i64 %to.i64, 101
252 ; CHECK-NEXT: %res.1 = add i1 %c.1, %c.2
253 ; CHECK-NEXT: %res.2 = add i1 %res.1, %c.3
254 ; CHECK-NEXT: %res.3 = add i1 %res.2, %c.4
255 ; CHECK-NEXT: ret i1 %res.3
257 %to.ptr = inttoptr i64 %x to i8*
258 %to.i64 = ptrtoint i8* %to.ptr to i64
259 %c.1 = icmp sgt i64 %to.i64, 300
260 %c.2 = icmp sgt i64 %to.i64, 299
261 %c.3 = icmp slt i64 %to.i64, 100
262 %c.4 = icmp slt i64 %to.i64, 101
263 %res.1 = add i1 %c.1, %c.2
264 %res.2 = add i1 %res.1, %c.3
265 %res.3 = add i1 %res.2, %c.4
269 define i1 @caller.inttoptr.ptrtoint() {
270 ; CHECK-LABEL: define i1 @caller.inttoptr.ptrtoint() {
271 ; CHECK-NEXT: %call.1 = tail call i1 @f.inttoptr.ptrtoint(i64 100)
272 ; CHECK-NEXT: %call.2 = tail call i1 @f.inttoptr.ptrtoint(i64 300)
273 ; CHECK-NEXT: %res = and i1 %call.1, %call.2
274 ; CHECK-NEXT: ret i1 %res
276 %call.1 = tail call i1 @f.inttoptr.ptrtoint(i64 100)
277 %call.2 = tail call i1 @f.inttoptr.ptrtoint(i64 300)
278 %res = and i1 %call.1, %call.2
282 ; Make sure we do not create constant ranges for int to fp casts.
283 define i1 @int_range_to_double_cast(i32 %a) {
284 ; CHECK-LABEL: define i1 @int_range_to_double_cast(i32 %a)
285 ; CHECK-NEXT: %r = and i32 %a, 255
286 ; CHECK-NEXT: %tmp4 = sitofp i32 %r to double
287 ; CHECK-NEXT: %tmp10 = fadd double 0.000000e+00, %tmp4
288 ; CHECK-NEXT: %tmp11 = fcmp olt double %tmp4, %tmp10
289 ; CHECK-NEXT: ret i1 %tmp11
292 %tmp4 = sitofp i32 %r to double
293 %tmp10 = fadd double 0.000000e+00, %tmp4
294 %tmp11 = fcmp olt double %tmp4, %tmp10
298 ; Make sure we do not use ranges to propagate info from vectors.
299 define i16 @vector_binop_and_cast() {
300 ; CHECK-LABEL: define i16 @vector_binop_and_cast(
302 ; CHECK-NEXT: %vecinit7 = insertelement <8 x i16> <i16 undef, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7>, i16 undef, i32 0
303 ; CHECK-NEXT: %rem = srem <8 x i16> <i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2>, %vecinit7
304 ; CHECK-NEXT: %0 = bitcast <8 x i16> %rem to i128
305 ; CHECK-NEXT: %1 = trunc i128 %0 to i16
306 ; CHECK-NEXT: ret i16 %1
308 %vecinit7 = insertelement <8 x i16> <i16 undef, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7>, i16 undef, i32 0
309 %rem = srem <8 x i16> <i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2>, %vecinit7
310 %0 = bitcast <8 x i16> %rem to i128
311 %1 = trunc i128 %0 to i16