Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions llvm/include/llvm/Transforms/Yk/BasicBlockTracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

// The name of the trace function - used in swt tracing.
#define YK_TRACE_FUNCTION "__yk_trace_basicblock"
#define YK_TRACE_FUNCTION_WRAPPER "__yk_trace_basicblock_wrapper"

// The name of the thread tracing state thread local.
#define YK_THREAD_TRACING_STATE_TL "__yk_thread_tracing_state"
Expand Down
28 changes: 24 additions & 4 deletions llvm/lib/Transforms/Yk/BasicBlockTracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,28 @@ struct YkBasicBlockTracer : public ModulePass {

FunctionType *FType = FunctionType::get(
ReturnType, {FunctionIndexArgType, BlockIndexArgType}, false);
Function *TraceFunc = Function::Create(
Function *TraceFuncInner = Function::Create(
FType, GlobalVariable::ExternalLinkage, YK_TRACE_FUNCTION, M);

// Define the trace recorder wrapper.
//
// We use a wrapper so we can use an ABI that disrupts register allocation
// in the interpreter code to a lesser extent. The wrapper is required
// because the actual recorder function is defined in the JIT runtime's
// shared object and we can't change the ABI for library calls.
llvm::Function *TraceFunc = Function::Create(
FType, llvm::Function::InternalLinkage, YK_TRACE_FUNCTION_WRAPPER, M);
TraceFunc->setCallingConv(llvm::CallingConv::PreserveAll);
TraceFunc->addFnAttr(YK_OUTLINE_FNATTR);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As is often the case: raise a PR, spot a potential tweak.

I'm just wondering if I should mark the wrapper noinline...

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we mind if it's inlined: in a sense, we do the "right thing" no matter which stack frame we run things in.

[That said, my guess would be that LLVM won't inline functions with this ABI. But I could be wrong about that.]

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, shall we try this as-is then?

llvm::BasicBlock *WrapperBB = BasicBlock::Create(Context, "", TraceFunc);
IRBuilder<> Builder(WrapperBB);
std::vector<Value *> InnerArgs;
for (Argument &A : TraceFunc->args()) {
InnerArgs.push_back(&A);
}
Builder.CreateCall(TraceFuncInner, InnerArgs);
Builder.CreateRetVoid();

// Metadata used to help the serialiser identify the purpose of a block.
//
// This block is a "are we tracing" check:
Expand All @@ -90,7 +109,6 @@ struct YkBasicBlockTracer : public ModulePass {
MDNode *SerialiseBBMD =
MDNode::get(Context, MDString::get(Context, "swt-serialise-bb"));

IRBuilder<> Builder(Context);
uint32_t FunctionIndex = 0;
for (auto &F : M) {
// If we won't ever trace this, don't insert calls to the tracer, as it
Expand Down Expand Up @@ -160,8 +178,10 @@ struct YkBasicBlockTracer : public ModulePass {
// Make the block that calls the recorder.
BasicBlock *RecBB = llvm::BasicBlock::Create(Context, "", &F, RestBB);
Builder.SetInsertPoint(RecBB);
Builder.CreateCall(TraceFunc, {Builder.getInt32(FunctionIndex),
Builder.getInt32(BlockIndex)});
CallInst *CI =
Builder.CreateCall(TraceFunc, {Builder.getInt32(FunctionIndex),
Builder.getInt32(BlockIndex)});
CI->setCallingConv(llvm::CallingConv::PreserveAll);
Builder.CreateBr(RestBB);

// Update the terminator of the "are we tracing?" block We jump over
Expand Down
18 changes: 9 additions & 9 deletions llvm/test/Transforms/Yk/BasicBlockTracer.ll
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; RUNNING TEST EXAMPLE: llvm-lit llvm/test/Transforms/Yk/BasicBlockTracer.ll
; RUN: llc -stop-after yk-basicblock-tracer-pass --yk-basicblock-tracer < %s | FileCheck %s

; CHECK: call void @__yk_trace_basicblock(i32 0, i32 0)
; CHECK: call preserve_allcc void @__yk_trace_basicblock_wrapper(i32 0, i32 0)
define dso_local noundef i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
Expand All @@ -11,47 +11,47 @@ define dso_local noundef i32 @main() #0 {
store i32 0, i32* %3, align 4
br label %4

; CHECK: call void @__yk_trace_basicblock(i32 0, i32 1)
; CHECK: call preserve_allcc void @__yk_trace_basicblock_wrapper(i32 0, i32 1)
4: ; preds = %13, %0
%5 = load i32, i32* %3, align 4
%6 = icmp slt i32 %5, 43
br i1 %6, label %7, label %16

; CHECK: call void @__yk_trace_basicblock(i32 0, i32 2)
; CHECK: call preserve_allcc void @__yk_trace_basicblock_wrapper(i32 0, i32 2)
7: ; preds = %4
%8 = load i32, i32* %3, align 4
%9 = icmp eq i32 %8, 42
br i1 %9, label %10, label %12

; CHECK: call void @__yk_trace_basicblock(i32 0, i32 3)
; CHECK: call preserve_allcc void @__yk_trace_basicblock_wrapper(i32 0, i32 3)
10: ; preds = %7
%11 = load i32, i32* %3, align 4
store i32 %11, i32* %1, align 4
br label %17

; CHECK: call void @__yk_trace_basicblock(i32 0, i32 4)
; CHECK: call preserve_allcc void @__yk_trace_basicblock_wrapper(i32 0, i32 4)
12: ; preds = %7
br label %13

; CHECK: call void @__yk_trace_basicblock(i32 0, i32 5)
; CHECK: call preserve_allcc void @__yk_trace_basicblock_wrapper(i32 0, i32 5)
13: ; preds = %12
%14 = load i32, i32* %3, align 4
%15 = add nsw i32 %14, 1
store i32 %15, i32* %3, align 4
br label %4, !llvm.loop !6

; CHECK: call void @__yk_trace_basicblock(i32 0, i32 6)
; CHECK: call preserve_allcc void @__yk_trace_basicblock_wrapper(i32 0, i32 6)
16: ; preds = %4
store i32 0, i32* %1, align 4
br label %17

; CHECK: call void @__yk_trace_basicblock(i32 0, i32 7)
; CHECK: call preserve_allcc void @__yk_trace_basicblock_wrapper(i32 0, i32 7)
17: ; preds = %16, %10
%18 = load i32, i32* %1, align 4
ret i32 %18
}

; CHECK: call void @__yk_trace_basicblock(i32 1, i32 0)
; CHECK: call preserve_allcc void @__yk_trace_basicblock_wrapper(i32 1, i32 0)
define dso_local noundef i32 @_Z5checki(i32 noundef %0) #1 {
%2 = alloca i32, align 4
store i32 %0, i32* %2, align 4
Expand Down