LDC LLVM profiling instrumentation

From D Wiki
Revision as of 20:50, 21 November 2015 by JohanEngelen (talk | contribs)
Jump to: navigation, search

This page functions as a place to collect information and to document how the implementation in LDC is done.

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 }