This reverts #201194, thus relanding @orodley's PR #184065 (and #200323): > This allows us to keep GUIDs consistent across compilation phases which may change the name or linkage type. > See https://discourse.llvm.org/t/rfc-keep-globalvalue-guids-stable/84801 The CFI issues that triggered the original revert are fixed by #201370, together with the addressing of the TODOs in `LowerTypeTests.cpp` left in the latter. The [graphite diff](https://app.graphite.com/github/pr/llvm/llvm-project/201849/Reland-%23184065) between this change's V1 and V2 shows what's been added: - the `TODO`s from #201370 are done - in LowerTypeTests.cpp, passing `!guid` when creating a new declaration and when converting a definition to a declaration. - `llvm/test/Transforms/LowerTypeTests/export-icall.ll` tests also the above def->decl conversion - removed `test/Analysis/CtxProfAnalysis/flatten-prethinlink-requires-guid-metadata.ll` introduced in #194383 (this was between the revert and this PR), as now the general expectation is that GUID assignment happens appropriately and all passes use `getGUID`, so there's no reason for `CtxProfAnalysis` to do something different. Currently, we reassign GUIDs when CFI promotes internal linkage symbols, which is counter to the goal of the RFC. This is addressed in PR #203171. The reason for this split fix can be explained on `compiler-rt/test/cfi/icall/wrong-signature-mixed-lto.c`. Here, a module with the exact same source path is compiled twice, under different conditional compilation, to produce 2 objects. Each object defines an internal linkage symbol with the same name (this is `install_trap_loop_detection` from `compiler-rt/test/cfi/trap_loop_signal_handler.inc` which is `-include`\-d by both - see how `%clang_cfi` is defined). The ThinLTO GUID of this symbol will be the same. Its name won't be - because CFI promotes it and renames it using a hash that is based on the IR Module content (rather than the source path). During thinlink, `LTO::addThinLTO`will mark each of the 2 exported symbols as prevailing in their corresponding modules. But that is done by associating their GUID to the module. So whichever comes last wins. The other symbol will be marked available externally and its body DCEd later in backend. But each module will refer to its copy of `install_trap_loop_detection`, and so we end up with a linker error. As mentioned, the fix is in PR #203171, and this relanding PR just maintains the existing ThinLTO behavior by rewriting the GUIDs. Since we haven't yet leveraged the GUID mechanics for e.g. simplifying PGO, this aspect of this change is essentially NFC. Co-authored-by: Owen Rodley <orodley@google.com>
174 lines
8.0 KiB
LLVM
174 lines
8.0 KiB
LLVM
; REQUIRES: x86-registered-target
|
|
|
|
; Do setup work for all below tests: generate bitcode and combined index
|
|
; RUN: opt -module-summary %s -o %t.bc
|
|
; RUN: opt -module-summary %p/Inputs/funcimport.ll -o %t2.bc
|
|
; RUN: llvm-lto -thinlto -print-summary-global-ids -o %t3 %t.bc %t2.bc 2>&1 | FileCheck %s --check-prefix=GUID
|
|
|
|
; Do the import now
|
|
; RUN: opt -passes=function-import -stats -print-imports -enable-import-metadata -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=INSTLIMDEF
|
|
; Try again with new pass manager
|
|
; RUN: opt -passes='function-import' -stats -print-imports -enable-import-metadata -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=INSTLIMDEF
|
|
; RUN: opt -passes='function-import' -debug-only=function-import -enable-import-metadata -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=DUMP
|
|
; "-stats" and "-debug-only" require +Asserts.
|
|
; REQUIRES: asserts
|
|
|
|
; Test import with smaller instruction limit
|
|
; RUN: opt -passes=function-import -enable-import-metadata -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=5 -S | FileCheck %s --check-prefix=CHECK --check-prefix=INSTLIM5
|
|
; INSTLIM5-NOT: @staticfunc.llvm.
|
|
|
|
; Test force import all
|
|
; RUN: llvm-lto -thinlto-action=run -force-import-all %t.bc %t2.bc 2>&1 \
|
|
; RUN: | FileCheck %s --check-prefix=IMPORTALL
|
|
; IMPORTALL-DAG: Error importing module: Failed to import function weakalias due to InterposableLinkage
|
|
|
|
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
|
target triple = "x86_64-apple-macosx10.11.0"
|
|
|
|
define i32 @main() #0 {
|
|
entry:
|
|
call void (...) @weakalias()
|
|
call void (...) @analias()
|
|
call void (...) @linkoncealias()
|
|
%call = call i32 (...) @referencestatics()
|
|
%call1 = call i32 (...) @referenceglobals()
|
|
%call2 = call i32 (...) @referencecommon()
|
|
call void (...) @setfuncptr()
|
|
call void (...) @callfuncptr()
|
|
call void (...) @weakfunc()
|
|
call void (...) @linkoncefunc2()
|
|
call void (...) @referencelargelinkonce()
|
|
call void (...) @variadic_no_va_start()
|
|
call void (...) @variadic_va_start()
|
|
ret i32 0
|
|
}
|
|
|
|
; Won't import weak alias
|
|
; CHECK-DAG: declare void @weakalias
|
|
declare void @weakalias(...) #1
|
|
|
|
; External alias imported as available_externally copy of aliasee
|
|
; CHECK-DAG: define available_externally void @analias
|
|
declare void @analias(...) #1
|
|
|
|
; External alias imported as available_externally copy of aliasee
|
|
; (linkoncealias is an external alias to a linkonce_odr)
|
|
declare void @linkoncealias(...) #1
|
|
; CHECK-DAG: define available_externally void @linkoncealias()
|
|
|
|
; INSTLIMDEF-DAG: Import referencestatics
|
|
; INSTLIMDEF-DAG: define available_externally i32 @referencestatics(i32 %i) !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
|
|
; INSTLIM5-DAG: declare i32 @referencestatics(...)
|
|
declare i32 @referencestatics(...) #1
|
|
|
|
; The import of referencestatics will expose call to staticfunc that
|
|
; should in turn be imported as a promoted/renamed and hidden function.
|
|
; Ensure that the call is to the properly-renamed function.
|
|
; INSTLIMDEF-DAG: Import staticfunc
|
|
; INSTLIMDEF-DAG: %call = call i32 @staticfunc.llvm.
|
|
; INSTLIMDEF-DAG: define available_externally hidden i32 @staticfunc.llvm.{{.*}} !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
|
|
|
|
; INSTLIMDEF-DAG: Import referenceglobals
|
|
; CHECK-DAG: define available_externally i32 @referenceglobals(i32 %i) !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
|
|
declare i32 @referenceglobals(...) #1
|
|
|
|
; The import of referenceglobals will expose call to globalfunc1 that
|
|
; should in turn be imported.
|
|
; INSTLIMDEF-DAG: Import globalfunc1
|
|
; CHECK-DAG: define available_externally void @globalfunc1() !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]]
|
|
|
|
; INSTLIMDEF-DAG: Import referencecommon
|
|
; CHECK-DAG: define available_externally i32 @referencecommon(i32 %i) !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
|
|
declare i32 @referencecommon(...) #1
|
|
|
|
; INSTLIMDEF-DAG: Import setfuncptr
|
|
; CHECK-DAG: define available_externally void @setfuncptr() !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
|
|
declare void @setfuncptr(...) #1
|
|
|
|
; INSTLIMDEF-DAG: Import callfuncptr
|
|
; CHECK-DAG: define available_externally void @callfuncptr() !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
|
|
declare void @callfuncptr(...) #1
|
|
|
|
; Ensure that all uses of local variable @P which has used in setfuncptr
|
|
; and callfuncptr are to the same promoted/renamed global.
|
|
; CHECK-DAG: @P.llvm.{{.*}} = available_externally hidden global ptr null
|
|
; CHECK-DAG: %0 = load ptr, ptr @P.llvm.
|
|
; CHECK-DAG: store ptr @staticfunc2.llvm.{{.*}}, ptr @P.llvm.
|
|
|
|
; Ensure that @referencelargelinkonce definition is pulled in, but later we
|
|
; also check that the linkonceodr function is not.
|
|
; CHECK-DAG: define available_externally void @referencelargelinkonce() !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
|
|
; INSTLIM5-DAG: declare void @linkonceodr()
|
|
declare void @referencelargelinkonce(...)
|
|
|
|
; Won't import weak func
|
|
; CHECK-DAG: declare void @weakfunc(...)
|
|
declare void @weakfunc(...) #1
|
|
|
|
; Won't import linkonce func
|
|
; CHECK-DAG: declare void @linkoncefunc2(...)
|
|
declare void @linkoncefunc2(...) #1
|
|
|
|
; INSTLIMDEF-DAG: Import funcwithpersonality
|
|
; INSTLIMDEF-DAG: define available_externally hidden void @funcwithpersonality.llvm.{{.*}}() personality ptr @__gxx_personality_v0 !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
|
|
; INSTLIM5-DAG: declare hidden void @funcwithpersonality.llvm.{{.*}}()
|
|
|
|
; We can import variadic functions without a va_start, since the inliner
|
|
; can handle them.
|
|
; INSTLIMDEF-DAG: Import variadic_no_va_start
|
|
; CHECK-DAG: define available_externally void @variadic_no_va_start(...) !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
|
|
declare void @variadic_no_va_start(...)
|
|
|
|
; We can import variadic functions with a va_start, since the inliner
|
|
; can sometimes handle them.
|
|
; CHECK-DAG: define available_externally void @variadic_va_start(...)
|
|
declare void @variadic_va_start(...)
|
|
|
|
; INSTLIMDEF-DAG: Import globalfunc2
|
|
; INSTLIMDEF-DAG: 15 function-import - Number of functions imported
|
|
; INSTLIMDEF-DAG: 4 function-import - Number of global variables imported
|
|
|
|
; CHECK-DAG: ![[MOD]] = !{!"{{.*}}.bc"}
|
|
; CHECK-DAG: ![[SRC]] = !{!"{{.*}}/Inputs/funcimport.ll"}
|
|
|
|
; The actual GUID values will depend on path to test.
|
|
; GUID-DAG: GUID {{.*}} is weakalias
|
|
; GUID-DAG: GUID {{.*}} is referenceglobals
|
|
; GUID-DAG: GUID {{.*}} is weakfunc
|
|
; GUID-DAG: GUID {{.*}} is main
|
|
; GUID-DAG: GUID {{.*}} is referencecommon
|
|
; GUID-DAG: GUID {{.*}} is analias
|
|
; GUID-DAG: GUID {{.*}} is referencestatics
|
|
; GUID-DAG: GUID {{.*}} is linkoncealias
|
|
; GUID-DAG: GUID {{.*}} is setfuncptr
|
|
; GUID-DAG: GUID {{.*}} is callfuncptr
|
|
; GUID-DAG: GUID {{.*}} is funcwithpersonality
|
|
; GUID-DAG: GUID {{.*}} is setfuncptr
|
|
; GUID-DAG: GUID {{.*}} is staticfunc2
|
|
; GUID-DAG: GUID {{.*}} is __gxx_personality_v0
|
|
; GUID-DAG: GUID {{.*}} is referencestatics
|
|
; GUID-DAG: GUID {{.*}} is globalfunc1
|
|
; GUID-DAG: GUID {{.*}} is globalfunc2
|
|
; GUID-DAG: GUID {{.*}} is P
|
|
; GUID-DAG: GUID {{.*}} is staticvar
|
|
; GUID-DAG: GUID {{.*}} is commonvar
|
|
; GUID-DAG: GUID {{.*}} is weakalias
|
|
; GUID-DAG: GUID {{.*}} is staticfunc
|
|
; GUID-DAG: GUID {{.*}} is weakfunc
|
|
; GUID-DAG: GUID {{.*}} is referenceglobals
|
|
; GUID-DAG: GUID {{.*}} is weakvar
|
|
; GUID-DAG: GUID {{.*}} is staticconstvar
|
|
; GUID-DAG: GUID {{.*}} is analias
|
|
; GUID-DAG: GUID {{.*}} is globalvar
|
|
; GUID-DAG: GUID {{.*}} is referencecommon
|
|
; GUID-DAG: GUID {{.*}} is linkoncealias
|
|
; GUID-DAG: GUID {{.*}} is callfuncptr
|
|
; GUID-DAG: GUID {{.*}} is linkoncefunc
|
|
|
|
; DUMP: Module [[M1:.*]] imports from 1 module
|
|
; DUMP-NEXT: 15 function definitions and 0 function declarations imported from [[M2:.*]]
|
|
; DUMP-NEXT: 4 vars imported from [[M2]]
|
|
|
|
; DUMP: Imported 15 functions for Module [[M1]]
|
|
; DUMP-NEXT: Imported 4 global variables for Module [[M1]]
|