Difference between revisions of "LDC LLVM profiling instrumentation"

From D Wiki
Jump to: navigation, search
(LLVM intrinsics)
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 of Clang's LLVM IR output ==
+
= Example with Clang 3.7  =
[show minimal C code example and Clang's -emit-llvm output for it]
+
 
 +
== 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.

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 }