Skip to content

Commit 406aa86

Browse files
authored
Merge pull request #41557 from atrick/addrlower-update
Update and reimplement AddressLowering pass (for SIL opaque values).
2 parents 2c5f019 + 6f3a0c3 commit 406aa86

37 files changed

+4865
-1847
lines changed

docs/SIL.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2193,6 +2193,26 @@ parts::
21932193
return %1 : $Klass
21942194
}
21952195

2196+
Forwarding Address-Only Values
2197+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2198+
2199+
Address-only values are potentially unmovable when borrowed. This
2200+
means that they cannot be forwarded with guaranteed ownership unless
2201+
the forwarded value has the same representation as in the original
2202+
value and can reuse the same storage. Non-destructive projection is
2203+
allowed, such as `struct_extract`. Aggregation, such as `struct`, and
2204+
destructive disaggregation, such as `switch_enum` is not allowed. This
2205+
is an invariant for OSSA with opaque SIL values for these reasons:
2206+
2207+
1. To avoid implicit semantic copies. For move-only values, this allows
2208+
complete diagnostics. And in general, it makes it impossible for SIL
2209+
passes to "accidentally" create copies.
2210+
2211+
2. To reuse borrowed storage. This allows the optimizer to share the same
2212+
storage for multiple exclusive reads of the same variable, avoiding
2213+
copies. It may also be necessary to support native Swift atomics, which
2214+
will be unmovable-when-borrowed.
2215+
21962216
Borrowed Object based Safe Interior Pointers
21972217
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21982218

