1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instsimplify -S | FileCheck %s
3
4define i32 @fold(i32 %x) {
5; CHECK-LABEL: @fold(
6; CHECK-NEXT:    [[Y:%.*]] = freeze i32 [[X:%.*]]
7; CHECK-NEXT:    ret i32 [[Y]]
8;
9  %y = freeze i32 %x
10  %z = freeze i32 %y
11  ret i32 %z
12}
13
14define i32 @make_const() {
15; CHECK-LABEL: @make_const(
16; CHECK-NEXT:    ret i32 10
17;
18  %x = freeze i32 10
19  ret i32 %x
20}
21
22define float @make_const2() {
23; CHECK-LABEL: @make_const2(
24; CHECK-NEXT:    ret float 1.000000e+01
25;
26  %x = freeze float 10.0
27  ret float %x
28}
29
30@glb = constant i32 0
31
32define i32* @make_const_glb() {
33; CHECK-LABEL: @make_const_glb(
34; CHECK-NEXT:    ret i32* @glb
35;
36  %k = freeze i32* @glb
37  ret i32* %k
38}
39
40define i32()* @make_const_fn() {
41; CHECK-LABEL: @make_const_fn(
42; CHECK-NEXT:    ret i32 ()* @make_const
43;
44  %k = freeze i32()* @make_const
45  ret i32()* %k
46}
47
48define i32* @make_const_null() {
49; CHECK-LABEL: @make_const_null(
50; CHECK-NEXT:    ret i32* null
51;
52  %k = freeze i32* null
53  ret i32* %k
54}
55
56define <2 x i32> @constvector() {
57; CHECK-LABEL: @constvector(
58; CHECK-NEXT:    ret <2 x i32> <i32 0, i32 1>
59;
60  %x = freeze <2 x i32> <i32 0, i32 1>
61  ret <2 x i32> %x
62}
63
64define <3 x i5> @constvector_weird() {
65; CHECK-LABEL: @constvector_weird(
66; CHECK-NEXT:    ret <3 x i5> <i5 0, i5 1, i5 10>
67;
68  %x = freeze <3 x i5> <i5 0, i5 1, i5 42>
69  ret <3 x i5> %x
70}
71
72define <2 x float> @constvector_FP() {
73; CHECK-LABEL: @constvector_FP(
74; CHECK-NEXT:    ret <2 x float> <float 0.000000e+00, float 1.000000e+00>
75;
76  %x = freeze <2 x float> <float 0.0, float 1.0>
77  ret <2 x float> %x
78}
79
80; Negative test
81
82define <2 x i32> @constvector_noopt() {
83; CHECK-LABEL: @constvector_noopt(
84; CHECK-NEXT:    [[X:%.*]] = freeze <2 x i32> <i32 0, i32 undef>
85; CHECK-NEXT:    ret <2 x i32> [[X]]
86;
87  %x = freeze <2 x i32> <i32 0, i32 undef>
88  ret <2 x i32> %x
89}
90
91; Negative test
92
93define <3 x i5> @constvector_weird_noopt() {
94; CHECK-LABEL: @constvector_weird_noopt(
95; CHECK-NEXT:    [[X:%.*]] = freeze <3 x i5> <i5 0, i5 undef, i5 10>
96; CHECK-NEXT:    ret <3 x i5> [[X]]
97;
98  %x = freeze <3 x i5> <i5 0, i5 undef, i5 42>
99  ret <3 x i5> %x
100}
101
102; Negative test
103
104define <2 x float> @constvector_FP_noopt() {
105; CHECK-LABEL: @constvector_FP_noopt(
106; CHECK-NEXT:    [[X:%.*]] = freeze <2 x float> <float 0.000000e+00, float undef>
107; CHECK-NEXT:    ret <2 x float> [[X]]
108;
109  %x = freeze <2 x float> <float 0.0, float undef>
110  ret <2 x float> %x
111}
112
113@g = external global i16, align 1
114@g2 = external global i16, align 1
115
116define float @constant_expr() {
117; CHECK-LABEL: @constant_expr(
118; CHECK-NEXT:    ret float bitcast (i32 ptrtoint (i16* @g to i32) to float)
119;
120  %r = freeze float bitcast (i32 ptrtoint (i16* @g to i32) to float)
121  ret float %r
122}
123
124define i8* @constant_expr2() {
125; CHECK-LABEL: @constant_expr2(
126; CHECK-NEXT:    ret i8* bitcast (i16* @g to i8*)
127;
128  %r = freeze i8* bitcast (i16* @g to i8*)
129  ret i8* %r
130}
131
132define i32* @constant_expr3() {
133; CHECK-LABEL: @constant_expr3(
134; CHECK-NEXT:    ret i32* getelementptr (i32, i32* @glb, i64 3)
135;
136  %r = freeze i32* getelementptr (i32, i32* @glb, i64 3)
137  ret i32* %r
138}
139
140define i64 @ptrdiff() {
141; CHECK-LABEL: @ptrdiff(
142; CHECK-NEXT:    ret i64 sub (i64 ptrtoint (i16* @g to i64), i64 ptrtoint (i16* @g2 to i64))
143;
144  %i = ptrtoint i16* @g to i64
145  %i2 = ptrtoint i16* @g2 to i64
146  %diff = sub i64 %i, %i2
147  %r = freeze i64 %diff
148  ret i64 %r
149}
150
151; Negative test
152
153define <2 x i31> @vector_element_constant_expr() {
154; CHECK-LABEL: @vector_element_constant_expr(
155; CHECK-NEXT:    [[R:%.*]] = freeze <2 x i31> <i31 34, i31 ptrtoint (i16* @g to i31)>
156; CHECK-NEXT:    ret <2 x i31> [[R]]
157;
158  %r = freeze <2 x i31> <i31 34, i31 ptrtoint (i16* @g to i31)>
159  ret <2 x i31> %r
160}
161
162define void @alloca() {
163; CHECK-LABEL: @alloca(
164; CHECK-NEXT:    [[P:%.*]] = alloca i8, align 1
165; CHECK-NEXT:    call void @f3(i8* [[P]])
166; CHECK-NEXT:    ret void
167;
168  %p = alloca i8
169  %y = freeze i8* %p
170  call void @f3(i8* %y)
171  ret void
172}
173
174define i8* @gep() {
175; CHECK-LABEL: @gep(
176; CHECK-NEXT:    [[P:%.*]] = alloca [4 x i8], align 1
177; CHECK-NEXT:    [[Q:%.*]] = getelementptr [4 x i8], [4 x i8]* [[P]], i32 0, i32 6
178; CHECK-NEXT:    ret i8* [[Q]]
179;
180  %p = alloca [4 x i8]
181  %q = getelementptr [4 x i8], [4 x i8]* %p, i32 0, i32 6
182  %q2 = freeze i8* %q
183  ret i8* %q2
184}
185
186define i8* @gep_noopt(i32 %arg) {
187; CHECK-LABEL: @gep_noopt(
188; CHECK-NEXT:    [[Q:%.*]] = getelementptr [4 x i8], [4 x i8]* null, i32 0, i32 [[ARG:%.*]]
189; CHECK-NEXT:    [[Q2:%.*]] = freeze i8* [[Q]]
190; CHECK-NEXT:    ret i8* [[Q2]]
191;
192  %q = getelementptr [4 x i8], [4 x i8]* null, i32 0, i32 %arg
193  %q2 = freeze i8* %q
194  ret i8* %q2
195}
196
197define i8* @gep_inbounds() {
198; CHECK-LABEL: @gep_inbounds(
199; CHECK-NEXT:    [[P:%.*]] = alloca [4 x i8], align 1
200; CHECK-NEXT:    [[Q:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[P]], i32 0, i32 0
201; CHECK-NEXT:    ret i8* [[Q]]
202;
203  %p = alloca [4 x i8]
204  %q = getelementptr inbounds [4 x i8], [4 x i8]* %p, i32 0, i32 0
205  %q2 = freeze i8* %q
206  ret i8* %q2
207}
208
209define i8* @gep_inbounds_noopt(i32 %arg) {
210; CHECK-LABEL: @gep_inbounds_noopt(
211; CHECK-NEXT:    [[P:%.*]] = alloca [4 x i8], align 1
212; CHECK-NEXT:    [[Q:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[P]], i32 0, i32 [[ARG:%.*]]
213; CHECK-NEXT:    [[Q2:%.*]] = freeze i8* [[Q]]
214; CHECK-NEXT:    ret i8* [[Q2]]
215;
216  %p = alloca [4 x i8]
217  %q = getelementptr inbounds [4 x i8], [4 x i8]* %p, i32 0, i32 %arg
218  %q2 = freeze i8* %q
219  ret i8* %q2
220}
221
222define i32* @gep_inbounds_null() {
223; CHECK-LABEL: @gep_inbounds_null(
224; CHECK-NEXT:    ret i32* null
225;
226  %p = getelementptr inbounds i32, i32* null, i32 0
227  %k = freeze i32* %p
228  ret i32* %k
229}
230
231define i32* @gep_inbounds_null_noopt(i32* %p) {
232; CHECK-LABEL: @gep_inbounds_null_noopt(
233; CHECK-NEXT:    [[K:%.*]] = freeze i32* [[P:%.*]]
234; CHECK-NEXT:    ret i32* [[K]]
235;
236  %q = getelementptr inbounds i32, i32* %p, i32 0
237  %k = freeze i32* %q
238  ret i32* %k
239}
240
241define i8* @load_ptr(i8* %ptr) {
242; CHECK-LABEL: @load_ptr(
243; CHECK-NEXT:    [[V:%.*]] = load i8, i8* [[PTR:%.*]], align 1
244; CHECK-NEXT:    call void @f4(i8 [[V]])
245; CHECK-NEXT:    ret i8* [[PTR]]
246;
247  %v = load i8, i8* %ptr
248  %q = freeze i8* %ptr
249  call void @f4(i8 %v) ; prevents %v from being DCEd
250  ret i8* %q
251}
252
253define i8* @store_ptr(i8* %ptr) {
254; CHECK-LABEL: @store_ptr(
255; CHECK-NEXT:    store i8 0, i8* [[PTR:%.*]], align 1
256; CHECK-NEXT:    ret i8* [[PTR]]
257;
258  store i8 0, i8* %ptr
259  %q = freeze i8* %ptr
260  ret i8* %q
261}
262
263define i8* @call_noundef_ptr(i8* %ptr) {
264; CHECK-LABEL: @call_noundef_ptr(
265; CHECK-NEXT:    call void @f3(i8* noundef [[PTR:%.*]])
266; CHECK-NEXT:    ret i8* [[PTR]]
267;
268  call void @f3(i8* noundef %ptr)
269  %q = freeze i8* %ptr
270  ret i8* %q
271}
272
273define i8* @invoke_noundef_ptr(i8* %ptr) personality i8 1 {
274; CHECK-LABEL: @invoke_noundef_ptr(
275; CHECK-NEXT:    invoke void @f3(i8* noundef [[PTR:%.*]])
276; CHECK-NEXT:    to label [[NORMAL:%.*]] unwind label [[UNWIND:%.*]]
277; CHECK:       normal:
278; CHECK-NEXT:    ret i8* [[PTR]]
279; CHECK:       unwind:
280; CHECK-NEXT:    [[TMP1:%.*]] = landingpad i8*
281; CHECK-NEXT:    cleanup
282; CHECK-NEXT:    resume i8* [[PTR]]
283;
284  %q = freeze i8* %ptr
285  invoke void @f3(i8* noundef %ptr) to label %normal unwind label %unwind
286normal:
287  ret i8* %q
288unwind:
289  landingpad i8* cleanup
290  resume i8* %q
291}
292
293define i8* @cmpxchg_ptr(i8* %ptr) {
294; CHECK-LABEL: @cmpxchg_ptr(
295; CHECK-NEXT:    [[TMP1:%.*]] = cmpxchg i8* [[PTR:%.*]], i8 1, i8 2 acq_rel monotonic, align 1
296; CHECK-NEXT:    ret i8* [[PTR]]
297;
298  cmpxchg i8* %ptr, i8 1, i8 2 acq_rel monotonic
299  %q = freeze i8* %ptr
300  ret i8* %q
301}
302
303define i8* @atomicrmw_ptr(i8* %ptr) {
304; CHECK-LABEL: @atomicrmw_ptr(
305; CHECK-NEXT:    [[TMP1:%.*]] = atomicrmw add i8* [[PTR:%.*]], i8 1 acquire, align 1
306; CHECK-NEXT:    ret i8* [[PTR]]
307;
308  atomicrmw add i8* %ptr, i8 1 acquire
309  %q = freeze i8* %ptr
310  ret i8* %q
311}
312
313define i1 @icmp(i32 %a, i32 %b) {
314; CHECK-LABEL: @icmp(
315; CHECK-NEXT:    [[A_FR:%.*]] = freeze i32 [[A:%.*]]
316; CHECK-NEXT:    [[B_FR:%.*]] = freeze i32 [[B:%.*]]
317; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[A_FR]], [[B_FR]]
318; CHECK-NEXT:    ret i1 [[C]]
319;
320  %a.fr = freeze i32 %a
321  %b.fr = freeze i32 %b
322  %c = icmp eq i32 %a.fr, %b.fr
323  %c.fr = freeze i1 %c
324  ret i1 %c.fr
325}
326
327define i1 @icmp_noopt(i32 %a, i32 %b) {
328; CHECK-LABEL: @icmp_noopt(
329; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
330; CHECK-NEXT:    [[C_FR:%.*]] = freeze i1 [[C]]
331; CHECK-NEXT:    ret i1 [[C_FR]]
332;
333  %c = icmp eq i32 %a, %b
334  %c.fr = freeze i1 %c
335  ret i1 %c.fr
336}
337
338define i1 @fcmp(float %x, float %y) {
339; CHECK-LABEL: @fcmp(
340; CHECK-NEXT:    [[FX:%.*]] = freeze float [[X:%.*]]
341; CHECK-NEXT:    [[FY:%.*]] = freeze float [[Y:%.*]]
342; CHECK-NEXT:    [[C:%.*]] = fcmp oeq float [[FX]], [[FY]]
343; CHECK-NEXT:    ret i1 [[C]]
344;
345  %fx = freeze float %x
346  %fy = freeze float %y
347  %c = fcmp oeq float %fx, %fy
348  %fc = freeze i1 %c
349  ret i1 %fc
350}
351
352define i1 @fcmp_noopt(float %x, float %y) {
353; CHECK-LABEL: @fcmp_noopt(
354; CHECK-NEXT:    [[FX:%.*]] = freeze float [[X:%.*]]
355; CHECK-NEXT:    [[FY:%.*]] = freeze float [[Y:%.*]]
356; CHECK-NEXT:    [[C:%.*]] = fcmp nnan oeq float [[FX]], [[FY]]
357; CHECK-NEXT:    [[FC:%.*]] = freeze i1 [[C]]
358; CHECK-NEXT:    ret i1 [[FC]]
359;
360  %fx = freeze float %x
361  %fy = freeze float %y
362  %c = fcmp nnan oeq float %fx, %fy
363  %fc = freeze i1 %c
364  ret i1 %fc
365}
366
367define i1 @brcond(i1 %c, i1 %c2) {
368; CHECK-LABEL: @brcond(
369; CHECK-NEXT:    br i1 [[C:%.*]], label [[A:%.*]], label [[B:%.*]]
370; CHECK:       A:
371; CHECK-NEXT:    br i1 [[C2:%.*]], label [[A2:%.*]], label [[B]]
372; CHECK:       A2:
373; CHECK-NEXT:    ret i1 [[C]]
374; CHECK:       B:
375; CHECK-NEXT:    ret i1 [[C]]
376;
377  br i1 %c, label %A, label %B
378A:
379  br i1 %c2, label %A2, label %B
380A2:
381  %f1 = freeze i1 %c
382  ret i1 %f1
383B:
384  %f2 = freeze i1 %c
385  ret i1 %f2
386}
387
388define i32 @phi(i1 %cond, i1 %cond2, i32 %a0, i32 %a1) {
389; CHECK-LABEL: @phi(
390; CHECK-NEXT:  ENTRY:
391; CHECK-NEXT:    [[A0_FR:%.*]] = freeze i32 [[A0:%.*]]
392; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
393; CHECK:       BB1:
394; CHECK-NEXT:    [[A1_FR:%.*]] = freeze i32 [[A1:%.*]]
395; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[BB2]], label [[EXIT:%.*]]
396; CHECK:       BB2:
397; CHECK-NEXT:    [[PHI1:%.*]] = phi i32 [ [[A0_FR]], [[ENTRY:%.*]] ], [ [[A1_FR]], [[BB1]] ]
398; CHECK-NEXT:    br label [[EXIT]]
399; CHECK:       EXIT:
400; CHECK-NEXT:    [[PHI2:%.*]] = phi i32 [ [[A0_FR]], [[BB1]] ], [ [[PHI1]], [[BB2]] ]
401; CHECK-NEXT:    ret i32 [[PHI2]]
402;
403ENTRY:
404  %a0.fr = freeze i32 %a0
405  br i1 %cond, label %BB1, label %BB2
406BB1:
407  %a1.fr = freeze i32 %a1
408  br i1 %cond2, label %BB2, label %EXIT
409BB2:
410  %phi1 = phi i32 [%a0.fr, %ENTRY], [%a1.fr, %BB1]
411  br label %EXIT
412EXIT:
413  %phi2 = phi i32 [%a0.fr, %BB1], [%phi1, %BB2]
414  %phi2.fr = freeze i32 %phi2
415  ret i32 %phi2.fr
416}
417
418define i32 @phi_noopt(i1 %cond, i1 %cond2, i32 %a0, i32 %a1) {
419; CHECK-LABEL: @phi_noopt(
420; CHECK-NEXT:  ENTRY:
421; CHECK-NEXT:    [[A0_FR:%.*]] = freeze i32 [[A0:%.*]]
422; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
423; CHECK:       BB1:
424; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[BB2]], label [[EXIT:%.*]]
425; CHECK:       BB2:
426; CHECK-NEXT:    [[PHI1:%.*]] = phi i32 [ [[A0_FR]], [[ENTRY:%.*]] ], [ [[A1:%.*]], [[BB1]] ]
427; CHECK-NEXT:    br label [[EXIT]]
428; CHECK:       EXIT:
429; CHECK-NEXT:    [[PHI2:%.*]] = phi i32 [ [[A0_FR]], [[BB1]] ], [ [[PHI1]], [[BB2]] ]
430; CHECK-NEXT:    [[PHI2_FR:%.*]] = freeze i32 [[PHI2]]
431; CHECK-NEXT:    ret i32 [[PHI2_FR]]
432;
433ENTRY:
434  %a0.fr = freeze i32 %a0
435  br i1 %cond, label %BB1, label %BB2
436BB1:
437  br i1 %cond2, label %BB2, label %EXIT
438BB2:
439  %phi1 = phi i32 [%a0.fr, %ENTRY], [%a1, %BB1]
440  br label %EXIT
441EXIT:
442  %phi2 = phi i32 [%a0.fr, %BB1], [%phi1, %BB2]
443  %phi2.fr = freeze i32 %phi2
444  ret i32 %phi2.fr
445}
446
447define i32 @brcond_switch(i32 %x) {
448; CHECK-LABEL: @brcond_switch(
449; CHECK-NEXT:    switch i32 [[X:%.*]], label [[EXIT:%.*]] [
450; CHECK-NEXT:    i32 0, label [[A:%.*]]
451; CHECK-NEXT:    ]
452; CHECK:       A:
453; CHECK-NEXT:    ret i32 [[X]]
454; CHECK:       EXIT:
455; CHECK-NEXT:    ret i32 [[X]]
456;
457  switch i32 %x, label %EXIT [ i32 0, label %A ]
458A:
459  %fr1 = freeze i32 %x
460  ret i32 %fr1
461EXIT:
462  %fr2 = freeze i32 %x
463  ret i32 %fr2
464}
465
466declare i32 @any_num()
467
468define i32 @brcond_call() {
469; CHECK-LABEL: @brcond_call(
470; CHECK-NEXT:    [[X:%.*]] = call i32 @any_num()
471; CHECK-NEXT:    switch i32 [[X]], label [[EXIT:%.*]] [
472; CHECK-NEXT:    ]
473; CHECK:       EXIT:
474; CHECK-NEXT:    ret i32 [[X]]
475;
476  %x = call i32 @any_num()
477  switch i32 %x, label %EXIT []
478EXIT:
479  %y = freeze i32 %x
480  ret i32 %y
481}
482
483define i1 @brcond_noopt(i1 %c, i1 %c2) {
484; CHECK-LABEL: @brcond_noopt(
485; CHECK-NEXT:    [[F:%.*]] = freeze i1 [[C:%.*]]
486; CHECK-NEXT:    call void @f1(i1 [[F]])
487; CHECK-NEXT:    call void @f2()
488; CHECK-NEXT:    br i1 [[C]], label [[A:%.*]], label [[B:%.*]]
489; CHECK:       A:
490; CHECK-NEXT:    ret i1 false
491; CHECK:       B:
492; CHECK-NEXT:    ret i1 true
493;
494  %f = freeze i1 %c
495  call void @f1(i1 %f) ; cannot optimize i1 %f to %c
496  call void @f2()      ; .. because if f2() exits, `br %c` cannot be reached
497  br i1 %c, label %A, label %B
498A:
499  ret i1 0
500B:
501  ret i1 1
502}
503declare void @f1(i1)
504declare void @f2()
505declare void @f3(i8*)
506declare void @f4(i8)
507