Skip to content

Commit 5bd64cb

Browse files
authored
Merge pull request rust-lang#111 from Pavel-Durov/basic-block-tracer-llvm-pass
Implement BasicBlockTracer pass
2 parents 6ad2989 + faab664 commit 5bd64cb

File tree

7 files changed

+181
-1
lines changed

7 files changed

+181
-1
lines changed

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ void initializeWinEHPreparePass(PassRegistry&);
342342
void initializeWriteBitcodePassPass(PassRegistry&);
343343
void initializeXRayInstrumentationPass(PassRegistry&);
344344
void initializeYkSplitBlocksAfterCallsPass(PassRegistry&);
345-
345+
void initializeYkBasicBlockTracerPass(PassRegistry&);
346346
} // end namespace llvm
347347

348348
#endif // LLVM_INITIALIZEPASSES_H
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#ifndef LLVM_TRANSFORMS_YK_HELLOWORLD_H
2+
#define LLVM_TRANSFORMS_YK_HELLOWORLD_H
3+
4+
#include "llvm/Pass.h"
5+
6+
// The name of the trace function
7+
#define YK_TRACE_FUNCTION "yk_trace_basicblock"
8+
9+
namespace llvm {
10+
ModulePass *createYkBasicBlockTracerPass();
11+
} // namespace llvm
12+
13+
#endif

llvm/lib/CodeGen/CodeGen.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,5 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
151151
initializeWinEHPreparePass(Registry);
152152
initializeXRayInstrumentationPass(Registry);
153153
initializeYkSplitBlocksAfterCallsPass(Registry);
154+
initializeYkBasicBlockTracerPass(Registry);
154155
}

llvm/lib/CodeGen/TargetPassConfig.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "llvm/Transforms/Yk/SplitBlocksAfterCalls.h"
5656
#include "llvm/Transforms/Yk/Stackmaps.h"
5757
#include "llvm/Transforms/Yk/NoCallsInEntryBlocks.h"
58+
#include "llvm/Transforms/Yk/BasicBlockTracer.h"
5859
#include <cassert>
5960
#include <optional>
6061
#include <string>
@@ -292,6 +293,11 @@ static cl::opt<bool>
292293
YkSplitBlocksAfterCalls("yk-split-blocks-after-calls", cl::init(false), cl::NotHidden,
293294
cl::desc("Split blocks after function calls."));
294295

296+
static cl::opt<bool>
297+
YkBasicBlockTracer("yk-basicblock-tracer", cl::init(false), cl::NotHidden,
298+
cl::desc("Enables YK Software Tracer capability"));
299+
300+
295301
/// Allow standard passes to be disabled by command line options. This supports
296302
/// simple binary flags that either suppress the pass or do nothing.
297303
/// i.e. -disable-mypass=false has no effect.
@@ -1181,6 +1187,10 @@ bool TargetPassConfig::addISelPasses() {
11811187
addPass(createYkStackmapsPass());
11821188
}
11831189

1190+
if (YkBasicBlockTracer) {
1191+
addPass(createYkBasicBlockTracerPass());
1192+
}
1193+
11841194
addISelPrepare();
11851195
return addCoreISelPasses();
11861196
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "llvm/Transforms/Yk/BasicBlockTracer.h"
2+
#include "llvm/IR/BasicBlock.h"
3+
#include "llvm/IR/Function.h"
4+
#include "llvm/IR/IRBuilder.h"
5+
#include "llvm/IR/Instruction.h"
6+
#include "llvm/IR/Instructions.h"
7+
#include "llvm/IR/LLVMContext.h"
8+
#include "llvm/IR/Module.h"
9+
#include "llvm/InitializePasses.h"
10+
#include "llvm/Pass.h"
11+
12+
#define DEBUG_TYPE "yk-basicblock-tracer-pass"
13+
14+
using namespace llvm;
15+
16+
namespace llvm {
17+
void initializeYkBasicBlockTracerPass(PassRegistry &);
18+
} // namespace llvm
19+
20+
namespace {
21+
struct YkBasicBlockTracer : public ModulePass {
22+
static char ID;
23+
24+
YkBasicBlockTracer() : ModulePass(ID) {
25+
initializeYkBasicBlockTracerPass(*PassRegistry::getPassRegistry());
26+
}
27+
28+
bool runOnModule(Module &M) override {
29+
LLVMContext &Context = M.getContext();
30+
// Create externally linked function declaration:
31+
// void yk_trace_basicblock(int functionIndex, int blockIndex)
32+
Type *ReturnType = Type::getVoidTy(Context);
33+
Type *FunctionIndexArgType = Type::getInt32Ty(Context);
34+
Type *BlockIndexArgType = Type::getInt32Ty(Context);
35+
36+
FunctionType *FType = FunctionType::get(
37+
ReturnType, {FunctionIndexArgType, BlockIndexArgType}, false);
38+
Function *TraceFunc = Function::Create(
39+
FType, GlobalVariable::ExternalLinkage, YK_TRACE_FUNCTION, M);
40+
41+
IRBuilder<> builder(Context);
42+
uint32_t FunctionIndex = 0;
43+
for (auto &F : M) {
44+
uint32_t BlockIndex = 0;
45+
for (auto &BB : F) {
46+
builder.SetInsertPoint(&*BB.getFirstInsertionPt());
47+
builder.CreateCall(TraceFunc, {builder.getInt32(FunctionIndex),
48+
builder.getInt32(BlockIndex)});
49+
assert(BlockIndex != UINT32_MAX &&
50+
"Expected BlockIndex to not overflow");
51+
BlockIndex++;
52+
}
53+
assert(FunctionIndex != UINT32_MAX &&
54+
"Expected FunctionIndex to not overflow");
55+
FunctionIndex++;
56+
}
57+
return true;
58+
}
59+
};
60+
} // namespace
61+
62+
char YkBasicBlockTracer::ID = 0;
63+
64+
INITIALIZE_PASS(YkBasicBlockTracer, DEBUG_TYPE, "yk basicblock tracer", false,
65+
false)
66+
67+
ModulePass *llvm::createYkBasicBlockTracerPass() {
68+
return new YkBasicBlockTracer();
69+
}

