1 ; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
3 ; CHECK-LABEL: @speculatable_attribute
5 define i32 @speculatable_attribute(i32 %a) {
7 %c = icmp sgt i32 %a, 64
8 br i1 %c, label %end, label %if
11 %val = call i32 @func() #0
15 %ret = phi i32 [%val, %if], [0, %entry]
19 define i32 @func() #0 {
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
28 define i32 @strip_attr(i32 * %p) {
29 ; CHECK-LABEL: strip_attr
31 ; CHECK: %nullchk = icmp ne i32* %p, null
32 ; CHECK: %val = call i32 @func_nonnull(i32* nonnull %p)
35 %nullchk = icmp ne i32* %p, null
36 br i1 %nullchk, label %if, label %end
39 %val = call i32 @func_nonnull(i32* nonnull %p) #1
43 %ret = phi i32 [%val, %if], [0, %entry]
47 ; We should strip the deref attribute since it can cause UB when the
48 ; speculatable call is moved.
49 define i32 @strip_attr2(i32 * %p) {
50 ; CHECK-LABEL: strip_attr2
52 ; CHECK: %nullchk = icmp ne i32* %p, null
53 ; CHECK: %val = call i32 @func_nonnull(i32* %p)
56 %nullchk = icmp ne i32* %p, null
57 br i1 %nullchk, label %if, label %end
60 %val = call i32 @func_nonnull(i32* dereferenceable(12) %p) #1
64 %ret = phi i32 [%val, %if], [0, %entry]
68 declare i32 @func_nonnull(i32*) #1
70 attributes #0 = { nounwind readnone speculatable }
71 attributes #1 = { nounwind argmemonly speculatable }