mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-07 03:16:05 +03:00
256 lines
9.9 KiB
D
256 lines
9.9 KiB
D
// Test PGO for different kinds of functions
|
|
//
|
|
// The tests should not test function name mangling, therefore the functionname
|
|
// matching strings contain regexp wildcards.
|
|
|
|
// RUN: %ldc -c -output-ll -fprofile-instr-generate -of=%t.ll %s && FileCheck %s --check-prefix=PROFGEN < %t.ll
|
|
|
|
// RUN: %ldc -fprofile-instr-generate=%t.profraw -run %s \
|
|
// RUN: && %profdata merge %t.profraw -o %t.profdata \
|
|
// RUN: && %ldc -c -output-ll -of=%t2.ll -fprofile-instr-use=%t.profdata %s \
|
|
// RUN: && FileCheck %s -check-prefix=PROFUSE < %t2.ll
|
|
|
|
// PROFGEN-DAG: @[[SMPL:__(llvm_profile_counters|profc).*simplefunction[A-Za-z0-9]*]] ={{[A-Za-z ]*}} [2 x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[TMPL:__(llvm_profile_counters|profc).*templatefunc[A-Za-z0-9]*]] ={{.*}} [2 x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[OUTR:__(llvm_profile_counters|profc).*outerfunc[A-Za-z0-9]*]] ={{.*}} [2 x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[NEST:__(llvm_profile_counters|profc).*nestedfunc[A-Za-z0-9]*]] ={{.*}} [2 x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[LMBD:__(llvm_profile_counters|profc).*testanonymous.*lambda.*]] ={{.*}} [2 x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[KCTR:__(llvm_profile_counters|profc).*Klass.*__ctor.*]] ={{.*}} [2 x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[KMTH:__(llvm_profile_counters|profc).*Klass.*stdmethod.*]] ={{.*}} [2 x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[KDTR:__(llvm_profile_counters|profc).*Klass.*__dtor.*]] ={{.*}} [2 x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[KSTC:__(llvm_profile_counters|profc).*Klass.*staticmethod.*]] ={{.*}} [2 x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[SCTR:__(llvm_profile_counters|profc).*Strukt.*__ctor.*]] ={{.*}} [2 x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[SMTH:__(llvm_profile_counters|profc).*Strukt.*stdmethod.*]] ={{.*}} [2 x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[SDTR:__(llvm_profile_counters|profc).*Strukt.*__dtor.*]] ={{.*}} [2 x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[CNTR:__(llvm_profile_counters|profc).*contractprog.*]] ={{.*}} [5 x i64] zeroinitializer
|
|
// PROFGEN-NOT: @{{__llvm_profile_counters_.*fwddecl.*}}
|
|
// PROFGEN-NOT: @{{__profc.*fwddecl.*}}
|
|
|
|
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}simplefunction{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}simplefunction{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[SMPL]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[SMPL0:[0-9]+]]
|
|
void simplefunction(int i) {
|
|
// PROFGEN: store {{.*}} @[[SMPL]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[SMPL1:[0-9]+]]
|
|
if (i % 3) {}
|
|
}
|
|
|
|
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}templatefunc{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}templatefunc{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[TMPL]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[TMPL0:[0-9]+]]
|
|
void templatefunc(T)(T i) {
|
|
// PROFGEN: store {{.*}} @[[TMPL]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[TMPL1:[0-9]+]]
|
|
if (i % 3) {}
|
|
}
|
|
// The purpose of this function is to pin the location of the instantiation of
|
|
// templatefunc at a defined location in IR.
|
|
void call_templatefunc(int i) {
|
|
templatefunc!uint(i);
|
|
}
|
|
|
|
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}outerfunc{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}outerfunc{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[OUTR]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[OUTR0:[0-9]+]]
|
|
// PROFGEN: store {{.*}} @[[OUTR]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[OUTR1:[0-9]+]]
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}nestedfunc{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}nestedfunc{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[NEST]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[NEST0:[0-9]+]]
|
|
// PROFGEN: store {{.*}} @[[NEST]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[NEST1:[0-9]+]]
|
|
void outerfunc(int i) {
|
|
void nestedfunc(int i) {
|
|
if (!(i % 3)) {}
|
|
}
|
|
nestedfunc(i);
|
|
if (i % 3) {}
|
|
}
|
|
|
|
|
|
void takedelegate(int i, int delegate(int) fd) {
|
|
if (fd(i) % 3) {}
|
|
}
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}testanonymous{{.*}}lambda{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}testanonymous{{.*}}lambda{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[LMBD]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[LMBD0:[0-9]+]]
|
|
// PROFGEN: store {{.*}} @[[LMBD]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[LMBD1:[0-9]+]]
|
|
void testanonymous(int i) {
|
|
takedelegate(i, (i) { if (i % 5) {} return i+1;} );
|
|
}
|
|
|
|
|
|
class Klass {
|
|
int a;
|
|
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}Klass{{.*}}__ctor{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}Klass{{.*}}__ctor{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[KCTR]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[KCTR0:[0-9]+]]
|
|
// PROFGEN: store {{.*}} @[[KCTR]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[KCTR1:[0-9]+]]
|
|
this(int i) {
|
|
a = i;
|
|
if (a % 3) {}
|
|
}
|
|
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}Klass{{.*}}__dtor{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}Klass{{.*}}__dtor{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[KDTR]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[KDTR0:[0-9]+]]
|
|
// PROFGEN: store {{.*}} @[[KDTR]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[KDTR1:[0-9]+]]
|
|
~this() {
|
|
if (!(a % 3)) {}
|
|
}
|
|
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}Klass{{.*}}stdmethod{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}Klass{{.*}}stdmethod{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[KMTH]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[KMTH0:[0-9]+]]
|
|
// Explicitly test that the assert(this) branch is *not* profiled
|
|
// PROFUSE: br i1 %{{.*}}, label %assertPassed, label %assertFailed{{$}}
|
|
// PROFGEN: store {{.*}} @[[KMTH]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[KMTH1:[0-9]+]]
|
|
void stdmethod() {
|
|
if (a % 4) {}
|
|
}
|
|
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}Klass{{.*}}staticmethod{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}Klass{{.*}}staticmethod{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[KSTC]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[KSTC0:[0-9]+]]
|
|
// PROFGEN: store {{.*}} @[[KSTC]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[KSTC1:[0-9]+]]
|
|
static void staticmethod(int i) {
|
|
if (i % 2) {}
|
|
}
|
|
}
|
|
|
|
|
|
struct Strukt {
|
|
int a;
|
|
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}Strukt{{.*}}__ctor{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}Strukt{{.*}}__ctor{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[SCTR]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[SCTR0:[0-9]+]]
|
|
// PROFGEN: store {{.*}} @[[SCTR]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[SCTR1:[0-9]+]]
|
|
this(int i) {
|
|
a = i;
|
|
if (a % 3) {}
|
|
}
|
|
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}Strukt{{.*}}stdmethod{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}Strukt{{.*}}stdmethod{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[SMTH]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[SMTH0:[0-9]+]]
|
|
// Explicitly test that the assert(this) branch is *not* profiled
|
|
// PROFUSE: br i1 %{{.*}}, label %assertPassed, label %assertFailed{{$}}
|
|
// PROFGEN: store {{.*}} @[[SMTH]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[SMTH1:[0-9]+]]
|
|
void stdmethod() {
|
|
if (a % 4) {}
|
|
}
|
|
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}Strukt{{.*}}__dtor{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}Strukt{{.*}}__dtor{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[SDTR]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[SDTR0:[0-9]+]]
|
|
// PROFGEN: store {{.*}} @[[SDTR]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[SDTR1:[0-9]+]]
|
|
~this() {
|
|
if (!(a % 3)) {}
|
|
}
|
|
}
|
|
|
|
// PROFGEN-LABEL: define {{.*}} @{{.*}}contractprog{{.*}}(
|
|
// PROFUSE-LABEL: define {{.*}} @{{.*}}contractprog{{.*}}(
|
|
// PROFGEN: store {{.*}} @[[CNTR]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[CNTR0:[0-9]+]]
|
|
void contractprog(int i)
|
|
in {
|
|
// PROFGEN: store {{.*}} @[[CNTR]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[CNTR1:[0-9]+]]
|
|
if (i < 3) {}
|
|
}
|
|
out {
|
|
if (i < 6) {}
|
|
}
|
|
body {
|
|
// PROFGEN: store {{.*}} @[[CNTR]], i64 0, i64 2
|
|
// PROFUSE: br {{.*}} !prof ![[CNTR2:[0-9]+]]
|
|
if (i % 2) {}
|
|
}
|
|
// Out label+body:
|
|
// PROFGEN: store {{.*}} @[[CNTR]], i64 0, i64 3
|
|
// PROFGEN: store {{.*}} @[[CNTR]], i64 0, i64 4
|
|
// PROFUSE: br {{.*}} !prof ![[CNTR4:[0-9]+]]
|
|
|
|
|
|
// Check that no code is generated for function declarations without definition.
|
|
// PROFGEN-NOT: define {{.*}} @fwddecl(
|
|
// PROFUSE-NOT: define {{.*}} @fwddecl(
|
|
extern (C) void fwddecl(int);
|
|
|
|
|
|
void main() {
|
|
foreach (int i; 0..10) {
|
|
simplefunction(i);
|
|
call_templatefunc(i);
|
|
outerfunc(i);
|
|
testanonymous(i);
|
|
auto k = new Klass(i);
|
|
k.stdmethod();
|
|
Klass.staticmethod(i);
|
|
auto s = Strukt(i);
|
|
s.stdmethod();
|
|
contractprog(i);
|
|
}
|
|
}
|
|
|
|
// PROFUSE-DAG: ![[SMPL0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[SMPL1]] = !{!"branch_weights", i32 7, i32 5}
|
|
|
|
// PROFUSE-DAG: ![[TMPL0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[TMPL1]] = !{!"branch_weights", i32 7, i32 5}
|
|
|
|
// PROFUSE-DAG: ![[OUTR0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[OUTR1]] = !{!"branch_weights", i32 7, i32 5}
|
|
// PROFUSE-DAG: ![[NEST0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[NEST1]] = !{!"branch_weights", i32 5, i32 7}
|
|
|
|
// PROFUSE-DAG: ![[LMBD0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[LMBD1]] = !{!"branch_weights", i32 9, i32 3}
|
|
|
|
// PROFUSE-DAG: ![[KCTR0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[KCTR1]] = !{!"branch_weights", i32 7, i32 5}
|
|
// PROFUSE-DAG: ![[KMTH0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[KMTH1]] = !{!"branch_weights", i32 8, i32 4}
|
|
// PROFUSE-DAG: ![[KDTR0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[KDTR1]] = !{!"branch_weights", i32 5, i32 7}
|
|
// PROFUSE-DAG: ![[KSTC0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[KSTC1]] = !{!"branch_weights", i32 6, i32 6}
|
|
|
|
// PROFUSE-DAG: ![[SCTR0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[SCTR1]] = !{!"branch_weights", i32 7, i32 5}
|
|
// PROFUSE-DAG: ![[SMTH0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[SMTH1]] = !{!"branch_weights", i32 8, i32 4}
|
|
// PROFUSE-DAG: ![[SDTR0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[SDTR1]] = !{!"branch_weights", i32 5, i32 7}
|
|
|
|
// PROFUSE-DAG: ![[CNTR0]] = !{!"function_entry_count", i64 10}
|
|
// PROFUSE-DAG: ![[CNTR1]] = !{!"branch_weights", i32 4, i32 8}
|
|
// PROFUSE-DAG: ![[CNTR2]] = !{!"branch_weights", i32 6, i32 6}
|
|
// PROFUSE-DAG: ![[CNTR4]] = !{!"branch_weights", i32 7, i32 5}
|
|
|