Files
clang-p2996/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll
Johannes Doerfert 84bf0da34d [Attributor][FIX] Ensure to always translate call site arguments (#107323)
When we propagate call site arguments we always need to translate them,
this is important as we ended up picking the function argument for a
recurisve call not the call site argument. `@recBad` and `@recGood` in
`returned.ll` show the problem as they used to transform them the same
way. The restructuring cleans the code up and helps derive more
"returned" arguments and better information in the presence of recursive
calls. The "dropped" attributes are simply dropped because we do not
query them anymore, not because we cannot derive them.
2024-09-05 13:37:21 -07:00

141 lines
5.7 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define void @fn2(ptr %P, i1 %C) {
;
; TUNIT: Function Attrs: nofree norecurse nosync nounwind memory(argmem: readwrite)
; TUNIT-LABEL: define {{[^@]+}}@fn2
; TUNIT-SAME: (ptr nocapture nofree [[P:%.*]], i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: br label [[IF_END:%.*]]
; TUNIT: for.cond1:
; TUNIT-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]]
; TUNIT: if.end:
; TUNIT-NEXT: [[E_2:%.*]] = phi ptr [ [[P]], [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ]
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr [[E_2]], align 4
; TUNIT-NEXT: store i32 [[TMP0]], ptr [[P]], align 4
; TUNIT-NEXT: br label [[FOR_COND1]]
; TUNIT: exit:
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: readwrite)
; CGSCC-LABEL: define {{[^@]+}}@fn2
; CGSCC-SAME: (ptr nocapture nofree nonnull align 4 dereferenceable(4) [[P:%.*]], i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: br label [[IF_END:%.*]]
; CGSCC: for.cond1:
; CGSCC-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]]
; CGSCC: if.end:
; CGSCC-NEXT: [[E_2:%.*]] = phi ptr [ [[P]], [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ]
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[E_2]], align 4
; CGSCC-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 [[TMP0]]) #[[ATTR3:[0-9]+]]
; CGSCC-NEXT: store i32 [[CALL]], ptr [[P]], align 4
; CGSCC-NEXT: br label [[FOR_COND1]]
; CGSCC: exit:
; CGSCC-NEXT: ret void
;
entry:
br label %if.end
for.cond1: ; preds = %if.end
br i1 %C, label %if.end, label %exit
if.end: ; preds = %entry, %for.cond1
%e.2 = phi ptr [ %P, %entry ], [ null, %for.cond1 ]
%0 = load i32, ptr %e.2, align 4
%call = call i32 @fn1(i32 %0)
store i32 %call, ptr %P
br label %for.cond1
exit:
ret void
}
define internal i32 @fn1(i32 %p1) {
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@fn1
; CGSCC-SAME: (i32 returned [[P1:%.*]]) #[[ATTR1:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: ret i32 [[P1]]
;
entry:
%tobool = icmp ne i32 %p1, 0
%cond = select i1 %tobool, i32 %p1, i32 %p1
ret i32 %cond
}
define void @fn_no_null_opt(ptr %P, i1 %C) null_pointer_is_valid {
;
; TUNIT: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid
; TUNIT-LABEL: define {{[^@]+}}@fn_no_null_opt
; TUNIT-SAME: (ptr nocapture nofree writeonly [[P:%.*]], i1 [[C:%.*]]) #[[ATTR1:[0-9]+]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: br label [[IF_END:%.*]]
; TUNIT: for.cond1:
; TUNIT-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]]
; TUNIT: if.end:
; TUNIT-NEXT: [[E_2:%.*]] = phi ptr [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ]
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr null, align 4294967296
; TUNIT-NEXT: store i32 [[TMP0]], ptr [[P]], align 4
; TUNIT-NEXT: br label [[FOR_COND1]]
; TUNIT: exit:
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind null_pointer_is_valid
; CGSCC-LABEL: define {{[^@]+}}@fn_no_null_opt
; CGSCC-SAME: (ptr nocapture nofree writeonly align 4 dereferenceable_or_null(4) [[P:%.*]], i1 [[C:%.*]]) #[[ATTR2:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: br label [[IF_END:%.*]]
; CGSCC: for.cond1:
; CGSCC-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]]
; CGSCC: if.end:
; CGSCC-NEXT: [[E_2:%.*]] = phi ptr [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ]
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr null, align 4294967296
; CGSCC-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) #[[ATTR3]]
; CGSCC-NEXT: store i32 [[CALL]], ptr [[P]], align 4
; CGSCC-NEXT: br label [[FOR_COND1]]
; CGSCC: exit:
; CGSCC-NEXT: ret void
;
entry:
br label %if.end
for.cond1: ; preds = %if.end
br i1 %C, label %if.end, label %exit
if.end: ; preds = %entry, %for.cond1
%e.2 = phi ptr [ undef, %entry ], [ null, %for.cond1 ]
%0 = load i32, ptr %e.2, align 4
%call = call i32 @fn0(i32 %0)
store i32 %call, ptr %P
br label %for.cond1
exit:
ret void
}
define internal i32 @fn0(i32 %p1) {
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@fn0
; CGSCC-SAME: (i32 returned [[P1:%.*]]) #[[ATTR1]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: ret i32 [[P1]]
;
entry:
%tobool = icmp ne i32 %p1, 0
%cond = select i1 %tobool, i32 %p1, i32 %p1
ret i32 %cond
}
;.
; TUNIT: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind memory(argmem: readwrite) }
; TUNIT: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind null_pointer_is_valid }
;.
; CGSCC: attributes #[[ATTR0]] = { nofree nosync nounwind memory(argmem: readwrite) }
; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR2]] = { nofree nosync nounwind null_pointer_is_valid }
; CGSCC: attributes #[[ATTR3]] = { nofree nosync }
;.
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CHECK: {{.*}}