1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-19 00:29:29 +00:00

Caching statement->block mapping for uplift performance

This commit is contained in:
jespergravgaard 2017-11-09 23:05:23 +01:00
parent fdf4e7ac3a
commit 88d765324a
12 changed files with 115 additions and 29 deletions

View File

@ -194,6 +194,7 @@ public class Compiler {
//program.getLog().setVerboseLiveRanges(true); //program.getLog().setVerboseLiveRanges(true);
new Pass3StatementBlocks(program).generateStatementBlocks();
new Pass3VariableReferenceInfos(program).generateVariableReferenceInfos(); new Pass3VariableReferenceInfos(program).generateVariableReferenceInfos();
new Pass3LiveRangesAnalysis(program).findLiveRanges(); new Pass3LiveRangesAnalysis(program).findLiveRanges();
program.getLog().append("CONTROL FLOW GRAPH - LIVE RANGES FOUND"); program.getLog().append("CONTROL FLOW GRAPH - LIVE RANGES FOUND");
@ -209,6 +210,7 @@ public class Compiler {
new Pass3AddNopBeforeCallOns(program).generate(); new Pass3AddNopBeforeCallOns(program).generate();
new Pass3StatementIndices(program).generateStatementIndices(); new Pass3StatementIndices(program).generateStatementIndices();
new Pass3CallGraphAnalysis(program).findCallGraph(); new Pass3CallGraphAnalysis(program).findCallGraph();
new Pass3StatementBlocks(program).generateStatementBlocks();
new Pass3VariableReferenceInfos(program).generateVariableReferenceInfos(); new Pass3VariableReferenceInfos(program).generateVariableReferenceInfos();
new Pass3LiveRangesAnalysis(program).findLiveRanges(); new Pass3LiveRangesAnalysis(program).findLiveRanges();
program.getLog().append("CONTROL FLOW GRAPH - BEFORE EFFECTIVE LIVE RANGES"); program.getLog().append("CONTROL FLOW GRAPH - BEFORE EFFECTIVE LIVE RANGES");

View File

@ -25,7 +25,7 @@ public class AsmFragmentSignature {
ControlFlowBlock block, ControlFlowBlock block,
Program program, Program program,
ControlFlowGraph graph) { ControlFlowGraph graph) {
this.codeScopeRef = program.getGraph().getBlockFromStatementIdx(conditionalJump.getIndex()).getScope(); this.codeScopeRef = program.getStatementBlocks().getBlock(conditionalJump).getScope();
this.bindings = new LinkedHashMap<>(); this.bindings = new LinkedHashMap<>();
this.program = program; this.program = program;
String conditionalJumpSignature = conditionalJumpSignature(conditionalJump, block, graph); String conditionalJumpSignature = conditionalJumpSignature(conditionalJump, block, graph);
@ -33,7 +33,7 @@ public class AsmFragmentSignature {
} }
public AsmFragmentSignature(StatementAssignment assignment, Program program) { public AsmFragmentSignature(StatementAssignment assignment, Program program) {
this.codeScopeRef = program.getGraph().getBlockFromStatementIdx(assignment.getIndex()).getScope(); this.codeScopeRef = program.getStatementBlocks().getBlock(assignment).getScope();
this.bindings = new LinkedHashMap<>(); this.bindings = new LinkedHashMap<>();
this.program = program; this.program = program;
setSignature(assignmentSignature( setSignature(assignmentSignature(
@ -51,14 +51,14 @@ public class AsmFragmentSignature {
} }
public AsmFragmentSignature(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) { public AsmFragmentSignature(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) {
this.codeScopeRef = program.getGraph().getBlockFromStatementIdx(assignment.getIndex()).getScope(); this.codeScopeRef = program.getStatementBlocks().getBlock(assignment).getScope();
this.bindings = new LinkedHashMap<>(); this.bindings = new LinkedHashMap<>();
this.program = program; this.program = program;
setSignature(assignmentWithAluSignature(assignment, assignmentAlu)); setSignature(assignmentWithAluSignature(assignment, assignmentAlu));
} }
private String assignmentWithAluSignature(StatementAssignment assignment, StatementAssignment assignmentAlu) { private String assignmentWithAluSignature(StatementAssignment assignment, StatementAssignment assignmentAlu) {
this.codeScopeRef = program.getGraph().getBlockFromStatementIdx(assignment.getIndex()).getScope(); this.codeScopeRef = program.getStatementBlocks().getBlock(assignment).getScope();
if (!(assignment.getrValue2() instanceof VariableRef)) { if (!(assignment.getrValue2() instanceof VariableRef)) {
throw new AsmFragment.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment); throw new AsmFragment.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment);
} }

View File

@ -146,19 +146,6 @@ public class ControlFlowGraph {
return null; return null;
} }
public ControlFlowBlock getBlockFromStatementIdx(int statementIdx) {
for (ControlFlowBlock block : getAllBlocks()) {
for (Statement statement : block.getStatements()) {
if(statementIdx==statement.getIndex()) {
return block;
}
}
}
return null;
}
@Override @Override
public String toString() { public String toString() {
return toString(null); return toString(null);

View File

@ -166,7 +166,7 @@ public class LiveRangeVariablesEffective {
List<VariableRef> aliveAtStmt = liveRangeVariables.getAlive(statement); List<VariableRef> aliveAtStmt = liveRangeVariables.getAlive(statement);
CallPaths callPaths; CallPaths callPaths;
Collection<VariableRef> referencedInProcedure; Collection<VariableRef> referencedInProcedure;
ControlFlowBlock block = program.getGraph().getBlockFromStatementIdx(statement.getIndex()); ControlFlowBlock block = program.getStatementBlocks().getBlock(statement);
ScopeRef scopeRef = block.getScope(); ScopeRef scopeRef = block.getScope();
Scope scope = program.getScope().getScope(scopeRef); Scope scope = program.getScope().getScope(scopeRef);
if (scope instanceof Procedure) { if (scope instanceof Procedure) {
@ -186,9 +186,9 @@ public class LiveRangeVariablesEffective {
for (CallPath calledPath : calledRefs.getCallPaths()) { for (CallPath calledPath : calledRefs.getCallPaths()) {
List<CallGraph.CallBlock.Call> path = calledPath.getPath(); List<CallGraph.CallBlock.Call> path = calledPath.getPath();
CallGraph.CallBlock.Call lastCall = path.get(path.size() - 1); CallGraph.CallBlock.Call lastCall = path.get(path.size() - 1);
Integer lastCallCallStatementIdx = lastCall.getCallStatementIdx(); Integer lastCallStatementIdx = lastCall.getCallStatementIdx();
ControlFlowBlock lastCallBlock = program.getGraph().getBlockFromStatementIdx(lastCallCallStatementIdx); LabelRef lastCallBlockRef = program.getStatementBlocks().getBlockRef(lastCallStatementIdx);
if(lastCallBlock.equals(block)) { if(lastCallBlockRef.equals(block.getLabel())) {
if (callAliases == null) { if (callAliases == null) {
// Found a matching call! // Found a matching call!
callAliases = calledPath.getInnerAliases(); callAliases = calledPath.getInnerAliases();

View File

@ -27,6 +27,8 @@ public class Program {
/** Information about loops. */ /** Information about loops. */
private NaturalLoopSet loopSet; private NaturalLoopSet loopSet;
/** Which block is each statement a part of. */
private StatementBlocks statementBlocks;
/** The variables freferenced by blocks/statements. */ /** The variables freferenced by blocks/statements. */
private VariableReferenceInfos variableReferenceInfos; private VariableReferenceInfos variableReferenceInfos;
/** The live ranges of all variables. */ /** The live ranges of all variables. */
@ -121,6 +123,14 @@ public class Program {
this.variableReferenceInfos = variableReferenceInfos; this.variableReferenceInfos = variableReferenceInfos;
} }
public StatementBlocks getStatementBlocks() {
return statementBlocks;
}
public void setStatementBlocks(StatementBlocks statementBlocks) {
this.statementBlocks = statementBlocks;
}
public void setLiveRangeVariables(LiveRangeVariables liveRangeVariables) { public void setLiveRangeVariables(LiveRangeVariables liveRangeVariables) {
this.liveRangeVariables = liveRangeVariables; this.liveRangeVariables = liveRangeVariables;
} }

View File

@ -0,0 +1,56 @@
package dk.camelot64.kickc.model;
import java.util.Map;
/** Cached information about which block each statement is a part of */
public class StatementBlocks {
/** The control flow graph. */
private ControlFlowGraph graph;
/** Maps statement index to block label. */
private Map<Integer, LabelRef> stmtBlocks;
public StatementBlocks(Program program, Map<Integer, LabelRef> stmtBlocks) {
this.graph = program.getGraph();
this.stmtBlocks = stmtBlocks;
}
/**
* Get the label of the block containing a statement
* @param stmtIdx The statement index
* @return The block label
*/
public LabelRef getBlockRef(Integer stmtIdx) {
return stmtBlocks.get(stmtIdx);
}
/**
* Get the label of the block containing a statement
* @param stmt The statement
* @return The block label
*/
public LabelRef getBlockRef(Statement stmt) {
return stmtBlocks.get(stmt.getIndex());
}
/**
* Get the block containing a statement
* @param stmt The statement
* @return The containing block
*/
public ControlFlowBlock getBlock(Statement stmt) {
return graph.getBlock(getBlockRef(stmt));
}
/**
* Get the block containing a statement
* @param stmtIdx The statement index
* @return The containing block
*/
public ControlFlowBlock getBlock(Integer stmtIdx) {
return graph.getBlock(getBlockRef(stmtIdx));
}
}

View File

@ -109,7 +109,7 @@ public class Pass3LiveRangesAnalysis extends Pass2Base {
// Add all used variables to the previous statement (taking into account phi from blocks) // Add all used variables to the previous statement (taking into account phi from blocks)
modified |= initUsedVars(liveRanges, stmt, previousStmt); modified |= initUsedVars(liveRanges, stmt, previousStmt);
// Add all alive variables to previous that are used inside the method // Add all alive variables to previous that are used inside the method
ControlFlowBlock procBlock = getProgram().getGraph().getBlockFromStatementIdx(stmt.getIndex()); ControlFlowBlock procBlock = getProgram().getStatementBlocks().getBlock(stmt);
Procedure procedure = (Procedure) getProgram().getScope().getSymbol(procBlock.getLabel()); Procedure procedure = (Procedure) getProgram().getScope().getSymbol(procBlock.getLabel());
Collection<VariableRef> procUsed = referenceInfo.getUsed(procedure.getRef().getLabelRef()); Collection<VariableRef> procUsed = referenceInfo.getUsed(procedure.getRef().getLabelRef());
// The call statement has no used or defined by itself so only work with the alive vars // The call statement has no used or defined by itself so only work with the alive vars
@ -153,7 +153,7 @@ public class Pass3LiveRangesAnalysis extends Pass2Base {
// If current statement is a phi add the used variables to previous based on the phi entries // If current statement is a phi add the used variables to previous based on the phi entries
StatementPhiBlock phi = (StatementPhiBlock) stmt; StatementPhiBlock phi = (StatementPhiBlock) stmt;
ControlFlowBlock previousBlock = ControlFlowBlock previousBlock =
getProgram().getGraph().getBlockFromStatementIdx(previousStmt.getStatement().getIndex()); getProgram().getStatementBlocks().getBlock(previousStmt.getStatement());
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) { for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
if (phiRValue.getPredecessor().equals(previousBlock.getLabel())) { if (phiRValue.getPredecessor().equals(previousBlock.getLabel())) {
@ -252,7 +252,7 @@ public class Pass3LiveRangesAnalysis extends Pass2Base {
} }
} else { } else {
// No preceding statements. Examine if this is the first statement in a call. // No preceding statements. Examine if this is the first statement in a call.
ControlFlowBlock block = getProgram().getGraph().getBlockFromStatementIdx(statement.getIndex()); ControlFlowBlock block = getProgram().getStatementBlocks().getBlock(statement);
if (block.isProcedureEntry(getProgram())) { if (block.isProcedureEntry(getProgram())) {
// Current is first statement of a call - add the statement preceding the call. // Current is first statement of a call - add the statement preceding the call.
Collection<CallGraph.CallBlock.Call> callers = getProgram().getCallGraph().getCallers(block.getLabel()); Collection<CallGraph.CallBlock.Call> callers = getProgram().getCallGraph().getCallers(block.getLabel());
@ -299,7 +299,7 @@ public class Pass3LiveRangesAnalysis extends Pass2Base {
private Collection<Statement> getPrecedingStatement(Statement statement) { private Collection<Statement> getPrecedingStatement(Statement statement) {
Statement previousStmt = null; Statement previousStmt = null;
Statement prev = null; Statement prev = null;
ControlFlowBlock block = getProgram().getGraph().getBlockFromStatementIdx(statement.getIndex()); ControlFlowBlock block = getProgram().getStatementBlocks().getBlock(statement);
List<Statement> statements = block.getStatements(); List<Statement> statements = block.getStatements();
for (Statement stmt : statements) { for (Statement stmt : statements) {
if (statement.getIndex().equals(stmt.getIndex())) { if (statement.getIndex().equals(stmt.getIndex())) {

View File

@ -58,7 +58,7 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
// Each caller creates its own call-paths // Each caller creates its own call-paths
StatementCall callStatement = StatementCall callStatement =
(StatementCall) getProgram().getGraph().getStatementByIndex(caller.getCallStatementIdx()); (StatementCall) getProgram().getGraph().getStatementByIndex(caller.getCallStatementIdx());
ControlFlowBlock callBlock = getProgram().getGraph().getBlockFromStatementIdx(callStatement.getIndex()); ControlFlowBlock callBlock = getProgram().getStatementBlocks().getBlock(callStatement);
ScopeRef callScopeRef = callBlock.getScope(); ScopeRef callScopeRef = callBlock.getScope();
Scope callScope = getProgram().getScope().getScope(callScopeRef); Scope callScope = getProgram().getScope().getScope(callScopeRef);
if (callScope instanceof Procedure) { if (callScope instanceof Procedure) {

View File

@ -44,7 +44,7 @@ public class Pass3LoopDepthAnalysis extends Pass2Base {
Collection<CallGraph.CallBlock.Call> calls = callingBlock.getCalls(currentScope); Collection<CallGraph.CallBlock.Call> calls = callingBlock.getCalls(currentScope);
for (CallGraph.CallBlock.Call call : calls) { for (CallGraph.CallBlock.Call call : calls) {
int callStatementIdx = call.getCallStatementIdx(); int callStatementIdx = call.getCallStatementIdx();
ControlFlowBlock callingControlBlock = getGraph().getBlockFromStatementIdx(callStatementIdx); ControlFlowBlock callingControlBlock = getProgram().getStatementBlocks().getBlock(callStatementIdx);
Collection<NaturalLoop> callingLoops = loopSet.getLoopsContainingBlock(callingControlBlock.getLabel()); Collection<NaturalLoop> callingLoops = loopSet.getLoopsContainingBlock(callingControlBlock.getLabel());
for (NaturalLoop callingLoop : callingLoops) { for (NaturalLoop callingLoop : callingLoops) {
int potentialDepth = callingLoop.getDepth()+1; int potentialDepth = callingLoop.getDepth()+1;

View File

@ -0,0 +1,31 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import java.util.LinkedHashMap;
/**
* Identify the block for each statement.
*/
public class Pass3StatementBlocks extends Pass2Base {
public Pass3StatementBlocks(Program program) {
super(program);
}
/**
* Create map from statement index to block
*/
public void generateStatementBlocks() {
LinkedHashMap<Integer, LabelRef> stmtBlocks = new LinkedHashMap<>();
for (ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
for (Statement statement : block.getStatements()) {
stmtBlocks.put(statement.getIndex(), block.getLabel());
}
}
getProgram().setStatementBlocks(new StatementBlocks(getProgram(), stmtBlocks));
}
}

View File

@ -49,7 +49,7 @@ public class Pass4AssertNoCpuClobber extends Pass2Base {
if(asmSegment.getPhiTransitionId()!=null && asmSegment.getPhiTransitionAssignmentIdx()!=null) { if(asmSegment.getPhiTransitionId()!=null && asmSegment.getPhiTransitionAssignmentIdx()!=null) {
String phiTransitionId = asmSegment.getPhiTransitionId(); String phiTransitionId = asmSegment.getPhiTransitionId();
int transitionAssignmentIdx = asmSegment.getPhiTransitionAssignmentIdx(); int transitionAssignmentIdx = asmSegment.getPhiTransitionAssignmentIdx();
ControlFlowBlock statementBlock = getProgram().getGraph().getBlockFromStatementIdx(statementIdx); ControlFlowBlock statementBlock = getProgram().getStatementBlocks().getBlock(statementIdx);
PhiTransitions phiTransitions = new PhiTransitions(getProgram(), statementBlock); PhiTransitions phiTransitions = new PhiTransitions(getProgram(), statementBlock);
PhiTransitions.PhiTransition phiTransition = phiTransitions.getTransition(phiTransitionId); PhiTransitions.PhiTransition phiTransition = phiTransitions.getTransition(phiTransitionId);
for (PhiTransitions.PhiTransition.PhiAssignment phiAssignment : phiTransition.getAssignments()) { for (PhiTransitions.PhiTransition.PhiAssignment phiAssignment : phiTransition.getAssignments()) {

View File

@ -182,7 +182,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
Integer statementIdx = asmSegment.getStatementIdx(); Integer statementIdx = asmSegment.getStatementIdx();
int maxLoopDepth = 1; int maxLoopDepth = 1;
if (statementIdx != null) { if (statementIdx != null) {
ControlFlowBlock block = graph.getBlockFromStatementIdx(statementIdx); ControlFlowBlock block = program.getStatementBlocks().getBlock(statementIdx);
maxLoopDepth = loopSet.getMaxLoopDepth(block.getLabel()); maxLoopDepth = loopSet.getMaxLoopDepth(block.getLabel());
} }
score += asmSegmentCycles * Math.pow(10, maxLoopDepth); score += asmSegmentCycles * Math.pow(10, maxLoopDepth);