diff --git a/include/swift/AST/SILOptions.h b/include/swift/AST/SILOptions.h index b3dcb9d2c68..c259292d593 100644 --- a/include/swift/AST/SILOptions.h +++ b/include/swift/AST/SILOptions.h @@ -31,15 +31,17 @@ namespace swift { enum class LexicalLifetimesOption : uint8_t { - // Do not insert any lexical lifetimes. + // Do not insert lexical markers. Off = 0, - // Insert lexical lifetimes in SILGen, but remove them before leaving Raw SIL. - Early, + // Insert lexical markers via lexical borrow scopes and the lexical flag on + // alloc_stacks produced from alloc_boxes, but strip them when lowering out of + // Raw SIL. + DiagnosticMarkersOnly, - // Insert lexical lifetimes and do not remove them until OSSA is lowered. This - // is experimental. - ExperimentalLate, + // Insert lexical markers and use them to lengthen object lifetime based on + // lexical scope. + On, }; class SILModule; @@ -59,7 +61,8 @@ public: bool RemoveRuntimeAsserts = false; /// Enable experimental support for emitting defined borrow scopes. - LexicalLifetimesOption LexicalLifetimes = LexicalLifetimesOption::Early; + LexicalLifetimesOption LexicalLifetimes = + LexicalLifetimesOption::DiagnosticMarkersOnly; /// Force-run SIL copy propagation to shorten object lifetime in whatever /// optimization pipeline is currently used. diff --git a/include/swift/SIL/SILModule.h b/include/swift/SIL/SILModule.h index 4ba3467d1db..80810b2e4e8 100644 --- a/include/swift/SIL/SILModule.h +++ b/include/swift/SIL/SILModule.h @@ -911,14 +911,17 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SILModule &M){ inline bool SILOptions::supportsLexicalLifetimes(const SILModule &mod) const { switch (mod.getStage()) { case SILStage::Raw: - // In Raw SIL, we support lexical lifetimes as long as lexical lifetimes is - // not turned off all the way. This means lexical lifetimes is set to either - // early or experimental late. + // In raw SIL, lexical markers are used for diagnostics. These markers are + // present as long as the lexical lifetimes feature is not disabled + // entirely. return LexicalLifetimes != LexicalLifetimesOption::Off; case SILStage::Canonical: - // In Canonical SIL, we only support lexical lifetimes when in experimental - // late mode. - return LexicalLifetimes == LexicalLifetimesOption::ExperimentalLate; + // In Canonical SIL, lexical markers are used to ensure that object + // lifetimes do not get observably shortened from the end of a lexical + // scope. That behavior only occurs when lexical lifetimes is (fully) + // enabled. (When only diagnostic markers are enabled, the markers are + // stripped as part of lowering from raw to canonical SIL.) + return LexicalLifetimes == LexicalLifetimesOption::On; case SILStage::Lowered: // We do not support OSSA in Lowered SIL, so this is always false. return false; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 6bf663b7637..89920fa61c6 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1525,23 +1525,27 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args, // -enable-copy-propagation implies -enable-lexical-lifetimes unless // otherwise specified. if (Args.hasArg(OPT_enable_copy_propagation)) - Opts.LexicalLifetimes = LexicalLifetimesOption::ExperimentalLate; + Opts.LexicalLifetimes = LexicalLifetimesOption::On; + + // -disable-copy-propagation implies -enable-lexical-lifetimes=false + if (Args.hasArg(OPT_disable_copy_propagation)) + Opts.LexicalLifetimes = LexicalLifetimesOption::DiagnosticMarkersOnly; // If move-only is enabled, always enable lexical lifetime as well. Move-only // depends on lexical lifetimes. if (Args.hasArg(OPT_enable_experimental_move_only)) - Opts.LexicalLifetimes = LexicalLifetimesOption::ExperimentalLate; + Opts.LexicalLifetimes = LexicalLifetimesOption::On; if (enableLexicalLifetimesFlag) { if (*enableLexicalLifetimesFlag) { - Opts.LexicalLifetimes = LexicalLifetimesOption::ExperimentalLate; + Opts.LexicalLifetimes = LexicalLifetimesOption::On; } else { - Opts.LexicalLifetimes = LexicalLifetimesOption::Early; + Opts.LexicalLifetimes = LexicalLifetimesOption::DiagnosticMarkersOnly; } } if (enableLexicalBorrowScopesFlag) { if (*enableLexicalBorrowScopesFlag) { - Opts.LexicalLifetimes = LexicalLifetimesOption::Early; + Opts.LexicalLifetimes = LexicalLifetimesOption::DiagnosticMarkersOnly; } else { Opts.LexicalLifetimes = LexicalLifetimesOption::Off; } diff --git a/lib/SILOptimizer/Mandatory/LexicalLifetimeEliminator.cpp b/lib/SILOptimizer/Mandatory/LexicalLifetimeEliminator.cpp index 11fe581594f..977a61b92e1 100644 --- a/lib/SILOptimizer/Mandatory/LexicalLifetimeEliminator.cpp +++ b/lib/SILOptimizer/Mandatory/LexicalLifetimeEliminator.cpp @@ -30,7 +30,7 @@ class LexicalLifetimeEliminatorPass : public SILFunctionTransform { // run this pass since we want lexical lifetimes to exist later in the // pipeline. if (fn->getModule().getOptions().LexicalLifetimes == - LexicalLifetimesOption::ExperimentalLate) + LexicalLifetimesOption::On) return; bool madeChange = false; diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp index 82929b0df72..796dcf1a1c2 100644 --- a/lib/SILOptimizer/PassManager/PassPipeline.cpp +++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp @@ -180,7 +180,7 @@ static void addMandatoryDiagnosticOptPipeline(SILPassPipelinePlan &P) { // Now that we have finished performing diagnostics that rely on lexical // scopes, if lexical lifetimes are not enabled, eliminate lexical lfietimes. - if (Options.LexicalLifetimes != LexicalLifetimesOption::ExperimentalLate) { + if (Options.LexicalLifetimes != LexicalLifetimesOption::On) { P.addLexicalLifetimeEliminator(); } diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index 800f19da74d..b7a70260c8d 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -316,8 +316,7 @@ static bool shouldAddLexicalLifetime(AllocStackInst *asi) { asi->getFunction() ->getModule() .getASTContext() - .SILOpts.LexicalLifetimes == - LexicalLifetimesOption::ExperimentalLate && + .SILOpts.LexicalLifetimes == LexicalLifetimesOption::On && asi->isLexical() && !asi->getElementType().isTrivial(*asi->getFunction()); } diff --git a/tools/sil-opt/SILOpt.cpp b/tools/sil-opt/SILOpt.cpp index d8f03256f5b..f7495a3ef9d 100644 --- a/tools/sil-opt/SILOpt.cpp +++ b/tools/sil-opt/SILOpt.cpp @@ -528,7 +528,9 @@ int main(int argc, char **argv) { SILOpts.DisableCopyPropagation = DisableCopyPropagation; if (EnableCopyPropagation) - SILOpts.LexicalLifetimes = LexicalLifetimesOption::ExperimentalLate; + SILOpts.LexicalLifetimes = LexicalLifetimesOption::On; + if (DisableCopyPropagation) + SILOpts.LexicalLifetimes = LexicalLifetimesOption::DiagnosticMarkersOnly; // Enable lexical lifetimes if it is set or if experimental move only is // enabled. This is because move only depends on lexical lifetimes being @@ -541,7 +543,7 @@ int main(int argc, char **argv) { exit(-1); } if (enableLexicalLifetimes) - SILOpts.LexicalLifetimes = LexicalLifetimesOption::ExperimentalLate; + SILOpts.LexicalLifetimes = LexicalLifetimesOption::On; if (!EnableLexicalBorrowScopes) SILOpts.LexicalLifetimes = LexicalLifetimesOption::Off;