1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-27 19:50:10 +00:00

Added commandline options for disabling uplift and outputting SIZE info.

This commit is contained in:
jespergravgaard 2019-09-16 00:51:03 +02:00
parent 0ce718371e
commit f16a29f5f7
11 changed files with 219 additions and 36 deletions

View File

@ -32,6 +32,11 @@ public class CompileLog {
*/
private boolean verboseSSAOptimize = false;
/**
* Should Memory usage be verbose
*/
private boolean verboseMemoryUsage = false;
/**
* Should loop unrolling be verbose.
*/
@ -96,6 +101,19 @@ public class CompileLog {
return log;
}
public CompileLog verboseMemoryUsage() {
setVerboseMemoryUsage(true);
return this;
}
public boolean isVerboseMemoryUsage() {
return verboseMemoryUsage;
}
public void setVerboseMemoryUsage(boolean verboseMemoryUsage) {
this.verboseMemoryUsage = verboseMemoryUsage;
}
public CompileLog verboseSsaSourceCode() {
setVerboseSsaSourceCode(true);
return this;

View File

@ -31,6 +31,9 @@ public class Compiler {
/** Enable the zero-page coalesce pass. It takes a lot of time, but limits the zero page usage significantly. */
private boolean enableZeroPageCoalasce = false;
/** Disable the entire register uplift. This will create significantly less optimized ASM since registers are not utilized. */
private boolean disableUplift = false;
/** Enable loop head constant optimization. It identified whenever a while()/for() has a constant condition on the first iteration and rewrites it.
* Currently the optimization is flaky and results in NPE's and wrong values in some programs. */
private boolean enableLoopHeadConstant = false;
@ -42,6 +45,10 @@ public class Compiler {
this.program = new Program();
}
public void setDisableUplift(boolean disableUplift) {
this.disableUplift = disableUplift;
}
public void setWarnFragmentMissing(boolean warnFragmentMissing) {
program.setWarnFragmentMissing(warnFragmentMissing);
}
@ -125,9 +132,15 @@ public class Compiler {
pass1GenerateSSA();
pass2Optimize();
pass2UnrollLoops();
pass2InlineConstants();
//getLog().append("\nCONTROL FLOW GRAPH PASS 2");
//getLog().append(program.getGraph().toString(program));
//getLog().append("SYMBOL TABLE PASS 2");
//getLog().append(program.getScope().toString(program, null));
pass3Analysis();
pass4RegisterAllocation();
pass5GenerateAndOptimizeAsm();
@ -307,6 +320,11 @@ public class Compiler {
}
private void pass2Optimize() {
if(getLog().isVerboseMemoryUsage()) {
getLog().append(program.getSizeInfo());
}
List<PassStep> optimizations = getPass2Optimizations();
pass2Execute(optimizations);
}
@ -354,6 +372,11 @@ public class Compiler {
}
private void pass2InlineConstants() {
if(getLog().isVerboseMemoryUsage()) {
getLog().append(program.getSizeInfo());
}
// Constant inlining optimizations - as the last step to ensure that constant identification has been completed
List<PassStep> constantOptimizations = new ArrayList<>();
constantOptimizations.add(new PassNStatementIndices(program));
@ -421,6 +444,11 @@ public class Compiler {
}
private void pass3Analysis() {
if(getLog().isVerboseMemoryUsage()) {
getLog().append(program.getSizeInfo());
}
new Pass3AssertNoTypeId(program).check();
new Pass3AssertRValues(program).check();
new Pass3AssertNoNumbers(program).check();
@ -471,6 +499,10 @@ public class Compiler {
private void pass4RegisterAllocation() {
if(getLog().isVerboseMemoryUsage()) {
getLog().append(program.getSizeInfo());
}
if(getLog().isVerboseLoopAnalysis()) {
getLog().append("DOMINATORS");
}
@ -509,30 +541,38 @@ public class Compiler {
getLog().append("Target platform is " + program.getTargetPlatform().getName() + " / " +program.getTargetCpu().getName().toUpperCase(Locale.ENGLISH));
getLog().append(program.getAsm().toString(new AsmProgram.AsmPrintState(true), program));
// Find potential registers for each live range equivalence class - based on clobbering of fragments
getLog().append("REGISTER UPLIFT POTENTIAL REGISTERS");
new Pass4RegisterUpliftPotentialInitialize(program).initPotentialRegisters();
new Pass4RegisterUpliftPotentialAluAnalysis(program).findPotentialAlu();
boolean change;
do {
change = new Pass4RegisterUpliftPotentialRegisterAnalysis(program).findPotentialRegisters();
} while(change);
getLog().append(program.getRegisterPotentials().toString());
if(disableUplift) {
getLog().append("REGISTER UPLIFT DISABLED!");
} else {
// Find potential registers for each live range equivalence class - based on clobbering of fragments
getLog().append("REGISTER UPLIFT POTENTIAL REGISTERS");
new Pass4RegisterUpliftPotentialInitialize(program).initPotentialRegisters();
new Pass4RegisterUpliftPotentialAluAnalysis(program).findPotentialAlu();
boolean change;
do {
change = new Pass4RegisterUpliftPotentialRegisterAnalysis(program).findPotentialRegisters();
} while(change);
getLog().append(program.getRegisterPotentials().toString());
// Find register uplift scopes
getLog().append("REGISTER UPLIFT SCOPES");
getLog().append(program.getRegisterUpliftProgram().toString((program.getVariableRegisterWeights())));
if(getLog().isVerboseMemoryUsage()) {
getLog().append(program.getSizeInfo());
}
// Attempt uplifting registers through a lot of combinations
//getLog().setVerboseUplift(true);
new Pass4RegisterUpliftCombinations(program).performUplift(upliftCombinations);
// Find register uplift scopes
getLog().append("REGISTER UPLIFT SCOPES");
getLog().append(program.getRegisterUpliftProgram().toString((program.getVariableRegisterWeights())));
//getLog().setVerboseUplift(true);
//new Pass4RegisterUpliftStatic(program).performUplift();
//getLog().setVerboseUplift(false);
// Attempt uplifting registers through a lot of combinations
//getLog().setVerboseUplift(true);
new Pass4RegisterUpliftCombinations(program).performUplift(upliftCombinations);
// Attempt uplifting registers one at a time to catch remaining potential not realized by combination search
new Pass4RegisterUpliftRemains(program).performUplift(upliftCombinations);
//getLog().setVerboseUplift(true);
//new Pass4RegisterUpliftStatic(program).performUplift();
//getLog().setVerboseUplift(false);
// Attempt uplifting registers one at a time to catch remaining potential not realized by combination search
new Pass4RegisterUpliftRemains(program).performUplift(upliftCombinations);
}
// Register coalesce on assignment (saving bytes & cycles)
new Pass4ZeroPageCoalesceAssignment(program).coalesce();

View File

@ -63,6 +63,9 @@ public class KickC implements Callable<Void> {
@CommandLine.Option(names = {"-Ouplift"}, description = "Optimization Option. Number of combinations to test when uplifting variables to registers in a scope. By default 100 combinations are tested.")
private Integer optimizeUpliftCombinations = null;
@CommandLine.Option(names = {"-Onouplift"}, description = "Optimization Option. Disable the register uplift allocation phase. This will be much faster but produce significantly slower ASM.")
private boolean optimizeNoUplift = false;
@CommandLine.Option(names = {"-Ocoalesce"}, description = "Optimization Option. Enables zero-page coalesce pass which limits zero-page usage significantly, but takes a lot of compile time.")
private boolean optimizeZeroPageCoalesce = false;
@ -87,6 +90,9 @@ public class KickC implements Callable<Void> {
@CommandLine.Option(names = {"-voptimize"}, description = "Verbosity Option. Control Flow Graph Optimization.")
private boolean verboseSSAOptimize = false;
@CommandLine.Option(names = {"-vmemory"}, description = "Verbosity Option. Compiler Data Structure Sizes.")
private boolean verboseMemory = false;
@CommandLine.Option(names = {"-vnonoptimize"}, description = "Verbosity Option. Choices not to optimize.")
private boolean verboseNonOptimization = false;
@ -236,6 +242,10 @@ public class KickC implements Callable<Void> {
asmFileName = fileBaseName + ".asm";
}
if(optimizeNoUplift) {
compiler.setDisableUplift(true);
}
if(optimizeUpliftCombinations != null) {
compiler.setUpliftCombinations(optimizeUpliftCombinations);
}
@ -370,6 +380,10 @@ public class KickC implements Callable<Void> {
compiler.getLog().setVerboseSSAOptimize(true);
compiler.getLog().setSysOut(true);
}
if(verboseMemory) {
compiler.getLog().setVerboseMemoryUsage(true);
compiler.getLog().setSysOut(true);
}
if(verboseNonOptimization) {
compiler.getLog().setVerboseNonOptimization(true);
compiler.getLog().setSysOut(true);

View File

@ -8,6 +8,7 @@ import dk.camelot64.kickc.model.values.ScopeRef;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A 6502 assembler program
@ -265,6 +266,19 @@ public class AsmProgram {
return null;
}
/**
* Get information about the size of the program
* @return Size information
*/
public String getSizeInfo() {
StringBuilder sizeInfo = new StringBuilder();
sizeInfo.append("SIZE ASM chunks "+ getChunks().size()).append("\n");
AtomicInteger numLines = new AtomicInteger();
getChunks().stream().forEach(asmChunk -> numLines.addAndGet(asmChunk.getLines().size()));
sizeInfo.append("SIZE ASM lines "+ numLines).append("\n");
return sizeInfo.toString();
}
public static class AsmPrintState {
// Output comments with information about the file/line number in the source file
private boolean sourceFileInfo;

View File

@ -271,4 +271,19 @@ public class ControlFlowGraph implements Serializable {
}
return scopeBlocks;
}
/**
* Get information about the size of the program
* @return Size information
*/
public String getSizeInfo() {
StringBuilder sizeInfo = new StringBuilder();
sizeInfo.append("SIZE blocks "+ getAllBlocks().size()).append("\n");
int numStmt = getAllBlocks().stream().mapToInt(block -> block.getStatements().size()).sum();
sizeInfo.append("SIZE statements "+ numStmt).append("\n");
int numPhiVars = getAllBlocks().stream().mapToInt(value -> value.getStatements().stream().mapToInt(value1 -> (value1 instanceof StatementPhiBlock)?((StatementPhiBlock) value1).getPhiVariables().size():0).sum()).sum();
sizeInfo.append("SIZE phi variables "+ numPhiVars).append("\n");
return sizeInfo.toString();
}
}

View File

@ -113,4 +113,13 @@ public class LiveRangeEquivalenceClassSet {
}
}
/**
* Get information about the size of the program
* @return Size information
*/
public String getSizeInfo() {
StringBuilder sizeInfo = new StringBuilder();
sizeInfo.append("SIZE live range equivalence classes "+ getEquivalenceClasses().size()).append("\n");
return sizeInfo.toString();
}
}

View File

@ -1,16 +1,17 @@
package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.ProcedureRef;
import dk.camelot64.kickc.model.values.ScopeRef;
import dk.camelot64.kickc.model.values.VariableRef;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.passes.Pass2AliasElimination;
import dk.camelot64.kickc.passes.calcs.PassNCalcLiveRangesEffective;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Effective variable live ranges for all statements.
@ -62,7 +63,7 @@ public class LiveRangeVariablesEffective {
*/
public Collection<VariableRef> getAliveEffective(Statement statement) {
Collection<VariableRef> effectiveAliveTotal = statementAliveEffective.get(statement.getIndex());
if(effectiveAliveTotal==null) {
if(effectiveAliveTotal == null) {
effectiveAliveTotal = new LinkedHashSet<>();
AliveCombinations aliveCombinations = getAliveCombinations(statement);
for(CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) {
@ -77,7 +78,7 @@ public class LiveRangeVariablesEffective {
/** Cached alive combinations. */
Map<Integer, AliveCombinations> statementAliveCombinations = new LinkedHashMap<>();
/** Special procedure reference used to represent the ROOT scope during live range analysis.*/
/** Special procedure reference used to represent the ROOT scope during live range analysis. */
static final ProcedureRef ROOT_PROCEDURE = new ProcedureRef("");
/**
@ -93,7 +94,7 @@ public class LiveRangeVariablesEffective {
*/
public AliveCombinations getAliveCombinations(Statement statement) {
AliveCombinations stmtCombinations = this.statementAliveCombinations.get(statement.getIndex());
if(stmtCombinations==null) {
if(stmtCombinations == null) {
Collection<VariableRef> aliveAtStmt = statementLiveVariables.get(statement.getIndex());
CallPaths callPaths;
Collection<VariableRef> referencedInProcedure;
@ -146,6 +147,50 @@ public class LiveRangeVariablesEffective {
return stmtCombinations;
}
public String getSizeInfo() {
StringBuilder sizeInfo = new StringBuilder();
if(this.procedureCallPaths != null) {
AtomicInteger numCallPaths = new AtomicInteger();
this.procedureCallPaths.values().forEach(callPaths -> numCallPaths.addAndGet(callPaths.getCallPaths().size()));
sizeInfo.append("SIZE procedureCallPaths ").append(numCallPaths.get()).append("\n");
}
if(this.statementAliveEffective != null) {
sizeInfo.append("SIZE statementAliveEffective ").append(statementAliveEffective.size()).append(" statements ");
int sub = 0;
for(Collection<VariableRef> variableRefs : statementAliveEffective.values()) {
sub += variableRefs.size();
}
sizeInfo.append(" ").append(sub).append(" varrefs").append("\n");
}
if(this.statementAliveCombinations != null) {
sizeInfo.append("SIZE statementAliveCombinations ").append(statementAliveCombinations.size()).append(" statements ");
int subVarRef = 0;
int subAlias = 0;
int subCallPath = 0;
int subEffectiveVarRef = 0;
for(AliveCombinations aliveCombinations : statementAliveCombinations.values()) {
subVarRef += aliveCombinations.aliveAtStmt.size();
subVarRef += aliveCombinations.referencedInProcedure.size();
if(aliveCombinations.callAliases!=null)
subAlias += aliveCombinations.callAliases.size();
if(aliveCombinations.callPaths.callPaths!=null)
subCallPath += aliveCombinations.callPaths.callPaths.size();
if(aliveCombinations.effectiveAliveAtStmt!=null)
for(Collection<VariableRef> varRefs : aliveCombinations.effectiveAliveAtStmt.values()) {
subEffectiveVarRef += varRefs.size();
}
}
sizeInfo.append(" ").append(subVarRef).append(" varrefs ");
sizeInfo.append(" ").append(subAlias).append(" aliases ");
sizeInfo.append(" ").append(subCallPath).append(" callpaths ");
sizeInfo.append(" ").append(subEffectiveVarRef).append(" eff-varrefs ");
sizeInfo.append("\n");
}
return sizeInfo.toString();
}
/**
* All call-paths leading into a specific procedure.
*/

View File

@ -498,4 +498,24 @@ public class Program {
public String getLinkScriptBody() {
return linkScriptBody;
}
/**
* Get information about the size of the program
* @return Size information
*/
public String getSizeInfo() {
StringBuilder sizeInfo = new StringBuilder();
sizeInfo.append(getScope().getSizeInfo());
sizeInfo.append(getGraph().getSizeInfo());
if(variableReferenceInfos!=null)
sizeInfo.append(variableReferenceInfos.getSizeInfo());
if(getLiveRangeEquivalenceClassSet()!=null)
sizeInfo.append(getLiveRangeEquivalenceClassSet().getSizeInfo());
if(liveRangeVariablesEffective!=null)
sizeInfo.append(liveRangeVariablesEffective.getSizeInfo());
if(getAsm()!=null)
sizeInfo.append(getAsm().getSizeInfo());
return sizeInfo.toString();
}
}

View File

@ -135,7 +135,7 @@ public class VariableReferenceInfos {
public String getSizeInfo() {
StringBuilder sizeInfo = new StringBuilder();
if(blockSuccessorClosure != null) {
sizeInfo.append("blockSuccessorClosure ").append(blockSuccessorClosure.size()).append(" labels ");
sizeInfo.append("SIZE blockSuccessorClosure ").append(blockSuccessorClosure.size()).append(" labels ");
int sub = 0;
for(Collection<LabelRef> labelRefs : blockSuccessorClosure.values()) {
sub += labelRefs.size();
@ -143,7 +143,7 @@ public class VariableReferenceInfos {
sizeInfo.append(" ").append(sub).append(" labels").append("\n");
}
{
sizeInfo.append("symbolVarReferences ").append(symbolVarReferences.size()).append(" SymbolVariableRefs ");
sizeInfo.append("SIZE symbolVarReferences ").append(symbolVarReferences.size()).append(" SymbolVariableRefs ");
int sub = 0;
for(Collection<ReferenceToSymbolVar> value : symbolVarReferences.values()) {
sub += value.size();
@ -151,7 +151,7 @@ public class VariableReferenceInfos {
sizeInfo.append(" ").append(sub).append(" ReferenceToSymbolVars").append("\n");
}
{
sizeInfo.append("statementVarReferences ").append(statementVarReferences.size()).append(" statements ");
sizeInfo.append("SIZE statementVarReferences ").append(statementVarReferences.size()).append(" statements ");
int sub = 0;
for(Collection<ReferenceToSymbolVar> value : statementVarReferences.values()) {
sub += value.size();
@ -159,7 +159,7 @@ public class VariableReferenceInfos {
sizeInfo.append(" ").append(sub).append(" ReferenceToSymbolVars").append("\n");
}
{
sizeInfo.append("blockVarReferences ").append(blockVarReferences.size()).append(" blocks ");
sizeInfo.append("SIZE blockVarReferences ").append(blockVarReferences.size()).append(" blocks ");
int sub = 0;
for(Collection<ReferenceToSymbolVar> value : blockVarReferences.values()) {
sub += value.size();

View File

@ -46,4 +46,16 @@ public class ProgramScope extends Scope {
return typeDefsScope;
}
/**
* Get information about the size of the program
* @return Size information
*/
public String getSizeInfo() {
StringBuilder sizeInfo = new StringBuilder();
sizeInfo.append("SIZE procedures "+ getAllProcedures(true).size()).append("\n");
sizeInfo.append("SIZE scopes "+ getAllScopes(true).size()).append("\n");
sizeInfo.append("SIZE variables "+ getAllVariables(true).size()).append("\n");
sizeInfo.append("SIZE constants "+ getAllConstants(true).size()).append("\n");
return sizeInfo.toString();
}
}

View File

@ -87,11 +87,7 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase<VariableRefer
}
});
}
VariableReferenceInfos variableReferenceInfos = new VariableReferenceInfos(blockSuccessors, symbolVarReferences, blockVarReferences, statementVarReferences);
//if(getLog().isVerboseSSAOptimize()) {
// getLog().append(variableReferenceInfos.getSizeInfo());
//}
return variableReferenceInfos;
return new VariableReferenceInfos(blockSuccessors, symbolVarReferences, blockVarReferences, statementVarReferences);
}
/**