Skip to content

Commit 2dfd232

Browse files
committed
Implement conditional stripping of type descriptors, protocols and protocol conformances via !llvm.used.conditional
A new LLVM IR affordance that allows expressing conditions under which globals can be removed/dropped (even when marked with @llvm.used) is being discussed at: - <https://reviews.llvm.org/D104496> - <https://lists.llvm.org/pipermail/llvm-dev/2021-September/152656.html> This is a preliminary implementation that marks runtime lookup records (namely protocol records, type descriptors records and protocol conformance records) with the !llvm.used.conditional descriptors. That allows link-time / LTO-time removal of these records (by GlobalDCE) based on whether they're actually used within the linkage unit. Effectively, this allows libraries that have a limited and known set of clients, to be optimized against the client at LTO time, and significantly reduce the code size of that library. Parts of the implementation: - New -conditional-runtime-records frontend flag to enable using !llvm.used.conditional - IRGen code that emits these records can now emit these either as a single contiguous array (asContiguousArray = true, the old way), which is used for JIT mode, or as indivial globals (asContiguousArray = false), which is necessary for the !llvm.used.conditional stripping to work. - When records are emitted as individual globals, they have new names of "\01l_protocol_" + mangled name of the protocol descriptor, and similarly for other records. - Fixed existing tests to account for individual records instead of a single array - Added an IR level test, and an end-to-end execution test to demonstrate that the !llvm.used.conditional-based stripping actually works.
1 parent d0e0500 commit 2dfd232

13 files changed

+435
-140
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,8 @@ class IRGenOptions {
361361

362362
unsigned WitnessMethodElimination : 1;
363363

364+
unsigned ConditionalRuntimeRecords : 1;
365+
364366
unsigned InternalizeAtLink : 1;
365367

366368
/// The number of threads for multi-threaded code generation.
@@ -422,7 +424,8 @@ class IRGenOptions {
422424
DisableRoundTripDebugTypes(false), DisableDebuggerShadowCopies(false),
423425
DisableConcreteTypeMetadataMangledNameAccessors(false),
424426
EnableGlobalISel(false), VirtualFunctionElimination(false),
425-
WitnessMethodElimination(false), InternalizeAtLink(false),
427+
WitnessMethodElimination(false), ConditionalRuntimeRecords(false),
428+
InternalizeAtLink(false),
426429
CmdArgs(),
427430
SanitizeCoverage(llvm::SanitizerCoverageOptions()),
428431
TypeInfoFilter(TypeInfoDumpFilter::All) {}

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,10 @@ def internalize_at_link : Flag<["-"], "internalize-at-link">,
507507
" all client code of public types is part of the same link unit, or that"
508508
" external symbols are explicitly requested via -exported_symbols_list)">;
509509

510+
def conditional_runtime_records : Flag<["-"], "conditional-runtime-records">,
511+
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
512+
HelpText<"Allow removal of runtime metadata records (public types, protocol conformances) based on whether they're used or unused">;
513+
510514
def disable_previous_implementation_calls_in_dynamic_replacements :
511515
Flag<["-"], "disable-previous-implementation-calls-in-dynamic-replacements">,
512516
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,6 +1934,10 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
19341934
Opts.WitnessMethodElimination = true;
19351935
}
19361936

1937+
if (Args.hasArg(OPT_conditional_runtime_records)) {
1938+
Opts.ConditionalRuntimeRecords = true;
1939+
}
1940+
19371941
if (Args.hasArg(OPT_internalize_at_link)) {
19381942
Opts.InternalizeAtLink = true;
19391943
}

0 commit comments

Comments
 (0)