Skip to content

Commit 0218fd9

Browse files
bors[bot]vext01
andauthored
17: Companion to "hook in transition location properly". r=ltratt a=vext01 Co-authored-by: Edd Barrett <vext01@gmail.com>
2 parents 64af73c + dc44b12 commit 0218fd9

File tree

2 files changed

+7
-161
lines changed

2 files changed

+7
-161
lines changed

Diff for: llvm/include/llvm/Transforms/Yk/ControlPoint.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#define YK_DUMMY_CONTROL_POINT "yk_control_point"
99

1010
// The name of the new control point replacing the user's dummy control point.
11-
#define YK_NEW_CONTROL_POINT "yk_new_control_point"
11+
#define YK_NEW_CONTROL_POINT "__ykrt_control_point"
1212

1313
namespace llvm {
1414
ModulePass *createYkControlPointPass();

Diff for: llvm/lib/Transforms/Yk/ControlPoint.cpp

+6-160
Original file line numberDiff line numberDiff line change
@@ -27,52 +27,22 @@
2727
// size_t pc;
2828
// }
2929
//
30+
// struct YkCtrlPointStruct cp_vars;
3031
// pc = 0;
3132
// while (...) {
32-
// struct YkCtrlPointStruct cp_in = { pc };
3333
// // Now we call the patched control point.
34-
// YkCtrlPointStruct cp_out = yk_new_control_point(cp_in);
35-
// pc = cp_out.pc;
34+
// cp_vars.pc = pc;
35+
// yk_new_control_point(&cp_vars);
36+
// pc = cp_vars.pc;
3637
// bc = program[pc];
3738
// switch (bc) {
3839
// // bytecode handlers here.
3940
// }
4041
// }
4142
// ```
4243
//
43-
// The call to the dummy control point must be the first thing that appears in
44-
// an interpreter dispatch loop.
45-
//
46-
// YKFIXME: The control point cannot yet be used in an interpreter using
47-
// threaded dispatch.
48-
//
49-
// YKFIXME: The tracing logic is currently over-simplified. The following items
50-
// need to be fixed:
51-
//
52-
// - The address of `YkLocation` instances are used for identity, but they are
53-
// intended to be freely moved by the user.
54-
//
55-
// - Tracing starts when we encounter a location for which we have no machine
56-
// code. A hot counter should be used instead.
57-
//
58-
// - There can be only one compiled trace for now. There should be a code
59-
// cache mapping from JIT locations to their machine code.
60-
//
61-
// - The interpreter is assumed to be single threaded. We should implement a
62-
// synchronisation function in Rust code that synchronises many threads which
63-
// are calling the control point concurrently. This function should return a
64-
// value that indicates if we should start/stop tracing, or jump to machine
65-
// code etc.
66-
//
67-
// - Guards are currently assumed to abort the program.
68-
// https://github.com/ykjit/yk/issues/443
69-
//
70-
// - The block that performs the call to JITted code branches back to itself
71-
// to achieve rudimentary trace stitching. The looping should really be
72-
// implemented in the JITted code itself so that it isn't necessary to
73-
// repeatedly enter and exit the JITted code.
74-
// https://github.com/ykjit/yk/issues/442
75-
//===----------------------------------------------------------------------===//
44+
// Note that this transformation occurs at the LLVM IR level. The above example
45+
// is shown as C code for easy comprehension.
7646

7747
#include "llvm/Transforms/Yk/ControlPoint.h"
7848
#include "llvm/IR/BasicBlock.h"
@@ -88,11 +58,6 @@
8858
#define DEBUG_TYPE "yk-control-point"
8959
#define JIT_STATE_PREFIX "jit-state: "
9060

91-
// These constants mirror `ykrt::mt::JITACTION_*`.
92-
const uintptr_t JITActionNop = 1;
93-
const uintptr_t JITActionStartTracing = 2;
94-
const uintptr_t JITActionStopTracing = 3;
95-
9661
using namespace llvm;
9762

9863
/// Find the call to the dummy control point that we want to patch.
@@ -113,124 +78,6 @@ CallInst *findControlPointCall(Module &M) {
11378
return cast<CallInst>(*U);
11479
}
11580

116-
/// Creates a call for printing debug information inside the control point.
117-
void createJITStatePrint(IRBuilder<> &Builder, Module *Mod, std::string Str) {
118-
if (std::getenv("YKD_PRINT_JITSTATE") == nullptr)
119-
return;
120-
LLVMContext &Context = Mod->getContext();
121-
FunctionCallee Puts = Mod->getOrInsertFunction(
122-
"__yk_debug_print",
123-
FunctionType::get(Type::getVoidTy(Context),
124-
PointerType::get(Type::getInt8Ty(Context), 0), true));
125-
Value *PutsString =
126-
Builder.CreateGlobalStringPtr(StringRef(JIT_STATE_PREFIX + Str));
127-
Builder.CreateCall(Puts, PutsString);
128-
}
129-
130-
/// Generates the new control point, which includes all logic to start/stop
131-
/// tracing and to compile/execute traces.
132-
void createControlPoint(Module &Mod, Function *F, std::vector<Value *> LiveVars,
133-
StructType *YkCtrlPointStruct, Type *YkLocTy) {
134-
auto &Context = Mod.getContext();
135-
136-
// Create control point blocks and setup the IRBuilder.
137-
BasicBlock *CtrlPointEntry = BasicBlock::Create(Context, "cpentry", F);
138-
BasicBlock *BBExecuteTrace = BasicBlock::Create(Context, "bbhexectrace", F);
139-
BasicBlock *BBStartTracing = BasicBlock::Create(Context, "bbstarttracing", F);
140-
BasicBlock *BBReturn = BasicBlock::Create(Context, "bbreturn", F);
141-
BasicBlock *BBStopTracing = BasicBlock::Create(Context, "bbstoptracing", F);
142-
143-
// Get the type for a pointer-sized integer.
144-
DataLayout DL(&Mod);
145-
unsigned PtrBitSize = DL.getPointerSize() * 8;
146-
IntegerType *PtrSizedInteger = IntegerType::getIntNTy(Context, PtrBitSize);
147-
148-
// Some frequently used constants.
149-
ConstantInt *JActNop = ConstantInt::get(PtrSizedInteger, JITActionNop);
150-
ConstantInt *JActStartTracing =
151-
ConstantInt::get(PtrSizedInteger, JITActionStartTracing);
152-
ConstantInt *JActStopTracing =
153-
ConstantInt::get(PtrSizedInteger, JITActionStopTracing);
154-
155-
// Add definitions for __yk functions.
156-
Function *FuncTransLoc = llvm::Function::Create(
157-
FunctionType::get(PtrSizedInteger, {Type::getInt8PtrTy(Context)}, false),
158-
GlobalValue::ExternalLinkage, "__ykrt_transition_location", Mod);
159-
160-
Function *FuncSetCodePtr = llvm::Function::Create(
161-
FunctionType::get(
162-
Type::getVoidTy(Context),
163-
{Type::getInt8PtrTy(Context), Type::getInt8PtrTy(Context)}, false),
164-
GlobalValue::ExternalLinkage, "__ykrt_set_loc_code_ptr", Mod);
165-
166-
Function *FuncStartTracing = llvm::Function::Create(
167-
FunctionType::get(Type::getVoidTy(Context), {Type::getInt64Ty(Context)},
168-
false),
169-
GlobalValue::ExternalLinkage, "__yktrace_start_tracing", Mod);
170-
171-
Function *FuncStopTracing = llvm::Function::Create(
172-
FunctionType::get(Type::getInt8PtrTy(Context), {}, false),
173-
GlobalValue::ExternalLinkage, "__yktrace_stop_tracing", Mod);
174-
175-
Function *FuncCompileTrace = llvm::Function::Create(
176-
FunctionType::get(Type::getInt8PtrTy(Context),
177-
{Type::getInt8PtrTy(Context)}, false),
178-
GlobalValue::ExternalLinkage, "__yktrace_irtrace_compile", Mod);
179-
180-
// Populate the entry block. This calls `__ykrt_transition_location()` to
181-
// decide what to do next.
182-
IRBuilder<> Builder(CtrlPointEntry);
183-
Value *CastLoc =
184-
Builder.CreateBitCast(F->getArg(0), Type::getInt8PtrTy(Context));
185-
Value *JITAction = Builder.CreateCall(FuncTransLoc->getFunctionType(),
186-
FuncTransLoc, {CastLoc});
187-
SwitchInst *ActionSw = Builder.CreateSwitch(JITAction, BBExecuteTrace, 3);
188-
ActionSw->addCase(JActNop, BBReturn);
189-
ActionSw->addCase(JActStartTracing, BBStartTracing);
190-
ActionSw->addCase(JActStopTracing, BBStopTracing);
191-
192-
// Populate the block that starts tracing.
193-
Builder.SetInsertPoint(BBStartTracing);
194-
createJITStatePrint(Builder, &Mod, "start-tracing");
195-
Builder.CreateCall(FuncStartTracing->getFunctionType(), FuncStartTracing,
196-
{ConstantInt::get(Context, APInt(64, 1))});
197-
Builder.CreateBr(BBReturn);
198-
199-
// Populate the block that calls a compiled trace. If execution gets into
200-
// this block then `JITAction` is a pointer to a compiled trace.
201-
Builder.SetInsertPoint(BBExecuteTrace);
202-
std::vector<Type *> TypeParams;
203-
for (Value *LV : LiveVars) {
204-
TypeParams.push_back(LV->getType());
205-
}
206-
FunctionType *FType = FunctionType::get(
207-
Type::getVoidTy(Context), {YkCtrlPointStruct->getPointerTo()}, false);
208-
Value *JITActionPtr =
209-
Builder.CreateIntToPtr(JITAction, Type::getInt8PtrTy(Context));
210-
Value *CastTrace = Builder.CreateBitCast(JITActionPtr, FType->getPointerTo());
211-
createJITStatePrint(Builder, &Mod, "enter-jit-code");
212-
CallInst *CTResult = Builder.CreateCall(FType, CastTrace, F->getArg(1));
213-
createJITStatePrint(Builder, &Mod, "exit-jit-code");
214-
CTResult->setTailCall(true);
215-
Builder.CreateBr(BBExecuteTrace);
216-
217-
// Create block that stops tracing, compiles a trace, and stores it in a
218-
// global variable.
219-
Builder.SetInsertPoint(BBStopTracing);
220-
Value *TR =
221-
Builder.CreateCall(FuncStopTracing->getFunctionType(), FuncStopTracing);
222-
Value *CT = Builder.CreateCall(FuncCompileTrace->getFunctionType(),
223-
FuncCompileTrace, {TR});
224-
Builder.CreateCall(FuncSetCodePtr->getFunctionType(), FuncSetCodePtr,
225-
{CastLoc, CT});
226-
createJITStatePrint(Builder, &Mod, "stop-tracing");
227-
Builder.CreateBr(BBReturn);
228-
229-
// Populate the return block.
230-
Builder.SetInsertPoint(BBReturn);
231-
Builder.CreateRetVoid();
232-
}
233-
23481
/// Extract all live variables that need to be passed into the control point.
23582
std::vector<Value *> getLiveVars(DominatorTree &DT, CallInst *OldCtrlPoint) {
23683
std::vector<Value *> Vec;
@@ -347,7 +194,6 @@ class YkControlPoint : public ModulePass {
347194
OldCtrlPointCall->eraseFromParent();
348195

349196
// Generate new control point logic.
350-
createControlPoint(M, NF, LiveVals, CtrlPointVarsTy, YkLocTy);
351197
return true;
352198
}
353199
};

0 commit comments

Comments
 (0)