1; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s 2 3; CHECK-LABEL: @speculatable_attribute 4; CHECK: select 5define i32 @speculatable_attribute(i32 %a) { 6entry: 7 %c = icmp sgt i32 %a, 64 8 br i1 %c, label %end, label %if 9 10if: 11 %val = call i32 @func() #0 12 br label %end 13 14end: 15 %ret = phi i32 [%val, %if], [0, %entry] 16 ret i32 %ret 17} 18 19define i32 @func() #0 { 20 ret i32 1 21} 22 23; We should correctly drop the attribute since it may no longer be valid 24; in the context the call is moved to. 25; Since the function is speculatable, the nonnull attribute need not be dropped 26; since it propagates poison (and call executes fine) if the parameter is indeed 27; null. 28define i32 @strip_attr(ptr %p) { 29; CHECK-LABEL: strip_attr 30; CHECK-LABEL: entry: 31; CHECK: %nullchk = icmp ne ptr %p, null 32; CHECK: %val = call i32 @func_nonnull(ptr nonnull %p) 33; CHECK: select 34entry: 35 %nullchk = icmp ne ptr %p, null 36 br i1 %nullchk, label %if, label %end 37 38if: 39 %val = call i32 @func_nonnull(ptr nonnull %p) #1 40 br label %end 41 42end: 43 %ret = phi i32 [%val, %if], [0, %entry] 44 ret i32 %ret 45} 46 47; We should strip the deref attribute since it can cause UB when the 48; speculatable call is moved. 49define i32 @strip_attr2(ptr %p) { 50; CHECK-LABEL: strip_attr2 51; CHECK-LABEL: entry: 52; CHECK: %nullchk = icmp ne ptr %p, null 53; CHECK: %val = call i32 @func_nonnull(ptr %p) 54; CHECK: select 55entry: 56 %nullchk = icmp ne ptr %p, null 57 br i1 %nullchk, label %if, label %end 58 59if: 60 %val = call i32 @func_nonnull(ptr dereferenceable(12) %p) #1 61 br label %end 62 63end: 64 %ret = phi i32 [%val, %if], [0, %entry] 65 ret i32 %ret 66} 67 68declare i32 @func_nonnull(ptr) #1 69 70attributes #0 = { nounwind readnone speculatable } 71attributes #1 = { nounwind argmemonly speculatable } 72 73