Skip to content

Commit 8d1eb7a

Browse files
authored
Merge pull request #29753 from slavapestov/got-entry-cleanup
IRGen GOT entry cleanup
2 parents 8b5a639 + 8617599 commit 8d1eb7a

File tree

11 files changed

+101
-297
lines changed

11 files changed

+101
-297
lines changed

include/swift/Basic/Statistics.def

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,10 @@ FRONTEND_STATISTIC(SILModule, NumSILOptWitnessTables)
286286
FRONTEND_STATISTIC(SILModule, NumSILOptDefaultWitnessTables)
287287
FRONTEND_STATISTIC(SILModule, NumSILOptGlobalVariables)
288288

289-
/// The next 9 statistics count kinds of LLVM entities produced
289+
/// The next 10 statistics count kinds of LLVM entities produced
290290
/// during the IRGen phase: globals, functions, aliases, ifuncs,
291291
/// named metadata, value and comdat symbols, basic blocks,
292-
/// and instructions.
292+
/// instructions, and GOT entries.
293293
FRONTEND_STATISTIC(IRModule, NumIRGlobals)
294294
FRONTEND_STATISTIC(IRModule, NumIRFunctions)
295295
FRONTEND_STATISTIC(IRModule, NumIRAliases)
@@ -299,6 +299,7 @@ FRONTEND_STATISTIC(IRModule, NumIRValueSymbols)
299299
FRONTEND_STATISTIC(IRModule, NumIRComdatSymbols)
300300
FRONTEND_STATISTIC(IRModule, NumIRBasicBlocks)
301301
FRONTEND_STATISTIC(IRModule, NumIRInsts)
302+
FRONTEND_STATISTIC(IRModule, NumGOTEntries)
302303

303304
/// Number of bytes written to the object-file output stream
304305
/// of the frontend job, which should be the same as the size of

