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:
parent
fdf4e7ac3a
commit
88d765324a
@ -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");
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
56
src/main/java/dk/camelot64/kickc/model/StatementBlocks.java
Normal file
56
src/main/java/dk/camelot64/kickc/model/StatementBlocks.java
Normal 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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())) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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()) {
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user