include/swift/AST/SILOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ class SILOptions {
140140
/// If this is disabled we do not serialize in OSSA form when optimizing.
141141
bool EnableOSSAModules = false;
142142

143+
/// If set to true, compile with the SIL Opaque Values enabled.
144+
bool EnableSILOpaqueValues = false;
145+
143146
// The kind of function bodies to skip emitting.
144147
FunctionBodySkipping SkipFunctionBodies = FunctionBodySkipping::None;
145148

include/swift/Basic/LangOptions.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -379,11 +379,6 @@ namespace swift {
379379
/// [TODO: Clang-type-plumbing] Turn on for feature rollout.
380380
bool UseClangFunctionTypes = false;
381381

382-
/// If set to true, compile with the SIL Opaque Values enabled.
383-
/// This is for bootstrapping. It can't be in SILOptions because the
384-
/// TypeChecker uses it to set resolve the ParameterConvention.
385-
bool EnableSILOpaqueValues = false;
386-
387382
/// If set to true, the diagnosis engine can assume the emitted diagnostics
388383
/// will be used in editor. This usually leads to more aggressive fixit.
389384
bool DiagnosticsEditorMode = false;

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -507,9 +507,6 @@ def disable_sil_ownership_verifier : Flag<["-"], "disable-sil-ownership-verifier
507507
def suppress_static_exclusivity_swap : Flag<["-"], "suppress-static-exclusivity-swap">,
508508
HelpText<"Suppress static violations of exclusive access with swap()">;
509509

510-
def enable_sil_opaque_values : Flag<["-"], "enable-sil-opaque-values">,
511-
HelpText<"Enable SIL Opaque Values">;
512-
513510
def enable_experimental_static_assert :
514511
Flag<["-"], "enable-experimental-static-assert">,
515512
HelpText<"Enable experimental #assert">;
@@ -1022,6 +1019,9 @@ def enable_ossa_modules : Flag<["-"], "enable-ossa-modules">,
10221019
HelpText<"Always serialize SIL in ossa form. If this flag is not passed in, "
10231020
"when optimizing ownership will be lowered before serializing SIL">;
10241021

1022+
def enable_sil_opaque_values : Flag<["-"], "enable-sil-opaque-values">,
1023+
HelpText<"Enable SIL Opaque Values">;
1024+
10251025
def new_driver_path
10261026
: Separate<["-"], "new-driver-path">, MetaVarName<"<path>">,
10271027
HelpText<"Path of the new driver to be used">;

include/swift/SIL/ApplySite.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -585,9 +585,9 @@ class FullApplySite : public ApplySite {
585585
}
586586

587587
/// Get the SIL value that represents all of the given call's results. For a
588-
/// single direct result, returns the result. For multiple results, returns a
589-
/// fake tuple value. The tuple has no storage of its own. The real results
590-
/// must be extracted from it.
588+
/// single direct result, returns the actual result. For multiple results,
589+
/// returns a pseudo-result tuple. The tuple has no storage of its own. The
590+
/// real results must be extracted from it.
591591
///
592592
/// For ApplyInst, returns the single-value instruction itself.
593593
///
@@ -596,7 +596,7 @@ class FullApplySite : public ApplySite {
596596
/// For BeginApplyInst, returns an invalid value. For coroutines, there is no
597597
/// single value representing all results. Yielded values are generally
598598
/// handled differently since they have the convention of incoming arguments.
599-
SILValue getPseudoResult() const {
599+
SILValue getResult() const {
600600
switch (getKind()) {
601601
case FullApplySiteKind::ApplyInst:
602602
return SILValue(cast<ApplyInst>(getInstruction()));

include/swift/SIL/SILBuilder.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,11 +266,10 @@ class SILBuilder {
266266
void clearInsertionPoint() { BB = nullptr; }
267267

268268
/// setInsertionPoint - Set the insertion point.
269-
void setInsertionPoint(SILBasicBlock *BB, SILBasicBlock::iterator InsertPt) {
269+
void setInsertionPoint(SILBasicBlock *BB, SILBasicBlock::iterator insertPt) {
270270
this->BB = BB;
271-
this->InsertPt = InsertPt;
272-
if (InsertPt == BB->end())
273-
return;
271+
this->InsertPt = insertPt;
272+
assert(insertPt == BB->end() || insertPt->getParent() == BB);
274273
}
275274

276275
/// setInsertionPoint - Set the insertion point to insert before the specified

include/swift/SIL/SILModule.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,12 @@ class SILModule {
307307
/// The stage of processing this module is at.
308308
SILStage Stage;
309309

310+
/// True if SIL conventions force address-only to be passed by address.
311+
///
312+
/// Used for bootstrapping the AddressLowering pass. This should eventually
313+
/// be inferred from the SIL stage to be true only when Stage == Lowered.
314+
bool loweredAddresses;
315+
310316
/// The set of deserialization notification handlers.
311317
DeserializationNotificationHandlerSet deserializationNotificationHandlers;
312318

@@ -806,6 +812,11 @@ class SILModule {
806812
Stage = s;
807813
}
808814

815+
/// True if SIL conventions force address-only to be passed by address.
816+
bool useLoweredAddresses() const { return loweredAddresses; }
817+
818+
void setLoweredAddresses(bool val) { loweredAddresses = val; }
819+
809820
llvm::IndexedInstrProfReader *getPGOReader() const { return PGOReader.get(); }
810821

811822
void setPGOReader(std::unique_ptr<llvm::IndexedInstrProfReader> IPR) {
@@ -972,15 +983,13 @@ inline bool SILOptions::supportsLexicalLifetimes(const SILModule &mod) const {
972983
// entirely.
973984
return LexicalLifetimes != LexicalLifetimesOption::Off;
974985
case SILStage::Canonical:
986+
case SILStage::Lowered:
975987
// In Canonical SIL, lexical markers are used to ensure that object
976988
// lifetimes do not get observably shortened from the end of a lexical
977989
// scope. That behavior only occurs when lexical lifetimes is (fully)
978990
// enabled. (When only diagnostic markers are enabled, the markers are
979991
// stripped as part of lowering from raw to canonical SIL.)
980992
return LexicalLifetimes == LexicalLifetimesOption::On;
981-
case SILStage::Lowered:
982-
// We do not support OSSA in Lowered SIL, so this is always false.
983-
return false;
984993
}
985994
}
986995

lib/Frontend/CompilerInvocation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
770770
Opts.EnableObjCInterop =
771771
Args.hasFlag(OPT_enable_objc_interop, OPT_disable_objc_interop,
772772
Target.isOSDarwin());
773-
Opts.EnableSILOpaqueValues |= Args.hasArg(OPT_enable_sil_opaque_values);
774773

775774
Opts.VerifyAllSubstitutionMaps |= Args.hasArg(OPT_verify_all_substitution_maps);
776775

@@ -1678,6 +1677,7 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
16781677
Opts.EnableARCOptimizations &= !Args.hasArg(OPT_disable_arc_opts);
16791678
Opts.EnableOSSAModules |= Args.hasArg(OPT_enable_ossa_modules);
16801679
Opts.EnableOSSAOptimizations &= !Args.hasArg(OPT_disable_ossa_opts);
1680+
Opts.EnableSILOpaqueValues |= Args.hasArg(OPT_enable_sil_opaque_values);
16811681
Opts.EnableSpeculativeDevirtualization |= Args.hasArg(OPT_enable_spec_devirt);
16821682
Opts.EnableActorDataRaceChecks |= Args.hasFlag(
16831683
OPT_enable_actor_data_race_checks,

lib/SIL/IR/SILModule.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ class SILModule::SerializationCallback final
9191

9292
SILModule::SILModule(llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
9393
Lowering::TypeConverter &TC, const SILOptions &Options)
94-
: Stage(SILStage::Raw), indexTrieRoot(new IndexTrieNode()),
95-
Options(Options), serialized(false),
94+
: Stage(SILStage::Raw), loweredAddresses(!Options.EnableSILOpaqueValues),
95+
indexTrieRoot(new IndexTrieNode()), Options(Options), serialized(false),
9696
regDeserializationNotificationHandlerForNonTransparentFuncOME(false),
9797
regDeserializationNotificationHandlerForAllFuncOME(false),
9898
prespecializedFunctionDeclsImported(false), SerializeSILAction(),

lib/SIL/IR/SILType.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -506,10 +506,7 @@ SILResultInfo::getOwnershipKind(SILFunction &F,
506506
}
507507

508508
SILModuleConventions::SILModuleConventions(SILModule &M)
509-
: M(&M),
510-
loweredAddresses(!M.getASTContext().LangOpts.EnableSILOpaqueValues
511-
|| M.getStage() == SILStage::Lowered)
512-
{}
509+
: M(&M), loweredAddresses(M.useLoweredAddresses()) {}
513510

514511
bool SILModuleConventions::isReturnedIndirectlyInSIL(SILType type,
515512
SILModule &M) {

lib/SIL/IR/TypeLowering.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,10 +1605,6 @@ namespace {
16051605
};
16061606

16071607
/// Lower address only types as opaque values.
1608-
///
1609-
/// Opaque values behave like loadable leaf types in SIL.
1610-
///
1611-
/// FIXME: When you remove an unreachable, just delete the method.
16121608
class OpaqueValueTypeLowering : public LeafLoadableTypeLowering {
16131609
public:
16141610
OpaqueValueTypeLowering(SILType type, RecursiveProperties properties,
@@ -1622,6 +1618,20 @@ namespace {
16221618
llvm_unreachable("copy into");
16231619
}
16241620

1621+
// OpaqueValue store cannot be decoupled from a destroy because it is not
1622+
// bitwise-movable.
1623+
void emitStore(SILBuilder &B, SILLocation loc, SILValue value,
1624+
SILValue addr, StoreOwnershipQualifier qual) const override {
1625+
B.createStore(loc, value, addr, qual);
1626+
}
1627+
1628+
// OpaqueValue load cannot be decoupled from a copy because it is not
1629+
// bitwise-movable.
1630+
SILValue emitLoad(SILBuilder &B, SILLocation loc, SILValue addr,
1631+
LoadOwnershipQualifier qual) const override {
1632+
return B.createLoad(loc, addr, qual);
1633+
}
1634+
16251635
// --- Same as LeafLoadableTypeLowering.
16261636

16271637
SILValue emitLoweredCopyValue(SILBuilder &B, SILLocation loc,
@@ -1683,7 +1693,7 @@ namespace {
16831693

16841694
TypeLowering *handleAddressOnly(CanType type,
16851695
RecursiveProperties properties) {
1686-
if (!TC.Context.LangOpts.EnableSILOpaqueValues) {
1696+
if (!TC.Context.SILOpts.EnableSILOpaqueValues) {
16871697
auto silType = SILType::getPrimitiveAddressType(type);
16881698
return new (TC) AddressOnlyTypeLowering(silType, properties,
16891699
Expansion);

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6535,6 +6535,9 @@ bool SILParserState::parseDeclSILStage(Parser &P) {
65356535
}
65366536

65376537
M.setStage(stage);
6538+
if (M.getOptions().EnableSILOpaqueValues) {
6539+
M.setLoweredAddresses(stage != SILStage::Raw);
6540+
}
65386541
DidParseSILStage = true;
65396542
return false;
65406543
}

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,13 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
10081008
auto *TI = predBB->getTerminator();
10091009
if (F.hasOwnership()) {
10101010
require(isa<BranchInst>(TI), "All phi inputs must be branch operands.");
1011+
1012+
// Address-only values are potentially unmovable when borrowed. See also
1013+
// checkOwnershipForwardingInst. A phi implies a move of its arguments
1014+
// because they can't necessarilly all reuse the same storage.
1015+
require((!arg->getType().isAddressOnly(F)
1016+
|| arg->getOwnershipKind() != OwnershipKind::Guaranteed),
1017+
"Guaranteed address-only phi not allowed--implies a copy");
10111018
} else {
10121019
// FIXME: when critical edges are removed and cond_br arguments are
10131020
// disallowed, only allow BranchInst.
@@ -1269,10 +1276,11 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
12691276
checkOwnershipForwardingTermInst(term);
12701277
}
12711278

1272-
// Address-only values are potentially move-only, and unmovable if they are
1273-
// borrowed. Ensure that guaranteed address-only values are forwarded with
1274-
// the same representation. Non-destructive projection is
1275-
// allowed. Aggregation and destructive disaggregation is not allowed.
1279+
// Address-only values are potentially unmovable when borrowed. Ensure that
1280+
// guaranteed address-only values are forwarded with the same
1281+
// representation. Non-destructive projection is allowed. Aggregation and
1282+
// destructive disaggregation is not allowed. See SIL.rst, Forwarding
1283+
// Addres-Only Values.
12761284
if (ownership == OwnershipKind::Guaranteed
12771285
&& OwnershipForwardingMixin::isAddressOnly(i)) {
12781286
require(OwnershipForwardingMixin::hasSameRepresentation(i),

lib/SILGen/SILGenFunction.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -290,13 +290,12 @@ void SILGenFunction::emitCaptures(SILLocation loc,
290290
// Get an address value for a SILValue if it is address only in an type
291291
// expansion context without opaque archetype substitution.
292292
auto getAddressValue = [&](SILValue entryValue) -> SILValue {
293-
if (SGM.Types
294-
.getTypeLowering(
295-
valueType,
296-
TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(
297-
expansion.getResilienceExpansion()))
298-
.isAddressOnly() &&
299-
!entryValue->getType().isAddress()) {
293+
if (SGM.Types.getTypeLowering(
294+
valueType,
295+
TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(
296+
expansion.getResilienceExpansion()))
297+
.isAddressOnly()
298+
&& !entryValue->getType().isAddress()) {
300299

301300
auto addr = emitTemporaryAllocation(vd, entryValue->getType());
302301
auto val = B.emitCopyValueOperation(vd, entryValue);

lib/SILGen/SILGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
245245
/// The SILModuleConventions for this SIL module.
246246
SILModuleConventions silConv;
247247

248+
bool useLoweredAddresses() const { return silConv.useLoweredAddresses(); }
249+
248250
/// The DeclContext corresponding to the function currently being emitted.
249251
DeclContext * const FunctionDC;
250252

0 commit comments

Comments
 (0)