Skip to content

Commit e102a63

Browse files
committed
SIL: add a dependency token operand to global_addr
Optionally, the dependency to the initialization of the global can be specified with a dependency token `depends_on <token>`. This is usually a `builtin "once"` which calls the initializer for the global variable.
1 parent 72980bd commit e102a63

31 files changed

+198
-77
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AllocVectorLowering.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ private func createOutlinedGlobal(
246246
}
247247

248248
let builder = Builder(before: allocVectorBuiltin, context)
249-
let globalAddr = builder.createGlobalAddr(global: outlinedGlobal)
249+
let globalAddr = builder.createGlobalAddr(global: outlinedGlobal, dependencyToken: nil)
250250
let rawVectorPointer = builder.createAddressToPointer(address: globalAddr, pointerType: allocVectorBuiltin.type,
251251
needStackProtection: false)
252252
allocVectorBuiltin.uses.replaceAll(with: rawVectorPointer, context)

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ObjectOutliner.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ private func replace(findStringCall: ApplyInst,
503503
_ = varBuilder.createStruct(type: cacheType, elements: [zero, zero])
504504

505505
let builder = Builder(before: findStringCall, context)
506-
let cacheAddr = builder.createGlobalAddr(global: cacheVar)
506+
let cacheAddr = builder.createGlobalAddr(global: cacheVar, dependencyToken: nil)
507507
let findStringRef = builder.createFunctionRef(cachedFindStringFunc)
508508
let newCall = builder.createApply(function: findStringRef, SubstitutionMap(),
509509
arguments: [findStringCall.arguments[0],

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ private extension BuiltinInst {
109109
if callee.instructions.contains(where: hasSideEffectForBuiltinOnce) {
110110
return
111111
}
112+
for use in uses {
113+
let ga = use.instruction as! GlobalAddrInst
114+
ga.clearToken(context)
115+
}
112116
context.erase(instruction: self)
113117
}
114118

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyLoad.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ extension LoadInst : OnoneSimplifyable, SILCombineSimplifyable {
110110
let initVal = cloner.clone(globalInitVal)
111111

112112
uses.replaceAll(with: initVal, context)
113+
// Also erases a builtin "once" on which the global_addr depends on. This is fine
114+
// because we only replace the load if the global init function doesn't have any side effect.
113115
transitivelyErase(load: self, context)
114116
return true
115117
}

SwiftCompilerSources/Sources/Optimizer/PassManager/Context.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,14 @@ extension RefElementAddrInst {
535535
}
536536
}
537537

538+
extension GlobalAddrInst {
539+
func clearToken(_ context: some MutatingContext) {
540+
context.notifyInstructionsChanged()
541+
bridged.GlobalAddrInst_clearToken()
542+
context.notifyInstructionChanged(self)
543+
}
544+
}
545+
538546
extension GlobalValueInst {
539547
func setIsBare(_ context: some MutatingContext) {
540548
context.notifyInstructionsChanged()

SwiftCompilerSources/Sources/SIL/Builder.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,8 @@ public struct Builder {
305305
return notifyNew(vectorInst.getAs(VectorInst.self))
306306
}
307307

308-
public func createGlobalAddr(global: GlobalVariable) -> GlobalAddrInst {
309-
return notifyNew(bridged.createGlobalAddr(global.bridged).getAs(GlobalAddrInst.self))
308+
public func createGlobalAddr(global: GlobalVariable, dependencyToken: Value?) -> GlobalAddrInst {
309+
return notifyNew(bridged.createGlobalAddr(global.bridged, dependencyToken.bridged).getAs(GlobalAddrInst.self))
310310
}
311311

312312
public func createGlobalValue(global: GlobalVariable, isBare: Bool) -> GlobalValueInst {

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,10 @@ final public class GlobalAddrInst : GlobalAccessInst, VarDeclInstruction {
650650
public var varDecl: VarDecl? {
651651
VarDecl(bridged: bridged.GlobalAddr_getDecl())
652652
}
653+
654+
public var dependencyToken: Value? {
655+
operands.count == 1 ? operands[0].value : nil
656+
}
653657
}
654658

655659
final public class GlobalValueInst : GlobalAccessInst {

docs/SIL.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5739,15 +5739,21 @@ global_addr
57395739

57405740
::
57415741

5742-
sil-instruction ::= 'global_addr' sil-global-name ':' sil-type
5742+
sil-instruction ::= 'global_addr' sil-global-name ':' sil-type ('depends_on' sil-operand)?
57435743

57445744
%1 = global_addr @foo : $*Builtin.Word
5745+
%3 = global_addr @globalvar : $*Builtin.Word depends_on %2
5746+
// %2 has type $Builtin.SILToken
57455747

57465748
Creates a reference to the address of a global variable which has been
57475749
previously initialized by ``alloc_global``. It is undefined behavior to
57485750
perform this operation on a global variable which has not been
57495751
initialized, except the global variable has a static initializer.
57505752

5753+
Optionally, the dependency to the initialization of the global can be
5754+
specified with a dependency token ``depends_on <token>``. This is usually
5755+
a ``builtin "once"`` which calls the initializer for the global variable.
5756+
57515757
global_value
57525758
`````````````
57535759
::

include/swift/AST/DiagnosticsParse.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,9 @@ WARNING(warning_in_effects_attribute,none,
15021502
ERROR(expected_in_attribute_list,none,
15031503
"expected ']' or ',' in attribute list", ())
15041504

1505+
ERROR(expected_depends_on,none,
1506+
"expected 'depends_on'", ())
1507+
15051508
ERROR(type_attribute_applied_to_decl,none,
15061509
"attribute can only be applied to types, not declarations", ())
15071510
ERROR(decl_attribute_applied_to_type,none,

include/swift/SIL/SILBridging.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,7 @@ struct BridgedInstruction {
809809
BRIDGED_INLINE void TermInst_replaceBranchTarget(BridgedBasicBlock from, BridgedBasicBlock to) const;
810810
BRIDGED_INLINE SwiftInt KeyPathInst_getNumComponents() const;
811811
BRIDGED_INLINE void KeyPathInst_getReferencedFunctions(SwiftInt componentIdx, KeyPathFunctionResults * _Nonnull results) const;
812+
BRIDGED_INLINE void GlobalAddrInst_clearToken() const;
812813
BRIDGED_INLINE bool GlobalValueInst_isBare() const;
813814
BRIDGED_INLINE void GlobalValueInst_setIsBare() const;
814815
BRIDGED_INLINE void LoadInst_setOwnership(SwiftInt ownership) const;
@@ -1093,7 +1094,8 @@ struct BridgedBuilder{
10931094
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createObject(BridgedType type, BridgedValueArray arguments,
10941095
SwiftInt numBaseElements) const;
10951096
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createVector(BridgedValueArray arguments) const;
1096-
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createGlobalAddr(BridgedGlobalVar global) const;
1097+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createGlobalAddr(BridgedGlobalVar global,
1098+
OptionalBridgedValue dependencyToken) const;
10971099
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createGlobalValue(BridgedGlobalVar global,
10981100
bool isBare) const;
10991101
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createStruct(BridgedType type,

include/swift/SIL/SILBridgingImpl.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,10 @@ void BridgedInstruction::KeyPathInst_getReferencedFunctions(SwiftInt componentId
11141114
}, [](swift::SILDeclRef) {});
11151115
}
11161116

1117+
void BridgedInstruction::GlobalAddrInst_clearToken() const {
1118+
getAs<swift::GlobalAddrInst>()->clearToken();
1119+
}
1120+
11171121
bool BridgedInstruction::GlobalValueInst_isBare() const {
11181122
return getAs<swift::GlobalValueInst>()->isBare();
11191123
}
@@ -1522,8 +1526,9 @@ BridgedInstruction BridgedBuilder::createVector(BridgedValueArray arguments) con
15221526
return {unbridged().createVector(swift::ArtificialUnreachableLocation(), arguments.getValues(argValues))};
15231527
}
15241528

1525-
BridgedInstruction BridgedBuilder::createGlobalAddr(BridgedGlobalVar global) const {
1526-
return {unbridged().createGlobalAddr(regularLoc(), global.getGlobal())};
1529+
BridgedInstruction BridgedBuilder::createGlobalAddr(BridgedGlobalVar global,
1530+
OptionalBridgedValue dependencyToken) const {
1531+
return {unbridged().createGlobalAddr(regularLoc(), global.getGlobal(), dependencyToken.getSILValue())};
15271532
}
15281533

15291534
BridgedInstruction BridgedBuilder::createGlobalValue(BridgedGlobalVar global, bool isBare) const {

include/swift/SIL/SILBuilder.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -680,14 +680,12 @@ class SILBuilder {
680680
return insert(new (getModule())
681681
AllocGlobalInst(getSILDebugLocation(Loc), g));
682682
}
683-
GlobalAddrInst *createGlobalAddr(SILLocation Loc, SILGlobalVariable *g) {
683+
GlobalAddrInst *createGlobalAddr(SILLocation Loc, SILGlobalVariable *g,
684+
SILValue dependencyToken) {
684685
return insert(new (getModule()) GlobalAddrInst(getSILDebugLocation(Loc), g,
686+
dependencyToken,
685687
getTypeExpansionContext()));
686688
}
687-
GlobalAddrInst *createGlobalAddr(SILLocation Loc, SILType Ty) {
688-
return insert(new (F->getModule())
689-
GlobalAddrInst(getSILDebugLocation(Loc), Ty));
690-
}
691689
GlobalValueInst *createGlobalValue(SILLocation Loc, SILGlobalVariable *g, bool isBare) {
692690
return insert(new (getModule()) GlobalValueInst(getSILDebugLocation(Loc), g,
693691
getTypeExpansionContext(), isBare));

include/swift/SIL/SILCloner.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,10 @@ SILCloner<ImplClass>::visitGlobalAddrInst(GlobalAddrInst *Inst) {
11241124
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
11251125
recordClonedInstruction(
11261126
Inst, getBuilder().createGlobalAddr(getOpLocation(Inst->getLoc()),
1127-
Inst->getReferencedGlobal()));
1127+
Inst->getReferencedGlobal(),
1128+
Inst->hasOperand() ?
1129+
getOpValue(Inst->getDependencyToken()) :
1130+
SILValue()));
11281131
}
11291132

11301133
template<typename ImplClass>

include/swift/SIL/SILInstruction.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4176,15 +4176,43 @@ class GlobalAddrInst
41764176
friend SILBuilder;
41774177

41784178
GlobalAddrInst(SILDebugLocation DebugLoc, SILGlobalVariable *Global,
4179+
SILValue dependencyToken,
41794180
TypeExpansionContext context);
41804181

4182+
llvm::Optional<FixedOperandList<1>> dependencyToken;
4183+
41814184
public:
41824185
// FIXME: This constructor should be private but is currently used
41834186
// in the SILParser.
41844187

41854188
/// Create a placeholder instruction with an unset global reference.
41864189
GlobalAddrInst(SILDebugLocation DebugLoc, SILType Ty)
41874190
: InstructionBase(DebugLoc, Ty, nullptr) {}
4191+
4192+
SILValue getDependencyToken() const {
4193+
if (hasOperand())
4194+
return getOperand();
4195+
return SILValue();
4196+
}
4197+
4198+
void clearToken() {
4199+
dependencyToken = llvm::None;
4200+
}
4201+
4202+
bool hasOperand() const { return dependencyToken.has_value(); }
4203+
SILValue getOperand() const { return dependencyToken->asValueArray()[0]; }
4204+
4205+
Operand &getOperandRef() { return dependencyToken->asArray()[0]; }
4206+
const Operand &getOperandRef() const { return dependencyToken->asArray()[0]; }
4207+
4208+
ArrayRef<Operand> getAllOperands() const {
4209+
return dependencyToken ? dependencyToken->asArray() : ArrayRef<Operand>{};
4210+
}
4211+
4212+
MutableArrayRef<Operand> getAllOperands() {
4213+
return dependencyToken
4214+
? dependencyToken->asArray() : MutableArrayRef<Operand>{};
4215+
}
41884216
};
41894217

41904218
/// Creates a base address for offset calculations.

lib/AST/Builtins.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,9 +1918,11 @@ static ValueDecl *getOnceOperation(ASTContext &Context,
19181918
.build();
19191919
auto BlockTy = FunctionType::get(CFuncParams, VoidTy, Thin);
19201920
SmallVector<swift::Type, 3> ArgTypes = {HandleTy, BlockTy};
1921-
if (withContext)
1921+
if (withContext) {
19221922
ArgTypes.push_back(ContextTy);
1923-
return getBuiltinFunction(Id, ArgTypes, VoidTy);
1923+
return getBuiltinFunction(Id, ArgTypes, VoidTy);
1924+
}
1925+
return getBuiltinFunction(Id, ArgTypes, Context.TheSILTokenType);
19241926
}
19251927

19261928
static ValueDecl *getPolymorphicBinaryOperation(ASTContext &ctx,

lib/IRGen/LoadableByAddress.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3164,7 +3164,8 @@ void LoadableByAddress::run() {
31643164
} else if (auto *globalAddr = dyn_cast<GlobalAddrInst>(inst)) {
31653165
SILBuilderWithScope builder(inst);
31663166
auto *newInst = builder.createGlobalAddr(
3167-
globalAddr->getLoc(), globalAddr->getReferencedGlobal());
3167+
globalAddr->getLoc(), globalAddr->getReferencedGlobal(),
3168+
globalAddr->getDependencyToken());
31683169
globalAddr->replaceAllUsesWith(newInst);
31693170
globalAddr->eraseFromParent();
31703171
} else if (auto *globalVal = dyn_cast<GlobalValueInst>(inst)) {

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ SHOULD_NEVER_VISIT_INST(FunctionRef)
107107
SHOULD_NEVER_VISIT_INST(DebugStep)
108108
SHOULD_NEVER_VISIT_INST(DynamicFunctionRef)
109109
SHOULD_NEVER_VISIT_INST(PreviousDynamicFunctionRef)
110-
SHOULD_NEVER_VISIT_INST(GlobalAddr)
111110
SHOULD_NEVER_VISIT_INST(GlobalValue)
112111
SHOULD_NEVER_VISIT_INST(BaseAddrForOffset)
113112
SHOULD_NEVER_VISIT_INST(HasSymbol)
@@ -207,6 +206,7 @@ OPERAND_OWNERSHIP(TrivialUse, PackPackIndex)
207206
OPERAND_OWNERSHIP(TrivialUse, PackElementGet)
208207
OPERAND_OWNERSHIP(TrivialUse, PackElementSet)
209208
OPERAND_OWNERSHIP(TrivialUse, TuplePackElementAddr)
209+
OPERAND_OWNERSHIP(TrivialUse, GlobalAddr)
210210

211211
// The dealloc_stack_ref operand needs to have NonUse ownership because
212212
// this use comes after the last consuming use (which is usually a dealloc_ref).

lib/SIL/IR/SILInstructions.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1038,10 +1038,15 @@ AllocGlobalInst::AllocGlobalInst(SILDebugLocation Loc,
10381038

10391039
GlobalAddrInst::GlobalAddrInst(SILDebugLocation DebugLoc,
10401040
SILGlobalVariable *Global,
1041+
SILValue dependencyToken,
10411042
TypeExpansionContext context)
10421043
: InstructionBase(DebugLoc,
10431044
Global->getLoweredTypeInContext(context).getAddressType(),
1044-
Global) {}
1045+
Global) {
1046+
if (dependencyToken) {
1047+
this->dependencyToken.emplace(this, dependencyToken);
1048+
}
1049+
}
10451050

10461051
GlobalValueInst::GlobalValueInst(SILDebugLocation DebugLoc,
10471052
SILGlobalVariable *Global,

lib/SIL/IR/SILPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,6 +1644,9 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
16441644
*this << "<<placeholder>>";
16451645
}
16461646
*this << " : " << GAI->getType();
1647+
if (SILValue token = GAI->getDependencyToken()) {
1648+
*this << " depends_on " << Ctx.getID(token);
1649+
}
16471650
}
16481651

16491652
void visitGlobalValueInst(GlobalValueInst *GVI) {

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5671,7 +5671,7 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
56715671
parseSILIdentifier(GlobalName, IdLoc,
56725672
diag::expected_sil_value_name) ||
56735673
P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") ||
5674-
parseSILType(Ty) || parseSILDebugLocation(InstLoc, B))
5674+
parseSILType(Ty))
56755675
return true;
56765676

56775677
// Go through list of global variables in the SILModule.
@@ -5681,6 +5681,18 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
56815681
return true;
56825682
}
56835683

5684+
SILValue dependencyToken;
5685+
if (Opcode == SILInstructionKind::GlobalAddrInst && P.Tok.isContextualKeyword("depends_on")) {
5686+
P.consumeToken();
5687+
if (parseValueRef(dependencyToken, SILType::getSILTokenType(P.Context),
5688+
RegularLocation(P.Tok.getLoc()), B)) {
5689+
return true;
5690+
}
5691+
}
5692+
5693+
if (parseSILDebugLocation(InstLoc, B))
5694+
return true;
5695+
56845696
SILType expectedType = (Opcode == SILInstructionKind::GlobalAddrInst
56855697
? global->getLoweredType().getAddressType()
56865698
: global->getLoweredType());
@@ -5692,7 +5704,7 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
56925704
}
56935705

56945706
if (Opcode == SILInstructionKind::GlobalAddrInst) {
5695-
ResultVal = B.createGlobalAddr(InstLoc, global);
5707+
ResultVal = B.createGlobalAddr(InstLoc, global, dependencyToken);
56965708
} else {
56975709
ResultVal = B.createGlobalValue(InstLoc, global, isBare);
56985710
}

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,6 +1515,11 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
15151515
if (isa<OpenPackElementInst>(value))
15161516
return true;
15171517

1518+
if (auto *bi = dyn_cast<BuiltinInst>(value)) {
1519+
if (bi->getBuiltinInfo().ID == BuiltinValueKind::Once)
1520+
return true;
1521+
}
1522+
15181523
// Add more token cases here as they arise.
15191524

15201525
return false;
@@ -2297,6 +2302,10 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
22972302
"global_addr cannot refer to a statically initialized object");
22982303
checkGlobalAccessInst(GAI);
22992304
checkAddressWalkerCanVisitAllTransitiveUses(GAI);
2305+
if (SILValue token = GAI->getDependencyToken()) {
2306+
require(token->getType().is<SILTokenType>(),
2307+
"depends_on operand of global_addr must be a token");
2308+
}
23002309
}
23012310

23022311
void checkGlobalValueInst(GlobalValueInst *GVI) {

lib/SILGen/SILGenDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1480,7 +1480,7 @@ SILGenFunction::emitInitializationForVarDecl(VarDecl *vd, bool forceImmutable,
14801480
RegularLocation loc(vd);
14811481
loc.markAutoGenerated();
14821482
B.createAllocGlobal(loc, silG);
1483-
SILValue addr = B.createGlobalAddr(loc, silG);
1483+
SILValue addr = B.createGlobalAddr(loc, silG, /*dependencyToken=*/ SILValue());
14841484
if (isUninitialized)
14851485
addr = B.createMarkUninitializedVar(loc, addr);
14861486

lib/SILGen/SILGenExpr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4344,14 +4344,14 @@ visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E, SGFContext C) {
43444344
SILGlobalVariable::create(M, SILLinkage::DefaultForDeclaration,
43454345
IsNotSerialized, "__ImageBase",
43464346
BuiltinRawPtrTy);
4347-
ModuleBase = B.createGlobalAddr(SILLoc, ImageBase);
4347+
ModuleBase = B.createGlobalAddr(SILLoc, ImageBase, /*dependencyToken=*/ SILValue());
43484348
} else {
43494349
auto DSOHandle = M.lookUpGlobalVariable("__dso_handle");
43504350
if (!DSOHandle)
43514351
DSOHandle = SILGlobalVariable::create(M, SILLinkage::PublicExternal,
43524352
IsNotSerialized, "__dso_handle",
43534353
BuiltinRawPtrTy);
4354-
ModuleBase = B.createGlobalAddr(SILLoc, DSOHandle);
4354+
ModuleBase = B.createGlobalAddr(SILLoc, DSOHandle, /*dependencyToken=*/ SILValue());
43554355
}
43564356

43574357
auto ModuleBasePointer =

0 commit comments

Comments
 (0)