1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
4 define i32 @fold(i32 %x) {
6 ; CHECK-NEXT: [[Y:%.*]] = freeze i32 [[X:%.*]]
7 ; CHECK-NEXT: ret i32 [[Y]]
14 define i32 @make_const() {
15 ; CHECK-LABEL: @make_const(
16 ; CHECK-NEXT: ret i32 10
22 define float @make_const2() {
23 ; CHECK-LABEL: @make_const2(
24 ; CHECK-NEXT: ret float 1.000000e+01
26 %x = freeze float 10.0
32 define ptr @make_const_glb() {
33 ; CHECK-LABEL: @make_const_glb(
34 ; CHECK-NEXT: ret ptr @glb
40 define ptr @make_const_fn() {
41 ; CHECK-LABEL: @make_const_fn(
42 ; CHECK-NEXT: ret ptr @make_const
44 %k = freeze ptr @make_const
48 define ptr @make_const_null() {
49 ; CHECK-LABEL: @make_const_null(
50 ; CHECK-NEXT: ret ptr null
56 define <2 x i32> @constvector() {
57 ; CHECK-LABEL: @constvector(
58 ; CHECK-NEXT: ret <2 x i32> <i32 0, i32 1>
60 %x = freeze <2 x i32> <i32 0, i32 1>
64 define <3 x i5> @constvector_weird() {
65 ; CHECK-LABEL: @constvector_weird(
66 ; CHECK-NEXT: ret <3 x i5> <i5 0, i5 1, i5 10>
68 %x = freeze <3 x i5> <i5 0, i5 1, i5 42>
72 define <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>
76 %x = freeze <2 x float> <float 0.0, float 1.0>
82 define <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]]
87 %x = freeze <2 x i32> <i32 0, i32 undef>
93 define <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]]
98 %x = freeze <3 x i5> <i5 0, i5 undef, i5 42>
104 define <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]]
109 %x = freeze <2 x float> <float 0.0, float undef>
113 @g = external global i16, align 1
114 @g2 = external global i16, align 1
116 define float @constant_expr() {
117 ; CHECK-LABEL: @constant_expr(
118 ; CHECK-NEXT: ret float bitcast (i32 ptrtoint (ptr @g to i32) to float)
120 %r = freeze float bitcast (i32 ptrtoint (ptr @g to i32) to float)
124 define ptr @constant_expr2() {
125 ; CHECK-LABEL: @constant_expr2(
126 ; CHECK-NEXT: ret ptr @g
132 define ptr @constant_expr3() {
133 ; CHECK-LABEL: @constant_expr3(
134 ; CHECK-NEXT: ret ptr getelementptr (i32, ptr @glb, i64 3)
136 %r = freeze ptr getelementptr (i32, ptr @glb, i64 3)
140 define i64 @ptrdiff() {
141 ; CHECK-LABEL: @ptrdiff(
142 ; CHECK-NEXT: ret i64 sub (i64 ptrtoint (ptr @g to i64), i64 ptrtoint (ptr @g2 to i64))
144 %i = ptrtoint ptr @g to i64
145 %i2 = ptrtoint ptr @g2 to i64
146 %diff = sub i64 %i, %i2
147 %r = freeze i64 %diff
153 define <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 (ptr @g to i31)>
156 ; CHECK-NEXT: ret <2 x i31> [[R]]
158 %r = freeze <2 x i31> <i31 34, i31 ptrtoint (ptr @g to i31)>
162 define void @alloca() {
163 ; CHECK-LABEL: @alloca(
164 ; CHECK-NEXT: [[P:%.*]] = alloca i8, align 1
165 ; CHECK-NEXT: call void @f3(ptr [[P]])
166 ; CHECK-NEXT: ret void
170 call void @f3(ptr %y)
176 ; CHECK-NEXT: [[P:%.*]] = alloca [4 x i8], align 1
177 ; CHECK-NEXT: [[Q:%.*]] = getelementptr [4 x i8], ptr [[P]], i32 0, i32 6
178 ; CHECK-NEXT: ret ptr [[Q]]
181 %q = getelementptr [4 x i8], ptr %p, i32 0, i32 6
186 define ptr @gep_noopt(i32 %arg) {
187 ; CHECK-LABEL: @gep_noopt(
188 ; CHECK-NEXT: [[Q:%.*]] = getelementptr [4 x i8], ptr null, i32 0, i32 [[ARG:%.*]]
189 ; CHECK-NEXT: [[Q2:%.*]] = freeze ptr [[Q]]
190 ; CHECK-NEXT: ret ptr [[Q2]]
192 %q = getelementptr [4 x i8], ptr null, i32 0, i32 %arg
197 define ptr @gep_inbounds() {
198 ; CHECK-LABEL: @gep_inbounds(
199 ; CHECK-NEXT: [[P:%.*]] = alloca [4 x i8], align 1
200 ; CHECK-NEXT: ret ptr [[P]]
207 define ptr @gep_inbounds_noopt(i32 %arg) {
208 ; CHECK-LABEL: @gep_inbounds_noopt(
209 ; CHECK-NEXT: [[P:%.*]] = alloca [4 x i8], align 1
210 ; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds [4 x i8], ptr [[P]], i32 0, i32 [[ARG:%.*]]
211 ; CHECK-NEXT: [[Q2:%.*]] = freeze ptr [[Q]]
212 ; CHECK-NEXT: ret ptr [[Q2]]
215 %q = getelementptr inbounds [4 x i8], ptr %p, i32 0, i32 %arg
220 define ptr @gep_inbounds_null() {
221 ; CHECK-LABEL: @gep_inbounds_null(
222 ; CHECK-NEXT: ret ptr null
228 define ptr @gep_inbounds_null_noopt(ptr %p) {
229 ; CHECK-LABEL: @gep_inbounds_null_noopt(
230 ; CHECK-NEXT: [[K:%.*]] = freeze ptr [[P:%.*]]
231 ; CHECK-NEXT: ret ptr [[K]]
237 define ptr @load_ptr(ptr %ptr) {
238 ; CHECK-LABEL: @load_ptr(
239 ; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[PTR:%.*]], align 1
240 ; CHECK-NEXT: call void @f4(i8 [[V]])
241 ; CHECK-NEXT: ret ptr [[PTR]]
243 %v = load i8, ptr %ptr
245 call void @f4(i8 %v) ; prevents %v from being DCEd
249 define ptr @store_ptr(ptr %ptr) {
250 ; CHECK-LABEL: @store_ptr(
251 ; CHECK-NEXT: store i8 0, ptr [[PTR:%.*]], align 1
252 ; CHECK-NEXT: ret ptr [[PTR]]
259 define ptr @call_noundef_ptr(ptr %ptr) {
260 ; CHECK-LABEL: @call_noundef_ptr(
261 ; CHECK-NEXT: call void @f3(ptr noundef [[PTR:%.*]])
262 ; CHECK-NEXT: ret ptr [[PTR]]
264 call void @f3(ptr noundef %ptr)
269 define ptr @invoke_noundef_ptr(ptr %ptr) personality i8 1 {
270 ; CHECK-LABEL: @invoke_noundef_ptr(
271 ; CHECK-NEXT: invoke void @f3(ptr noundef [[PTR:%.*]])
272 ; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[UNWIND:%.*]]
274 ; CHECK-NEXT: ret ptr [[PTR]]
276 ; CHECK-NEXT: [[TMP1:%.*]] = landingpad ptr
277 ; CHECK-NEXT: cleanup
278 ; CHECK-NEXT: resume ptr [[PTR]]
281 invoke void @f3(ptr noundef %ptr) to label %normal unwind label %unwind
285 landingpad ptr cleanup
289 define ptr @cmpxchg_ptr(ptr %ptr) {
290 ; CHECK-LABEL: @cmpxchg_ptr(
291 ; CHECK-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[PTR:%.*]], i8 1, i8 2 acq_rel monotonic, align 1
292 ; CHECK-NEXT: ret ptr [[PTR]]
294 cmpxchg ptr %ptr, i8 1, i8 2 acq_rel monotonic
299 define ptr @atomicrmw_ptr(ptr %ptr) {
300 ; CHECK-LABEL: @atomicrmw_ptr(
301 ; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[PTR:%.*]], i8 1 acquire, align 1
302 ; CHECK-NEXT: ret ptr [[PTR]]
304 atomicrmw add ptr %ptr, i8 1 acquire
309 define i1 @icmp(i32 %a, i32 %b) {
310 ; CHECK-LABEL: @icmp(
311 ; CHECK-NEXT: [[A_FR:%.*]] = freeze i32 [[A:%.*]]
312 ; CHECK-NEXT: [[B_FR:%.*]] = freeze i32 [[B:%.*]]
313 ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A_FR]], [[B_FR]]
314 ; CHECK-NEXT: ret i1 [[C]]
316 %a.fr = freeze i32 %a
317 %b.fr = freeze i32 %b
318 %c = icmp eq i32 %a.fr, %b.fr
323 define i1 @icmp_noopt(i32 %a, i32 %b) {
324 ; CHECK-LABEL: @icmp_noopt(
325 ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
326 ; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]
327 ; CHECK-NEXT: ret i1 [[C_FR]]
329 %c = icmp eq i32 %a, %b
334 define i1 @fcmp(float %x, float %y) {
335 ; CHECK-LABEL: @fcmp(
336 ; CHECK-NEXT: [[FX:%.*]] = freeze float [[X:%.*]]
337 ; CHECK-NEXT: [[FY:%.*]] = freeze float [[Y:%.*]]
338 ; CHECK-NEXT: [[C:%.*]] = fcmp oeq float [[FX]], [[FY]]
339 ; CHECK-NEXT: ret i1 [[C]]
341 %fx = freeze float %x
342 %fy = freeze float %y
343 %c = fcmp oeq float %fx, %fy
348 define i1 @fcmp_noopt(float %x, float %y) {
349 ; CHECK-LABEL: @fcmp_noopt(
350 ; CHECK-NEXT: [[FX:%.*]] = freeze float [[X:%.*]]
351 ; CHECK-NEXT: [[FY:%.*]] = freeze float [[Y:%.*]]
352 ; CHECK-NEXT: [[C:%.*]] = fcmp nnan oeq float [[FX]], [[FY]]
353 ; CHECK-NEXT: [[FC:%.*]] = freeze i1 [[C]]
354 ; CHECK-NEXT: ret i1 [[FC]]
356 %fx = freeze float %x
357 %fy = freeze float %y
358 %c = fcmp nnan oeq float %fx, %fy
363 define i1 @brcond(i1 %c, i1 %c2) {
364 ; CHECK-LABEL: @brcond(
365 ; CHECK-NEXT: br i1 [[C:%.*]], label [[A:%.*]], label [[B:%.*]]
367 ; CHECK-NEXT: br i1 [[C2:%.*]], label [[A2:%.*]], label [[B]]
369 ; CHECK-NEXT: ret i1 [[C]]
371 ; CHECK-NEXT: ret i1 [[C]]
373 br i1 %c, label %A, label %B
375 br i1 %c2, label %A2, label %B
384 define i32 @phi(i1 %cond, i1 %cond2, i32 %a0, i32 %a1) {
387 ; CHECK-NEXT: [[A0_FR:%.*]] = freeze i32 [[A0:%.*]]
388 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
390 ; CHECK-NEXT: [[A1_FR:%.*]] = freeze i32 [[A1:%.*]]
391 ; CHECK-NEXT: br i1 [[COND2:%.*]], label [[BB2]], label [[EXIT:%.*]]
393 ; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[A0_FR]], [[ENTRY:%.*]] ], [ [[A1_FR]], [[BB1]] ]
394 ; CHECK-NEXT: br label [[EXIT]]
396 ; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[A0_FR]], [[BB1]] ], [ [[PHI1]], [[BB2]] ]
397 ; CHECK-NEXT: ret i32 [[PHI2]]
400 %a0.fr = freeze i32 %a0
401 br i1 %cond, label %BB1, label %BB2
403 %a1.fr = freeze i32 %a1
404 br i1 %cond2, label %BB2, label %EXIT
406 %phi1 = phi i32 [%a0.fr, %ENTRY], [%a1.fr, %BB1]
409 %phi2 = phi i32 [%a0.fr, %BB1], [%phi1, %BB2]
410 %phi2.fr = freeze i32 %phi2
414 define i32 @phi_noopt(i1 %cond, i1 %cond2, i32 %a0, i32 %a1) {
415 ; CHECK-LABEL: @phi_noopt(
417 ; CHECK-NEXT: [[A0_FR:%.*]] = freeze i32 [[A0:%.*]]
418 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
420 ; CHECK-NEXT: br i1 [[COND2:%.*]], label [[BB2]], label [[EXIT:%.*]]
422 ; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[A0_FR]], [[ENTRY:%.*]] ], [ [[A1:%.*]], [[BB1]] ]
423 ; CHECK-NEXT: br label [[EXIT]]
425 ; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[A0_FR]], [[BB1]] ], [ [[PHI1]], [[BB2]] ]
426 ; CHECK-NEXT: [[PHI2_FR:%.*]] = freeze i32 [[PHI2]]
427 ; CHECK-NEXT: ret i32 [[PHI2_FR]]
430 %a0.fr = freeze i32 %a0
431 br i1 %cond, label %BB1, label %BB2
433 br i1 %cond2, label %BB2, label %EXIT
435 %phi1 = phi i32 [%a0.fr, %ENTRY], [%a1, %BB1]
438 %phi2 = phi i32 [%a0.fr, %BB1], [%phi1, %BB2]
439 %phi2.fr = freeze i32 %phi2
443 define i32 @brcond_switch(i32 %x) {
444 ; CHECK-LABEL: @brcond_switch(
445 ; CHECK-NEXT: switch i32 [[X:%.*]], label [[EXIT:%.*]] [
446 ; CHECK-NEXT: i32 0, label [[A:%.*]]
449 ; CHECK-NEXT: ret i32 [[X]]
451 ; CHECK-NEXT: ret i32 [[X]]
453 switch i32 %x, label %EXIT [ i32 0, label %A ]
462 declare i32 @any_num()
464 define i32 @brcond_call() {
465 ; CHECK-LABEL: @brcond_call(
466 ; CHECK-NEXT: [[X:%.*]] = call i32 @any_num()
467 ; CHECK-NEXT: switch i32 [[X]], label [[EXIT:%.*]] [
470 ; CHECK-NEXT: ret i32 [[X]]
472 %x = call i32 @any_num()
473 switch i32 %x, label %EXIT []
479 define i1 @brcond_noopt(i1 %c, i1 %c2) {
480 ; CHECK-LABEL: @brcond_noopt(
481 ; CHECK-NEXT: [[F:%.*]] = freeze i1 [[C:%.*]]
482 ; CHECK-NEXT: call void @f1(i1 [[F]])
483 ; CHECK-NEXT: call void @f2()
484 ; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]]
486 ; CHECK-NEXT: ret i1 false
488 ; CHECK-NEXT: ret i1 true
491 call void @f1(i1 %f) ; cannot optimize i1 %f to %c
492 call void @f2() ; .. because if f2() exits, `br %c` cannot be reached
493 br i1 %c, label %A, label %B
501 declare void @f3(ptr)