mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 01:20:51 +03:00
157 lines
5.3 KiB
D
157 lines
5.3 KiB
D
// Test instrumentation of statement types involving exceptions.
|
|
|
|
// XFAIL: Windows
|
|
|
|
// 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 -boundscheck=off -c -output-ll -of=%t2.ll -fprofile-instr-use=%t.profdata %s \
|
|
// RUN: && FileCheck %s -check-prefix=PROFUSE < %t2.ll
|
|
|
|
extern(C): // simplify name mangling for simpler string matching
|
|
|
|
// PROFGEN-DAG: @[[TC:__(llvm_profile_counters|profc)_try_catch]] ={{.*}} global [9 x i64] zeroinitializer
|
|
// FIXME: fix the nr of counter entries:
|
|
// PROFGEN-DAG: @[[TF:__(llvm_profile_counters|profc)_try_finally]] ={{.*}} global [{{[0-9]+}} x i64] zeroinitializer
|
|
// PROFGEN-DAG: @[[SCP:__(llvm_profile_counters|profc)_scope_stmts]] ={{.*}} global [{{[0-9]+}} x i64] zeroinitializer
|
|
|
|
// Simple classes to disambiguate different throw statements
|
|
class ExceptionTwo : Exception {
|
|
this(string s) { super(s); }
|
|
}
|
|
class ExceptionThree : Exception {
|
|
this(string s) { super(s); }
|
|
}
|
|
|
|
// PROFGEN-LABEL: @scope_stmts(
|
|
// PROFUSE-LABEL: @scope_stmts(
|
|
// PROFGEN: store {{.*}} @[[SCP]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[SCP0:[0-9]+]]
|
|
void scope_stmts(bool fail) {
|
|
int i;
|
|
scope(failure) i += 890;
|
|
scope(exit) i += 234;
|
|
scope(success) i += 456;
|
|
if (fail) throw new Exception(i ? "true string" : "fail scope_stmts");
|
|
|
|
// OnScope statements are lowered into TryCatch statements.
|
|
// Simplify the tests to only make sure that all conditional branches have
|
|
// branch weights,
|
|
// PROFUSE-NOT: {{br i1 %[0-9]+, label %[A-Za-z0-9\.]+, label %[A-Za-z0-9\.]+$}}
|
|
// and test that switches have profiling information too
|
|
// P ROFUSE-NOT: {{^[ ]+\]$}}
|
|
|
|
// Detect function end:
|
|
// PROFUSE: ret void
|
|
// PROFUSE-NEXT: }
|
|
}
|
|
|
|
// PROFGEN-LABEL: @try_catch()
|
|
// PROFUSE-LABEL: @try_catch()
|
|
// PROFGEN: store {{.*}} @[[TC]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[TC0:[0-9]+]]
|
|
void try_catch() {
|
|
// PROFGEN: store {{.*}} @[[TC]], i64 0, i64 1
|
|
// PROFUSE: br {{.*}} !prof ![[TC1:[0-9]+]]
|
|
for (int i = 0; i < 6; ++i) { // 6 : 0 (branch taken)
|
|
|
|
// The IR for TryStatements has a very unintuitive ordering.
|
|
// The IR block ordering needs to be improved, but for now we have to
|
|
// carefully read the generated IR and put the checks here in the according
|
|
// order.
|
|
// The try statement and exception catches receive their counter numbers
|
|
// before recursing into the try body and exception handlers.
|
|
|
|
try {
|
|
if (i < 2) { // 2 : 4 (branch taken)
|
|
throw new ExceptionThree("first"); // 2x
|
|
} else if (i < 5) { // 3 : 1 (branch taken)
|
|
throw new ExceptionTwo("two"); // 3x
|
|
}
|
|
throw new Exception("Uncaught exception");
|
|
}
|
|
catch (ExceptionTwo e) { // 3 : 3 (match : pass)
|
|
if (i) {} // 3 : 0 (branch taken)
|
|
}
|
|
catch (ExceptionThree e) { // 2 : 1 (match : pass)
|
|
if (i) {} // 1 : 1 (branch taken)
|
|
}
|
|
|
|
// Exception handlers (only the first BBs):
|
|
// PROFGEN: store {{.*}} @[[TC]], i64 0, i64 4
|
|
// PROFGEN: store {{.*}} @[[TC]], i64 0, i64 3
|
|
// ExceptionThree 2nd BB:
|
|
// PROFGEN: store {{.*}} @[[TC]], i64 0, i64 8
|
|
// ExceptionTwo 2nd BB:
|
|
// PROFGEN: store {{.*}} @[[TC]], i64 0, i64 7
|
|
// Try body 2nd BB: if(i < 2)
|
|
// PROFGEN: store {{.*}} @[[TC]], i64 0, i64 5
|
|
// Landingpad stuff:
|
|
// No counter increments
|
|
// More try body: if(i < 5)
|
|
// PROFGEN: store {{.*}} @[[TC]], i64 0, i64 6
|
|
// Try end:
|
|
// PROFGEN: store {{.*}} @[[TC]], i64 0, i64 2
|
|
|
|
// Try body: if(i < 2)
|
|
// PROFUSE: br {{.*}} !prof ![[TC5:[0-9]+]]
|
|
// Exception handlers: if(i){}
|
|
// PROFUSE: br {{.*}} !prof ![[TC8:[0-9]+]]
|
|
// PROFUSE: br {{.*}} !prof ![[TC7:[0-9]+]]
|
|
// More try body: if(i < 5)
|
|
// PROFUSE: br {{.*}} !prof ![[TC6:[0-9]+]]
|
|
// Landingpad stuff:
|
|
// Match ExceptionTwo:
|
|
// PROFUSE: br {{.*}} !prof ![[TC3:[0-9]+]]
|
|
// Match ExceptionThree:
|
|
// PROFUSE: br {{.*}} !prof ![[TC4:[0-9]+]]
|
|
}
|
|
}
|
|
|
|
// PROFGEN-LABEL: @try_finally()
|
|
// PROFUSE-LABEL: @try_finally()
|
|
// PROFGEN: store {{.*}} @[[TF]], i64 0, i64 0
|
|
// PROFUSE-SAME: !prof ![[TF0:[0-9]+]]
|
|
void try_finally() {
|
|
int i;
|
|
try {
|
|
i+=512;
|
|
if (!i) throw new Exception("first");
|
|
} finally {
|
|
i+=765;
|
|
//throw new Exception("second");
|
|
}
|
|
// } catch (Exception e) {
|
|
// i+=91;//if (true) {}
|
|
//}
|
|
}
|
|
|
|
// PROFGEN-LABEL: @_Dmain(
|
|
// PROFUSE-LABEL: @_Dmain(
|
|
extern(D):
|
|
void main() {
|
|
try { // for testing an escaping Exception
|
|
try_catch();
|
|
} catch (Exception e) {}
|
|
try_finally();
|
|
scope_stmts(false);
|
|
try {
|
|
scope_stmts(true);
|
|
} catch (Exception e) {}
|
|
|
|
// Detect function end:
|
|
// PROFUSE: ret i32 0
|
|
// PROFUSE-NEXT: }
|
|
}
|
|
|
|
// PROFUSE-DAG: ![[TC0]] = !{!"function_entry_count", i64 1}
|
|
// PROFUSE-DAG: ![[TC1]] = !{!"branch_weights", i32 7, i32 1}
|
|
// PROFUSE-DAG: ![[TC5]] = !{!"branch_weights", i32 3, i32 5}
|
|
// PROFUSE-DAG: ![[TC8]] = !{!"branch_weights", i32 2, i32 2}
|
|
// PROFUSE-DAG: ![[TC7]] = !{!"branch_weights", i32 4, i32 1}
|
|
// PROFUSE-DAG: ![[TC6]] = !{!"branch_weights", i32 4, i32 2}
|
|
// PROFUSE-DAG: ![[TC3]] = !{!"branch_weights", i32 4, i32 4}
|
|
// PROFUSE-DAG: ![[TC4]] = !{!"branch_weights", i32 3, i32 2}
|
|
|
|
// PROFUSE-DAG: ![[SCP0]] = !{!"function_entry_count", i64 2}
|