[CFI] Create an external linkage alias instead of promoting internals#203171
[CFI] Create an external linkage alias instead of promoting internals#203171mtrofin wants to merge 1 commit into
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
🪟 Windows x64 Test Results
✅ The build succeeded and all tests passed. |
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
d6411b2 to
e737beb
Compare
f8a1ec9 to
854a6f9
Compare
| }); | ||
|
|
||
| if (MustPromote) { | ||
| PromoteExtra->remove(&ExportGV); |
There was a problem hiding this comment.
Maybe rename Promote Extra to what it actually is, so that it is more obvious why the set needs an update (probably add a comment too, or at least)
There was a problem hiding this comment.
would do as NFC, before this. Just reusing the current name here.
| auto Name = ExportGV.getName(); | ||
| GlobalValue *ImportGV = nullptr; | ||
| if (!PromoteExtra.count(&ExportGV)) { | ||
| const bool MustPromote = PromoteExtra && PromoteExtra->count(&ExportGV); |
There was a problem hiding this comment.
Why does the SetVector need to be a pointer now? Can it just be a non-const ref?
There was a problem hiding this comment.
I was "meh" about it, too... yes, it could be, but then we'd have to pass down an empty CfiFunctions at the call site. When reading this function, the nuance that "it's empty in one case, intentionally" may be missed. The pointer sends a clearer message, imho.
|
|
||
| TargetsForSlot.push_back(VTP.FuncVI); | ||
| ValueInfo TheFn = VTP.FuncVI; | ||
| if (TheFn.getSummaryList().size() == 1) { |
There was a problem hiding this comment.
What happens if there is more than one? Also, add a comment about why we need to get aliasee
| report_fatal_error( | ||
| "unexpected call to llvm.icall.branch.funnel during import phase"); | ||
|
|
||
| for (auto &A : llvm::make_early_inc_range(M.aliases())) { |
There was a problem hiding this comment.
because of A.eraseFromParent(), which then invalidates the iterator.
8aa17d1 to
7a0e8d6
Compare
6dc97cf to
6f02138
Compare
7a0e8d6 to
d74770c
Compare
6f02138 to
c7ff207
Compare
d74770c to
59609f0
Compare
c7ff207 to
525046e
Compare
59609f0 to
d17b651
Compare
|
@llvm/pr-subscribers-lto @llvm/pr-subscribers-llvm-transforms Author: Mircea Trofin (mtrofin) ChangesThe problem is described in PR #201849. This is a simple fix - thanks, @teresajohnson for the idea. When CFI promotes an internal symbol, it previously would have to create an alias to avoid breakages in the case of references from inline asm. The alternative here is to leave the symbol as-is and create an alias for CFI's purposes. This makes the calculation of a GUID for this new symbol avoid the class of colisions discussed in the earlier PR. An alternative we discussed would be to use the same kind of hash as CFI uses - based on module content. That would add some cost to compile time for all modules (it could be paid only in PGO/ThinLTO cases, though). We preferred this alternative here because it's simpler and has no compile-time penalty. Full diff: https://github.com/llvm/llvm-project/pull/203171.diff 9 Files Affected:
diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
index 7c045c90ead5b..d399b6f9d1090 100644
--- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
+++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
@@ -2138,6 +2138,22 @@ bool LowerTypeTestsModule::lower() {
report_fatal_error(
"unexpected call to llvm.icall.branch.funnel during import phase");
+ for (auto &A : llvm::make_early_inc_range(M.aliases())) {
+ if (A.hasLocalLinkage())
+ continue;
+ if (ImportSummary->cfiFunctionDefs().contains(A.getName()) ||
+ ImportSummary->cfiFunctionDecls().contains(A.getName())) {
+ if (auto *F = dyn_cast<Function>(A.getAliasee()->stripPointerCasts())) {
+ A.replaceAllUsesWith(F);
+ std::string Name = std::string(A.getName());
+ A.eraseFromParent();
+ F->setName(Name);
+ F->setLinkage(GlobalValue::ExternalLinkage);
+ F->setVisibility(GlobalValue::HiddenVisibility);
+ }
+ }
+ }
+
SmallVector<Function *, 8> Defs;
SmallVector<Function *, 8> Decls;
for (auto &F : M) {
diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
index 40200a6554249..1f4dff0aae472 100644
--- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
+++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
@@ -30,23 +30,10 @@ using namespace llvm;
namespace {
-// Determine if a promotion alias should be created for a symbol name.
-static bool allowPromotionAlias(const std::string &Name) {
- // Promotion aliases are used only in inline assembly. It's safe to
- // simply skip unusual names. Subset of MCAsmInfo::isAcceptableChar()
- // and MCAsmInfoXCOFF::isAcceptableChar().
- for (const char &C : Name) {
- if (isAlnum(C) || C == '_' || C == '.')
- continue;
- return false;
- }
- return true;
-}
-
// Promote each local-linkage entity defined by ExportM and used by ImportM by
// changing visibility and appending the given ModuleId.
void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId,
- const SetVector<GlobalValue *> &PromoteExtra) {
+ SetVector<GlobalValue *> *PromoteExtra = nullptr) {
DenseMap<const Comdat *, Comdat *> RenamedComdats;
for (auto &ExportGV : ExportM.global_values()) {
if (!ExportGV.hasLocalLinkage())
@@ -54,7 +41,8 @@ void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId,
auto Name = ExportGV.getName();
GlobalValue *ImportGV = nullptr;
- if (!PromoteExtra.count(&ExportGV)) {
+ const bool MustPromote = PromoteExtra && PromoteExtra->count(&ExportGV);
+ if (!MustPromote) {
ImportGV = ImportM.getNamedValue(Name);
if (!ImportGV)
continue;
@@ -72,24 +60,24 @@ void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId,
if (C->getName() == Name)
RenamedComdats.try_emplace(C, ExportM.getOrInsertComdat(NewName));
- ExportGV.setName(NewName);
- ExportGV.setLinkage(GlobalValue::ExternalLinkage);
- ExportGV.setVisibility(GlobalValue::HiddenVisibility);
- // TODO: remove this reassign and instead create an alias.
- ExportGV.reassignGUID();
+ auto *ExternalAlias = GlobalAlias::create(
+ ExportGV.getType(), ExportGV.getAddressSpace(),
+ GlobalValue::ExternalLinkage, NewName, &ExportGV, &ExportM);
+ ExternalAlias->setVisibility(GlobalValue::HiddenVisibility);
+ ExportGV.replaceUsesWithIf(ExternalAlias, [ExternalAlias](Use &U) {
+ return U.getUser() != ExternalAlias;
+ });
+
+ if (MustPromote) {
+ PromoteExtra->remove(&ExportGV);
+ PromoteExtra->insert(ExternalAlias);
+ }
+
if (ImportGV) {
ImportGV->setName(NewName);
ImportGV->setVisibility(GlobalValue::HiddenVisibility);
ImportGV->reassignGUID();
}
-
- if (isa<Function>(&ExportGV) && allowPromotionAlias(OldName)) {
- // Create a local alias with the original name to avoid breaking
- // references from inline assembly.
- std::string Alias =
- ".lto_set_conditional " + OldName + "," + NewName + "\n";
- ExportM.appendModuleInlineAsm(Alias);
- }
}
if (!RenamedComdats.empty())
@@ -191,9 +179,8 @@ void simplifyExternals(Module &M) {
F.getName().starts_with("llvm."))
continue;
- Function *NewF =
- Function::Create(EmptyFT, GlobalValue::ExternalLinkage,
- F.getAddressSpace(), "", &M);
+ Function *NewF = Function::Create(EmptyFT, GlobalValue::ExternalLinkage,
+ F.getAddressSpace(), "", &M);
NewF->copyAttributesFrom(&F);
// Only copy function attribtues.
NewF->setAttributes(AttributeList::get(M.getContext(),
@@ -419,8 +406,8 @@ void splitAndWriteThinLTOBitcode(
// match values from its first argument (the "exporting module") in
// CfiFunctions. So we only need CfiFunctions for the second promotion (M ->
// MergedM)
- promoteInternals(*MergedM, M, ModuleId, {});
- promoteInternals(M, *MergedM, ModuleId, CfiFunctions);
+ promoteInternals(*MergedM, M, ModuleId, nullptr);
+ promoteInternals(M, *MergedM, ModuleId, &CfiFunctions);
auto &Ctx = MergedM->getContext();
SmallVector<MDNode *, 8> CfiFunctionMDs;
diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
index f876d4f02bb15..2c199896e2fe3 100644
--- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
+++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
@@ -1147,6 +1147,8 @@ bool DevirtModule::tryFindVirtualCallTargets(
// target.
auto *GV = dyn_cast<GlobalValue>(C);
assert(GV);
+ if (auto *GA = dyn_cast<GlobalAlias>(GV))
+ GV = GA->getAliaseeObject();
TargetsForSlot.push_back({GV, &TM});
}
@@ -1203,7 +1205,17 @@ bool DevirtIndex::tryFindVirtualCallTargets(
if (mustBeUnreachableFunction(VTP.FuncVI))
continue;
- TargetsForSlot.push_back(VTP.FuncVI);
+ ValueInfo TheFn = VTP.FuncVI;
+ // Internal linkage functions get an external linkage alias to them.
+ if (!TheFn.getSummaryList().empty())
+ if (auto *AS =
+ dyn_cast<AliasSummary>(TheFn.getSummaryList()[0].get())) {
+ assert(TheFn.getSummaryList().size() == 1 &&
+ "Aliases to internal linkage targets of indirect calls are "
+ "expected to point to exactly one definition.");
+ TheFn = AS->getAliaseeVI();
+ }
+ TargetsForSlot.push_back(TheFn);
}
}
@@ -2261,10 +2273,13 @@ void DevirtModule::importResolution(VTableSlot Slot, VTableSlotInfo &SlotInfo) {
assert(!Res.SingleImplName.empty());
// The type of the function in the declaration is irrelevant because every
// call site will cast it to the correct type.
- Constant *SingleImpl =
- cast<Constant>(M.getOrInsertFunction(Res.SingleImplName,
- Type::getVoidTy(M.getContext()))
- .getCallee());
+ Value *SingleImplVal =
+ M.getOrInsertFunction(Res.SingleImplName,
+ Type::getVoidTy(M.getContext()))
+ .getCallee();
+ if (auto *A = dyn_cast<GlobalAlias>(SingleImplVal->stripPointerCasts()))
+ SingleImplVal = A->getAliaseeObject();
+ Constant *SingleImpl = cast<Constant>(SingleImplVal);
// This is the import phase so we should not be exporting anything.
bool IsExported = false;
diff --git a/llvm/test/ThinLTO/X86/devirt_function_alias2.ll b/llvm/test/ThinLTO/X86/devirt_function_alias2.ll
index 3b3208e300aa8..e4f93208fba54 100644
--- a/llvm/test/ThinLTO/X86/devirt_function_alias2.ll
+++ b/llvm/test/ThinLTO/X86/devirt_function_alias2.ll
@@ -24,8 +24,8 @@
; RUN: 2>&1 | FileCheck %s --check-prefix=REMARK --check-prefix=PRINT
; RUN: llvm-dis %t2.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR1
-; PRINT-DAG: Devirtualized call to {{.*}} (_ZN1D1mEiAlias)
-; REMARK-DAG: single-impl: devirtualized a call to _ZN1D1mEiAlias
+; PRINT-DAG: Devirtualized call to {{.*}} (_ZN1D1mEi)
+; REMARK-DAG: single-impl: devirtualized a call to _ZN1D1mEi
;; Test hybrid Thin/Regular LTO
@@ -63,13 +63,15 @@ target triple = "x86_64-grtev4-linux-gnu"
@_ZTV1D = constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr undef, ptr @_ZN1D1mEiAlias] }, !type !3
-define i32 @_ZN1D1mEi(ptr %this, i32 %a) {
+define i32 @_ZN1D1mEi(ptr %this, i32 %a) #0 {
ret i32 0;
}
@_ZN1D1mEiAlias = unnamed_addr alias i32 (ptr, i32), ptr @_ZN1D1mEi
-; CHECK-IR1-LABEL: define i32 @test
+attributes #0 = { noinline optnone }
+
+; CHECK-IR1-LABEL: define {{.*}}i32 @test
define i32 @test(ptr %obj2, i32 %a) {
entry:
%vtable2 = load ptr, ptr %obj2
diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-icall-static-inline-asm.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-icall-static-inline-asm.ll
index d8ebae17d4693..9d2ee425031ab 100644
--- a/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-icall-static-inline-asm.ll
+++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-icall-static-inline-asm.ll
@@ -3,7 +3,7 @@
target triple = "x86_64-unknown-linux-gnu"
-; CHECK: module asm ".lto_set_conditional a,a.[[HASH:[0-9a-f]+]]"
+; CHECK: @a.[[HASH:[0-9a-f]+]] = hidden alias
define void @b() {
%f = alloca ptr, align 8
@@ -14,7 +14,7 @@ define void @b() {
ret void
}
-; CHECK: define{{.*}} @a.[[HASH]](){{.*}} !type
+; CHECK: define internal void @a() {{.*}}!type
define internal void @a() !type !0 {
ret void
}
diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/comdat.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/comdat.ll
index f9545e2010c10..48d371531ed7b 100644
--- a/llvm/test/Transforms/ThinLTOBitcodeWriter/comdat.ll
+++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/comdat.ll
@@ -25,9 +25,8 @@ $nt = comdat any
; MERGED-SAME: comdat(${{"?lwt[^ ]+}})
@lwt_aliasee = private unnamed_addr global [1 x ptr] [ptr null], comdat($lwt), !type !0
-; MERGED: {{@"?lwt_nl[^ ]+}} = hidden unnamed_addr global
-; MERGED-SAME: comdat(${{"?lwt[^ ]+}})
-; THIN: {{@"?lwt_nl[^ ]+}} = external hidden
+; MERGED: @lwt_nl = internal unnamed_addr global i32 0, comdat(${{"?lwt[^ ]+}})
+; THIN: {{@"?lwt_nl\.[^ ]+}} = external hidden unnamed_addr global i32
@lwt_nl = internal unnamed_addr global i32 0, comdat($lwt)
; MERGED: @nlwt_aliasee = private unnamed_addr global
@@ -47,12 +46,16 @@ $nt = comdat any
; THIN-SAME: comdat($nt)
@nt_nl = internal unnamed_addr global i32 0, comdat($nt)
-; MERGED: {{@"?lwt[^ ]+}} = hidden unnamed_addr alias
-; THIN: {{@"?lwt[^ ]+}} = external hidden
+; MERGED: @lwt = internal unnamed_addr alias [1 x ptr], ptr @lwt_aliasee
+; MERGED: @nlwt_nl = internal unnamed_addr alias [1 x ptr], ptr @nlwt_aliasee
+; MERGED: {{@"?lwt_nl\.[^ ]+}} = hidden alias ptr, ptr @lwt_nl
+; MERGED: {{@"?lwt\.[^ ]+}} = hidden alias ptr, ptr @lwt
+; MERGED: {{@"?nlwt_nl\.[^ ]+}} = hidden alias ptr, ptr @nlwt_nl
+
+; THIN: {{@"?lwt\.[^ ]+}} = external hidden global [1 x ptr]
@lwt = internal unnamed_addr alias [1 x ptr], ptr @lwt_aliasee
-; MERGED: {{@"?nlwt_nl[^ ]+}} = hidden unnamed_addr alias
-; THIN: {{@"?nlwt_nl[^ ]+}} = external hidden
+; THIN: {{@"?nlwt_nl\.[^ ]+}} = external hidden global [1 x ptr]
@nlwt_nl = internal unnamed_addr alias [1 x ptr], ptr @nlwt_aliasee
; The functions below exist just to make sure the globals are used.
diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/split-internal1.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/split-internal1.ll
index 1a6cbb7e7e84b..2c84ab86cac63 100644
--- a/llvm/test/Transforms/ThinLTOBitcodeWriter/split-internal1.ll
+++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/split-internal1.ll
@@ -13,7 +13,8 @@
; BCA1-NOT: <GLOBALVAL_SUMMARY_BLOCK
; M0: @g.581d7631532fa146ba4061179da39272 = external hidden global i8
-; M1: @g.581d7631532fa146ba4061179da39272 = hidden global i8 42, !type !0
+; M1: @g = internal global i8 42, !type !0
+; M1: @g.581d7631532fa146ba4061179da39272 = hidden alias ptr, ptr @g
@g = internal global i8 42, !type !0
; M0: define ptr @f()
diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/split-internal2.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/split-internal2.ll
index 1a7b1aba66576..d9d9f516015d9 100644
--- a/llvm/test/Transforms/ThinLTOBitcodeWriter/split-internal2.ll
+++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/split-internal2.ll
@@ -20,8 +20,9 @@ target triple = "x86_64-unknown-linux-gnu"
; M1: @g = global ptr @f.13757e0fb71915e385efa4dc9d1e08fd, !type !0
@g = global ptr @f, !type !0
-; M0: define hidden void @f.13757e0fb71915e385efa4dc9d1e08fd()
-; M1: declare !guid !4 hidden void @f.13757e0fb71915e385efa4dc9d1e08fd()
+; M0: @f.13757e0fb71915e385efa4dc9d1e08fd = hidden alias ptr, ptr @f
+; M0: define internal void @f()
+; M1: declare !guid !{{[0-9]+}} hidden void @f.13757e0fb71915e385efa4dc9d1e08fd()
define internal void @f() {
call void @f2()
ret void
diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/split-vfunc-internal.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/split-vfunc-internal.ll
index 75932fd84d83e..1d17699be1c3c 100644
--- a/llvm/test/Transforms/ThinLTOBitcodeWriter/split-vfunc-internal.ll
+++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/split-vfunc-internal.ll
@@ -10,12 +10,14 @@ define ptr @source() {
}
; M0: @g.84f59439b469192440047efc8de357fb = external hidden constant [1 x ptr]
-; M1: @g.84f59439b469192440047efc8de357fb = hidden constant [1 x ptr] [ptr @ok.84f59439b469192440047efc8de357fb]
+; M1: @g = internal constant [1 x ptr] [ptr @ok.84f59439b469192440047efc8de357fb]
+; M1: @g.84f59439b469192440047efc8de357fb = hidden alias ptr, ptr @g
@g = internal constant [1 x ptr] [
ptr @ok
], !type !0
-; M0: define hidden i64 @ok.84f59439b469192440047efc8de357fb
+; M0: @ok.84f59439b469192440047efc8de357fb = hidden alias ptr, ptr @ok
+; M0: define internal i64 @ok(ptr %this)
; M1: define available_externally hidden i64 @ok.84f59439b469192440047efc8de357fb
define internal i64 @ok(ptr %this) {
ret i64 42
|
525046e to
fa7961a
Compare
1bca656 to
6bc8b3c
Compare
fa7961a to
1817d11
Compare
6bc8b3c to
ff0a5e1
Compare
2829ab3 to
a6fdde1
Compare
ff0a5e1 to
e0392b6
Compare
a6fdde1 to
4da2c32
Compare
c1b8c2a to
677d378
Compare
4bf5379 to
1cbfe8b
Compare
677d378 to
9b228b5
Compare
9b228b5 to
d9d66bd
Compare
1cbfe8b to
55df97c
Compare
bdc1c87 to
ff1fe38
Compare
55df97c to
e432443
Compare
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>
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>
ff1fe38 to
774d8a8
Compare

The problem is described in PR #201849. This is a simple fix - thanks, @teresajohnson for the idea. When CFI promotes an internal symbol, it previously would have to create an alias to avoid breakages in the case of references from inline asm. The alternative here is to leave the symbol as-is and create an alias for CFI's purposes. This makes the calculation of a GUID for this new symbol avoid the class of colisions discussed in the earlier PR. Then, during
LowerTypeTests, we give the functon the alias' name and the rest of the CFI functionality remains unaffected.An alternative we discussed would be to use the same kind of hash as CFI uses - based on module content. That would add some cost to compile time for all modules (it could be paid only in PGO/ThinLTO cases, though). We preferred this alternative here because it's simpler and has no compile-time penalty.
Co-authored-by: Teresa Johnson <tejohnson@google.com>