mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-22 21:29:50 +00:00
Split unroll prepare into separate pass
This commit is contained in:
parent
b19bf2246e
commit
4f23ed5079
@ -222,6 +222,7 @@ public class Compiler {
|
||||
loopUnrolling.add(new Pass3StatementInfos(program));
|
||||
loopUnrolling.add(new Pass2DominatorsAnalysis(program));
|
||||
loopUnrolling.add(new Pass2LoopAnalysis(program));
|
||||
loopUnrolling.add(new Pass2LoopUnrollPhiPrepare(program));
|
||||
loopUnrolling.add(new Pass2LoopUnroll(program));
|
||||
pass2OptimizeSSA(loopUnrolling);
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package dk.camelot64.kickc.passes;
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
|
||||
import dk.camelot64.kickc.model.statements.StatementInfos;
|
||||
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||
import dk.camelot64.kickc.model.symbols.Label;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
@ -25,7 +24,7 @@ public class Pass2LoopUnroll extends Pass2SsaOptimization {
|
||||
public boolean step() {
|
||||
// Look for loops to unroll
|
||||
NaturalLoopSet loops = getProgram().getLoopSet();
|
||||
List<NaturalLoop> unrollLoopCandidates = findUnrollLoopCandidates(loops);
|
||||
List<NaturalLoop> unrollLoopCandidates = findUnrollLoopCandidates(getProgram(), loops);
|
||||
// Is there any unrolling to do?
|
||||
if(unrollLoopCandidates.isEmpty()) {
|
||||
return false;
|
||||
@ -82,51 +81,6 @@ public class Pass2LoopUnroll extends Pass2SsaOptimization {
|
||||
loopSuccessorPredecessors.add(block.getLabel());
|
||||
}
|
||||
}
|
||||
// - Add any needed PHI-statements to the successors
|
||||
StatementInfos statementInfos = getProgram().getStatementInfos();
|
||||
for(VariableRef definedVarRef : definedToNewVar.keySet()) {
|
||||
|
||||
// Find out if the variable is ever referenced outside the loop
|
||||
boolean referencedOutsideLoop = false;
|
||||
Collection<Integer> varRefStatements = variableReferenceInfos.getVarRefStatements(definedVarRef);
|
||||
for(Integer varRefStatement : varRefStatements) {
|
||||
ControlFlowBlock refBlock = statementInfos.getBlock(varRefStatement);
|
||||
if(!unrollLoop.getBlocks().contains(refBlock.getLabel())) {
|
||||
referencedOutsideLoop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(referencedOutsideLoop) {
|
||||
for(int i = 0; i < loopSuccessors.size(); i++) {
|
||||
LabelRef successorBlockRef = loopSuccessors.get(i);
|
||||
LabelRef successorPredecessorRef = loopSuccessorPredecessors.get(i);
|
||||
ControlFlowBlock successorBlock = getGraph().getBlock(successorBlockRef);
|
||||
StatementPhiBlock phiBlock = successorBlock.getPhiBlock();
|
||||
|
||||
// Look for a phi-variable
|
||||
boolean phiFound = false;
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
|
||||
if(phiVariable.getVariable().isVersion() && definedVarRef.isVersion()) {
|
||||
if(phiVariable.getVariable().getFullNameUnversioned().equals(definedVarRef.getFullNameUnversioned())) {
|
||||
phiFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!phiFound) {
|
||||
Variable definedVar = getScope().getVariable(definedVarRef);
|
||||
Variable newVar = ((VariableVersion) definedVar).getVersionOf().createVersion();
|
||||
StatementPhiBlock.PhiVariable newPhiVar = phiBlock.addPhiVariable(newVar.getRef());
|
||||
newPhiVar.setrValue(successorPredecessorRef, definedVarRef);
|
||||
getLog().append("Missing PHI for " + definedVarRef.getFullName() + " in block " + successorBlock.getLabel() + " - " + phiBlock.toString(getProgram(), false));
|
||||
|
||||
// TODO: Replace all references to definedVarRef outside loop to newVar!
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getLog().append(getGraph().toString(getProgram()));
|
||||
|
||||
// 1. Copy all loop blocks to create the "rest of the loop" and modifying the existing loop to only be the first iteration)
|
||||
// - Unroll Statements (copy all statements, replace symbols properly (with the new versions / the versions assigned in the existing loop)
|
||||
@ -203,9 +157,9 @@ public class Pass2LoopUnroll extends Pass2SsaOptimization {
|
||||
* @param loops All loops identified in the program
|
||||
* @return All loops declared to be unrolled
|
||||
*/
|
||||
private List<NaturalLoop> findUnrollLoopCandidates(NaturalLoopSet loops) {
|
||||
static List<NaturalLoop> findUnrollLoopCandidates(Program program, NaturalLoopSet loops) {
|
||||
List<NaturalLoop> unrollLoopCandidates = new ArrayList<>();
|
||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementConditionalJump) {
|
||||
if(((StatementConditionalJump) statement).isDeclaredUnroll()) {
|
||||
|
@ -0,0 +1,127 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementInfos;
|
||||
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.symbols.VariableVersion;
|
||||
import dk.camelot64.kickc.model.values.LabelRef;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Prepare for unrolling loops declared as inline.
|
||||
* This is done byensuring that all variables defined inside the loops and used outside the loop is passed through a PHI-functions
|
||||
* upon loop exit thus ensuring that these variables are only used inside the loop and in the PHI-function.
|
||||
* This makes it much easier to perform the unrolling as only a few parts of the program must be modified.
|
||||
*/
|
||||
public class Pass2LoopUnrollPhiPrepare extends Pass2SsaOptimization {
|
||||
|
||||
public Pass2LoopUnrollPhiPrepare(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
// Look for loops to unroll
|
||||
NaturalLoopSet loops = getProgram().getLoopSet();
|
||||
List<NaturalLoop> unrollLoopCandidates = Pass2LoopUnroll.findUnrollLoopCandidates(getProgram(), loops);
|
||||
// Is there any unrolling to do?
|
||||
if(unrollLoopCandidates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
|
||||
|
||||
for(NaturalLoop unrollLoop : unrollLoopCandidates) {
|
||||
|
||||
|
||||
List<ControlFlowBlock> unrollBlocks = new ArrayList<>();
|
||||
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
|
||||
if(unrollLoop.getBlocks().contains(block.getLabel())) {
|
||||
unrollBlocks.add(block);
|
||||
}
|
||||
}
|
||||
|
||||
List<VariableRef> definedInLoop = new ArrayList<>();
|
||||
for(ControlFlowBlock block : unrollBlocks) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
Collection<VariableRef> definedVars = variableReferenceInfos.getDefinedVars(statement);
|
||||
for(VariableRef definedVarRef : definedVars) {
|
||||
definedInLoop.add(definedVarRef);
|
||||
getLog().append("Defined in loop: " + definedVarRef.getFullName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// - Ensure that all variables assigned inside the loop has a PHI in successor blocks to the loop
|
||||
// - Find loop successor blocks
|
||||
List<LabelRef> loopSuccessors = new ArrayList<>();
|
||||
List<LabelRef> loopSuccessorPredecessors = new ArrayList<>();
|
||||
for(ControlFlowBlock block : unrollBlocks) {
|
||||
if(block.getDefaultSuccessor() != null && !unrollLoop.getBlocks().contains(block.getDefaultSuccessor())) {
|
||||
// Default successor is outside
|
||||
loopSuccessors.add(block.getDefaultSuccessor());
|
||||
loopSuccessorPredecessors.add(block.getLabel());
|
||||
}
|
||||
if(block.getConditionalSuccessor() != null && !unrollLoop.getBlocks().contains(block.getConditionalSuccessor())) {
|
||||
// Default successor is outside
|
||||
loopSuccessors.add(block.getConditionalSuccessor());
|
||||
loopSuccessorPredecessors.add(block.getLabel());
|
||||
}
|
||||
}
|
||||
// - Add any needed PHI-statements to the successors
|
||||
StatementInfos statementInfos = getProgram().getStatementInfos();
|
||||
for(VariableRef definedVarRef : definedInLoop) {
|
||||
|
||||
// Find out if the variable is ever referenced outside the loop
|
||||
boolean referencedOutsideLoop = false;
|
||||
Collection<Integer> varRefStatements = variableReferenceInfos.getVarRefStatements(definedVarRef);
|
||||
for(Integer varRefStatement : varRefStatements) {
|
||||
ControlFlowBlock refBlock = statementInfos.getBlock(varRefStatement);
|
||||
if(!unrollLoop.getBlocks().contains(refBlock.getLabel())) {
|
||||
referencedOutsideLoop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(referencedOutsideLoop) {
|
||||
for(int i = 0; i < loopSuccessors.size(); i++) {
|
||||
LabelRef successorBlockRef = loopSuccessors.get(i);
|
||||
LabelRef successorPredecessorRef = loopSuccessorPredecessors.get(i);
|
||||
ControlFlowBlock successorBlock = getGraph().getBlock(successorBlockRef);
|
||||
StatementPhiBlock phiBlock = successorBlock.getPhiBlock();
|
||||
|
||||
// Look for a phi-variable
|
||||
boolean phiFound = false;
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
|
||||
if(phiVariable.getVariable().isVersion() && definedVarRef.isVersion()) {
|
||||
if(phiVariable.getVariable().getFullNameUnversioned().equals(definedVarRef.getFullNameUnversioned())) {
|
||||
phiFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!phiFound) {
|
||||
Variable definedVar = getScope().getVariable(definedVarRef);
|
||||
Variable newVar = ((VariableVersion) definedVar).getVersionOf().createVersion();
|
||||
StatementPhiBlock.PhiVariable newPhiVar = phiBlock.addPhiVariable(newVar.getRef());
|
||||
newPhiVar.setrValue(successorPredecessorRef, definedVarRef);
|
||||
getLog().append("Missing PHI for " + definedVarRef.getFullName() + " in block " + successorBlock.getLabel() + " - " + phiBlock.toString(getProgram(), false));
|
||||
|
||||
// TODO: Replace all references to definedVarRef outside loop to newVar!
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getLog().append(getGraph().toString(getProgram()));
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user