================
@@ -99,82 +90,71 @@ void SplitModuleCG::calculateFunctionCosts() {
continue;
CostType FnCost = 0;
- for (const auto &BB : Fn) {
- CostType CostVal = std::distance(BB.begin(), BB.end());
- FnCost += CostVal;
- }
+ for (const auto &BB : Fn)
+ FnCost += std::distance(BB.begin(), BB.end());
assert(FnCost != 0);
FuncsCosts[&Fn] = FnCost;
assert((ModuleCost + FnCost) >= ModuleCost && "Overflow!");
ModuleCost += FnCost;
}
}
-void SplitModuleCG::dealWithMpart(Module &MPart, unsigned I,
- function_ref<bool(const GlobalValue *)>
NeedsConservativeImport) {
- // Collect promoted symbols (those that were local but are now external due
- // to externalize(), and therefore are not in the OriginalExternals set
- // captured at construction time).
- //
- // Note: here we only *record* the rename in PromotedRenames; we do not
- // perform the actual renaming immediately. The rename is applied after the
- // opt pipeline has completed. This is intentional: deferring the rename
- // minimizes the impact of renaming on subsequent optimizations.
- auto checkPromoted = [&](const GlobalValue &GV) {
- // now is external (not local), but not in external set.
- if (!GV.hasLocalLinkage() && !OriginalExternals.contains(GV.getName())) {
- if (PromotedRenames.count(GV.getName()))
- return;
- // Use the naming convention "name.llvm.<suffix>" so the
- // promoted local cannot clash with an external that happens to share
- // the same name in another module/partition.
- std::string Suffix = getUniqueModuleId(&M);
- std::string NewName = (GV.getName() + ".llvm" + Suffix).str();
- PromotedRenames[GV.getName()] = NewName;
- }
- };
-
- auto AvailableExternalizeFunc = [&](llvm::Function &Func) {
- Func.setLinkage(GlobalValue::AvailableExternallyLinkage);
- Func.setComdat(nullptr);
- };
-
- for (const auto &GV : MPart.global_values())
- checkPromoted(GV);
- // Clean-up conservatively imported GVs without any users.
- for (auto &GV : make_early_inc_range(MPart.globals())) {
- if (NeedsConservativeImport(&GV) && GV.use_empty())
- GV.eraseFromParent();
- }
-
+void SplitModuleCG::dealWithMpart(Module &MPart, unsigned I) {
+ // Downgrade duplicate definitions of external functions to
+ // available_externally. The first partition to define such a function keeps
+ // the real definition; all other partitions get available_externally copies.
for (auto &func : MPart.functions()) {
+ if (func.isDeclaration())
+ continue;
auto Fn = M.getFunction(func.getName());
- if (externalFunction.count(Fn) && !func.isDeclaration()) {
- if (!externalFunction[Fn]) {
- AvailableExternalizeFunc(func);
- } else {
- externalFunction[Fn] = false;
- }
+ if (!externalFunction.contains(Fn))
+ continue;
+ if (!externalFunction[Fn]) {
+ func.setLinkage(GlobalValue::AvailableExternallyLinkage);
+ func.setComdat(nullptr);
+ } else {
+ externalFunction[Fn] = false;
}
}
+ // Rename GlobalValues whose linkage was promoted from local to external,
+ // to avoid duplicate symbols across partitions in ThinLTO. Use the naming
+ // convention "name.llvm.<suffix>" so the promoted local cannot clash with
+ // an external that happens to share the same name. The suffix is derived
+ // from the module via getUniqueModuleId, so it is consistent across all
+ // partitions.
+ std::string Suffix = getUniqueModuleId(&M);
+ for (auto &GV : MPart.global_values()) {
+ // Now external (not local), but was not originally external.
+ if (GV.hasLocalLinkage() || OriginalExternals.contains(GV.getName()))
+ continue;
+ // Skip declarations of functions that were not explicitly externalized
----------------
mmjjpp wrote:
A function skipped by the hasOneUse() check in SplitModule (e.g. a local
function with a single direct call) stays internal in the source module and is
not recorded in externalFunction. However, CloneModule still creates a
declaration for such a function in any partition that doesn't hold its
definition, and promotes the linkage from internal to dso_local for that
declaration (an internal declaration is meaningless). So we can end up with:
; partition 1 (owns the definition)
define internal void @foo() { ... }
; partition 0 (CloneModule-created declaration)
declare dso_local void @foo()
The declaration in partition 0 is not local and is not in OriginalExternals, so
it would otherwise match the rename condition. Without this check it would
become @foo.llvm.<suffix> while the internal definition in partition 1 keeps
the original name — a link-time mismatch. This check therefore keeps such
declarations unrenamed, consistent with the unrenamed internal definitions in
the partitions that own them.
https://github.com/llvm/llvm-project/pull/198702
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits