@@ -169,14 +169,15 @@ void createControlPoint(Module &Mod, Function *F, std::vector<Value *> LiveVars,
169
169
(GlobalVariable *)nullptr );
170
170
171
171
// Create control point entry block. Checks if we are currently tracing.
172
- Value *GVTracingVal = Builder.CreateLoad (GVTracing);
172
+ Value *GVTracingVal = Builder.CreateLoad (Type::getInt8Ty (Context), GVTracing);
173
173
Value *IsTracing =
174
174
Builder.CreateICmp (CmpInst::Predicate::ICMP_EQ, GVTracingVal, Int0);
175
175
Builder.CreateCondBr (IsTracing, BBNotTracing, BBTracing);
176
176
177
177
// Create block for "not tracing" case. Checks if we already compiled a trace.
178
178
Builder.SetInsertPoint (BBNotTracing);
179
- Value *GVCompiledTraceVal = Builder.CreateLoad (GVCompiledTrace);
179
+ Value *GVCompiledTraceVal =
180
+ Builder.CreateLoad (Type::getInt8PtrTy (Context), GVCompiledTrace);
180
181
Value *HasTrace = Builder.CreateICmp (CmpInst::Predicate::ICMP_EQ,
181
182
GVCompiledTraceVal, PtNull);
182
183
Builder.CreateCondBr (HasTrace, BBHasNoTrace, BBHasTrace);
@@ -193,7 +194,8 @@ void createControlPoint(Module &Mod, Function *F, std::vector<Value *> LiveVars,
193
194
// Create block that checks if we've reached the same location again so we
194
195
// can execute a compiled trace.
195
196
Builder.SetInsertPoint (BBHasTrace);
196
- Value *ValStartLoc = Builder.CreateLoad (GVStartLoc);
197
+ Value *ValStartLoc =
198
+ Builder.CreateLoad (Type::getInt32Ty (Context), GVStartLoc);
197
199
Value *ExecTraceCond = Builder.CreateICmp (CmpInst::Predicate::ICMP_EQ,
198
200
ValStartLoc, F->getArg (0 ));
199
201
Builder.CreateCondBr (ExecTraceCond, BBExecuteTrace, BBReturn);
@@ -216,7 +218,8 @@ void createControlPoint(Module &Mod, Function *F, std::vector<Value *> LiveVars,
216
218
217
219
// Create block that decides when to stop tracing.
218
220
Builder.SetInsertPoint (BBTracing);
219
- Value *ValStartLoc2 = Builder.CreateLoad (GVStartLoc);
221
+ Value *ValStartLoc2 =
222
+ Builder.CreateLoad (Type::getInt32Ty (Context), GVStartLoc);
220
223
Value *StopTracingCond = Builder.CreateICmp (CmpInst::Predicate::ICMP_EQ,
221
224
ValStartLoc2, F->getArg (0 ));
222
225
Builder.CreateCondBr (StopTracingCond, BBStopTracing, BBReturn);
@@ -264,102 +267,86 @@ std::vector<Value *> getLiveVars(DominatorTree &DT, CallInst *OldCtrlPoint) {
264
267
return Vec;
265
268
}
266
269
267
- namespace {
268
- struct YkControlPointPass : public ModulePass {
269
- static char ID;
270
+ YkControlPointPass::YkControlPointPass () {}
270
271
271
- YkControlPointPass () : ModulePass(ID) {}
272
+ PreservedAnalyses YkControlPointPass::run (Module &M,
273
+ ModuleAnalysisManager &AM) {
274
+ LLVMContext &Context = M.getContext ();
272
275
273
- StringRef getPassName () const override {
274
- return " Control Point Patching Pass" ;
276
+ // Locate the "dummy" control point provided by the user.
277
+ CallInst *OldCtrlPointCall = findControlPointCall (M);
278
+ if (OldCtrlPointCall == nullptr ) {
279
+ Context.emitError (" ykllvm couldn't find the call to `yk_control_point()`" );
280
+ return PreservedAnalyses::all ();
275
281
}
276
282
277
- bool runOnModule (Module &M) override {
278
- LLVMContext &Context = M.getContext ();
279
-
280
- // Locate the "dummy" control point provided by the user.
281
- CallInst *OldCtrlPointCall = findControlPointCall (M);
282
- if (OldCtrlPointCall == nullptr ) {
283
- Context.emitError (
284
- " ykllvm couldn't find the call to `yk_control_point()`" );
285
- return false ;
286
- }
287
-
288
- // Replace old control point call.
289
- IRBuilder<> Builder (OldCtrlPointCall);
290
-
291
- // Get function containing the control point.
292
- Function *Caller = OldCtrlPointCall->getFunction ();
293
-
294
- // Find all live variables just before the call to the control point.
295
- DominatorTree DT (*Caller);
296
- std::vector<Value *> LiveVals = getLiveVars (DT, OldCtrlPointCall);
297
- if (LiveVals.size () == 0 ) {
298
- Context.emitError (
299
- " The interpreter loop has no live variables!\n "
300
- " ykllvm doesn't support this scenario, as such an interpreter would "
301
- " make little sense." );
302
- return false ;
303
- }
304
-
305
- // Generate the YkCtrlPointVars struct. This struct is used to package up a
306
- // copy of all LLVM variables that are live just before the call to the
307
- // control point. These are passed in to the patched control point so that
308
- // they can be used as inputs and outputs to JITted trace code. The control
309
- // point returns a new YkCtrlPointVars whose members may have been mutated
310
- // by JITted trace code (if a trace was executed).
311
- std::vector<Type *> TypeParams;
312
- for (Value *V : LiveVals) {
313
- TypeParams.push_back (V->getType ());
314
- }
315
- StructType *CtrlPointReturnTy =
316
- StructType::create (TypeParams, " YkCtrlPointVars" );
317
-
318
- // Create the new control point.
319
- FunctionType *FType = FunctionType::get (
320
- CtrlPointReturnTy, {Type::getInt32Ty (Context), CtrlPointReturnTy},
321
- false );
322
- Function *NF = Function::Create (FType, GlobalVariable::ExternalLinkage,
323
- YK_NEW_CONTROL_POINT, M);
324
-
325
- // Instantiate the YkCtrlPointStruct to pass in to the control point.
326
- Value *InputStruct = cast<Value>(Constant::getNullValue (CtrlPointReturnTy));
327
- unsigned LvIdx = 0 ;
328
- for (Value *LV : LiveVals) {
329
- InputStruct = Builder.CreateInsertValue (InputStruct, LV, LvIdx);
330
- assert (LvIdx != UINT_MAX);
331
- LvIdx++;
332
- }
283
+ // Replace old control point call.
284
+ IRBuilder<> Builder (OldCtrlPointCall);
285
+
286
+ // Get function containing the control point.
287
+ Function *Caller = OldCtrlPointCall->getFunction ();
288
+
289
+ // Find all live variables just before the call to the control point.
290
+ DominatorTree DT (*Caller);
291
+ std::vector<Value *> LiveVals = getLiveVars (DT, OldCtrlPointCall);
292
+ if (LiveVals.size () == 0 ) {
293
+ Context.emitError (
294
+ " The interpreter loop has no live variables!\n "
295
+ " ykllvm doesn't support this scenario, as such an interpreter would "
296
+ " make little sense." );
297
+ return PreservedAnalyses::all ();
298
+ }
333
299
334
- // Insert call to the new control point.
335
- CallInst *CtrlPointRet = Builder.CreateCall (
336
- NF, {OldCtrlPointCall->getArgOperand (0 ), InputStruct});
337
-
338
- // Once the control point returns we need to extract the (potentially
339
- // mutated) values from the returned YkCtrlPointStruct and reassign them to
340
- // their corresponding live variables. In LLVM IR we can do this by simply
341
- // replacing all future references with the new values.
342
- LvIdx = 0 ;
343
- for (Value *LV : LiveVals) {
344
- Value *New = Builder.CreateExtractValue (cast<Value>(CtrlPointRet), LvIdx);
345
- LV->replaceUsesWithIf (
346
- New, [&](Use &U) { return DT.dominates (CtrlPointRet, U); });
347
- assert (LvIdx != UINT_MAX);
348
- LvIdx++;
349
- }
300
+ // Generate the YkCtrlPointVars struct. This struct is used to package up a
301
+ // copy of all LLVM variables that are live just before the call to the
302
+ // control point. These are passed in to the patched control point so that
303
+ // they can be used as inputs and outputs to JITted trace code. The control
304
+ // point returns a new YkCtrlPointVars whose members may have been mutated
305
+ // by JITted trace code (if a trace was executed).
306
+ std::vector<Type *> TypeParams;
307
+ for (Value *V : LiveVals) {
308
+ TypeParams.push_back (V->getType ());
309
+ }
310
+ StructType *CtrlPointReturnTy =
311
+ StructType::create (TypeParams, " YkCtrlPointVars" );
312
+
313
+ // Create the new control point.
314
+ FunctionType *FType = FunctionType::get (
315
+ CtrlPointReturnTy, {Type::getInt32Ty (Context), CtrlPointReturnTy}, false );
316
+ Function *NF = Function::Create (FType, GlobalVariable::ExternalLinkage,
317
+ YK_NEW_CONTROL_POINT, M);
318
+
319
+ // Instantiate the YkCtrlPointStruct to pass in to the control point.
320
+ Value *InputStruct = cast<Value>(Constant::getNullValue (CtrlPointReturnTy));
321
+ unsigned LvIdx = 0 ;
322
+ for (Value *LV : LiveVals) {
323
+ InputStruct = Builder.CreateInsertValue (InputStruct, LV, LvIdx);
324
+ assert (LvIdx != UINT_MAX);
325
+ LvIdx++;
326
+ }
350
327
351
- // Replace the call to the dummy control point.
352
- OldCtrlPointCall->eraseFromParent ();
328
+ // Insert call to the new control point.
329
+ CallInst *CtrlPointRet =
330
+ Builder.CreateCall (NF, {OldCtrlPointCall->getArgOperand (0 ), InputStruct});
331
+
332
+ // Once the control point returns we need to extract the (potentially
333
+ // mutated) values from the returned YkCtrlPointStruct and reassign them to
334
+ // their corresponding live variables. In LLVM IR we can do this by simply
335
+ // replacing all future references with the new values.
336
+ LvIdx = 0 ;
337
+ for (Value *LV : LiveVals) {
338
+ Value *New = Builder.CreateExtractValue (cast<Value>(CtrlPointRet), LvIdx);
339
+ LV->replaceUsesWithIf (
340
+ New, [&](Use &U) { return DT.dominates (CtrlPointRet, U); });
341
+ assert (LvIdx != UINT_MAX);
342
+ LvIdx++;
343
+ }
353
344
354
- // Generate new control point logic .
355
- createControlPoint (M, NF, LiveVals, CtrlPointReturnTy );
345
+ // Replace the call to the dummy control point.
346
+ OldCtrlPointCall-> eraseFromParent ( );
356
347
357
- return true ;
358
- }
359
- };
360
- char YkControlPointPass::ID = 0 ;
361
- } // namespace
348
+ // Generate new control point logic.
349
+ createControlPoint (M, NF, LiveVals, CtrlPointReturnTy);
362
350
363
- namespace llvm {
364
- ModulePass *createYkControlPointPass () { return new YkControlPointPass (); }
365
- } // namespace llvm
351
+ return PreservedAnalyses::none ();
352
+ }
0 commit comments