Skip to content

Commit 4f6f8b3

Browse files
committed
Rewrite hop_to_executor so that it takes a Builtin.Executor in IRGen
The comment in LowerHopToActor explains the design here. We want SILGen to emit hops to actors, ignoring executors, because it's easier to fully optimize in a world where deriving an executor is a non-trivial operation. But we also want something prior to IRGen to lower the executor derivation because there are useful static optimizations we can do, such as doing the derivation exactly once on a dominance path and strength-reducing the derivation (e.g. exploiting static knowledge that an actor is a default actor). There are probably phase-ordering problems with doing this so late, but hopefully they're restricted to situations like actors that share an executor. We'll want to optimize that eventually, but in the meantime, this unblocks the executor work.
1 parent 85c486c commit 4f6f8b3

File tree

21 files changed

+472
-77
lines changed

21 files changed

+472
-77
lines changed

docs/SIL.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3302,7 +3302,7 @@ hop_to_executor
33023302

33033303
hop_to_executor %0 : $T
33043304

3305-
// $T must conform to the Actor protocol
3305+
// $T must be Builtin.Executor or conform to the Actor protocol
33063306

33073307
Ensures that all instructions, which need to run on the actor's executor
33083308
actually run on that executor.
@@ -3312,6 +3312,11 @@ Checks if the current executor is the one which is bound to the operand actor.
33123312
If not, begins a suspension point and enqueues the continuation to the executor
33133313
which is bound to the operand actor.
33143314

3315+
SIL generation emits this instruction with operands of actor type as
3316+
well as of type ``Builtin.Executor``. The former are expected to be
3317+
lowered by the SIL pipeline, so that IR generation only operands of type
3318+
``Builtin.Executor`` remain.
3319+
33153320
The operand is a guaranteed operand, i.e. not consumed.
33163321

33173322
dealloc_stack

include/swift/AST/Builtins.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,10 @@ BUILTIN_MISC_OPERATION(ResumeThrowingContinuationReturning,
735735
BUILTIN_MISC_OPERATION(ResumeThrowingContinuationThrowing,
736736
"resumeThrowingContinuationThrowing", "", Special)
737737

738+
/// Build a Builtin.Executor value from the given serial executor reference.
739+
BUILTIN_MISC_OPERATION(BuildSerialExecutorRef,
740+
"buildSerialExecutorRef", "", Special)
741+
738742
// BUILTIN_MISC_OPERATION_WITH_SILGEN - Miscellaneous operations that are
739743
// specially emitted during SIL generation.
740744
//

include/swift/SIL/SILCloner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3053,7 +3053,7 @@ ::visitHopToExecutorInst(HopToExecutorInst *Inst) {
30533053
recordClonedInstruction(Inst,
30543054
getBuilder().createHopToExecutor(
30553055
getOpLocation(Inst->getLoc()),
3056-
getOpValue(Inst->getActor())));
3056+
getOpValue(Inst->getTargetExecutor())));
30573057
}
30583058

30593059

include/swift/SIL/SILInstruction.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3474,11 +3474,12 @@ class HopToExecutorInst
34743474
{
34753475
friend SILBuilder;
34763476

3477-
HopToExecutorInst(SILDebugLocation DebugLoc, SILValue Actor, bool HasOwnership)
3478-
: UnaryInstructionBase(DebugLoc, Actor) { }
3477+
HopToExecutorInst(SILDebugLocation debugLoc, SILValue executor,
3478+
bool hasOwnership)
3479+
: UnaryInstructionBase(debugLoc, executor) { }
34793480

34803481
public:
3481-
SILValue getActor() const { return getOperand(); }
3482+
SILValue getTargetExecutor() const { return getOperand(); }
34823483
};
34833484

