Skip to content

Commit febcfc1

Browse files
committed
use fewer access calls
1 parent 9ca1e35 commit febcfc1

File tree

4 files changed

+213
-35
lines changed

4 files changed

+213
-35
lines changed

CFFunctionInstrumentation/parse_found_funcs.py

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
from utils import demangle_function_name
44

55
def unique_funcs(funcs_per_module):
6-
unique_funcs = set()
6+
unique_functions = set()
77
for module, funcs in funcs_per_module.items():
8-
unique_funcs.update(funcs)
9-
return unique_funcs
8+
unique_functions.update(funcs)
9+
return unique_functions
1010

1111

1212
def parse_called_funcs(filename):
@@ -35,22 +35,72 @@ def get_unique_funcs(filename):
3535
funcs_per_module = parse_called_funcs(filename)
3636
return unique_funcs(funcs_per_module)
3737

38+
def get_stored_funcs_dict(filename):
39+
file = open(filename, "r")
40+
funcs_per_module = eval(file.read())
41+
42+
return funcs_per_module
43+
44+
def print_stats(funcs_per_module):
45+
46+
unique_functions = unique_funcs(funcs_per_module)
47+
48+
print(f'Found {len(funcs_per_module)} modules')
49+
50+
print(f'Found {len(unique_functions)} unique functions')
51+
52+
def build_folder_hierarchy(modules):
53+
hierarchy = {}
54+
for module in modules:
55+
module = module.removeprefix('/home/webmiche/questions/llvm-project/')
56+
parts = module.split('/')
57+
current = hierarchy
58+
for part in parts:
59+
if part not in current:
60+
current[part] = {}
61+
current = current[part]
62+
return hierarchy
63+
64+
def print_hierarchy(hierarchy):
65+
for outer_most, inner in hierarchy.items():
66+
print(outer_most)
67+
for inner_most, inner_inner in inner.items():
68+
print(f' {inner_most}')
69+
for inner_inner_most in inner_inner:
70+
print(f' {inner_inner_most}')
71+
for inner_inner_inner in inner_inner[inner_inner_most]:
72+
print(f' {inner_inner_inner}')
73+
for inner_inner_inner_inner in inner_inner[inner_inner_most][inner_inner_inner]:
74+
print(f' {inner_inner_inner_inner}')
75+
print()
76+
print()
77+
print()
78+
79+
80+
3881
if __name__ == '__main__':
3982
# pass the filename as an argument
4083
parser = ArgumentParser()
4184
parser.add_argument('filename')
4285
args = parser.parse_args()
4386
filename = args.filename
87+
funcs_per_module = get_stored_funcs_dict(filename)
4488

45-
unique_funcs = get_unique_funcs(filename)
4689

47-
print(f'Found {len(unique_funcs)} unique functions in {filename}:')
90+
hierarchy = build_folder_hierarchy(funcs_per_module.keys())
4891

49-
funcs_per_module = parse_called_funcs(filename)
92+
print_hierarchy(hierarchy)
5093

51-
print(f'Found {len(funcs_per_module)} modules in {filename}:')
94+
# add up all the functions in the TableGen folder
95+
functions_in_tablegen = {}
5296
for module, funcs in funcs_per_module.items():
53-
print(f'{module}: {len(funcs)} functions')
97+
if module.startswith('/home/webmiche/questions/llvm-project/llvm/utils/TableGen'):
98+
functions_in_tablegen[module] = funcs
99+
100+
unique_functions = unique_funcs(functions_in_tablegen)
101+
total_functions = len(unique_functions)
102+
103+
104+
print_stats(funcs_per_module)
54105

55-
f = open("funcs_per_module.txt", "w")
56-
f.write(str(funcs_per_module))
106+
print(f'Functions in TableGen: {total_functions}')

