1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
2 ; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
4 define void @test1(i1 %C, ptr %BP) {
7 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[C:%.*]], true
8 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
12 br i1 %C, label %T, label %F
20 define void @test2() personality ptr @__gxx_personality_v0 {
21 ; CHECK-LABEL: @test2(
23 ; CHECK-NEXT: call void @test2() #[[ATTR3:[0-9]+]]
24 ; CHECK-NEXT: ret void
28 to label %N unwind label %U
30 %res = landingpad { ptr }
37 declare i32 @__gxx_personality_v0(...)
39 define i32 @test3(i32 %v) {
40 ; CHECK-LABEL: @test3(
42 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[V:%.*]], 2
43 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[COND]], i32 2, i32 1
44 ; CHECK-NEXT: ret i32 [[SPEC_SELECT]]
47 switch i32 %v, label %default [
60 ;; We can either convert the following control-flow to a select or remove the
61 ;; unreachable control flow because of the undef store of null. Make sure we do
64 define void @test5(i1 %cond, ptr %ptr) {
65 ; CHECK-LABEL: @test5(
67 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[COND:%.*]], true
68 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
69 ; CHECK-NEXT: store i8 2, ptr [[PTR:%.*]], align 8
70 ; CHECK-NEXT: ret void
73 br i1 %cond, label %bb1, label %bb3
82 %ptr.2 = phi ptr [ %ptr, %bb3 ], [ null, %bb1 ]
83 store i8 2, ptr %ptr.2, align 8
87 declare void @llvm.assume(i1)
88 declare i1 @llvm.type.test(ptr, metadata) nounwind readnone
90 ;; Same as the above test but make sure the unreachable control flow is still
91 ;; removed in the presence of a type test / assume sequence.
93 define void @test5_type_test_assume(i1 %cond, ptr %ptr, ptr %vtable) {
94 ; CHECK-LABEL: @test5_type_test_assume(
96 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[COND:%.*]], true
97 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
98 ; CHECK-NEXT: [[P:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE:%.*]], metadata !"foo")
99 ; CHECK-NEXT: tail call void @llvm.assume(i1 [[P]])
100 ; CHECK-NEXT: store i8 2, ptr [[PTR:%.*]], align 8
101 ; CHECK-NEXT: ret void
104 br i1 %cond, label %bb1, label %bb3
113 %ptr.2 = phi ptr [ %ptr, %bb3 ], [ null, %bb1 ]
114 %p = call i1 @llvm.type.test(ptr %vtable, metadata !"foo")
115 tail call void @llvm.assume(i1 %p)
116 store i8 2, ptr %ptr.2, align 8
120 define void @test5_no_null_opt(i1 %cond, ptr %ptr) #0 {
121 ; CHECK-LABEL: @test5_no_null_opt(
123 ; CHECK-NEXT: [[DOTPTR:%.*]] = select i1 [[COND:%.*]], ptr null, ptr [[PTR:%.*]]
124 ; CHECK-NEXT: store i8 2, ptr [[DOTPTR]], align 8
125 ; CHECK-NEXT: ret void
128 br i1 %cond, label %bb1, label %bb3
137 %ptr.2 = phi ptr [ %ptr, %bb3 ], [ null, %bb1 ]
138 store i8 2, ptr %ptr.2, align 8
142 define void @test6(i1 %cond, ptr %ptr) {
143 ; CHECK-LABEL: @test6(
145 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[COND:%.*]], true
146 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
147 ; CHECK-NEXT: store i8 2, ptr [[PTR:%.*]], align 8
148 ; CHECK-NEXT: ret void
151 br i1 %cond, label %bb1, label %bb2
157 %ptr.2 = phi ptr [ %ptr, %entry ], [ null, %bb1 ]
158 store i8 2, ptr %ptr.2, align 8
162 define void @test6_no_null_opt(i1 %cond, ptr %ptr) #0 {
163 ; CHECK-LABEL: @test6_no_null_opt(
165 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[COND:%.*]], ptr null, ptr [[PTR:%.*]]
166 ; CHECK-NEXT: store i8 2, ptr [[SPEC_SELECT]], align 8
167 ; CHECK-NEXT: ret void
170 br i1 %cond, label %bb1, label %bb2
176 %ptr.2 = phi ptr [ %ptr, %entry ], [ null, %bb1 ]
177 store i8 2, ptr %ptr.2, align 8
182 define i32 @test7(i1 %X) {
183 ; CHECK-LABEL: @test7(
185 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true
186 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
187 ; CHECK-NEXT: ret i32 0
190 br i1 %X, label %if, label %else
197 %phi = phi i32 [ 0, %entry ], [ 1, %if ]
201 define void @test8(i1 %X, ptr %Y) {
202 ; CHECK-LABEL: @test8(
204 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true
205 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
206 ; CHECK-NEXT: call void [[Y:%.*]]()
207 ; CHECK-NEXT: ret void
210 br i1 %X, label %if, label %else
216 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
221 define void @test8_no_null_opt(i1 %X, ptr %Y) #0 {
222 ; CHECK-LABEL: @test8_no_null_opt(
224 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[X:%.*]], ptr null, ptr [[Y:%.*]]
225 ; CHECK-NEXT: call void [[SPEC_SELECT]]()
226 ; CHECK-NEXT: ret void
229 br i1 %X, label %if, label %else
235 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
240 declare ptr @fn_nonnull_noundef_arg(ptr nonnull noundef %p)
241 declare ptr @fn_nonnull_deref_arg(ptr nonnull dereferenceable(4) %p)
242 declare ptr @fn_nonnull_deref_or_null_arg(ptr nonnull dereferenceable_or_null(4) %p)
243 declare ptr @fn_nonnull_arg(ptr nonnull %p)
244 declare ptr @fn_noundef_arg(ptr noundef %p)
246 define void @test9(i1 %X, ptr %Y) {
247 ; CHECK-LABEL: @test9(
249 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true
250 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
251 ; CHECK-NEXT: [[TMP1:%.*]] = call ptr @fn_nonnull_noundef_arg(ptr [[Y:%.*]])
252 ; CHECK-NEXT: ret void
255 br i1 %X, label %if, label %else
261 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
262 call ptr @fn_nonnull_noundef_arg(ptr %phi)
266 ; Optimizing this code should produce assume.
267 define void @test9_deref(i1 %X, ptr %Y) {
268 ; CHECK-LABEL: @test9_deref(
270 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true
271 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
272 ; CHECK-NEXT: [[TMP1:%.*]] = call ptr @fn_nonnull_deref_arg(ptr [[Y:%.*]])
273 ; CHECK-NEXT: ret void
276 br i1 %X, label %if, label %else
282 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
283 call ptr @fn_nonnull_deref_arg(ptr %phi)
287 ; Optimizing this code should produce assume.
288 define void @test9_deref_or_null(i1 %X, ptr %Y) {
289 ; CHECK-LABEL: @test9_deref_or_null(
291 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true
292 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
293 ; CHECK-NEXT: [[TMP1:%.*]] = call ptr @fn_nonnull_deref_or_null_arg(ptr [[Y:%.*]])
294 ; CHECK-NEXT: ret void
297 br i1 %X, label %if, label %else
303 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
304 call ptr @fn_nonnull_deref_or_null_arg(ptr %phi)
308 define void @test9_undef(i1 %X, ptr %Y) {
309 ; CHECK-LABEL: @test9_undef(
311 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @fn_noundef_arg(ptr [[Y:%.*]])
312 ; CHECK-NEXT: ret void
315 br i1 %X, label %if, label %else
321 %phi = phi ptr [ %Y, %entry ], [ undef, %if ]
322 call ptr @fn_noundef_arg(ptr %phi)
326 define void @test9_undef_null_defined(i1 %X, ptr %Y) #0 {
327 ; CHECK-LABEL: @test9_undef_null_defined(
329 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @fn_noundef_arg(ptr [[Y:%.*]])
330 ; CHECK-NEXT: ret void
333 br i1 %X, label %if, label %else
339 %phi = phi ptr [ %Y, %entry ], [ undef, %if ]
340 call ptr @fn_noundef_arg(ptr %phi)
344 define void @test9_null_callsite(i1 %X, ptr %Y) {
345 ; CHECK-LABEL: @test9_null_callsite(
347 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true
348 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
349 ; CHECK-NEXT: [[TMP1:%.*]] = call ptr @fn_nonnull_arg(ptr noundef nonnull [[Y:%.*]])
350 ; CHECK-NEXT: ret void
353 br i1 %X, label %if, label %else
359 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
360 call ptr @fn_nonnull_arg(ptr nonnull noundef %phi)
364 define void @test9_gep_mismatch(i1 %X, ptr %Y, ptr %P) {
365 ; CHECK-LABEL: @test9_gep_mismatch(
367 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[X:%.*]], ptr null, ptr [[Y:%.*]]
368 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @fn_nonnull_noundef_arg(ptr [[P:%.*]])
369 ; CHECK-NEXT: ret void
372 br i1 %X, label %if, label %else
378 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
379 call ptr @fn_nonnull_noundef_arg(ptr %P)
383 define void @test9_gep_zero(i1 %X, ptr %Y) {
384 ; CHECK-LABEL: @test9_gep_zero(
386 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true
387 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
388 ; CHECK-NEXT: [[TMP1:%.*]] = call ptr @fn_nonnull_noundef_arg(ptr [[Y:%.*]])
389 ; CHECK-NEXT: ret void
392 br i1 %X, label %if, label %else
398 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
399 call ptr @fn_nonnull_noundef_arg(ptr %phi)
403 define void @test9_gep_bitcast(i1 %X, ptr %Y) {
404 ; CHECK-LABEL: @test9_gep_bitcast(
406 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true
407 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
408 ; CHECK-NEXT: [[TMP1:%.*]] = call ptr @fn_nonnull_noundef_arg(ptr [[Y:%.*]])
409 ; CHECK-NEXT: ret void
412 br i1 %X, label %if, label %else
418 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
419 call ptr @fn_nonnull_noundef_arg(ptr %phi)
423 define void @test9_gep_nonzero(i1 %X, ptr %Y) {
424 ; CHECK-LABEL: @test9_gep_nonzero(
426 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[X:%.*]], ptr null, ptr [[Y:%.*]]
427 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[SPEC_SELECT]], i64 12
428 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @fn_nonnull_noundef_arg(ptr [[GEP]])
429 ; CHECK-NEXT: ret void
432 br i1 %X, label %if, label %else
438 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
439 %gep = getelementptr i8, ptr %phi, i64 12
440 call ptr @fn_nonnull_noundef_arg(ptr %gep)
444 define void @test9_gep_inbounds_nonzero(i1 %X, ptr %Y) {
445 ; CHECK-LABEL: @test9_gep_inbounds_nonzero(
447 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[X:%.*]], ptr null, ptr [[Y:%.*]]
448 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[SPEC_SELECT]], i64 12
449 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @fn_nonnull_noundef_arg(ptr [[GEP]])
450 ; CHECK-NEXT: ret void
453 br i1 %X, label %if, label %else
459 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
460 %gep = getelementptr inbounds i8, ptr %phi, i64 12
461 call ptr @fn_nonnull_noundef_arg(ptr %gep)
466 define void @test9_gep_inbouds_unknown_null(i1 %X, ptr %Y, i64 %I) {
467 ; CHECK-LABEL: @test9_gep_inbouds_unknown_null(
469 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[X:%.*]], ptr null, ptr [[Y:%.*]]
470 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[SPEC_SELECT]], i64 [[I:%.*]]
471 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @fn_nonnull_noundef_arg(ptr [[GEP]])
472 ; CHECK-NEXT: ret void
475 br i1 %X, label %if, label %else
481 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
482 %gep = getelementptr inbounds i8, ptr %phi, i64 %I
483 call ptr @fn_nonnull_noundef_arg(ptr %gep)
487 define void @test9_gep_unknown_null(i1 %X, ptr %Y, i64 %I) {
488 ; CHECK-LABEL: @test9_gep_unknown_null(
490 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[X:%.*]], ptr null, ptr [[Y:%.*]]
491 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[SPEC_SELECT]], i64 [[I:%.*]]
492 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @fn_nonnull_noundef_arg(ptr [[GEP]])
493 ; CHECK-NEXT: ret void
496 br i1 %X, label %if, label %else
502 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
503 %gep = getelementptr i8, ptr %phi, i64 %I
504 call ptr @fn_nonnull_noundef_arg(ptr %gep)
508 define void @test9_gep_unknown_undef(i1 %X, ptr %Y, i64 %I) {
509 ; CHECK-LABEL: @test9_gep_unknown_undef(
511 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[Y:%.*]], i64 [[I:%.*]]
512 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @fn_noundef_arg(ptr [[GEP]])
513 ; CHECK-NEXT: ret void
516 br i1 %X, label %if, label %else
522 %phi = phi ptr [ %Y, %entry ], [ undef, %if ]
523 %gep = getelementptr i8, ptr %phi, i64 %I
524 call ptr @fn_noundef_arg(ptr %gep)
528 define void @test9_missing_noundef(i1 %X, ptr %Y) {
529 ; CHECK-LABEL: @test9_missing_noundef(
531 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[X:%.*]], ptr null, ptr [[Y:%.*]]
532 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @fn_nonnull_arg(ptr [[SPEC_SELECT]])
533 ; CHECK-NEXT: ret void
536 br i1 %X, label %if, label %else
542 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
543 call ptr @fn_nonnull_arg(ptr %phi)
547 define void @test9_null_defined(i1 %X, ptr %Y) #0 {
548 ; CHECK-LABEL: @test9_null_defined(
550 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[X:%.*]], ptr null, ptr [[Y:%.*]]
551 ; CHECK-NEXT: [[TMP0:%.*]] = call ptr @fn_nonnull_noundef_arg(ptr [[SPEC_SELECT]])
552 ; CHECK-NEXT: ret void
555 br i1 %X, label %if, label %else
561 %phi = phi ptr [ %Y, %entry ], [ null, %if ]
562 call ptr @fn_nonnull_noundef_arg(ptr %phi)
568 attributes #0 = { null_pointer_is_valid }
570 ; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
571 ; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
572 ; CHECK: attributes #[[ATTR2:[0-9]+]] = { null_pointer_is_valid }
573 ; CHECK: attributes #[[ATTR3]] = { nounwind }