include/swift/IRGen/Linking.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,11 +1029,6 @@ class LinkEntity {
10291029
std::string mangleAsString() const;
10301030
SILLinkage getLinkage(ForDefinition_t isDefinition) const;
10311031

1032-
/// Returns true if this function or global variable is potentially defined
1033-
/// in a different module.
1034-
///
1035-
bool isAvailableExternally(IRGenModule &IGM) const;
1036-
10371032
const ValueDecl *getDecl() const {
10381033
assert(isDeclKind(getKind()));
10391034
return reinterpret_cast<ValueDecl*>(Pointer);
@@ -1130,16 +1125,16 @@ class LinkEntity {
11301125
bool isSILFunction() const {
11311126
return getKind() == Kind::SILFunction;
11321127
}
1133-
bool isNominalTypeDescriptor() const {
1134-
return getKind() == Kind::NominalTypeDescriptor;
1128+
bool isDynamicallyReplaceableFunctionKey() const {
1129+
return getKind() == Kind::DynamicallyReplaceableFunctionKey;
11351130
}
11361131

11371132
/// Determine whether this entity will be weak-imported.
11381133
bool isWeakImported(ModuleDecl *module) const;
11391134

1140-
/// Return the source file whose codegen should trigger emission of this
1141-
/// link entity, if one can be identified.
1142-
const SourceFile *getSourceFileForEmission() const;
1135+
/// Return the module scope context whose codegen should trigger emission
1136+
/// of this link entity, if one can be identified.
1137+
DeclContext *getDeclContextForEmission() const;
11431138

11441139
/// Get the preferred alignment for the definition of this entity.
11451140
Alignment getAlignment(IRGenModule &IGM) const;

lib/IRGen/GenDecl.cpp

Lines changed: 62 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,6 @@ class PrettySourceFileEmission : public llvm::PrettyStackTraceEntry {
428428
/// Emit all the top-level code in the source file.
429429
void IRGenModule::emitSourceFile(SourceFile &SF) {
430430
PrettySourceFileEmission StackEntry(SF);
431-
llvm::SaveAndRestore<SourceFile *> SetCurSourceFile(CurSourceFile, &SF);
432431

433432
// Emit types and other global decls.
434433
for (auto *decl : SF.getTopLevelDecls())
@@ -764,19 +763,9 @@ IRGenModule::getAddrOfContextDescriptorForParent(DeclContext *parent,
764763
// descriptor, so we'll just emit an extension context.
765764
auto clas = dyn_cast<ClassDecl>(nominal);
766765
if (!clas || clas->isForeign() || hasKnownSwiftMetadata(*this, clas)) {
767-
// Some targets don't support relative references to undefined symbols.
768-
// If the extension is in a different file from the original type
769-
// declaration, it may not get emitted in this TU. Use an indirect
770-
// reference to work around the object format limitation.
771-
auto shouldBeIndirect =
772-
parent->getModuleScopeContext() != ofChild->getModuleScopeContext()
773-
? ConstantReference::Indirect
774-
: ConstantReference::Direct;
775-
776766
IRGen.noteUseOfTypeContextDescriptor(nominal, DontRequireMetadata);
777767
return getAddrOfLLVMVariableOrGOTEquivalent(
778-
LinkEntity::forNominalTypeDescriptor(nominal),
779-
shouldBeIndirect);
768+
LinkEntity::forNominalTypeDescriptor(nominal));
780769
}
781770
}
782771
return {getAddrOfExtensionContextDescriptor(ext),
@@ -2695,6 +2684,9 @@ llvm::Constant *IRGenModule::getOrCreateGOTEquivalent(llvm::Constant *global,
26952684
return gotEntry;
26962685
}
26972686

2687+
if (Context.Stats)
2688+
Context.Stats->getFrontendCounters().NumGOTEntries++;
2689+
26982690
// Use the global as the initializer for an anonymous constant. LLVM can treat
26992691
// this as equivalent to the global's GOT entry.
27002692
auto gotEquivalent = createGOTEquivalent(*this, global, entity);
@@ -2867,16 +2859,19 @@ IRGenModule::getAddrOfLLVMVariable(LinkEntity entity,
28672859
/// global variable. LLVM can replace relative references to this variable with
28682860
/// relative references to the GOT entry for the variable in the object file.
28692861
ConstantReference
2870-
IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
2871-
ConstantReference::Directness forceIndirectness) {
2862+
IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity) {
2863+
auto canDirectlyReferenceSILFunction = [&](SILFunction *silFn) {
2864+
return (silFn->isDefinition() &&
2865+
!isAvailableExternally(silFn->getLinkage()) &&
2866+
this == IRGen.getGenModule(silFn));
2867+
};
2868+
28722869
// Handle SILFunctions specially, because unlike other entities they aren't
28732870
// variables and aren't kept in the GlobalVars table.
28742871
if (entity.isSILFunction()) {
28752872
auto *silFn = entity.getSILFunction();
28762873
auto fn = getAddrOfSILFunction(silFn, NotForDefinition);
2877-
if (silFn->isDefinition() &&
2878-
!isAvailableExternally(silFn->getLinkage()) &&
2879-
this == IRGen.getGenModule(silFn)) {
2874+
if (canDirectlyReferenceSILFunction(silFn)) {
28802875
return {fn, ConstantReference::Direct};
28812876
}
28822877

@@ -2896,22 +2891,6 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
28962891
// Ensure the variable is at least forward-declared.
28972892
getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
28982893

2899-
// Guess whether a global entry is a definition from this TU. This isn't
2900-
// bulletproof, but at the point we emit conformance tables, we're far enough
2901-
// along that we should have emitted any metadata objects we were going to.
2902-
auto isDefinition = [&](llvm::Constant *global) -> bool {
2903-
// We only emit aliases for definitions. (An extern alias would be an
2904-
// extern global.)
2905-
if (isa<llvm::GlobalAlias>(global))
2906-
return true;
2907-
// Global vars are definitions if they have an initializer.
2908-
if (auto var = dyn_cast<llvm::GlobalVariable>(global))
2909-
return var->hasInitializer();
2910-
// Assume anything else isn't a definition.
2911-
return false;
2912-
};
2913-
2914-
//
29152894
auto entry = GlobalVars[entity];
29162895

29172896
/// Returns a direct reference.
@@ -2931,43 +2910,64 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
29312910
return {gotEquivalent, ConstantReference::Indirect};
29322911
};
29332912

2934-
// Return the GOT entry if we were asked to.
2935-
if (forceIndirectness == ConstantReference::Indirect)
2936-
return indirect();
2937-
29382913
// The integrated REPL incrementally adds new definitions, so always use
29392914
// indirect references in this mode.
29402915
if (IRGen.Opts.IntegratedREPL)
29412916
return indirect();
29422917

2943-
// Nominal type descriptors are only emitted once and can only be
2944-
// referenced directly from the same TU.
2945-
if (entity.isNominalTypeDescriptor()) {
2946-
auto *dc = entity.getDecl()->getDeclContext();
2947-
if (isa<ClangModuleUnit>(dc->getModuleScopeContext()) &&
2948-
this != IRGen.getGenModule(dc))
2949-
return indirect();
2950-
}
2918+
// Dynamically replaceable function keys are stored in the GlobalVars
2919+
// table, but they don't have an associated Decl, so they require
2920+
// special treatment here.
2921+
if (entity.isDynamicallyReplaceableFunctionKey()) {
2922+
auto *silFn = entity.getSILFunction();
2923+
if (canDirectlyReferenceSILFunction(silFn))
2924+
return direct();
29512925

2952-
// If the variable has already been defined in this TU,
2953-
// then it definitely doesn't need a GOT entry, and we can
2954-
// relative-reference it directly.
2955-
if (!entity.isAvailableExternally(*this) || isDefinition(entry)) {
2956-
return direct();
2926+
return indirect();
29572927
}
29582928

2959-
// If the entity will be emitted as part of the current source file
2960-
// (if we know what that is), then we can reference it directly.
2961-
if (CurSourceFile
2962-
&& !isa<ClangModuleUnit>(CurSourceFile)
2963-
&& CurSourceFile == entity.getSourceFileForEmission())
2964-
return direct();
2965-
2966-
// TODO: If we know the target entry is going to be linked into the same
2967-
// binary, then we ought to be able to directly relative-reference the
2968-
// symbol. However, some platforms don't have the necessary relocations to
2969-
// represent a relative reference to an undefined symbol, so conservatively
2970-
// produce an indirect reference in this case.
2929+
if (auto *entityDC = entity.getDeclContextForEmission()) {
2930+
auto *entitySF = entityDC->getModuleScopeContext();
2931+
bool clangImportedEntity = isa<ClangModuleUnit>(entitySF);
2932+
2933+
auto &mod = getSILModule();
2934+
2935+
if (!mod.isWholeModule()) {
2936+
// In non-WMO builds, the associated context of the SILModule must
2937+
// be a source file. Every source file is its own translation unit.
2938+
auto *modDC = mod.getAssociatedContext();
2939+
auto *modSF = modDC->getModuleScopeContext();
2940+
assert(modSF != nullptr);
2941+
2942+
// Imported entities are in a different Swift module, but are emitted
2943+
// on demand and can be referenced directly. Entities in the same
2944+
// source file can also be referenced directly.
2945+
if (clangImportedEntity ||
2946+
modSF == entitySF)
2947+
return direct();
2948+
2949+
// Everything else must be referenced indirectly.
2950+
return indirect();
2951+
}
2952+
2953+
// We're performing a WMO build.
2954+
//
2955+
// The associated context of the SILModule is the entire AST ModuleDecl,
2956+
// but we might be doing a multi-threaded IRGen build, in which case
2957+
// there is one translation unit per source file.
2958+
2959+
// Imported entities are in a different Swift module and are emitted
2960+
// on demand. In multi-threaded builds, they will be emitted into one
2961+
// translation unit only.
2962+
if (clangImportedEntity ||
2963+
entitySF->getParentModule() == mod.getSwiftModule()) {
2964+
// If we're doing a single-threaded WMO build, or if the entity is
2965+
// scheduled to be emitted in the same translation unit, reference
2966+
// it directly.
2967+
if (this == IRGen.getGenModule(entitySF))
2968+
return direct();
2969+
}
2970+
}
29712971

29722972
// Fall back to an indirect reference if we can't establish that a direct
29732973
// reference is OK.

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,6 @@ class IRGenModule {
542542
SILModuleConventions silConv;
543543
ModuleDecl *ObjCModule = nullptr;
544544
ModuleDecl *ClangImporterModule = nullptr;
545-
SourceFile *CurSourceFile = nullptr;
546545

547546
llvm::StringMap<ModuleDecl*> OriginalModules;
548547
llvm::SmallString<128> OutputFilename;
@@ -1483,8 +1482,7 @@ private: \
14831482
GenericEnvironment *getGenericEnvironment();
14841483

14851484
ConstantReference
1486-
getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
1487-
ConstantReference::Directness forceIndirect = ConstantReference::Direct);
1485+
getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity);
14881486

14891487
llvm::Constant *
14901488
emitRelativeReference(ConstantReference target,

lib/IRGen/IRGenSIL.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,12 +1585,6 @@ void IRGenModule::emitSILFunction(SILFunction *f) {
15851585
return;
15861586

15871587
PrettyStackTraceSILFunction stackTrace("emitting IR", f);
1588-
llvm::SaveAndRestore<SourceFile *> SetCurSourceFile(CurSourceFile);
1589-
if (auto dc = f->getModule().getAssociatedContext()) {
1590-
if (auto sf = dc->getParentSourceFile()) {
1591-
CurSourceFile = sf;
1592-
}
1593-
}
15941588
IRGenSILFunction(*this, f).emitSILFunction();
15951589
}
15961590

0 commit comments

Comments
 (0)