Skip to content

Commit c97ca9f

Browse files
DinoVmeta-codesync[bot]
authored andcommitted
Break kYieldValue into components
Summary: Breaks kYieldValue into a few smaller instructions: * kYieldValue - populates the return value into the return register * kStoreGenYieldPoint * kBranchToYieldExit * kResumeGenYield This is going to ultimately let us get rid of `kYieldValue` instead - instead we'll be able to flow the return register directly to the end instead of having a hard-coded assignment into it. But before we can do that we need these broken up like this. Reviewed By: kddnewton Differential Revision: D95829402 fbshipit-source-id: 5a1d077af1714c41ff5f1ab84c82c94e787206f8
1 parent b236e9c commit c97ca9f

5 files changed

Lines changed: 108 additions & 35 deletions

File tree

cinderx/Jit/codegen/autogen.cpp

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "cinderx/Jit/codegen/gen_asm_utils.h"
99
#include "cinderx/Jit/frame.h"
1010
#include "cinderx/Jit/generators_rt.h"
11+
#include "cinderx/Jit/hir/hir.h"
1112
#include "cinderx/Jit/jit_rt.h"
1213
#include "cinderx/Jit/lir/instruction.h"
1314
#include "cinderx/Jit/lir/printer.h"
@@ -823,23 +824,64 @@ void translateYieldValue(Environ* env, const Instruction* instr) {
823824
PhyLocation value_out = instr->getInput(1)->getStackSlot();
824825
as->mov(x86::rax, x86::ptr(x86::rbp, value_out.loc));
825826
}
827+
#elif defined(CINDER_AARCH64)
828+
a64::Builder* as = env->as;
826829

827-
// Arbitrary scratch register for use in emitStoreGenYieldPoint()
830+
// Value to send goes to x0 so it can be yielded (returned) by epilogue.
831+
if (instr->getInput(1)->isImm()) {
832+
as->mov(a64::x0, instr->getInput(1)->getConstant());
833+
} else {
834+
PhyLocation value_out = instr->getInput(1)->getStackSlot();
835+
as->ldr(
836+
a64::x0,
837+
arch::ptr_resolve(as, arch::fp, value_out.loc, arch::reg_scratch_0));
838+
}
839+
#else
840+
CINDER_UNSUPPORTED
841+
#endif
842+
}
843+
844+
void translateStoreGenYieldPoint(Environ* env, const Instruction* instr) {
845+
#if defined(CINDER_X86_64)
846+
arch::Builder* as = env->as;
828847
auto scratch_r = x86::r9;
829-
auto resume_label = as->newLabel();
830-
emitStoreGenYieldPoint(as, env, instr, resume_label, x86::rbp, scratch_r);
848+
env->pending_yield_resume_label = as->newLabel();
849+
emitStoreGenYieldPoint(
850+
as, env, instr, env->pending_yield_resume_label, x86::rbp, scratch_r);
851+
#elif defined(CINDER_AARCH64)
852+
a64::Builder* as = env->as;
853+
auto scratch_r = arch::reg_scratch_0;
854+
env->pending_yield_resume_label = as->newLabel();
855+
emitStoreGenYieldPoint(
856+
as, env, instr, env->pending_yield_resume_label, arch::fp, scratch_r);
857+
#else
858+
CINDER_UNSUPPORTED
859+
#endif
860+
}
831861

