Skip to content

Commit 72eb5e2

Browse files
committed
[move-operator] Specify if LexicalLifetimes is enabled using an enum instead of a bool.
The reason why I am doing this is that we are going to be enabling lexical lifetimes early in the pipeline so that I can use it for the move operator's diagnostics. To make it easy for passes to know whether or not they should support lexical lifetimes, I included a query on SILOptions called supportsLexicalLifetimes. This will return true if the pass (given the passed in option) should insert the lexical lifetime flag. This ensures that passes that run in both pipelines (e.x.: AllocBoxToStack) know whether or not to set the lexical lifetime flag without having to locally reason about it. This is just chopping off layers of a larger patch I am upstreaming. NOTE: This is technically NFC since it leaves the default alone of not inserting lexical lifetimes at all.
1 parent d0cc575 commit 72eb5e2

File tree

12 files changed

+101
-32
lines changed

12 files changed

+101
-32
lines changed

include/swift/AST/SILOptions.h

Lines changed: 18 additions & 1 deletion
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

Lines changed: 7 additions & 1 deletion
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

Lines changed: 16 additions & 0 deletions
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

Lines changed: 14 additions & 3 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 2 additions & 1 deletion
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

Lines changed: 5 additions & 3 deletions
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

Lines changed: 4 additions & 2 deletions
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

Lines changed: 2 additions & 4 deletions
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

Lines changed: 4 additions & 3 deletions
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
}

0 commit comments

Comments
 (0)