From 1f54a914638ec88dadd70fce072fe884998a90c9 Mon Sep 17 00:00:00 2001 From: Travis Fisher Date: Wed, 10 Apr 2019 19:47:54 -0400 Subject: [PATCH 1/3] use static array of short number strings (~3% test speedup) --- .../camelot64/kickc/fragment/AsmFormat.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java index 238c621f8..6c0dec81f 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java @@ -174,11 +174,29 @@ public class AsmFormat { } } + private static String shortNumberStrings[] = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "$a", "$b", "$c", "$d", "$e", "$f", + "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$1a", "$1b", "$1c", "$1d", "$1e", "$1f", + "$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$2a", "$2b", "$2c", "$2d", "$2e", "$2f", + "$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37", "$38", "$39", "$3a", "$3b", "$3c", "$3d", "$3e", "$3f", + "$40", "$41", "$42", "$43", "$44", "$45", "$46", "$47", "$48", "$49", "$4a", "$4b", "$4c", "$4d", "$4e", "$4f", + "$50", "$51", "$52", "$53", "$54", "$55", "$56", "$57", "$58", "$59", "$5a", "$5b", "$5c", "$5d", "$5e", "$5f", + "$60", "$61", "$62", "$63", "$64", "$65", "$66", "$67", "$68", "$69", "$6a", "$6b", "$6c", "$6d", "$6e", "$6f", + "$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", "$78", "$79", "$7a", "$7b", "$7c", "$7d", "$7e", "$7f", + "$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87", "$88", "$89", "$8a", "$8b", "$8c", "$8d", "$8e", "$8f", + "$90", "$91", "$92", "$93", "$94", "$95", "$96", "$97", "$98", "$99", "$9a", "$9b", "$9c", "$9d", "$9e", "$9f", + "$a0", "$a1", "$a2", "$a3", "$a4", "$a5", "$a6", "$a7", "$a8", "$a9", "$aa", "$ab", "$ac", "$ad", "$ae", "$af", + "$b0", "$b1", "$b2", "$b3", "$b4", "$b5", "$b6", "$b7", "$b8", "$b9", "$ba", "$bb", "$bc", "$bd", "$be", "$bf", + "$c0", "$c1", "$c2", "$c3", "$c4", "$c5", "$c6", "$c7", "$c8", "$c9", "$ca", "$cb", "$cc", "$cd", "$ce", "$cf", + "$d0", "$d1", "$d2", "$d3", "$d4", "$d5", "$d6", "$d7", "$d8", "$d9", "$da", "$db", "$dc", "$dd", "$de", "$df", + "$e0", "$e1", "$e2", "$e3", "$e4", "$e5", "$e6", "$e7", "$e8", "$e9", "$ea", "$eb", "$ec", "$ed", "$ee", "$ef", + "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", "$fa", "$fb", "$fc", "$fd", "$fe", "$ff" + }; public static String getAsmNumber(Number number) { if(number instanceof Long || number instanceof Integer) { - if(number.longValue() >= 0L && number.longValue() <= 9L) { - return String.format("%d", number.longValue()); + if(number.longValue() >= 0L && number.longValue() <= 255L) { + return shortNumberStrings[number.intValue()]; } else { return String.format("$%x", number.longValue()); } From b81349b3de37d38e00d3adff3b893b1f6e9c6fb8 Mon Sep 17 00:00:00 2001 From: Travis Fisher Date: Wed, 10 Apr 2019 22:22:17 -0400 Subject: [PATCH 2/3] make StatementInfos map control flow block objects instead of labelRef's (~5% compiler speedup) --- .../kickc/model/LiveRangeVariablesEffective.java | 3 +-- .../kickc/model/statements/StatementInfos.java | 10 +++++----- .../dk/camelot64/kickc/passes/PassNStatementInfos.java | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java index 063d2af7b..70566cf77 100644 --- a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java +++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java @@ -276,9 +276,8 @@ public class LiveRangeVariablesEffective { * @return All variables effectively alive at the statement on the call-path */ public Collection getEffectiveAliveAtStmt(CallPath callPath) { - LinkedHashSet effectiveAlive = new LinkedHashSet<>(); // Add alive at call - effectiveAlive.addAll(callPath.getAlive()); + LinkedHashSet effectiveAlive = new LinkedHashSet<>(callPath.getAlive()); // Clear out any variables referenced in the method effectiveAlive.removeAll(referencedInProcedure); // Add alive at statement diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementInfos.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementInfos.java index b13d7cbc0..53572d2f2 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementInfos.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementInfos.java @@ -14,12 +14,12 @@ public class StatementInfos { private ControlFlowGraph graph; /** Maps statement index to block label. */ - private Map stmtBlocks; + private Map stmtBlocks; /** Maps statement index to statement. */ private Map stmtIdx; - public StatementInfos(Program program, Map stmtBlocks, Map stmtIdx) { + public StatementInfos(Program program, Map stmtBlocks, Map stmtIdx) { this.graph = program.getGraph(); this.stmtBlocks = stmtBlocks; this.stmtIdx = stmtIdx; @@ -32,7 +32,7 @@ public class StatementInfos { * @return The block label */ public LabelRef getBlockRef(Integer stmtIdx) { - return stmtBlocks.get(stmtIdx); + return stmtBlocks.get(stmtIdx).getLabel(); } /** @@ -42,7 +42,7 @@ public class StatementInfos { * @return The block label */ public LabelRef getBlockRef(Statement stmt) { - return stmtBlocks.get(stmt.getIndex()); + return stmtBlocks.get(stmt.getIndex()).getLabel(); } /** @@ -52,7 +52,7 @@ public class StatementInfos { * @return The containing block */ public ControlFlowBlock getBlock(Statement stmt) { - return graph.getBlock(getBlockRef(stmt)); + return stmtBlocks.get(stmt.getIndex()); } /** diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNStatementInfos.java b/src/main/java/dk/camelot64/kickc/passes/PassNStatementInfos.java index e9e115400..224719d9f 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNStatementInfos.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNStatementInfos.java @@ -24,11 +24,11 @@ public class PassNStatementInfos extends Pass2SsaOptimization { */ @Override public boolean step() { - LinkedHashMap stmtBlocks = new LinkedHashMap<>(); + LinkedHashMap stmtBlocks = new LinkedHashMap<>(); LinkedHashMap stmtIdx = new LinkedHashMap<>(); for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) { for(Statement statement : block.getStatements()) { - stmtBlocks.put(statement.getIndex(), block.getLabel()); + stmtBlocks.put(statement.getIndex(), block); stmtIdx.put(statement.getIndex(), statement); } } From c9cce92509eebb4c04d97fc2cff7ff5918766151 Mon Sep 17 00:00:00 2001 From: Travis Fisher Date: Thu, 11 Apr 2019 00:14:31 -0400 Subject: [PATCH 3/3] make live range analysis use statement index instead of statement where it helps with speed --- .../dk/camelot64/kickc/model/LiveRange.java | 30 +------------------ .../kickc/model/LiveRangeVariables.java | 18 +++++------ .../model/LiveRangeVariablesEffective.java | 2 +- .../kickc/model/statements/StatementBase.java | 2 +- .../kickc/passes/Pass3LiveRangesAnalysis.java | 20 ++++++++----- .../Pass3LiveRangesEffectiveAnalysis.java | 7 ++--- 6 files changed, 27 insertions(+), 52 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRange.java b/src/main/java/dk/camelot64/kickc/model/LiveRange.java index f124b12e9..288cdbf51 100644 --- a/src/main/java/dk/camelot64/kickc/model/LiveRange.java +++ b/src/main/java/dk/camelot64/kickc/model/LiveRange.java @@ -22,24 +22,6 @@ public class LiveRange { this.intervals = new ArrayList<>(); } - /** - * Add a statement to the live range - * - * @param statement The statement to add - * @return true if the live range was modified by the addition. false otherwise - */ - public boolean add(Statement statement) { - return add(getIndex(statement)); - } - - private Integer getIndex(Statement statement) { - Integer index = statement.getIndex(); - if(index == null) { - throw new RuntimeException("Statement index not defined! Live Ranges only work after defining statement indexes (Pass3LiveRangesAnalysis.generateStatementIndices)."); - } - return index; - } - /** * Get the number of statements in the live range. * @@ -125,23 +107,13 @@ public class LiveRange { } } - /** - * Determines if the live range contains a statement - * - * @param statement The statement to examine - * @return true if the live range contains the statement - */ - public boolean contains(Statement statement) { - return contains(getIndex(statement)); - } - /** * Determines if the live range contains an index * * @param index * @return true if the live range contains the index */ - private boolean contains(int index) { + public boolean contains(int index) { for(LiveInterval interval : intervals) { if(interval.lastStatementIdx >= index) { if(interval.firstStatementIdx <= index) { diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariables.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariables.java index 689f1ff16..ded3dee6b 100644 --- a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariables.java +++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariables.java @@ -8,6 +8,7 @@ import dk.camelot64.kickc.passes.PassNCallGraphAnalysis; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; /** * Live ranges for all variables. @@ -28,16 +29,16 @@ public class LiveRangeVariables { * Add a single statement to the live range of a variable. * * @param variable The variable - * @param statement The statement to add + * @param statementIdx Index of the statement to add * @return true if a live range was modified by the addition */ - public boolean addAlive(VariableRef variable, Statement statement) { + public boolean addAlive(VariableRef variable, int statementIdx) { LiveRange liveRange = liveRanges.get(variable); if(liveRange == null) { liveRange = new LiveRange(); liveRanges.put(variable, liveRange); } - return liveRange.add(statement); + return liveRange.add(statementIdx); } /** @@ -56,15 +57,14 @@ public class LiveRangeVariables { /** * Get all variables alive at a specific statement * - * @param statement The statement + * @param statementIdx Index of the statement * @return List of all live variables. */ - public List getAlive(Statement statement) { + public List getAlive(int statementIdx) { ArrayList aliveVars = new ArrayList<>(); - for(VariableRef variable : liveRanges.keySet()) { - LiveRange liveRange = liveRanges.get(variable); - if(liveRange.contains(statement)) { - aliveVars.add(variable); + for(Map.Entry entry : liveRanges.entrySet()) { + if(entry.getValue().contains(statementIdx)) { + aliveVars.add(entry.getKey()); } } return aliveVars; diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java index 70566cf77..02b0f347a 100644 --- a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java +++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java @@ -43,7 +43,7 @@ public class LiveRangeVariablesEffective { this.statementLiveVariables = new LinkedHashMap<>(); for(ControlFlowBlock block : program.getGraph().getAllBlocks()) { for(Statement statement : block.getStatements()) { - statementLiveVariables.put(statement.getIndex(), liveRangeVariables.getAlive(statement)); + statementLiveVariables.put(statement.getIndex(), liveRangeVariables.getAlive(statement.getIndex())); } } } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementBase.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementBase.java index efcab4a06..34ef15104 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementBase.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementBase.java @@ -80,7 +80,7 @@ public abstract class StatementBase implements Statement { } LiveRangeVariables liveRanges = program.getLiveRangeVariables(); StringBuilder alive = new StringBuilder(); - alive.append(getAliveString(liveRanges.getAlive(this))); + alive.append(getAliveString(liveRanges.getAlive(index))); LiveRangeVariablesEffective liveRangeVariablesEffective = program.getLiveRangeVariablesEffective(); if(liveRangeVariablesEffective != null) { LiveRangeVariablesEffective.AliveCombinations aliveCombinations = liveRangeVariablesEffective.getAliveCombinations(this); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesAnalysis.java index 5b0c0a47a..9d2234f0b 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesAnalysis.java @@ -65,7 +65,7 @@ public class Pass3LiveRangesAnalysis extends Pass2Base { boolean modified = false; for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) { for(Statement stmt : block.getStatements()) { - List aliveNextStmt = liveRanges.getAlive(stmt); + List aliveNextStmt = liveRanges.getAlive(stmt.getIndex()); Collection definedNextStmt = referenceInfo.getDefinedVars(stmt); initLiveRange(liveRanges, definedNextStmt); Collection previousStmts = getPreviousStatements(stmt); @@ -76,7 +76,7 @@ public class Pass3LiveRangesAnalysis extends Pass2Base { // Add all vars alive in the next statement for(VariableRef aliveVar : aliveNextStmt) { if(!definedNextStmt.contains(aliveVar)) { - boolean addAlive = liveRanges.addAlive(aliveVar, previousStmt.getStatement()); + boolean addAlive = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx()); modified |= addAlive; if(addAlive && getLog().isVerboseLiveRanges()) { getLog().append("Propagated alive var " + aliveVar + " to " + previousStmt.getStatement()); @@ -92,7 +92,7 @@ public class Pass3LiveRangesAnalysis extends Pass2Base { for(VariableRef aliveVar : aliveNextStmt) { // Add all variables to previous that are not used inside the method if(procUsed.contains(aliveVar)) { - boolean addUsedVar = liveRanges.addAlive(aliveVar, previousStmt.getStatement()); + boolean addUsedVar = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx()); modified |= addUsedVar; if(addUsedVar && getLog().isVerboseLiveRanges()) { getLog().append("Propagated alive var used in method into method " + aliveVar + " to " + previousStmt.getStatement()); @@ -108,7 +108,7 @@ public class Pass3LiveRangesAnalysis extends Pass2Base { for(VariableRef aliveVar : aliveNextStmt) { // Add all variables to previous that are not used inside the method if(!procUsed.contains(aliveVar)) { - boolean addSkipVar = liveRanges.addAlive(aliveVar, previousStmt.getStatement()); + boolean addSkipVar = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx()); modified |= addSkipVar; if(addSkipVar && getLog().isVerboseLiveRanges()) { getLog().append("Propagated alive var unused in method by skipping call " + aliveVar + " to " + previousStmt.getStatement()); @@ -127,7 +127,7 @@ public class Pass3LiveRangesAnalysis extends Pass2Base { // Add all variables to previous that are used inside the method if(procUsed.contains(aliveVar)) { if(!definedNextStmt.contains(aliveVar)) { - boolean usedVar = liveRanges.addAlive(aliveVar, previousStmt.getStatement()); + boolean usedVar = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx()); modified |= usedVar; if(usedVar && getLog().isVerboseLiveRanges()) { getLog().append("Propagated alive used in method out of method " + aliveVar + " to " + previousStmt.getStatement()); @@ -164,13 +164,13 @@ public class Pass3LiveRangesAnalysis extends Pass2Base { // If current statement is a phi add the used variables to previous based on the phi entries StatementPhiBlock phi = (StatementPhiBlock) stmt; ControlFlowBlock previousBlock = - getProgram().getStatementInfos().getBlock(previousStmt.getStatement()); + getProgram().getStatementInfos().getBlock(previousStmt.getStatementIdx()); for(StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) { for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { if(phiRValue.getPredecessor().equals(previousBlock.getLabel())) { if(phiRValue.getrValue() instanceof VariableRef) { VariableRef usedVar = (VariableRef) phiRValue.getrValue(); - boolean addUsed = liveRanges.addAlive(usedVar, previousStmt.getStatement()); + boolean addUsed = liveRanges.addAlive(usedVar, previousStmt.getStatementIdx()); modified |= addUsed; if(addUsed && getLog().isVerboseLiveRanges()) { getLog().append("Adding used phi var " + usedVar + " to " + previousStmt.getStatement()); @@ -182,7 +182,7 @@ public class Pass3LiveRangesAnalysis extends Pass2Base { } else { // Not a phi block - add used vars to all previous blocks for(VariableRef usedVar : usedNextStmt) { - boolean addUsed = liveRanges.addAlive(usedVar, previousStmt.getStatement()); + boolean addUsed = liveRanges.addAlive(usedVar, previousStmt.getStatementIdx()); modified |= addUsed; if(addUsed && getLog().isVerboseLiveRanges()) { getLog().append("Adding used var " + usedVar + " to " + previousStmt.getStatement()); @@ -346,6 +346,10 @@ public class Pass3LiveRangesAnalysis extends Pass2Base { return statement; } + public int getStatementIdx() { + return statement.getIndex(); + } + public Type getType() { return type; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesEffectiveAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesEffectiveAnalysis.java index d6b91e25c..04d82407a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesEffectiveAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesEffectiveAnalysis.java @@ -75,9 +75,8 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base { getProgram().getCallGraph().getCallers(procedure.getRef()); for(CallGraph.CallBlock.Call caller : callers) { // Each caller creates its own call-paths - StatementCall callStatement = - (StatementCall) getProgram().getStatementInfos().getStatement(caller.getCallStatementIdx()); - ControlFlowBlock callBlock = getProgram().getStatementInfos().getBlock(callStatement); + int callStatementIdx = caller.getCallStatementIdx(); + ControlFlowBlock callBlock = getProgram().getStatementInfos().getBlock(callStatementIdx); ScopeRef callScopeRef = callBlock.getScope(); Scope callScope = getProgram().getScope().getScope(callScopeRef); if(callScope instanceof Procedure) { @@ -95,7 +94,7 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base { Collection alive = new LinkedHashSet<>(); alive.addAll(callerPath.getAlive()); alive.removeAll(referencedInCaller); - alive.addAll(liveRangeVariables.getAlive(callStatement)); + alive.addAll(liveRangeVariables.getAlive(callStatementIdx)); Pass2AliasElimination.Aliases innerAliases = getCallAliases(procedure, callBlock); Pass2AliasElimination.Aliases pathAliases = new Pass2AliasElimination.Aliases(); pathAliases.addAll(callerPath.getPathAliases());