34843485
/// Instantiates a key path object.

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ PASS(HighLevelLICM, "high-level-licm",
210210
"Loop Invariant Code Motion in High-Level SIL")
211211
PASS(IVInfoPrinter, "iv-info-printer",
212212
"Print Induction Variable Information for Testing")
213+
PASS(LowerHopToActor, "lower-hop-to-actor",
214+
"Lower hop_to_executor instructions with actor operands")
213215
PASS(OptimizeHopToExecutor, "optimize-hop-to-executor",
214216
"Optimize hop_to_executor instructions for actor isolated code")
215217
PASS(InstCount, "inst-count",

lib/AST/Builtins.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,15 @@ static ValueDecl *getResumeContinuationThrowing(ASTContext &ctx,
14811481
_void);
14821482
}
14831483

1484+
static ValueDecl *getBuildSerialExecutorRef(ASTContext &ctx, Identifier id) {
1485+
// TODO: restrict the generic parameter to the SerialExecutor protocol
1486+
return getBuiltinFunction(ctx, id, _thin,
1487+
_generics(_unrestricted,
1488+
_layout(_typeparam(0), _classLayout())),
1489+
_parameters(_typeparam(0)),
1490+
_executor);
1491+
}
1492+
14841493
static ValueDecl *getAutoDiffCreateLinearMapContext(ASTContext &ctx,
14851494
Identifier id) {
14861495
return getBuiltinFunction(
@@ -2658,6 +2667,9 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
26582667
case BuiltinValueKind::ConvertTaskToJob:
26592668
return getConvertTaskToJob(Context, Id);
26602669

2670+
case BuiltinValueKind::BuildSerialExecutorRef:
2671+
return getBuildSerialExecutorRef(Context, Id);
2672+
26612673
case BuiltinValueKind::PoundAssert:
26622674
return getPoundAssert(Context, Id);
26632675

lib/IRGen/GenBuiltin.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,14 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
306306
return;
307307
}
308308

309+
if (Builtin.ID == BuiltinValueKind::BuildSerialExecutorRef) {
310+
auto executor = args.claimNext();
311+
executor = IGF.Builder.CreateBitCast(executor,
312+
IGF.IGM.SwiftExecutorPtrTy);
313+
out.add(executor);
314+
return;
315+
}
316+
309317
// If this is an LLVM IR intrinsic, lower it to an intrinsic call.
310318
const IntrinsicInfo &IInfo = IGF.getSILModule().getIntrinsicInfo(FnId);
311319
llvm::Intrinsic::ID IID = IInfo.ID;

lib/IRGen/IRGenSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6134,6 +6134,7 @@ void IRGenSILFunction::visitCheckedCastAddrBranchInst(
61346134
}
61356135

61366136
void IRGenSILFunction::visitHopToExecutorInst(HopToExecutorInst *i) {
6137+
assert(i->getTargetExecutor()->getType().is<BuiltinExecutorType>());
61376138
llvm::Value *resumeFn = Builder.CreateIntrinsicCall(
61386139
llvm::Intrinsic::coro_async_resume, {});
61396140

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,8 @@ BUILTIN_OPERAND_OWNERSHIP(ForwardingBorrow, AutoDiffProjectTopLevelSubcontext)
814814
// ownership should be 'TrivialUse'.
815815
BUILTIN_OPERAND_OWNERSHIP(ForwardingConsume, ConvertTaskToJob)
816816

817+
BUILTIN_OPERAND_OWNERSHIP(BitwiseEscape, BuildSerialExecutorRef)
818+
817819
BUILTIN_OPERAND_OWNERSHIP(TrivialUse, AutoDiffCreateLinearMapContext)
818820

819821
#undef BUILTIN_OPERAND_OWNERSHIP

lib/SIL/IR/SILPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2144,7 +2144,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
21442144
}
21452145

21462146
void visitHopToExecutorInst(HopToExecutorInst *HTEI) {
2147-
*this << getIDAndType(HTEI->getActor());
2147+
*this << getIDAndType(HTEI->getTargetExecutor());
21482148
}
21492149

21502150
void visitSwitchValueInst(SwitchValueInst *SII) {

0 commit comments

Comments
 (0)