We're using this flag (IsNewDbgInfoFormat) to detect the boundaries in LLVM of what's treating debug-info as intrinsics (i.e. dbg.value), and what's using DPValue objects (the non-intrinsic replacement). The attributor tends to create new wrapper functions and doesn't insert them into Modules in the usual way, thus we have to manually update that flag to signal what debug-info mode it's using. I've added some --try-experimental-debuginfo-iterators RUN lines to tests that would otherwise crash because of this, so that they're exercised by our new-debuginfo-iterators buildbot. NB: there's an attributor test with a dbg.value in it, however attributes re-order themselves in RemoveDIs mode for various reasons, so we're going to address that in a different patch.
119 lines
4.9 KiB
LLVM
119 lines
4.9 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
|
|
|
|
;; Test with RemoveDIs debug-info mode to exercise a potential crash path.
|
|
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s --try-experimental-debuginfo-iterators | FileCheck %s --check-prefixes=CHECK,TUNIT
|
|
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s --try-experimental-debuginfo-iterators | FileCheck %s --check-prefixes=CHECK,CGSCC
|
|
|
|
define void @f() {
|
|
; TUNIT-LABEL: define {{[^@]+}}@f() {
|
|
; TUNIT-NEXT: entry:
|
|
; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 1
|
|
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 1
|
|
; TUNIT-NEXT: call void @g(i32 [[TMP0]])
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC-LABEL: define {{[^@]+}}@f() {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: call void @g(i32 undef)
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
entry:
|
|
%a = alloca i32, align 1
|
|
call void @g(ptr %a)
|
|
ret void
|
|
}
|
|
|
|
define internal void @g(ptr %a) {
|
|
; CHECK: Function Attrs: memory(readwrite, argmem: none)
|
|
; CHECK-LABEL: define {{[^@]+}}@g
|
|
; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] {
|
|
; CHECK-NEXT: [[A_PRIV:%.*]] = alloca i32, align 4
|
|
; CHECK-NEXT: store i32 [[TMP0]], ptr [[A_PRIV]], align 4
|
|
; CHECK-NEXT: [[AA:%.*]] = load i32, ptr [[A_PRIV]], align 1
|
|
; CHECK-NEXT: call void @z(i32 [[AA]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%aa = load i32, ptr %a, align 1
|
|
call void @z(i32 %aa)
|
|
ret void
|
|
}
|
|
|
|
declare void @z(i32)
|
|
|
|
; Test2
|
|
; Different alignemnt privatizable arguments
|
|
define internal i32 @test(ptr %X, ptr %Y) {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test
|
|
; CGSCC-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[X:%.*]], i64 [[TMP0:%.*]]) #[[ATTR1:[0-9]+]] {
|
|
; CGSCC-NEXT: [[Y_PRIV:%.*]] = alloca i64, align 8
|
|
; CGSCC-NEXT: store i64 [[TMP0]], ptr [[Y_PRIV]], align 4
|
|
; CGSCC-NEXT: [[A:%.*]] = load i32, ptr [[X]], align 4
|
|
; CGSCC-NEXT: [[B:%.*]] = load i64, ptr [[Y_PRIV]], align 8
|
|
; CGSCC-NEXT: [[C:%.*]] = add i32 [[A]], 1
|
|
; CGSCC-NEXT: [[D:%.*]] = add i64 [[B]], 1
|
|
; CGSCC-NEXT: [[COND:%.*]] = icmp sgt i64 [[D]], -1
|
|
; CGSCC-NEXT: br i1 [[COND]], label [[RETURN1:%.*]], label [[RETURN2:%.*]]
|
|
; CGSCC: Return1:
|
|
; CGSCC-NEXT: ret i32 [[C]]
|
|
; CGSCC: Return2:
|
|
; CGSCC-NEXT: ret i32 [[A]]
|
|
;
|
|
%A = load i32, ptr %X
|
|
%B = load i64, ptr %Y
|
|
%C = add i32 %A, 1
|
|
%D = add i64 %B, 1
|
|
%cond = icmp sgt i64 %D, -1
|
|
br i1 %cond, label %Return1, label %Return2
|
|
Return1:
|
|
ret i32 %C
|
|
Return2:
|
|
ret i32 %A
|
|
}
|
|
|
|
define internal i32 @caller(ptr %A) {
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@caller
|
|
; CGSCC-SAME: (i32 [[TMP0:%.*]]) #[[ATTR2:[0-9]+]] {
|
|
; CGSCC-NEXT: [[A_PRIV:%.*]] = alloca i32, align 4
|
|
; CGSCC-NEXT: store i32 [[TMP0]], ptr [[A_PRIV]], align 4
|
|
; CGSCC-NEXT: [[C:%.*]] = call i32 @test(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A_PRIV]], i64 noundef 1) #[[ATTR3:[0-9]+]]
|
|
; CGSCC-NEXT: ret i32 [[C]]
|
|
;
|
|
%B = alloca i64
|
|
store i64 1, ptr %B
|
|
%C = call i32 @test(ptr %A, ptr %B)
|
|
ret i32 %C
|
|
}
|
|
|
|
define i32 @callercaller() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@callercaller
|
|
; TUNIT-SAME: () #[[ATTR1:[0-9]+]] {
|
|
; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 4
|
|
; TUNIT-NEXT: ret i32 3
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@callercaller
|
|
; CGSCC-SAME: () #[[ATTR2]] {
|
|
; CGSCC-NEXT: [[X:%.*]] = call i32 @caller(i32 noundef 2) #[[ATTR4:[0-9]+]]
|
|
; CGSCC-NEXT: ret i32 [[X]]
|
|
;
|
|
%B = alloca i32
|
|
store i32 2, ptr %B
|
|
%X = call i32 @caller(ptr %B)
|
|
ret i32 %X
|
|
}
|
|
;.
|
|
; TUNIT: attributes #[[ATTR0]] = { memory(readwrite, argmem: none) }
|
|
; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
|
|
;.
|
|
; CGSCC: attributes #[[ATTR0]] = { memory(readwrite, argmem: none) }
|
|
; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
|
|
; CGSCC: attributes #[[ATTR2]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
|
|
; CGSCC: attributes #[[ATTR3]] = { nofree willreturn memory(read) }
|
|
; CGSCC: attributes #[[ATTR4]] = { nofree nosync willreturn }
|
|
;.
|