Skip to content

Commit 3eba144

Browse files
authored
Merge pull request #40189 from gottesmm/pr-aeffd0309402b8c9a744770c71ce40ca6f0459ff
[move-operator] Specify if LexicalLifetimes is enabled using an enum instead of a bool.
2 parents 66bd5e6 + 72eb5e2 commit 3eba144

File tree

12 files changed

+101
-32
lines changed

12 files changed

+101
-32
lines changed

include/swift/AST/SILOptions.h

+18-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@
3030

3131
namespace swift {
3232

33+
enum class LexicalLifetimesOption : uint8_t {
34+
// Do not insert any lexical lifetimes.
35+
Off = 0,
36+
37+
// Insert lexical lifetimes and do not remove them until OSSA is lowered. This
38+
// is experimental.
39+
ExperimentalLate,
40+
};
41+
42+
class SILModule;
43+
3344
class SILOptions {
3445
public:
3546
/// Controls the aggressiveness of the performance inliner.
@@ -45,7 +56,7 @@ class SILOptions {
4556
bool RemoveRuntimeAsserts = false;
4657

4758
/// Enable experimental support for emitting defined borrow scopes.
48-
bool EnableExperimentalLexicalLifetimes = false;
59+
LexicalLifetimesOption LexicalLifetimes = LexicalLifetimesOption::Off;
4960

5061
/// Force-run SIL copy propagation to shorten object lifetime in whatever
5162
/// optimization pipeline is currently used.
@@ -226,6 +237,12 @@ class SILOptions {
226237
bool shouldOptimize() const {
227238
return OptMode > OptimizationMode::NoOptimization;
228239
}
240+
241+
/// Returns true if we support inserting lexical lifetimes given the current
242+
/// SIL stage.
243+
///
244+
/// Defined in SILModule.h.
245+
bool supportsLexicalLifetimes(const SILModule &mod) const;
229246
};
230247

231248
} // end namespace swift

include/swift/Option/FrontendOptions.td

+7-1
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,15 @@ def enable_experimental_concurrency :
255255
Flag<["-"], "enable-experimental-concurrency">,
256256
HelpText<"Enable experimental concurrency model">;
257257

258+
def disable_lexical_lifetimes :
259+
Flag<["-"], "disable-lexical-lifetimes">,
260+
HelpText<"Disables early lexical lifetimes. Mutually exclusive with "
261+
"-enable-experimental-lexical-lifetimes">;
262+
258263
def enable_experimental_lexical_lifetimes :
259264
Flag<["-"], "enable-experimental-lexical-lifetimes">,
260-
HelpText<"Enable experimental lexical lifetimes">;
265+
HelpText<"Enable experimental lexical lifetimes. Mutually exclusive with "
266+
"-disable-early-lexical-lifetimes">;
261267

262268
def enable_experimental_move_only :
263269
Flag<["-"], "enable-experimental-move-only">,

include/swift/SIL/SILModule.h

+16
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,22 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SILModule &M){
908908
return OS;
909909
}
910910

911+
inline bool SILOptions::supportsLexicalLifetimes(const SILModule &mod) const {
912+
switch (mod.getStage()) {
913+
case SILStage::Raw:
914+
// In Raw SIL, we support lexical lifetimes as long as lexical lifetimes is
915+
// not turned off all the way.
916+
return LexicalLifetimes != LexicalLifetimesOption::Off;
917+
case SILStage::Canonical:
918+
// In Canonical SIL, we only support lexical lifetimes when in experimental
919+
// late mode.
920+
return LexicalLifetimes == LexicalLifetimesOption::ExperimentalLate;
921+
case SILStage::Lowered:
922+
// We do not support OSSA in Lowered SIL, so this is always false.
923+
return false;
924+
}
925+
}
926+
911927
/// Print a simple description of a SILModule for the request evaluator.
912928
void simple_display(llvm::raw_ostream &out, const SILModule *M);
913929

lib/Frontend/CompilerInvocation.cpp

+14-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "swift/AST/SILOptions.h"
1314
#include "swift/Frontend/Frontend.h"
1415

1516
#include "ArgsToFrontendOptionsConverter.h"
@@ -1430,12 +1431,22 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
14301431
// -Ounchecked might also set removal of runtime asserts (cond_fail).
14311432
Opts.RemoveRuntimeAsserts |= Args.hasArg(OPT_RemoveRuntimeAsserts);
14321433

1433-
Opts.EnableExperimentalLexicalLifetimes |=
1434-
Args.hasArg(OPT_enable_experimental_lexical_lifetimes);
14351434
// If experimental move only is enabled, always enable lexical lifetime as
14361435
// well. Move only depends on lexical lifetimes.
1437-
Opts.EnableExperimentalLexicalLifetimes |=
1436+
bool enableExperimentalLexicalLifetimes =
1437+
Args.hasArg(OPT_enable_experimental_lexical_lifetimes) ||
14381438
Args.hasArg(OPT_enable_experimental_move_only);
1439+
// Error if both experimental lexical lifetimes and disable lexical lifetimes
1440+
// are both set.
1441+
if (enableExperimentalLexicalLifetimes &&
1442+
Args.hasArg(OPT_disable_lexical_lifetimes)) {
1443+
return true;
1444+
} else {
1445+
if (enableExperimentalLexicalLifetimes)
1446+
Opts.LexicalLifetimes = LexicalLifetimesOption::ExperimentalLate;
1447+
if (Args.hasArg(OPT_disable_lexical_lifetimes))
1448+
Opts.LexicalLifetimes = LexicalLifetimesOption::Off;
1449+
}
14391450

14401451
Opts.EnableCopyPropagation |= Args.hasArg(OPT_enable_copy_propagation);
14411452
Opts.DisableCopyPropagation |= Args.hasArg(OPT_disable_copy_propagation);

lib/SILGen/SILGenDecl.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ class LetValueInitialization : public Initialization {
540540
address = value;
541541
SILLocation PrologueLoc(vd);
542542

543-
if (SGF.getASTContext().SILOpts.EnableExperimentalLexicalLifetimes &&
543+
if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule()) &&
544544
value->getOwnershipKind() != OwnershipKind::None) {
545545
if (!SGF.getASTContext().LangOpts.EnableExperimentalMoveOnly) {
546546
value = SILValue(
@@ -1760,7 +1760,7 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
17601760
return;
17611761
}
17621762

1763-
if (!getASTContext().SILOpts.EnableExperimentalLexicalLifetimes ||
1763+
if (!getASTContext().SILOpts.supportsLexicalLifetimes(getModule()) ||
17641764
Val->getOwnershipKind() == OwnershipKind::None) {
17651765
B.emitDestroyValueOperation(silLoc, Val);
17661766
return;

lib/SILGen/SILGenProlog.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,8 @@ struct ArgumentInitHelper {
273273
SILValue value = argrv.getValue();
274274
SILDebugVariable varinfo(pd->isImmutable(), ArgNo);
275275
if (!argrv.getType().isAddress()) {
276-
if (SGF.getASTContext().SILOpts.EnableExperimentalLexicalLifetimes &&
276+
if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(
277+
SGF.getModule()) &&
277278
value->getOwnershipKind() == OwnershipKind::Owned) {
278279
bool isNoImplicitCopy = false;
279280
if (auto *arg = dyn_cast<SILFunctionArgument>(value))

lib/SILOptimizer/Mandatory/LexicalLifetimeEliminator.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ class LexicalLifetimeEliminatorPass : public SILFunctionTransform {
2626
if (fn->wasDeserializedCanonical())
2727
return;
2828

29-
// If we have experimental lexical lifetimes enabled, we do not want to run
30-
// this pass since we want lexical lifetimes to exist later in the pipeline.
31-
if (fn->getModule().getOptions().EnableExperimentalLexicalLifetimes)
29+
// If we have experimental late lexical lifetimes enabled, we do not want to
30+
// run this pass since we want lexical lifetimes to exist later in the
31+
// pipeline.
32+
if (fn->getModule().getOptions().LexicalLifetimes ==
33+
LexicalLifetimesOption::ExperimentalLate)
3234
return;
3335

3436
bool madeChange = false;

lib/SILOptimizer/PassManager/PassPipeline.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
///
2020
//===----------------------------------------------------------------------===//
2121

22+
#include "swift/AST/SILOptions.h"
2223
#define DEBUG_TYPE "sil-passpipeline-plan"
2324
#include "swift/SILOptimizer/PassManager/PassPipeline.h"
2425
#include "swift/AST/ASTContext.h"
@@ -138,7 +139,8 @@ static void addMandatoryDiagnosticOptPipeline(SILPassPipelinePlan &P) {
138139
P.addSILSkippingChecker();
139140
#endif
140141

141-
if (Options.shouldOptimize() && !Options.EnableExperimentalLexicalLifetimes) {
142+
if (Options.shouldOptimize() &&
143+
Options.LexicalLifetimes != LexicalLifetimesOption::ExperimentalLate) {
142144
P.addDestroyHoisting();
143145
}
144146
P.addMandatoryInlining();
@@ -171,7 +173,7 @@ static void addMandatoryDiagnosticOptPipeline(SILPassPipelinePlan &P) {
171173

172174
// Now that we have finished performing diagnostics that rely on lexical
173175
// scopes, if lexical lifetimes are not enabled, eliminate lexical lfietimes.
174-
if (!Options.EnableExperimentalLexicalLifetimes) {
176+
if (Options.LexicalLifetimes != LexicalLifetimesOption::ExperimentalLate) {
175177
P.addLexicalLifetimeEliminator();
176178
}
177179

lib/SILOptimizer/Transforms/AllocBoxToStack.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -533,10 +533,8 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
533533
SILBuilderWithScope Builder(ABI);
534534
assert(ABI->getBoxType()->getLayout()->getFields().size() == 1
535535
&& "rewriting multi-field box not implemented");
536-
bool isLexical = ABI->getFunction()
537-
->getModule()
538-
.getASTContext()
539-
.SILOpts.EnableExperimentalLexicalLifetimes;
536+
auto &mod = ABI->getFunction()->getModule();
537+
bool isLexical = mod.getASTContext().SILOpts.supportsLexicalLifetimes(mod);
540538
auto *ASI = Builder.createAllocStack(
541539
ABI->getLoc(),
542540
getSILBoxFieldType(TypeExpansionContext(*ABI->getFunction()),

lib/SILOptimizer/Transforms/SILMem2Reg.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -314,9 +314,10 @@ static SILValue createValueForEmptyTuple(SILType ty,
314314
static bool shouldAddLexicalLifetime(AllocStackInst *asi) {
315315
return asi->getFunction()->hasOwnership() &&
316316
asi->getFunction()
317-
->getModule()
318-
.getASTContext()
319-
.SILOpts.EnableExperimentalLexicalLifetimes &&
317+
->getModule()
318+
.getASTContext()
319+
.SILOpts.LexicalLifetimes ==
320+
LexicalLifetimesOption::ExperimentalLate &&
320321
asi->isLexical() &&
321322
!asi->getElementType().isTrivial(*asi->getFunction());
322323
}

lib/SILOptimizer/Utils/SILInliner.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -578,10 +578,9 @@ void SILInlineCloner::postFixUp(SILFunction *calleeFunction) {
578578

579579
SILValue SILInlineCloner::borrowFunctionArgument(SILValue callArg,
580580
FullApplySite AI) {
581-
auto enableLexicalLifetimes = Apply.getFunction()
582-
->getModule()
583-
.getASTContext()
584-
.SILOpts.EnableExperimentalLexicalLifetimes;
581+
auto &mod = Apply.getFunction()->getModule();
582+
auto enableLexicalLifetimes =
583+
mod.getASTContext().SILOpts.supportsLexicalLifetimes(mod);
585584
auto argOwnershipRequiresBorrow = [&]() {
586585
auto kind = callArg.getOwnershipKind();
587586
if (enableLexicalLifetimes) {

tools/sil-opt/SILOpt.cpp

+24-8
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,13 @@ EnableExperimentalConcurrency("enable-experimental-concurrency",
107107

108108
static llvm::cl::opt<bool> EnableExperimentalLexicalLifetimes(
109109
"enable-experimental-lexical-lifetimes",
110-
llvm::cl::desc("Enable experimental lexical lifetimes."));
110+
llvm::cl::desc("Enable experimental lexical lifetimes. Mutually exclusive "
111+
"with disable-lexical-lifetimes."));
112+
113+
static llvm::cl::opt<bool> DisableLexicalLifetimes(
114+
"disable-lexical-lifetimes",
115+
llvm::cl::desc("Disable the default early lexical lifetimes. Mutually "
116+
"exclusive with enable-experimental-lexical-lifetimes"));
111117

112118
static llvm::cl::opt<bool>
113119
EnableExperimentalMoveOnly("enable-experimental-move-only",
@@ -519,13 +525,23 @@ int main(int argc, char **argv) {
519525
SILOpts.EnableOSSAModules = EnableOSSAModules;
520526
SILOpts.EnableCopyPropagation = EnableCopyPropagation;
521527
SILOpts.DisableCopyPropagation = DisableCopyPropagation;
522-
SILOpts.EnableExperimentalLexicalLifetimes =
523-
EnableExperimentalLexicalLifetimes;
524-
// Also enable lexical lifetimes if experimental move only is enabled. This is
525-
// because move only depends on lexical lifetimes being enabled and it saved
526-
// some typing ; ).
527-
SILOpts.EnableExperimentalLexicalLifetimes |=
528-
EnableExperimentalMoveOnly;
528+
529+
// Enable lexical lifetimes if it is set or if experimental move only is
530+
// enabled. This is because move only depends on lexical lifetimes being
531+
// enabled and it saved some typing ; ).
532+
bool enableExperimentalLexicalLifetimes =
533+
EnableExperimentalLexicalLifetimes | EnableExperimentalMoveOnly;
534+
if (enableExperimentalLexicalLifetimes && DisableLexicalLifetimes) {
535+
fprintf(
536+
stderr,
537+
"Error! Can not specify both -enable-experimental-lexical-lifetimes "
538+
"and -disable-lexical-lifetimes!\n");
539+
exit(-1);
540+
}
541+
if (enableExperimentalLexicalLifetimes)
542+
SILOpts.LexicalLifetimes = LexicalLifetimesOption::ExperimentalLate;
543+
if (DisableLexicalLifetimes)
544+
SILOpts.LexicalLifetimes = LexicalLifetimesOption::Off;
529545

530546
serialization::ExtendedValidationInfo extendedInfo;
531547
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =

0 commit comments

Comments
 (0)