llvm/lib/Transforms/Utils/CFFunctionInstrumentation.cpp

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ CFFunctionInstrumentationPass::run(Module &M, ModuleAnalysisManager &AM) {
4949
// for all return instructions, print the return value to a file with the
5050
// name of the function
5151

52+
auto GV = new GlobalVariable(
53+
M, Type::getInt32Ty(M.getContext()), true,
54+
GlobalValue::LinkageTypes::PrivateLinkage,
55+
ConstantInt::get(IntegerType::getInt32Ty(M.getContext()), 0),
56+
"init" + F.getName());
5257
// store already handled blocks
5358
std::set<BasicBlock *> HandledBlocks;
5459
for (auto &BB : F) {
@@ -88,10 +93,44 @@ CFFunctionInstrumentationPass::run(Module &M, ModuleAnalysisManager &AM) {
8893
// split at return
8994
BasicBlock *ReturnBB = BB.splitBasicBlock(RI, "return", false);
9095

96+
BasicBlock *CheckBB =
97+
BasicBlock::Create(M.getContext(), "access_check", &F);
98+
BasicBlock *Check2BB =
99+
BasicBlock::Create(M.getContext(), "no_init_check", &F);
91100
BasicBlock *AccessBB =
92101
BasicBlock::Create(M.getContext(), "access", &F);
102+
BasicBlock *UpdateGVBB =
103+
BasicBlock::Create(M.getContext(), "update", &F);
104+
BasicBlock *NoAccessBB =
105+
BasicBlock::Create(M.getContext(), "no_access", &F);
106+
93107
BasicBlock *PrintBB = BasicBlock::Create(M.getContext(), "print", &F);
94108

109+
LLVM_DEBUG(dbgs() << "Created BBs\n");
110+
111+
IRBuilder<> CheckBuilder(CheckBB);
112+
113+
Value *GV_value = CheckBuilder.CreateLoad(
114+
IntegerType::getInt32Ty(M.getContext()), GV);
115+
116+
// check if GV is 0 (not yet accessed) or -1 (no access) or 1 (access)
117+
Value *CmpGV = CheckBuilder.CreateICmpEQ(
118+
GV_value,
119+
ConstantInt::get(IntegerType::getInt32Ty(M.getContext()), 1));
120+
121+
CheckBuilder.CreateCondBr(CmpGV, PrintBB, Check2BB);
122+
123+
LLVM_DEBUG(dbgs() << "Created check BB\n");
124+
125+
IRBuilder<> Check2Builder(Check2BB);
126+
Value *CmpGV2 = Check2Builder.CreateICmpEQ(
127+
GV_value,
128+
ConstantInt::get(IntegerType::getInt32Ty(M.getContext()), -1));
129+
130+
Check2Builder.CreateCondBr(CmpGV2, ReturnBB, AccessBB);
131+
132+
LLVM_DEBUG(dbgs() << "Created check2 BB\n");
133+
95134
IRBuilder<> AccessBuilder(AccessBB);
96135
// insert call to access function with filename and 0
97136
Value *status = AccessBuilder.CreateCall(
@@ -100,7 +139,25 @@ CFFunctionInstrumentationPass::run(Module &M, ModuleAnalysisManager &AM) {
100139
Value *Cmp = AccessBuilder.CreateICmpEQ(
101140
status,
102141
ConstantInt::get(IntegerType::getInt32Ty(M.getContext()), 0));
103-
AccessBuilder.CreateCondBr(Cmp, PrintBB, ReturnBB);
142+
AccessBuilder.CreateCondBr(Cmp, UpdateGVBB, NoAccessBB);
143+
144+
LLVM_DEBUG(dbgs() << "Created access BB\n");
145+
146+
IRBuilder<> NoAccessBuilder(NoAccessBB);
147+
NoAccessBuilder.CreateStore(
148+
ConstantInt::get(IntegerType::getInt32Ty(M.getContext()), -1),
149+
GV);
150+
NoAccessBuilder.CreateBr(ReturnBB);
151+
152+
LLVM_DEBUG(dbgs() << "Created no access BB\n");
153+
154+
IRBuilder<> UpdateGVBuilder(UpdateGVBB);
155+
UpdateGVBuilder.CreateStore(
156+
ConstantInt::get(IntegerType::getInt32Ty(M.getContext()), 1), GV);
157+
158+
UpdateGVBuilder.CreateBr(PrintBB);
159+
160+
LLVM_DEBUG(dbgs() << "Created update BB\n");
104161

105162
IRBuilder<> PrintBuilder(PrintBB);
106163
FunctionCallee PrintFunc = M.getOrInsertFunction(
@@ -131,14 +188,18 @@ CFFunctionInstrumentationPass::run(Module &M, ModuleAnalysisManager &AM) {
131188
PrintBuilder.CreateCall(CloseFunc, write_fptr);
132189
PrintBuilder.CreateBr(ReturnBB);
133190

134-
BB.getTerminator()->setSuccessor(0, AccessBB);
191+
BB.getTerminator()->setSuccessor(0, CheckBB);
135192

136193
// place new BBs in the correct order
137194
ReturnBB->moveAfter(PrintBB);
138195

139196
HandledBlocks.insert(AccessBB);
140197
HandledBlocks.insert(PrintBB);
141198
HandledBlocks.insert(ReturnBB);
199+
HandledBlocks.insert(CheckBB);
200+
HandledBlocks.insert(Check2BB);
201+
HandledBlocks.insert(UpdateGVBB);
202+
HandledBlocks.insert(NoAccessBB);
142203
}
143204
}
144205
HandledBlocks.insert(&BB);

print_example/instrumented.ll

Lines changed: 90 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,82 @@
11
; ModuleID = 'test.ll'
22
source_filename = "test.ll"
33

4+
@initfoo = private constant i32 0
45
@0 = private unnamed_addr constant [19 x i8] c"function_trace.txt\00", align 1
56
@1 = private unnamed_addr constant [2 x i8] c"a\00", align 1
67
@2 = private unnamed_addr constant [10 x i8] c"foo %lld\0A\00", align 1
7-
@3 = private unnamed_addr constant [10 x i8] c"baz %lld\0A\00", align 1
8+
@initbat = private constant i32 0
9+
@3 = private unnamed_addr constant [10 x i8] c"bat %lld\0A\00", align 1
10+
@initbaz = private constant i32 0
11+
@4 = private unnamed_addr constant [10 x i8] c"baz %lld\0A\00", align 1
812

913
define i1 @foo() {
10-
br label %access
14+
br label %access_check
1115

12-
access: ; preds = %0
13-
%1 = call i32 @access(ptr @0, i32 0)
14-
%2 = icmp eq i32 %1, 0
15-
br i1 %2, label %print, label %return
16+
access_check: ; preds = %0
17+
%1 = load i32, ptr @initfoo, align 4
18+
%2 = icmp eq i32 %1, 1
19+
br i1 %2, label %print, label %no_init_check
20+
21+
no_init_check: ; preds = %access_check
22+
%3 = icmp eq i32 %1, -1
23+
br i1 %3, label %return, label %access
24+
25+
access: ; preds = %no_init_check
26+
%4 = call i32 @access(ptr @0, i32 0)
27+
%5 = icmp eq i32 %4, 0
28+
br i1 %5, label %update, label %no_access
29+
30+
update: ; preds = %access
31+
store i32 1, ptr @initfoo, align 4
32+
br label %print
33+
34+
no_access: ; preds = %access
35+
store i32 -1, ptr @initfoo, align 4
36+
br label %return
1637

17-
print: ; preds = %access
18-
%3 = call ptr @fopen(ptr @0, ptr @1)
19-
call void (ptr, ...) @fprintf(ptr %3, ptr @2, i1 false)
20-
%4 = call i32 @fclose(ptr %3)
38+
print: ; preds = %update, %access_check
39+
%6 = call ptr @fopen(ptr @0, ptr @1)
40+
call void (ptr, ...) @fprintf(ptr %6, ptr @2, i1 false)
41+
%7 = call i32 @fclose(ptr %6)
2142
br label %return
2243

23-
return: ; preds = %print, %access
44+
return: ; preds = %print, %no_access, %no_init_check
2445
ret i1 false
2546
}
2647

2748
define i32 @bat() {
49+
br label %access_check
50+
51+
access_check: ; preds = %0
52+
%1 = load i32, ptr @initbat, align 4
53+
%2 = icmp eq i32 %1, 1
54+
br i1 %2, label %print, label %no_init_check
55+
56+
no_init_check: ; preds = %access_check
57+
%3 = icmp eq i32 %1, -1
58+
br i1 %3, label %return, label %access
59+
60+
access: ; preds = %no_init_check
61+
%4 = call i32 @access(ptr @0, i32 0)
62+
%5 = icmp eq i32 %4, 0
63+
br i1 %5, label %update, label %no_access
64+
65+
update: ; preds = %access
66+
store i32 1, ptr @initbat, align 4
67+
br label %print
68+
69+
no_access: ; preds = %access
70+
store i32 -1, ptr @initbat, align 4
71+
br label %return
72+
73+
print: ; preds = %update, %access_check
74+
%6 = call ptr @fopen(ptr @0, ptr @1)
75+
call void (ptr, ...) @fprintf(ptr %6, ptr @3, i32 0)
76+
%7 = call i32 @fclose(ptr %6)
77+
br label %return
78+
79+
return: ; preds = %print, %no_access, %no_init_check
2880
ret i32 0
2981
}
3082

@@ -43,20 +95,37 @@ else: ; preds = %0
4395
br label %end
4496

4597
end: ; preds = %else, %then
46-
br label %access
98+
br label %access_check
4799

48-
access: ; preds = %end
49-
%2 = call i32 @access(ptr @0, i32 0)
50-
%3 = icmp eq i32 %2, 0
51-
br i1 %3, label %print, label %return
100+
access_check: ; preds = %end
101+
%2 = load i32, ptr @initbaz, align 4
102+
%3 = icmp eq i32 %2, 1
103+
br i1 %3, label %print, label %no_init_check
104+
105+
no_init_check: ; preds = %access_check
106+
%4 = icmp eq i32 %2, -1
107+
br i1 %4, label %return, label %access
108+
109+
access: ; preds = %no_init_check
110+
%5 = call i32 @access(ptr @0, i32 0)
111+
%6 = icmp eq i32 %5, 0
112+
br i1 %6, label %update, label %no_access
113+
114+
update: ; preds = %access
115+
store i32 1, ptr @initbaz, align 4
116+
br label %print
117+
118+
no_access: ; preds = %access
119+
store i32 -1, ptr @initbaz, align 4
120+
br label %return
52121

53-
print: ; preds = %access
54-
%4 = call ptr @fopen(ptr @0, ptr @1)
55-
call void (ptr, ...) @fprintf(ptr %4, ptr @3, i32 5)
56-
%5 = call i32 @fclose(ptr %4)
122+
print: ; preds = %update, %access_check
123+
%7 = call ptr @fopen(ptr @0, ptr @1)
124+
call void (ptr, ...) @fprintf(ptr %7, ptr @4, i32 5)
125+
%8 = call i32 @fclose(ptr %7)
57126
br label %return
58127

59-
return: ; preds = %print, %access
128+
return: ; preds = %print, %no_access, %no_init_check
60129
ret i32 5
61130
}
62131

print_example/test.c

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)