Difference between revisions of "LDC LLVM profiling instrumentation"
JohanEngelen (talk | contribs) (→LLVM intrinsics) |
JohanEngelen (talk | contribs) |
||
Line 14: | Line 14: | ||
* [http://llvm.org/docs/LangRef.html#llvm-instrprof-value-profile-intrinsic |llvm.instrprof_value_profile] | * [http://llvm.org/docs/LangRef.html#llvm-instrprof-value-profile-intrinsic |llvm.instrprof_value_profile] | ||
− | + | = Example with Clang 3.7 = | |
− | [ | + | |
+ | == C code == | ||
+ | |||
+ | int main(int argc, const char *argv[]) { | ||
+ | if (argc) | ||
+ | return 0; | ||
+ | else | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | == LLVM IR with clang -fprofile-instr-generate == | ||
+ | |||
+ | Unimportant IR has been stripped. | ||
+ | |||
+ | @__llvm_profile_name_main = private constant [4 x i8] c"main", section "__DATA,__llvm_prf_names", align 1 | ||
+ | @__llvm_profile_counters_main = private global [2 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 | ||
+ | @__llvm_profile_data_main = private constant { i32, i32, i64, i8*, i64* } { i32 4, i32 2, i64 10, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @__llvm_profile_name_main, i32 0, i32 0), i64* getelementptr inbounds ([2 x i64], [2 x i64]* @__llvm_profile_counters_main, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 | ||
+ | @__llvm_profile_runtime = external global i32 | ||
+ | |||
+ | ; Function Attrs: nounwind ssp uwtable | ||
+ | define i32 @main(i32 %argc, i8** %argv) #0 { | ||
+ | entry: | ||
+ | %retval = alloca i32, align 4 | ||
+ | %argc.addr = alloca i32, align 4 | ||
+ | %argv.addr = alloca i8**, align 8 | ||
+ | store i32 0, i32* %retval | ||
+ | store i32 %argc, i32* %argc.addr, align 4 | ||
+ | store i8** %argv, i8*** %argv.addr, align 8 | ||
+ | %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @__llvm_profile_counters_main, i64 0, i64 0) | ||
+ | %0 = add i64 %pgocount, 1 | ||
+ | store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @__llvm_profile_counters_main, i64 0, i64 0) | ||
+ | %1 = load i32, i32* %argc.addr, align 4 | ||
+ | %tobool = icmp ne i32 %1, 0 | ||
+ | br i1 %tobool, label %if.then, label %if.else | ||
+ | if.then: ; preds = %entry | ||
+ | %pgocount1 = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @__llvm_profile_counters_main, i64 0, i64 1) | ||
+ | %2 = add i64 %pgocount1, 1 | ||
+ | store i64 %2, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @__llvm_profile_counters_main, i64 0, i64 1) | ||
+ | store i32 0, i32* %retval | ||
+ | br label %return | ||
+ | if.else: ; preds = %entry | ||
+ | store i32 1, i32* %retval | ||
+ | br label %return | ||
+ | return: ; preds = %if.else, %if.then | ||
+ | %3 = load i32, i32* %retval | ||
+ | ret i32 %3 | ||
+ | } | ||
+ | |||
+ | ; Function Attrs: nounwind | ||
+ | declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #1 | ||
+ | |||
+ | ; Function Attrs: noinline | ||
+ | define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #2 { | ||
+ | %1 = load i32, i32* @__llvm_profile_runtime | ||
+ | ret i32 %1 | ||
+ | } | ||
+ | |||
+ | attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" } | ||
+ | attributes #1 = { nounwind } | ||
+ | attributes #2 = { noinline } |
Revision as of 20:50, 21 November 2015
This page functions as a place to collect information and to document how the implementation in LDC is done.
Contents
LLVM InstrProf
[describe what and how LLVM supports profile instrumentation]
LLVM intrinsics
These intrinsics were introduced with LLVM commit r223672, and Clang was modified to use them in Clang commit r223683.
LLVM features two intrinsics for instrumentation:
Example with Clang 3.7
C code
int main(int argc, const char *argv[]) { if (argc) return 0; else return 1; }
LLVM IR with clang -fprofile-instr-generate
Unimportant IR has been stripped.
@__llvm_profile_name_main = private constant [4 x i8] c"main", section "__DATA,__llvm_prf_names", align 1 @__llvm_profile_counters_main = private global [2 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 @__llvm_profile_data_main = private constant { i32, i32, i64, i8*, i64* } { i32 4, i32 2, i64 10, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @__llvm_profile_name_main, i32 0, i32 0), i64* getelementptr inbounds ([2 x i64], [2 x i64]* @__llvm_profile_counters_main, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8 @__llvm_profile_runtime = external global i32
; Function Attrs: nounwind ssp uwtable define i32 @main(i32 %argc, i8** %argv) #0 { entry: %retval = alloca i32, align 4 %argc.addr = alloca i32, align 4 %argv.addr = alloca i8**, align 8 store i32 0, i32* %retval store i32 %argc, i32* %argc.addr, align 4 store i8** %argv, i8*** %argv.addr, align 8 %pgocount = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @__llvm_profile_counters_main, i64 0, i64 0) %0 = add i64 %pgocount, 1 store i64 %0, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @__llvm_profile_counters_main, i64 0, i64 0) %1 = load i32, i32* %argc.addr, align 4 %tobool = icmp ne i32 %1, 0 br i1 %tobool, label %if.then, label %if.else if.then: ; preds = %entry %pgocount1 = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @__llvm_profile_counters_main, i64 0, i64 1) %2 = add i64 %pgocount1, 1 store i64 %2, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @__llvm_profile_counters_main, i64 0, i64 1) store i32 0, i32* %retval br label %return if.else: ; preds = %entry store i32 1, i32* %retval br label %return return: ; preds = %if.else, %if.then %3 = load i32, i32* %retval ret i32 %3 }
; Function Attrs: nounwind declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #1
; Function Attrs: noinline define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #2 { %1 = load i32, i32* @__llvm_profile_runtime ret i32 %1 }
attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind } attributes #2 = { noinline }