Skip to content

Commit

Permalink
Add SsaCoverage
Browse files Browse the repository at this point in the history
  • Loading branch information
titzer committed Sep 23, 2023
1 parent 67881b4 commit 0585d68
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 4 deletions.
3 changes: 3 additions & 0 deletions aeneas/src/jvm/SsaJvmGen.v3
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,9 @@ class SsaJvmGen(jprog: JvmProgram, context: SsaContext, jsig: JvmSig, code: JvmC
x: SsaGoto => emitGotoOrFallThru(x.succs[0].dest);
x: SsaSwitch => emitSwitch(block, x);
x: SsaThrow => emitThrow(x.exception);
x: SsaNewVar => ; // do nothing
x: SsaDeleteVar => ; // do nothing
x: SsaProbe => ; // do nothing
_ => context.fail("unexpected SSA end type");
}
}
Expand Down
5 changes: 3 additions & 2 deletions aeneas/src/mach/MachBackend.v3
Original file line number Diff line number Diff line change
Expand Up @@ -424,8 +424,9 @@ class SsaMachGen(context: SsaContext, mach: MachProgram, regSet: MachRegSet, w:
x: SsaSwitch => visitSwitch(block, x);
x: SsaThrow => visitThrow(block, x);
x: SsaCheckpoint => visitCheckpoint(x);
x: SsaNewVar => ;
x: SsaDeleteVar => ;
x: SsaNewVar => ; // do nothing
x: SsaDeleteVar => ; // do nothing
x: SsaProbe => ; // do nothing
_ => context.fail("invalid instruction type");
}
}
Expand Down
3 changes: 2 additions & 1 deletion aeneas/src/main/Aeneas.v3
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ component Aeneas {
var compilation = Compilation.new(compiler, prog);
var after: void -> void;
if (CLOptions.COVERAGE.val != VstMatcher.None) {
after = IcCoverage.new(compiler, prog, CLOptions.COVERAGE.val, CLOptions.INSTR_COVERAGE.val).report;
if (CLOptions.SSA_INT.val) after = SsaCoverage.new(compiler, prog, CLOptions.COVERAGE.val, CLOptions.INSTR_COVERAGE.val).report;
else after = IcCoverage.new(compiler, prog, CLOptions.COVERAGE.val, CLOptions.INSTR_COVERAGE.val).report;
} else if (CLOptions.INSTR_PROFILE.val != VstMatcher.None) {
after = IcInstrProfiler.new(compiler, prog, CLOptions.INSTR_PROFILE.val).report;
} else if (CLOptions.PROFILE.val != VstMatcher.None) {
Expand Down
2 changes: 2 additions & 0 deletions aeneas/src/main/Compiler.v3
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class Compiler(target: Target) {
def printOptMatcher = CLOptions.PRINT_OPT.get();
def useGlobalRegAllocMatcher = if(level >= 2, VstMatcher.All, CLOptions.USE_GLOBALREGALLOC.get());
var icMon: (IrSpec, IcMethod) -> void; // monitor for IC generation
var ssaMon: IrSpec -> void;
// major phases of compilation
var Trace = CLOptions.TRACE.get();
var TraceCalls = CLOptions.TRACE_CALLS.get();
Expand Down Expand Up @@ -322,6 +323,7 @@ class Compilation(compiler: Compiler, prog: Program) {
opt.optGraph();
context.printSsa("Postpass Optimized");
}
if (compiler.ssaMon != null) compiler.ssaMon(memberRef);
}
return meth.ssa;
}
Expand Down
2 changes: 1 addition & 1 deletion aeneas/src/main/Version.v3
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@

// Updated by VCS scripts. DO NOT EDIT.
component Version {
def version: string = "III-7.1653";
def version: string = "III-7.1654";
var buildData: string;
}
9 changes: 9 additions & 0 deletions aeneas/src/ssa/Ssa.v3
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,15 @@ class SsaCheckpoint extends SsaInstr {
new(source, a: Array<SsaInstr>) super(a) { }
def getType() -> Type { return Void.TYPE; }
}
// Support for instrumentation
class SsaProbe extends SsaInstr(Ssa.NO_INSTRS) {
def getType() -> Type { return Void.TYPE; }
def fire(i: SsaInterpreter) { }
def dup() -> SsaProbe { return SsaProbe.new(); }
def render(buf: StringBuilder) -> StringBuilder {
return buf.puts("probe");
}
}
// A new local variable
class SsaNewVar extends SsaInstr {
def name: string;
Expand Down
80 changes: 80 additions & 0 deletions aeneas/src/ssa/SsaCoverage.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright 2023 Virgil authors. All rights reserved.
// See LICENSE for details of Apache 2.0 license.

class SsaCoverage(compiler: Compiler, prog: Program, matcher: VstMatcher, instr: bool) {
var methList: List<IrMethod>;

new() {
compiler.ssaMon = onGen;
}
def onGen(memberRef: IrSpec) {
if (!matcher.matches(memberRef.source())) return;
var m = memberRef.asMethod();
methList = List.new(m, methList);
for (b in m.ssa.bfBlocks(null)) {
var p = SsaCoverageProbe.new();
var i = b.next;
while (i != b && SsaPhi.?(i)) i = i.next;
p.insertBefore(i);
}
}
def report() {
var results = Arrays.map(Lists.toArray(methList), count);
results = Arrays.sort(results, 0, results.length, cmp);
for (e in results) print(e);
}
def count(m: IrMethod) -> (IrMethod, int, int) {
var count = 0, executed = 0;
for (b in m.ssa.bfBlocks(null)) {
for (i = b.next; i != b; i = i.next) match (i) {
x: SsaCoverageProbe => {
count++;
if (x.executed) executed++;
}
}
}
return (m, executed, count);
}
def cmp(a: (IrMethod, int, int), b: (IrMethod, int, int)) -> bool {
var ap = double.!(a.1) / double.!(a.2);
var bp = double.!(b.1) / double.!(b.2);
return ap > bp;
}
def print(m: IrMethod, executed: int, count: int) {
var percent = (executed * 100) / count;
if (percent < 100) Terminal.sp();
if (percent < 10) Terminal.sp();
Terminal.cyan("%d", percent);
Terminal.put("% ");
if (percent < 100) Terminal.yellow("%q", m.renderLong);
else Terminal.green("%q", m.renderLong);
Terminal.ln();
/*TODO if (percent < 100 && instr) {
var printer = IcPrinter.new(null);
printer.indent = 2;
for (i < m.iccode.length) {
var buf = TerminalBuffer.new();
if (!wasExecuted(m, i)) buf.red();
printer.render(buf, i, m.iccode[i]);
buf.end().outt();
}
}
*/
}
}

class SsaCoverageProbe extends SsaProbe {
var executed = false;

def fire(i: SsaInterpreter) {
executed = true;
}
def dup() -> SsaProbe {
var x = SsaCoverageProbe.new();
x.executed = this.executed;
return x;
}
def render(buf: StringBuilder) -> StringBuilder {
return buf.put1("coverage-probe[executed=%z]", executed);
}
}
4 changes: 4 additions & 0 deletions aeneas/src/ssa/SsaInterpreter.v3
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ class SsaInterpreter(prog: Program, genSsa: (IrSpec, int) -> SsaGraph) {
x: SsaParam, x: SsaCheckpoint, x: SsaNewVar, x: SsaDeleteVar => {
return nextInstr(i);
}
x: SsaProbe => {
x.fire(this);
return nextInstr(i);
}
}
return fail("unexpected SsaInstr type");
}
Expand Down
3 changes: 3 additions & 0 deletions aeneas/src/ssa/SsaPrinter.v3
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ class SsaPrinter {
x: SsaDeleteVar => {
buf.put1("deleteVar %d", x.n);
}
x: SsaProbe => {
x.render(buf);
}
}
if (args) {
var args = i.inputs;
Expand Down
1 change: 1 addition & 0 deletions aeneas/src/ssa/SsaRebuilder.v3
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class SsaRebuilder(context: SsaContext) {
x: SsaCheckpoint => genCheckpoint(x);
x: SsaNewVar => genNewVar(x);
x: SsaDeleteVar => genDeleteVar(x);
x: SsaProbe => curBlock.append(x.dup());
_ => context.fail1("unexpected block end @%d", i.uid);
}
}
Expand Down
3 changes: 3 additions & 0 deletions aeneas/src/x86/X86CodeGen.v3
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ class X86CodeGen extends OldCodeGen {
x: SsaGoto => genGoto(x.target());
x: SsaSwitch => genSwitch(x);
x: SsaThrow => genThrow(x);
x: SsaNewVar => ; // do nothing
x: SsaDeleteVar => ; // do nothing
x: SsaProbe => ; // do nothing
}
v.end = code.length;
if (v.varSize > 0) {
Expand Down

0 comments on commit 0585d68

Please sign in to comment.