832-
// Jump to epilogue
833-
as->jmp(env->exit_for_yield_label);
862+
void translateBranchToYieldExit(Environ* env, const Instruction*) {
863+
#if defined(CINDER_X86_64)
864+
env->as->jmp(env->exit_for_yield_label);
865+
#elif defined(CINDER_AARCH64)
866+
env->as->b(env->exit_for_yield_label);
867+
#else
868+
CINDER_UNSUPPORTED
869+
#endif
870+
}
871+
872+
void translateResumeGenYield(Environ* env, const Instruction* instr) {
873+
#if defined(CINDER_X86_64)
874+
arch::Builder* as = env->as;
834875

835876
// Resumed execution in this generator begins here
836-
as->bind(resume_label);
877+
as->bind(env->pending_yield_resume_label);
837878

838879
#if PY_VERSION_HEX < 0x030C0000
839880
// On 3.10, for yield-from yield points, store the finish_yield_from arg
840881
// (RDX from resume entry) into GenDataFooter so the subsequent Send
841882
// instruction can load it.
842-
if (instr->isInYieldFromContext()) {
883+
if (instr->origin() &&
884+
static_cast<const hir::YieldValue*>(instr->origin())->isYieldFrom()) {
843885
auto fyf_offset = offsetof(GenDataFooter, finishYieldFrom);
844886
as->mov(x86::qword_ptr(x86::rbp, fyf_offset), x86::rdx);
845887
}
@@ -850,32 +892,15 @@ void translateYieldValue(Environ* env, const Instruction* instr) {
850892
#elif defined(CINDER_AARCH64)
851893
a64::Builder* as = env->as;
852894

853-
// Value to send goes to x0 so it can be yielded (returned) by epilogue.
854-
if (instr->getInput(1)->isImm()) {
855-
as->mov(a64::x0, instr->getInput(1)->getConstant());
856-
} else {
857-
PhyLocation value_out = instr->getInput(1)->getStackSlot();
858-
as->ldr(
859-
a64::x0,
860-
arch::ptr_resolve(as, arch::fp, value_out.loc, arch::reg_scratch_0));
861-
}
862-
863-
// Arbitrary scratch register for use in emitStoreGenYieldPoint()
864-
auto scratch_r = arch::reg_scratch_0;
865-
auto resume_label = as->newLabel();
866-
emitStoreGenYieldPoint(as, env, instr, resume_label, arch::fp, scratch_r);
867-
868-
// Jump to epilogue
869-
as->b(env->exit_for_yield_label);
870-
871895
// Resumed execution in this generator begins here
872-
as->bind(resume_label);
896+
as->bind(env->pending_yield_resume_label);
873897

874898
#if PY_VERSION_HEX < 0x030C0000
875899
// On 3.10, for yield-from yield points, store the finish_yield_from arg
876900
// (X2 from resume entry) into GenDataFooter so the subsequent Send
877901
// instruction can load it.
878-
if (instr->isInYieldFromContext()) {
902+
if (instr->origin() &&
903+
static_cast<const hir::YieldValue*>(instr->origin())->isYieldFrom()) {
879904
auto fyf_offset = offsetof(GenDataFooter, finishYieldFrom);
880905
as->str(
881906
a64::x2,
@@ -1702,6 +1727,18 @@ BEGIN_RULES(Instruction::kYieldValue)
17021727
GEN(ANY, CALL_C(translateYieldValue))
17031728
END_RULES
17041729

1730+
BEGIN_RULES(Instruction::kStoreGenYieldPoint)
1731+
GEN(ANY, CALL_C(translateStoreGenYieldPoint))
1732+
END_RULES
1733+
1734+
BEGIN_RULES(Instruction::kBranchToYieldExit)
1735+
GEN(ANY, CALL_C(translateBranchToYieldExit))
1736+
END_RULES
1737+
1738+
BEGIN_RULES(Instruction::kResumeGenYield)
1739+
GEN(ANY, CALL_C(translateResumeGenYield))
1740+
END_RULES
1741+
17051742
BEGIN_RULES(Instruction::kYieldExitPoint)
17061743
GEN(ANY, CALL_C(translateYieldExitPoint))
17071744
END_RULES
@@ -2993,6 +3030,18 @@ BEGIN_RULES(Instruction::kYieldValue)
29933030
GEN(ANY, CALL_C(translateYieldValue))
29943031
END_RULES
29953032

3033+
BEGIN_RULES(Instruction::kStoreGenYieldPoint)
3034+
GEN(ANY, CALL_C(translateStoreGenYieldPoint))
3035+
END_RULES
3036+
3037+
BEGIN_RULES(Instruction::kBranchToYieldExit)
3038+
GEN(ANY, CALL_C(translateBranchToYieldExit))
3039+
END_RULES
3040+
3041+
BEGIN_RULES(Instruction::kResumeGenYield)
3042+
GEN(ANY, CALL_C(translateResumeGenYield))
3043+
END_RULES
3044+
29963045
BEGIN_RULES(Instruction::kYieldExitPoint)
29973046
GEN(ANY, CALL_C(translateYieldExitPoint))
29983047
END_RULES

cinderx/Jit/codegen/environ.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ struct Environ {
4242
asmjit::Label exit_for_yield_label;
4343
asmjit::Label gen_resume_entry_label;
4444

45+
// Resume label shared between StoreGenYieldPoint and ResumeGenYield.
46+
// Created by translateStoreGenYieldPoint, bound by translateResumeGenYield.
47+
asmjit::Label pending_yield_resume_label;
48+
4549
// Deopt exits. One per guard.
4650
struct DeoptExit {
4751
DeoptExit(size_t idx, asmjit::Label lbl, const jit::lir::Instruction* ins)

cinderx/Jit/lir/generator.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,18 +1309,34 @@ LIRGenerator::TranslatedBlock LIRGenerator::TranslateOneBasicBlock(
13091309
}
13101310
case Opcode::kYieldValue: {
13111311
auto hir_instr = static_cast<const YieldValue*>(&i);
1312-
Instruction* instr = bbb.appendInstr(
1313-
hir_instr->output(),
1314-
Instruction::kYieldValue,
1315-
env_->asm_tstate,
1316-
hir_instr->reg());
1312+
1313+
// 1. kYieldValue: load tstate and yield value into ABI registers.
1314+
// No output — the yielded value goes to the return register in
1315+
// codegen.
1316+
bbb.appendInstr(
1317+
Instruction::kYieldValue, env_->asm_tstate, hir_instr->reg());
1318+
1319+
// 2. kStoreGenYieldPoint: store yield point metadata and live regs.
1320+
Instruction* store_instr =
1321+
bbb.appendInstr(Instruction::kStoreGenYieldPoint);
13171322
if (hir_instr->isYieldFrom()) {
13181323
// Add the sub-iterator as an extra input so that
13191324
// emitStoreGenYieldPoint can capture its spill offset.
1320-
instr->addOperands(VReg{bbb.getDefInstr(hir_instr->yieldFromIter())});
1321-
instr->setYieldFromInputIdx(instr->getNumInputs() - 1);
1325+
store_instr->addOperands(
1326+
VReg{bbb.getDefInstr(hir_instr->yieldFromIter())});
1327+
store_instr->setYieldFromInputIdx(store_instr->getNumInputs() - 1);
13221328
}
1323-
finishYield(bbb, instr, hir_instr);
1329+
finishYield(bbb, store_instr, hir_instr);
1330+
1331+
// 3. kBranchToYieldExit: jump to yield exit epilogue.
1332+
bbb.appendInstr(Instruction::kBranchToYieldExit);
1333+
1334+
// 4. kResumeGenYield: bind resume label, load resumed inputs.
1335+
// Has output (the sent-in value) and takes tstate as input.
1336+
bbb.appendInstr(
1337+
hir_instr->output(),
1338+
Instruction::kResumeGenYield,
1339+
env_->asm_tstate);
13241340
break;
13251341
}
13261342
case Opcode::kInitialYield: {

cinderx/Jit/lir/instruction.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ bool Instruction::isAnyYield() const {
289289
switch (opcode_) {
290290
case kYieldInitial:
291291
case kYieldValue:
292+
case kStoreGenYieldPoint:
292293
return true;
293294
default:
294295
return false;

cinderx/Jit/lir/instruction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ enum OperandSizeType {
168168
X(IntToBool, false, FlagEffects::kSet, kDefault, 1, {1}) \
169169
X(YieldInitial, false, FlagEffects::kInvalidate, kDefault, 0, {}, 1) \
170170
X(YieldValue, false, FlagEffects::kInvalidate, kDefault, 0, {}, 1) \
171+
X(StoreGenYieldPoint, false, FlagEffects::kInvalidate, kDefault, 0, {}, 1) \
172+
X(BranchToYieldExit, false, FlagEffects::kNone, kDefault, 0, {}, 1) \
173+
X(ResumeGenYield, false, FlagEffects::kInvalidate, kDefault, 0, {}, 1) \
171174
X(YieldExitPoint, false, FlagEffects::kNone, kDefault, 0, {}, 1) \
172175
X(EpilogueEnd, false, FlagEffects::kInvalidate, kDefault, 0, {}, 1)
173176

0 commit comments

Comments
 (0)