llvm/lib/Transforms/Yk/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ add_llvm_component_library(LLVMYkPasses
77
ShadowStack.cpp
88
NoCallsInEntryBlocks.cpp
99
SplitBlocksAfterCalls.cpp
10+
BasicBlockTracer.cpp
1011

1112
DEPENDS
1213
intrinsics_gen
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
; RUNNING TEST EXAMPLE: llvm-lit llvm/test/Transforms/Yk/BasicBlockTracer.ll
2+
; RUN: llc -stop-after yk-basicblock-tracer-pass --yk-basicblock-tracer < %s | FileCheck %s
3+
4+
; CHECK-LABEL: define dso_local noundef i32 @main()
5+
; CHECK-NEXT: call void @yk_trace_basicblock(i32 0, i32 0)
6+
define dso_local noundef i32 @main() #0 {
7+
%1 = alloca i32, align 4
8+
%2 = alloca i32, align 4
9+
%3 = alloca i32, align 4
10+
store i32 0, i32* %1, align 4
11+
store i32 0, i32* %2, align 4
12+
store i32 0, i32* %3, align 4
13+
br label %4
14+
15+
; CHECK-LABEL: 4:{{.*}}
16+
; CHECK-NEXT: call void @yk_trace_basicblock(i32 0, i32 1)
17+
4: ; preds = %13, %0
18+
%5 = load i32, i32* %3, align 4
19+
%6 = icmp slt i32 %5, 43
20+
br i1 %6, label %7, label %16
21+
22+
; CHECK-LABEL: 7:{{.*}}
23+
; CHECK-NEXT: call void @yk_trace_basicblock(i32 0, i32 2)
24+
7: ; preds = %4
25+
%8 = load i32, i32* %3, align 4
26+
%9 = icmp eq i32 %8, 42
27+
br i1 %9, label %10, label %12
28+
29+
; CHECK-LABEL: 10:{{.*}}
30+
; CHECK-NEXT: call void @yk_trace_basicblock(i32 0, i32 3)
31+
10: ; preds = %7
32+
%11 = load i32, i32* %3, align 4
33+
store i32 %11, i32* %1, align 4
34+
br label %17
35+
36+
; CHECK-LABEL: 12:{{.*}}
37+
; CHECK-NEXT: call void @yk_trace_basicblock(i32 0, i32 4)
38+
12: ; preds = %7
39+
br label %13
40+
41+
; CHECK-LABEL: 13:{{.*}}
42+
; CHECK-NEXT: call void @yk_trace_basicblock(i32 0, i32 5)
43+
13: ; preds = %12
44+
%14 = load i32, i32* %3, align 4
45+
%15 = add nsw i32 %14, 1
46+
store i32 %15, i32* %3, align 4
47+
br label %4, !llvm.loop !6
48+
49+
; CHECK-LABEL: 16:{{.*}}
50+
; CHECK-NEXT: call void @yk_trace_basicblock(i32 0, i32 6)
51+
16: ; preds = %4
52+
store i32 0, i32* %1, align 4
53+
br label %17
54+
55+
; CHECK-LABEL: 17:{{.*}}
56+
; CHECK-NEXT: call void @yk_trace_basicblock(i32 0, i32 7)
57+
17: ; preds = %16, %10
58+
%18 = load i32, i32* %1, align 4
59+
ret i32 %18
60+
}
61+
62+
; CHECK-LABEL: define dso_local noundef i32 @_Z5checki(i32 noundef %0)
63+
; CHECK-NEXT: call void @yk_trace_basicblock(i32 1, i32 0)
64+
define dso_local noundef i32 @_Z5checki(i32 noundef %0) #1 {
65+
%2 = alloca i32, align 4
66+
store i32 %0, i32* %2, align 4
67+
%3 = load i32, i32* %2, align 4
68+
%4 = icmp eq i32 %3, 42
69+
%5 = zext i1 %4 to i32
70+
ret i32 %5
71+
}
72+
73+
attributes #0 = { mustprogress noinline norecurse nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
74+
attributes #1 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
75+
76+
!llvm.module.flags = !{!0, !1, !2, !3, !4}
77+
!llvm.ident = !{!5}
78+
79+
!0 = !{i32 1, !"wchar_size", i32 4}
80+
!1 = !{i32 7, !"PIC Level", i32 2}
81+
!2 = !{i32 7, !"PIE Level", i32 2}
82+
!3 = !{i32 7, !"uwtable", i32 1}
83+
!4 = !{i32 7, !"frame-pointer", i32 2}
84+
!5 = !{!"Debian clang version 14.0.6"}
85+
!6 = distinct !{!6, !7}
86+
!7 = !{!"llvm.loop.mustprogress"}

0 commit comments

Comments
 (0)