; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s ; CHECK-LABEL: @speculatable_attribute ; CHECK: select define i32 @speculatable_attribute(i32 %a) { entry: %c = icmp sgt i32 %a, 64 br i1 %c, label %end, label %if if: %val = call i32 @func() #0 br label %end end: %ret = phi i32 [%val, %if], [0, %entry] ret i32 %ret } define i32 @func() #0 { ret i32 1 } ; We should correctly drop the attribute since it may no longer be valid ; in the context the call is moved to. ; Since the function is speculatable, the nonnull attribute need not be dropped ; since it propagates poison (and call executes fine) if the parameter is indeed ; null. define i32 @strip_attr(i32 * %p) { ; CHECK-LABEL: strip_attr ; CHECK-LABEL: entry: ; CHECK: %nullchk = icmp ne i32* %p, null ; CHECK: %val = call i32 @func_nonnull(i32* nonnull %p) ; CHECK: select entry: %nullchk = icmp ne i32* %p, null br i1 %nullchk, label %if, label %end if: %val = call i32 @func_nonnull(i32* nonnull %p) #1 br label %end end: %ret = phi i32 [%val, %if], [0, %entry] ret i32 %ret } ; We should strip the deref attribute since it can cause UB when the ; speculatable call is moved. define i32 @strip_attr2(i32 * %p) { ; CHECK-LABEL: strip_attr2 ; CHECK-LABEL: entry: ; CHECK: %nullchk = icmp ne i32* %p, null ; CHECK: %val = call i32 @func_nonnull(i32* %p) ; CHECK: select entry: %nullchk = icmp ne i32* %p, null br i1 %nullchk, label %if, label %end if: %val = call i32 @func_nonnull(i32* dereferenceable(12) %p) #1 br label %end end: %ret = phi i32 [%val, %if], [0, %entry] ret i32 %ret } declare i32 @func_nonnull(i32*) #1 attributes #0 = { nounwind readnone speculatable } attributes #1 = { nounwind argmemonly speculatable }