mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-08 14:37:40 +00:00
Optimized live range effective - vastly improving compile speed.
This commit is contained in:
parent
d551f8c569
commit
520361f7b6
@ -206,6 +206,7 @@ public class Compiler {
|
||||
new Pass3StatementIndices(program).generateStatementIndices();
|
||||
new Pass3CallGraphAnalysis(program).findCallGraph();
|
||||
new Pass3LiveRangesAnalysis(program).findLiveRanges();
|
||||
new Pass3LiveRangesEffectiveAnalysis(program).findLiveRangesEffective();
|
||||
program.getLog().append("CONTROL FLOW GRAPH - PHI MEM COALESCED");
|
||||
program.getLog().append(program.getGraph().toString(program));
|
||||
pass2AssertSSA(program);
|
||||
|
@ -1,3 +1,4 @@
|
||||
Known Problems
|
||||
|
||||
Features
|
||||
- Move the main code into a main() function, and disallow code outside functions. The main function per default has no parameters and exits with RTS.
|
||||
@ -21,16 +22,9 @@ Features
|
||||
- Allow complex array expressions in lValues eg. (SCREEN+$100)[idx]
|
||||
- Optimize loops by unrolling them somewhat
|
||||
- Optimize loops with Strength reduction (https://en.wikipedia.org/wiki/Strength_reduction)
|
||||
+ Create a proper main function for the compiler
|
||||
+ Add ++/-- incrementing/decrementing operators.
|
||||
+ Optimize if's without else if(expr) { stmt; } -> $1=!expr; if($1) goto @1; stmt; @1:
|
||||
+ Add a for loop for(init;condition;increment) {stmt} -> { init; do { stmt; increment } while (condition) }
|
||||
+ Add for loop for(byte i: 1..100) { } and for(byte i : 100..0) {} (plus maybe .+. and .-. to make the inc/dec unambiguous)
|
||||
|
||||
Assembler Improvements
|
||||
- Make generated ASM human readable.
|
||||
+ Use hex-numbers
|
||||
+ add labels for constants and zp-variables.
|
||||
- Relabel blocks eliminating long labels such as b3_from_b11
|
||||
- Eliminate chained JMP's (replace by direct JMP) - example: loopsplit.asm
|
||||
- Better ASM static value analysis
|
||||
- Not just constants - but also other values (value of var, value of var1[var2], value of var+4 etc.)
|
||||
@ -41,11 +35,6 @@ Assembler Improvements
|
||||
- Eliminate LDA from STA $11, LDA $11 (using ASM static value analysis of A-register)
|
||||
- Optimize by allowing resequencing of ASM (statements and phi assignments) in a final phase.
|
||||
- ASM loop analysis: If all usages of a register has the same value move the assignment out of the loop (if the assignment is simple enough).
|
||||
+ Eliminate unnecessary labels in ASM
|
||||
|
||||
Known Problems
|
||||
+ Procedures that modify variables outside their scope does not work. Outer vars must be transfered in/out like parameters/return values to get it working.
|
||||
+ Alive vars are propagated backward through procedures (correctly). However they are then propagated back through ALL calls to the procedure incorrectly. They should only be alive at calls where they are alive after the call. In summin.kc s1#0 is incirrectly backpropagated through the first call, where it is not alive.
|
||||
|
||||
Register Allocation
|
||||
- Allow user to limit number of combinations tested
|
||||
@ -58,6 +47,46 @@ Register Allocation
|
||||
- Improve combination testing by finding live range overlaps and not creating combinations that would create an overlap conflict.
|
||||
- Combinations should be created in a tree-structure instead of just doing all combinations
|
||||
- Example: For equivalence classes a, b, c if a&c have overlapping live ranges they can never have the same register. Therefore the combination iterator should not create combinations where C has the same register as a.
|
||||
|
||||
Process/Code Structure Improvement
|
||||
- Eliminate copy visitor
|
||||
- Refactor Expression Operator Implementation & Evaluation into one class per operator
|
||||
- Improve error messages to give better context
|
||||
- Offer to compile resulting ASM with KickAssembler
|
||||
+ Implemenent Assertions for the output of different phases (ensuring that the result of the phase is consistent)
|
||||
+ Make each phase return a separate object graph (allowing for keeeping the history in memory & performing rollbacks)
|
||||
|
||||
Testing
|
||||
- Implement ICL syntax (printer & parser). Drop the JSON.
|
||||
- Test that the parse tree for specific KC syntax is as expected. Use a print function for the parse tree to generate output for comparison.
|
||||
- Test the ICL result of a specific phase on a specific ICL input. Create an ICL syntax for parsing directly to ICL and a printer for the syntax.
|
||||
- Emulate/Run the ASM for a specific KC program compiled. Compare the emulated ASM output to output calculated by executing directly on the KC tree.
|
||||
- Add assert statements to the language. Create KC programs that test the compiler by compiling, running and testing assertions.
|
||||
|
||||
Usages
|
||||
- Implement library for memory allocation in main memory
|
||||
- Implement library for output on the screen (using basic functions)
|
||||
|
||||
Real Usage
|
||||
- Implement library for fast multiply (mul.asm)
|
||||
- Implement spline library (spline.asm)
|
||||
- Implement polygon filler for complex polygons.
|
||||
- Implement a true type font renderer.
|
||||
|
||||
|
||||
Done
|
||||
+ Test the ASM program output resulting from compiling specific KC program input.
|
||||
+ Create a proper main function for the compiler
|
||||
+ Add ++/-- incrementing/decrementing operators.
|
||||
+ Optimize if's without else if(expr) { stmt; } -> $1=!expr; if($1) goto @1; stmt; @1:
|
||||
+ Add a for loop for(init;condition;increment) {stmt} -> { init; do { stmt; increment } while (condition) }
|
||||
+ Add for loop for(byte i: 1..100) { } and for(byte i : 100..0) {} (plus maybe .+. and .-. to make the inc/dec unambiguous)
|
||||
+ Eliminate unnecessary labels in ASM
|
||||
+ Make generated ASM human readable.
|
||||
+ Use hex-numbers
|
||||
+ add labels for constants and zp-variables.
|
||||
+ Procedures that modify variables outside their scope does not work. Outer vars must be transfered in/out like parameters/return values to get it working.
|
||||
+ Alive vars are propagated backward through procedures (correctly). However they are then propagated back through ALL calls to the procedure incorrectly. They should only be alive at calls where they are alive after the call. In summin.kc s1#0 is incirrectly backpropagated through the first call, where it is not alive.
|
||||
+ Reuse phi-transitions that are identical
|
||||
+ Optimize phi transitions by ensuring that identical phi-transitions with regards to register allocation are collected into a single transition.
|
||||
+ Limit number of combinations tested
|
||||
@ -72,33 +101,6 @@ Register Allocation
|
||||
+ Register types: A, X, Y, ZP, (memory).
|
||||
+ Implement a register allocation (coloring) algorithm using by liveness intervals, preferences, weights & clobbering information.
|
||||
+ Optimize register allocation by combining with knowledge of ASM program cost (bytes/cycles) and different ASM fragments with different clobbering.
|
||||
|
||||
Process/Code Structure Improvement
|
||||
- Eliminate copy visitor
|
||||
- Refactor Expression Operator Implementation & Evaluation into one class per operator
|
||||
- Improve error messages to give better context
|
||||
- Offer to compile resulting ASM with KickAssembler
|
||||
+ Implemenent Assertions for the output of different phases (ensuring that the result of the phase is consistent)
|
||||
+ Make each phase return a separate object graph (allowing for keeeping the history in memory & performing rollbacks)
|
||||
|
||||
Testing
|
||||
- Test that the parse tree for specific KC syntax is as expected. Use a print function for the parse tree to generate output for comparison.
|
||||
- Test the ICL result of a specific phase on a specific ICL input. Create an ICL syntax for parsing directly to ICL and a printer for the syntax.
|
||||
- Emulate/Run the ASM for a specific KC program compiled. Compare the emulated ASM output to output calculated by executing directly on the KC tree.
|
||||
- Add assert statements to the language. Create KC programs that test the compiler by compiling, running and testing assertions.
|
||||
+ Test the ASM program output resulting from compiling specific KC program input.
|
||||
|
||||
Usages
|
||||
- Implement library for memory allocation in main memory
|
||||
- Implement library for output on the screen (using basic functions)
|
||||
|
||||
Real Usage
|
||||
- Implement library for fast multiply (mul.asm)
|
||||
- Implement spline library (spline.asm)
|
||||
- Implement polygon filler for complex polygons.
|
||||
- Implement a true type font renderer.
|
||||
|
||||
New Constant Solution
|
||||
+ Live range overlap analysis of register combinations inside methods must also look at registers alive at all calls.
|
||||
+ Examine why temp-vars are used in flipper.
|
||||
+ Examine why flipper is plotted in a wrong position on the screen.
|
||||
@ -112,3 +114,4 @@ New Constant Solution
|
||||
+ Fix by introducing "effective alive vars" which includes alive vars at all calls to containing methods and using that during clobber check.
|
||||
+ In loopnest.asm x&y are used in both loops - the outer x&y are clobbered by the inner loop.
|
||||
+ In voronoi.asm in render() x is clobbered during call to findcol().
|
||||
+ Optimize getAliveEffective() to improve speed
|
||||
|
@ -68,40 +68,5 @@ public class LiveRangeVariables {
|
||||
return liveRanges.get(variable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all variables alive at a statement.
|
||||
* If the statement is inside a method this also includes all variables alive at the exit of the calls.
|
||||
* <p>
|
||||
* This method requires a number of other analysis to be present and updated in the (global) program - especailly the Call Graph.
|
||||
* </p>
|
||||
* @param statement The statement to examine
|
||||
* @return All variables alive at the statement
|
||||
*/
|
||||
public Collection<VariableRef> getAliveEffective(Statement statement) {
|
||||
// Get variables alive from live range analysis
|
||||
Collection<VariableRef> effectiveAlive = new LinkedHashSet<>();
|
||||
effectiveAlive.addAll(getAlive(statement));
|
||||
// If the statement is inside a method recurse back to all calls
|
||||
// For each call add the variables alive after the call that are not referenced (used/defined) inside the method
|
||||
ControlFlowBlock block = program.getGraph().getBlockFromStatementIdx(statement.getIndex());
|
||||
ScopeRef scopeRef = block.getScope();
|
||||
Scope scope = program.getScope().getScope(scopeRef);
|
||||
if (scope instanceof Procedure) {
|
||||
Procedure procedure = (Procedure) scope;
|
||||
Collection<CallGraph.CallBlock.Call> callers =
|
||||
program.getCallGraph().getCallers(procedure.getLabel().getRef());
|
||||
VariableReferenceInfo referenceInfo = new VariableReferenceInfo(program);
|
||||
Collection<VariableRef> referencedInProcedure = referenceInfo.getReferenced(procedure.getRef().getLabelRef());
|
||||
for (CallGraph.CallBlock.Call caller : callers) {
|
||||
StatementCall callStatement =
|
||||
(StatementCall) program.getGraph().getStatementByIndex(caller.getCallStatementIdx());
|
||||
Set<VariableRef> callAliveEffective = new LinkedHashSet<>(getAliveEffective(callStatement));
|
||||
// Clear out any variables referenced in the method
|
||||
callAliveEffective.removeAll(referencedInProcedure);
|
||||
effectiveAlive.addAll(callAliveEffective);
|
||||
}
|
||||
}
|
||||
return effectiveAlive;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/** Effective variable live ranges for all statements. (Including variables alive in calling methods)
|
||||
* Created by {@link dk.camelot64.kickc.passes.Pass3CallGraphAnalysis}
|
||||
*/
|
||||
public class LiveRangeVariablesEffective {
|
||||
|
||||
/** Effectively alive variables by statement index. */
|
||||
Map<Integer, Collection<VariableRef>> effectiveLiveVariables;
|
||||
|
||||
public LiveRangeVariablesEffective(Map<Integer, Collection<VariableRef>> effectiveLiveVariables) {
|
||||
this.effectiveLiveVariables = effectiveLiveVariables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all variables alive at a statement.
|
||||
* If the statement is inside a method this also includes all variables alive at the exit of the calls.
|
||||
* <p>
|
||||
* This method requires a number of other analysis to be present and updated in the (global) program - especailly the Call Graph.
|
||||
* </p>
|
||||
* @param statement The statement to examine
|
||||
* @return All variables alive at the statement
|
||||
*/
|
||||
public Collection<VariableRef> getAliveEffective(Statement statement) {
|
||||
return effectiveLiveVariables.get(statement.getIndex());
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -32,6 +32,8 @@ public class Program {
|
||||
private LiveRangeVariables liveRangeVariables;
|
||||
/** Live range equivalence classes containing variables that do not have overlapping live ranges. */
|
||||
private LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet;
|
||||
/** The effective live ranges of all variables. */
|
||||
private LiveRangeVariablesEffective liveRangeVariablesEffective;
|
||||
/** The register weight of all variables describing how much the variable would theoretically gain from being in a register */
|
||||
private VariableRegisterWeights variableRegisterWeights;
|
||||
/** Registers potentially usable as allocation for each live range equivalence class. */
|
||||
@ -118,6 +120,14 @@ public class Program {
|
||||
return liveRangeVariables;
|
||||
}
|
||||
|
||||
public LiveRangeVariablesEffective getLiveRangeVariablesEffective() {
|
||||
return liveRangeVariablesEffective;
|
||||
}
|
||||
|
||||
public void setLiveRangeVariablesEffective(LiveRangeVariablesEffective liveRangeVariablesEffective) {
|
||||
this.liveRangeVariablesEffective = liveRangeVariablesEffective;
|
||||
}
|
||||
|
||||
public void setLiveRangeEquivalenceClassSet(LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet) {
|
||||
this.liveRangeEquivalenceClassSet = liveRangeEquivalenceClassSet;
|
||||
}
|
||||
|
@ -0,0 +1,72 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
/**
|
||||
* Find effective alive intervals for all variables in all statements. Add the intervals to the Program.
|
||||
*/
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
|
||||
|
||||
public Pass3LiveRangesEffectiveAnalysis(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
public void findLiveRangesEffective() {
|
||||
LiveRangeVariablesEffective aliveEffective = findAliveEffective(getProgram());
|
||||
getProgram().setLiveRangeVariablesEffective(aliveEffective);
|
||||
//getLog().append("Calculated effective variable live ranges");
|
||||
}
|
||||
|
||||
|
||||
private LiveRangeVariablesEffective findAliveEffective(Program program) {
|
||||
LiveRangeVariables liveRangeVariables = program.getLiveRangeVariables();
|
||||
Map<Integer, Collection<VariableRef>> effectiveLiveVariables = new HashMap<>();
|
||||
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
Collection<VariableRef> aliveEffective = findAliveEffective( liveRangeVariables, statement);
|
||||
effectiveLiveVariables.put(statement.getIndex(), aliveEffective);
|
||||
}
|
||||
}
|
||||
return new LiveRangeVariablesEffective(effectiveLiveVariables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all variables alive at a statement.
|
||||
* If the statement is inside a method this also includes all variables alive at the exit of the calls.
|
||||
* <p>
|
||||
* This method requires a number of other analysis to be present and updated in the (global) program - especailly the Call Graph.
|
||||
* </p>
|
||||
* @param statement The statement to examine
|
||||
* @return All variables alive at the statement
|
||||
*/
|
||||
private Collection<VariableRef> findAliveEffective(LiveRangeVariables liveRangeVariables, Statement statement) {
|
||||
// Get variables alive from live range analysis
|
||||
Collection<VariableRef> effectiveAlive = new LinkedHashSet<>();
|
||||
effectiveAlive.addAll(liveRangeVariables.getAlive(statement));
|
||||
// If the statement is inside a method recurse back to all calls
|
||||
// For each call add the variables alive after the call that are not referenced (used/defined) inside the method
|
||||
ControlFlowBlock block = getProgram().getGraph().getBlockFromStatementIdx(statement.getIndex());
|
||||
ScopeRef scopeRef = block.getScope();
|
||||
Scope scope = getProgram().getScope().getScope(scopeRef);
|
||||
if (scope instanceof Procedure) {
|
||||
Procedure procedure = (Procedure) scope;
|
||||
Collection<CallGraph.CallBlock.Call> callers =
|
||||
getProgram().getCallGraph().getCallers(procedure.getLabel().getRef());
|
||||
VariableReferenceInfo referenceInfo = new VariableReferenceInfo(getProgram());
|
||||
Collection<VariableRef> referencedInProcedure = referenceInfo.getReferenced(procedure.getRef().getLabelRef());
|
||||
for (CallGraph.CallBlock.Call caller : callers) {
|
||||
StatementCall callStatement =
|
||||
(StatementCall) getProgram().getGraph().getStatementByIndex(caller.getCallStatementIdx());
|
||||
Set<VariableRef> callAliveEffective = new LinkedHashSet<>(findAliveEffective(liveRangeVariables, callStatement));
|
||||
// Clear out any variables referenced in the method
|
||||
callAliveEffective.removeAll(referencedInProcedure);
|
||||
effectiveAlive.addAll(callAliveEffective);
|
||||
}
|
||||
}
|
||||
return effectiveAlive;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -64,7 +64,7 @@ public class Pass4AssertNoCpuClobber extends Pass2Base {
|
||||
}
|
||||
|
||||
// Find alive variables
|
||||
List<VariableRef> aliveVars = new ArrayList<>(getProgram().getLiveRangeVariables().getAliveEffective(statement));
|
||||
List<VariableRef> aliveVars = new ArrayList<>(getProgram().getLiveRangeVariablesEffective().getAliveEffective(statement));
|
||||
// Non-assigned alive variables must not be clobbered
|
||||
for (VariableRef aliveVar : aliveVars) {
|
||||
Variable variable = getProgram().getScope().getVariable(aliveVar);
|
||||
|
@ -220,7 +220,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
|
||||
Statement statement,
|
||||
LinkedHashMap<Registers.Register, LiveRangeEquivalenceClass> usedRegisters) {
|
||||
ProgramScope programScope = program.getScope();
|
||||
Collection<VariableRef> alive = program.getLiveRangeVariables().getAliveEffective(statement);
|
||||
Collection<VariableRef> alive = program.getLiveRangeVariablesEffective().getAliveEffective(statement);
|
||||
for (VariableRef varRef : alive) {
|
||||
Variable var = programScope.getVariable(varRef);
|
||||
Registers.Register allocation = var.getAllocation();
|
||||
|
@ -90,7 +90,7 @@ public class Pass4RegisterUpliftPotentialRegisterAnalysis extends Pass2Base {
|
||||
}
|
||||
|
||||
// For all non-assigned live variables: remove always clobbered registers from their potential allocation
|
||||
Collection<VariableRef> aliveVars = getProgram().getLiveRangeVariables().getAliveEffective(statement);
|
||||
Collection<VariableRef> aliveVars = getProgram().getLiveRangeVariablesEffective().getAliveEffective(statement);
|
||||
for (VariableRef aliveVar : aliveVars) {
|
||||
LiveRangeEquivalenceClass aliveClass = liveRangeEquivalenceClassSet.getEquivalenceClass(aliveVar);
|
||||
if (assignedClasses.contains(aliveClass)) {
|
||||
|
@ -56,8 +56,8 @@ public class TestCompilationOutput extends TestCase {
|
||||
compileAndCompare("bresenhamarr");
|
||||
}
|
||||
|
||||
public void testMinus() throws IOException, URISyntaxException {
|
||||
compileAndCompare("minus");
|
||||
public void testIterArray() throws IOException, URISyntaxException {
|
||||
compileAndCompare("iterarray");
|
||||
}
|
||||
|
||||
public void testLoopMin() throws IOException, URISyntaxException {
|
||||
|
10
src/main/java/dk/camelot64/kickc/test/iterarray.kc
Normal file
10
src/main/java/dk/camelot64/kickc/test/iterarray.kc
Normal file
@ -0,0 +1,10 @@
|
||||
main();
|
||||
|
||||
void main() {
|
||||
byte[16] buf = $1100;
|
||||
byte i = 5;
|
||||
do {
|
||||
buf[i] = 2+i+2;
|
||||
i = i+1;
|
||||
} while(i<10)
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
byte[16] p = $1100;
|
||||
byte i = 5;
|
||||
do {
|
||||
p[i] = 2+i+2;
|
||||
i = i+1;
|
||||
} while(i<10)
|
14
src/main/java/dk/camelot64/kickc/test/ref/iterarray.asm
Normal file
14
src/main/java/dk/camelot64/kickc/test/ref/iterarray.asm
Normal file
@ -0,0 +1,14 @@
|
||||
jsr main
|
||||
main: {
|
||||
.const buf = $1100
|
||||
ldx #5
|
||||
b1:
|
||||
txa
|
||||
clc
|
||||
adc #2+2
|
||||
sta buf,x
|
||||
inx
|
||||
cpx #$a
|
||||
bcc b1
|
||||
rts
|
||||
}
|
17
src/main/java/dk/camelot64/kickc/test/ref/iterarray.cfg
Normal file
17
src/main/java/dk/camelot64/kickc/test/ref/iterarray.cfg
Normal file
@ -0,0 +1,17 @@
|
||||
@begin: scope:[] from
|
||||
[0] call main param-assignment [ ]
|
||||
to:@end
|
||||
@end: scope:[] from @begin
|
||||
main: scope:[main] from @begin
|
||||
[1] phi() [ ]
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[2] (byte) main::i#2 ← phi( main/(byte) 5 main::@1/(byte) main::i#1 ) [ main::i#2 ]
|
||||
[3] (byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2 [ main::i#2 main::$1 ]
|
||||
[4] *((const byte[16]) main::buf#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ]
|
||||
[5] (byte) main::i#1 ← (byte) main::i#2 + (byte) 1 [ main::i#1 ]
|
||||
[6] if((byte) main::i#1<(byte) 10) goto main::@1 [ main::i#1 ]
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[7] return [ ]
|
||||
to:@return
|
803
src/main/java/dk/camelot64/kickc/test/ref/iterarray.log
Normal file
803
src/main/java/dk/camelot64/kickc/test/ref/iterarray.log
Normal file
@ -0,0 +1,803 @@
|
||||
main();
|
||||
|
||||
void main() {
|
||||
byte[16] buf = $1100;
|
||||
byte i = 5;
|
||||
do {
|
||||
buf[i] = 2+i+2;
|
||||
i = i+1;
|
||||
} while(i<10)
|
||||
}
|
||||
PROGRAM
|
||||
(void~) $0 ← call main
|
||||
proc (void()) main()
|
||||
(byte[16]) main::buf ← (word) 4352
|
||||
(byte) main::i ← (byte) 5
|
||||
main::@1:
|
||||
(byte~) main::$0 ← (byte) 2 + (byte) main::i
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2
|
||||
*((byte[16]) main::buf + (byte) main::i) ← (byte~) main::$1
|
||||
(byte~) main::$2 ← (byte) main::i + (byte) 1
|
||||
(byte) main::i ← (byte~) main::$2
|
||||
(boolean~) main::$3 ← (byte) main::i < (byte) 10
|
||||
if((boolean~) main::$3) goto main::@1
|
||||
main::@return:
|
||||
return
|
||||
endproc // main()
|
||||
|
||||
SYMBOLS
|
||||
(void~) $0
|
||||
(void()) main()
|
||||
(byte~) main::$0
|
||||
(byte~) main::$1
|
||||
(byte~) main::$2
|
||||
(boolean~) main::$3
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(byte[16]) main::buf
|
||||
(byte) main::i
|
||||
|
||||
INITIAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
(void~) $0 ← call main
|
||||
to:@1
|
||||
main: scope:[main] from
|
||||
(byte[16]) main::buf ← (word) 4352
|
||||
(byte) main::i ← (byte) 5
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte~) main::$0 ← (byte) 2 + (byte) main::i
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2
|
||||
*((byte[16]) main::buf + (byte) main::i) ← (byte~) main::$1
|
||||
(byte~) main::$2 ← (byte) main::i + (byte) 1
|
||||
(byte) main::i ← (byte~) main::$2
|
||||
(boolean~) main::$3 ← (byte) main::i < (byte) 10
|
||||
if((boolean~) main::$3) goto main::@1
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
Removing empty block main::@2
|
||||
Removing empty block @1
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
(void~) $0 ← call main
|
||||
to:@end
|
||||
main: scope:[main] from
|
||||
(byte[16]) main::buf ← (word) 4352
|
||||
(byte) main::i ← (byte) 5
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte~) main::$0 ← (byte) 2 + (byte) main::i
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2
|
||||
*((byte[16]) main::buf + (byte) main::i) ← (byte~) main::$1
|
||||
(byte~) main::$2 ← (byte) main::i + (byte) 1
|
||||
(byte) main::i ← (byte~) main::$2
|
||||
(boolean~) main::$3 ← (byte) main::i < (byte) 10
|
||||
if((boolean~) main::$3) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @begin
|
||||
|
||||
PROCEDURE MODIFY VARIABLE ANALYSIS
|
||||
|
||||
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@2
|
||||
@2: scope:[] from @begin
|
||||
to:@end
|
||||
main: scope:[main] from @begin
|
||||
(byte[16]) main::buf ← (word) 4352
|
||||
(byte) main::i ← (byte) 5
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte~) main::$0 ← (byte) 2 + (byte) main::i
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2
|
||||
*((byte[16]) main::buf + (byte) main::i) ← (byte~) main::$1
|
||||
(byte~) main::$2 ← (byte) main::i + (byte) 1
|
||||
(byte) main::i ← (byte~) main::$2
|
||||
(boolean~) main::$3 ← (byte) main::i < (byte) 10
|
||||
if((boolean~) main::$3) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @2
|
||||
|
||||
Completing Phi functions...
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@2
|
||||
@2: scope:[] from @begin
|
||||
to:@end
|
||||
main: scope:[main] from @begin
|
||||
(byte[16]) main::buf#0 ← (word) 4352
|
||||
(byte) main::i#0 ← (byte) 5
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte[16]) main::buf#1 ← phi( main/(byte[16]) main::buf#0 main::@1/(byte[16]) main::buf#1 )
|
||||
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
|
||||
(byte~) main::$0 ← (byte) 2 + (byte) main::i#2
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2
|
||||
*((byte[16]) main::buf#1 + (byte) main::i#2) ← (byte~) main::$1
|
||||
(byte~) main::$2 ← (byte) main::i#2 + (byte) 1
|
||||
(byte) main::i#1 ← (byte~) main::$2
|
||||
(boolean~) main::$3 ← (byte) main::i#1 < (byte) 10
|
||||
if((boolean~) main::$3) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @2
|
||||
|
||||
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@2
|
||||
@2: scope:[] from @begin
|
||||
to:@end
|
||||
main: scope:[main] from @begin
|
||||
(byte[16]) main::buf#0 ← (word) 4352
|
||||
(byte) main::i#0 ← (byte) 5
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte[16]) main::buf#1 ← phi( main/(byte[16]) main::buf#0 main::@1/(byte[16]) main::buf#1 )
|
||||
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
|
||||
(byte~) main::$0 ← (byte) 2 + (byte) main::i#2
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2
|
||||
*((byte[16]) main::buf#1 + (byte) main::i#2) ← (byte~) main::$1
|
||||
(byte~) main::$2 ← (byte) main::i#2 + (byte) 1
|
||||
(byte) main::i#1 ← (byte~) main::$2
|
||||
(boolean~) main::$3 ← (byte) main::i#1 < (byte) 10
|
||||
if((boolean~) main::$3) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @2
|
||||
|
||||
INITIAL SSA SYMBOL TABLE
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) main()
|
||||
(byte~) main::$0
|
||||
(byte~) main::$1
|
||||
(byte~) main::$2
|
||||
(boolean~) main::$3
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(byte[16]) main::buf
|
||||
(byte[16]) main::buf#0
|
||||
(byte[16]) main::buf#1
|
||||
(byte) main::i
|
||||
(byte) main::i#0
|
||||
(byte) main::i#1
|
||||
(byte) main::i#2
|
||||
|
||||
Culled Empty Block (label) @2
|
||||
Succesful SSA optimization Pass2CullEmptyBlocks
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@end
|
||||
main: scope:[main] from @begin
|
||||
(byte[16]) main::buf#0 ← (word) 4352
|
||||
(byte) main::i#0 ← (byte) 5
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte[16]) main::buf#1 ← phi( main/(byte[16]) main::buf#0 main::@1/(byte[16]) main::buf#1 )
|
||||
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
|
||||
(byte~) main::$0 ← (byte) 2 + (byte) main::i#2
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2
|
||||
*((byte[16]) main::buf#1 + (byte) main::i#2) ← (byte~) main::$1
|
||||
(byte~) main::$2 ← (byte) main::i#2 + (byte) 1
|
||||
(byte) main::i#1 ← (byte~) main::$2
|
||||
(boolean~) main::$3 ← (byte) main::i#1 < (byte) 10
|
||||
if((boolean~) main::$3) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @begin
|
||||
|
||||
Alias (byte) main::i#1 = (byte~) main::$2
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@end
|
||||
main: scope:[main] from @begin
|
||||
(byte[16]) main::buf#0 ← (word) 4352
|
||||
(byte) main::i#0 ← (byte) 5
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte[16]) main::buf#1 ← phi( main/(byte[16]) main::buf#0 main::@1/(byte[16]) main::buf#1 )
|
||||
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
|
||||
(byte~) main::$0 ← (byte) 2 + (byte) main::i#2
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2
|
||||
*((byte[16]) main::buf#1 + (byte) main::i#2) ← (byte~) main::$1
|
||||
(byte) main::i#1 ← (byte) main::i#2 + (byte) 1
|
||||
(boolean~) main::$3 ← (byte) main::i#1 < (byte) 10
|
||||
if((boolean~) main::$3) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @begin
|
||||
|
||||
Self Phi Eliminated (byte[16]) main::buf#1
|
||||
Succesful SSA optimization Pass2SelfPhiElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@end
|
||||
main: scope:[main] from @begin
|
||||
(byte[16]) main::buf#0 ← (word) 4352
|
||||
(byte) main::i#0 ← (byte) 5
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte[16]) main::buf#1 ← phi( main/(byte[16]) main::buf#0 )
|
||||
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
|
||||
(byte~) main::$0 ← (byte) 2 + (byte) main::i#2
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2
|
||||
*((byte[16]) main::buf#1 + (byte) main::i#2) ← (byte~) main::$1
|
||||
(byte) main::i#1 ← (byte) main::i#2 + (byte) 1
|
||||
(boolean~) main::$3 ← (byte) main::i#1 < (byte) 10
|
||||
if((boolean~) main::$3) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @begin
|
||||
|
||||
Simple Condition (boolean~) main::$3 if((byte) main::i#1<(byte) 10) goto main::@1
|
||||
Succesful SSA optimization Pass2ConditionalJumpSimplification
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@end
|
||||
main: scope:[main] from @begin
|
||||
(byte[16]) main::buf#0 ← (word) 4352
|
||||
(byte) main::i#0 ← (byte) 5
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte[16]) main::buf#1 ← phi( main/(byte[16]) main::buf#0 )
|
||||
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
|
||||
(byte~) main::$0 ← (byte) 2 + (byte) main::i#2
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2
|
||||
*((byte[16]) main::buf#1 + (byte) main::i#2) ← (byte~) main::$1
|
||||
(byte) main::i#1 ← (byte) main::i#2 + (byte) 1
|
||||
if((byte) main::i#1<(byte) 10) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @begin
|
||||
|
||||
Constant (const byte[16]) main::buf#0 = 4352
|
||||
Constant (const byte) main::i#0 = 5
|
||||
Succesful SSA optimization Pass2ConstantIdentification
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@end
|
||||
main: scope:[main] from @begin
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte[16]) main::buf#1 ← phi( main/(const byte[16]) main::buf#0 )
|
||||
(byte) main::i#2 ← phi( main/(const byte) main::i#0 main::@1/(byte) main::i#1 )
|
||||
(byte~) main::$0 ← (byte) 2 + (byte) main::i#2
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2
|
||||
*((byte[16]) main::buf#1 + (byte) main::i#2) ← (byte~) main::$1
|
||||
(byte) main::i#1 ← (byte) main::i#2 + (byte) 1
|
||||
if((byte) main::i#1<(byte) 10) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @begin
|
||||
|
||||
Constant (const byte[16]) main::buf#1 = main::buf#0
|
||||
Succesful SSA optimization Pass2ConstantIdentification
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@end
|
||||
main: scope:[main] from @begin
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte) main::i#2 ← phi( main/(const byte) main::i#0 main::@1/(byte) main::i#1 )
|
||||
(byte~) main::$0 ← (byte) 2 + (byte) main::i#2
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2
|
||||
*((const byte[16]) main::buf#1 + (byte) main::i#2) ← (byte~) main::$1
|
||||
(byte) main::i#1 ← (byte) main::i#2 + (byte) 1
|
||||
if((byte) main::i#1<(byte) 10) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @begin
|
||||
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2
|
||||
Consolidated constant in assignment main::$1
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2
|
||||
Succesful SSA optimization Pass2ConstantAdditionElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@end
|
||||
main: scope:[main] from @begin
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte) main::i#2 ← phi( main/(const byte) main::i#0 main::@1/(byte) main::i#1 )
|
||||
(byte~) main::$0 ← (byte) main::i#2
|
||||
(byte~) main::$1 ← (byte~) main::$0 + (byte) 2+(byte) 2
|
||||
*((const byte[16]) main::buf#1 + (byte) main::i#2) ← (byte~) main::$1
|
||||
(byte) main::i#1 ← (byte) main::i#2 + (byte) 1
|
||||
if((byte) main::i#1<(byte) 10) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @begin
|
||||
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2
|
||||
Alias (byte) main::i#2 = (byte~) main::$0
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@end
|
||||
main: scope:[main] from @begin
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte) main::i#2 ← phi( main/(const byte) main::i#0 main::@1/(byte) main::i#1 )
|
||||
(byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2
|
||||
*((const byte[16]) main::buf#1 + (byte) main::i#2) ← (byte~) main::$1
|
||||
(byte) main::i#1 ← (byte) main::i#2 + (byte) 1
|
||||
if((byte) main::i#1<(byte) 10) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @begin
|
||||
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2
|
||||
Constant inlined main::buf#1 = (const byte[16]) main::buf#0
|
||||
Constant inlined main::i#0 = (byte) 5
|
||||
Succesful SSA optimization Pass2ConstantInlining
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@end
|
||||
main: scope:[main] from @begin
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte) main::i#2 ← phi( main/(byte) 5 main::@1/(byte) main::i#1 )
|
||||
(byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2
|
||||
*((const byte[16]) main::buf#0 + (byte) main::i#2) ← (byte~) main::$1
|
||||
(byte) main::i#1 ← (byte) main::i#2 + (byte) 1
|
||||
if((byte) main::i#1<(byte) 10) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@end: scope:[] from @begin
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) main()
|
||||
(byte~) main::$1
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(byte[16]) main::buf
|
||||
(const byte[16]) main::buf#0 = (word) 4352
|
||||
(byte) main::i
|
||||
(byte) main::i#1
|
||||
(byte) main::i#2
|
||||
|
||||
Block Sequence Planned @begin @end main main::@1 main::@return
|
||||
Added new block during phi lifting main::@3(between main::@1 and main::@1)
|
||||
Block Sequence Planned @begin @end main main::@1 main::@return main::@3
|
||||
CONTROL FLOW GRAPH - PHI LIFTED
|
||||
@begin: scope:[] from
|
||||
call main param-assignment
|
||||
to:@end
|
||||
@end: scope:[] from @begin
|
||||
main: scope:[main] from @begin
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@3
|
||||
(byte) main::i#2 ← phi( main/(byte) 5 main::@3/(byte~) main::i#3 )
|
||||
(byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2
|
||||
*((const byte[16]) main::buf#0 + (byte) main::i#2) ← (byte~) main::$1
|
||||
(byte) main::i#1 ← (byte) main::i#2 + (byte) 1
|
||||
if((byte) main::i#1<(byte) 10) goto main::@3
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
main::@3: scope:[main] from main::@1
|
||||
(byte~) main::i#3 ← (byte) main::i#1
|
||||
to:main::@1
|
||||
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
Calls in [] to 0:main
|
||||
|
||||
Propagating live ranges...
|
||||
Propagating live ranges...
|
||||
CONTROL FLOW GRAPH - LIVE RANGES FOUND
|
||||
@begin: scope:[] from
|
||||
[0] call main param-assignment [ ]
|
||||
to:@end
|
||||
@end: scope:[] from @begin
|
||||
main: scope:[main] from @begin
|
||||
[1] phi() [ ]
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@3
|
||||
[2] (byte) main::i#2 ← phi( main/(byte) 5 main::@3/(byte~) main::i#3 ) [ main::i#2 ]
|
||||
[3] (byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2 [ main::i#2 main::$1 ]
|
||||
[4] *((const byte[16]) main::buf#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ]
|
||||
[5] (byte) main::i#1 ← (byte) main::i#2 + (byte) 1 [ main::i#1 ]
|
||||
[6] if((byte) main::i#1<(byte) 10) goto main::@3 [ main::i#1 ]
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[7] return [ ]
|
||||
to:@return
|
||||
main::@3: scope:[main] from main::@1
|
||||
[8] (byte~) main::i#3 ← (byte) main::i#1 [ main::i#3 ]
|
||||
to:main::@1
|
||||
|
||||
Created 1 initial phi equivalence classes
|
||||
Coalesced [8] main::i#3 ← main::i#1
|
||||
Coalesced down to 1 phi equivalence classes
|
||||
Culled Empty Block (label) main::@3
|
||||
Block Sequence Planned @begin @end main main::@1 main::@return
|
||||
Adding NOP phi() at start of main
|
||||
Propagating live ranges...
|
||||
Propagating live ranges...
|
||||
CONTROL FLOW GRAPH - PHI MEM COALESCED
|
||||
@begin: scope:[] from
|
||||
[0] call main param-assignment [ ]
|
||||
to:@end
|
||||
@end: scope:[] from @begin
|
||||
main: scope:[main] from @begin
|
||||
[1] phi() [ ]
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[2] (byte) main::i#2 ← phi( main/(byte) 5 main::@1/(byte) main::i#1 ) [ main::i#2 ]
|
||||
[3] (byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2 [ main::i#2 main::$1 ]
|
||||
[4] *((const byte[16]) main::buf#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ]
|
||||
[5] (byte) main::i#1 ← (byte) main::i#2 + (byte) 1 [ main::i#1 ]
|
||||
[6] if((byte) main::i#1<(byte) 10) goto main::@1 [ main::i#1 ]
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[7] return [ ]
|
||||
to:@return
|
||||
|
||||
DOMINATORS
|
||||
@begin dominated by @begin
|
||||
@end dominated by @end @begin
|
||||
main dominated by @begin main
|
||||
main::@1 dominated by @begin main::@1 main
|
||||
main::@return dominated by main::@return @begin main::@1 main
|
||||
|
||||
Found back edge: Loop head: main::@1 tails: main::@1 blocks: null
|
||||
Populated: Loop head: main::@1 tails: main::@1 blocks: main::@1
|
||||
NATURAL LOOPS
|
||||
Loop head: main::@1 tails: main::@1 blocks: main::@1
|
||||
|
||||
Found 0 loops in scope []
|
||||
Found 1 loops in scope [main]
|
||||
Loop head: main::@1 tails: main::@1 blocks: main::@1
|
||||
NATURAL LOOPS WITH DEPTH
|
||||
Loop head: main::@1 tails: main::@1 blocks: main::@1 depth: 1
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(void()) main()
|
||||
(byte~) main::$1 22.0
|
||||
(byte[16]) main::buf
|
||||
(byte) main::i
|
||||
(byte) main::i#1 16.5
|
||||
(byte) main::i#2 14.666666666666666
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
Added variable main::$1 to zero page equivalence class [ main::$1 ]
|
||||
Complete equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ main::$1 ]
|
||||
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Allocated zp ZP_BYTE:3 [ main::$1 ]
|
||||
INITIAL ASM
|
||||
//SEG0 Global Constants & labels
|
||||
//SEG1 @begin
|
||||
bbegin:
|
||||
//SEG2 [0] call main param-assignment [ ]
|
||||
//SEG3 [1] phi from @begin to main
|
||||
main_from_bbegin:
|
||||
jsr main
|
||||
jmp bend
|
||||
//SEG4 @end
|
||||
bend:
|
||||
//SEG5 main
|
||||
main: {
|
||||
.const buf = $1100
|
||||
.label _1 = 3
|
||||
.label i = 2
|
||||
//SEG6 [2] phi from main to main::@1
|
||||
b1_from_main:
|
||||
//SEG7 [2] phi (byte) main::i#2 = (byte) 5 -- zpby1=coby1
|
||||
lda #5
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG8 [2] phi from main::@1 to main::@1
|
||||
b1_from_b1:
|
||||
//SEG9 [2] phi (byte) main::i#2 = (byte) main::i#1 -- register_copy
|
||||
jmp b1
|
||||
//SEG10 main::@1
|
||||
b1:
|
||||
//SEG11 [3] (byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2 [ main::i#2 main::$1 ] -- zpby1=zpby2_plus_coby1
|
||||
lda i
|
||||
clc
|
||||
adc #2+2
|
||||
sta _1
|
||||
//SEG12 [4] *((const byte[16]) main::buf#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] -- cowo1_staridx_zpby1=zpby2
|
||||
lda _1
|
||||
ldx i
|
||||
sta buf,x
|
||||
//SEG13 [5] (byte) main::i#1 ← (byte) main::i#2 + (byte) 1 [ main::i#1 ] -- zpby1=zpby1_plus_1
|
||||
inc i
|
||||
//SEG14 [6] if((byte) main::i#1<(byte) 10) goto main::@1 [ main::i#1 ] -- zpby1_lt_coby1_then_la1
|
||||
lda i
|
||||
cmp #$a
|
||||
bcc b1_from_b1
|
||||
jmp breturn
|
||||
//SEG15 main::@return
|
||||
breturn:
|
||||
//SEG16 [7] return [ ]
|
||||
rts
|
||||
}
|
||||
|
||||
Statement [3] (byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2 [ main::i#2 main::$1 ] always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Statement [3] (byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2 [ main::i#2 main::$1 ] always clobbers reg byte a
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:3 [ main::$1 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 31.17: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 22: zp ZP_BYTE:3 [ main::$1 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 300 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$1 ]
|
||||
Uplifting [] best 300 combination
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
ASSEMBLER
|
||||
//SEG0 Global Constants & labels
|
||||
//SEG1 @begin
|
||||
bbegin:
|
||||
//SEG2 [0] call main param-assignment [ ]
|
||||
//SEG3 [1] phi from @begin to main
|
||||
main_from_bbegin:
|
||||
jsr main
|
||||
//SEG4 @end
|
||||
bend:
|
||||
//SEG5 main
|
||||
main: {
|
||||
.const buf = $1100
|
||||
//SEG6 [2] phi from main to main::@1
|
||||
b1_from_main:
|
||||
//SEG7 [2] phi (byte) main::i#2 = (byte) 5 -- xby=coby1
|
||||
ldx #5
|
||||
jmp b1
|
||||
//SEG8 [2] phi from main::@1 to main::@1
|
||||
b1_from_b1:
|
||||
//SEG9 [2] phi (byte) main::i#2 = (byte) main::i#1 -- register_copy
|
||||
//SEG10 main::@1
|
||||
b1:
|
||||
//SEG11 [3] (byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2 [ main::i#2 main::$1 ] -- aby=xby_plus_coby1
|
||||
txa
|
||||
clc
|
||||
adc #2+2
|
||||
//SEG12 [4] *((const byte[16]) main::buf#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] -- cowo1_staridx_xby=aby
|
||||
sta buf,x
|
||||
//SEG13 [5] (byte) main::i#1 ← (byte) main::i#2 + (byte) 1 [ main::i#1 ] -- xby=xby_plus_1
|
||||
inx
|
||||
//SEG14 [6] if((byte) main::i#1<(byte) 10) goto main::@1 [ main::i#1 ] -- xby_lt_coby1_then_la1
|
||||
cpx #$a
|
||||
bcc b1_from_b1
|
||||
//SEG15 main::@return
|
||||
breturn:
|
||||
//SEG16 [7] return [ ]
|
||||
rts
|
||||
}
|
||||
|
||||
Replacing label b1_from_b1 with b1
|
||||
Removing instruction main_from_bbegin:
|
||||
Removing instruction b1_from_b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
ASSEMBLER
|
||||
//SEG0 Global Constants & labels
|
||||
//SEG1 @begin
|
||||
bbegin:
|
||||
//SEG2 [0] call main param-assignment [ ]
|
||||
//SEG3 [1] phi from @begin to main
|
||||
jsr main
|
||||
//SEG4 @end
|
||||
bend:
|
||||
//SEG5 main
|
||||
main: {
|
||||
.const buf = $1100
|
||||
//SEG6 [2] phi from main to main::@1
|
||||
b1_from_main:
|
||||
//SEG7 [2] phi (byte) main::i#2 = (byte) 5 -- xby=coby1
|
||||
ldx #5
|
||||
jmp b1
|
||||
//SEG8 [2] phi from main::@1 to main::@1
|
||||
//SEG9 [2] phi (byte) main::i#2 = (byte) main::i#1 -- register_copy
|
||||
//SEG10 main::@1
|
||||
b1:
|
||||
//SEG11 [3] (byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2 [ main::i#2 main::$1 ] -- aby=xby_plus_coby1
|
||||
txa
|
||||
clc
|
||||
adc #2+2
|
||||
//SEG12 [4] *((const byte[16]) main::buf#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] -- cowo1_staridx_xby=aby
|
||||
sta buf,x
|
||||
//SEG13 [5] (byte) main::i#1 ← (byte) main::i#2 + (byte) 1 [ main::i#1 ] -- xby=xby_plus_1
|
||||
inx
|
||||
//SEG14 [6] if((byte) main::i#1<(byte) 10) goto main::@1 [ main::i#1 ] -- xby_lt_coby1_then_la1
|
||||
cpx #$a
|
||||
bcc b1
|
||||
//SEG15 main::@return
|
||||
breturn:
|
||||
//SEG16 [7] return [ ]
|
||||
rts
|
||||
}
|
||||
|
||||
Removing instruction bbegin:
|
||||
Removing instruction bend:
|
||||
Removing instruction b1_from_main:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
ASSEMBLER
|
||||
//SEG0 Global Constants & labels
|
||||
//SEG1 @begin
|
||||
//SEG2 [0] call main param-assignment [ ]
|
||||
//SEG3 [1] phi from @begin to main
|
||||
jsr main
|
||||
//SEG4 @end
|
||||
//SEG5 main
|
||||
main: {
|
||||
.const buf = $1100
|
||||
//SEG6 [2] phi from main to main::@1
|
||||
//SEG7 [2] phi (byte) main::i#2 = (byte) 5 -- xby=coby1
|
||||
ldx #5
|
||||
jmp b1
|
||||
//SEG8 [2] phi from main::@1 to main::@1
|
||||
//SEG9 [2] phi (byte) main::i#2 = (byte) main::i#1 -- register_copy
|
||||
//SEG10 main::@1
|
||||
b1:
|
||||
//SEG11 [3] (byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2 [ main::i#2 main::$1 ] -- aby=xby_plus_coby1
|
||||
txa
|
||||
clc
|
||||
adc #2+2
|
||||
//SEG12 [4] *((const byte[16]) main::buf#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] -- cowo1_staridx_xby=aby
|
||||
sta buf,x
|
||||
//SEG13 [5] (byte) main::i#1 ← (byte) main::i#2 + (byte) 1 [ main::i#1 ] -- xby=xby_plus_1
|
||||
inx
|
||||
//SEG14 [6] if((byte) main::i#1<(byte) 10) goto main::@1 [ main::i#1 ] -- xby_lt_coby1_then_la1
|
||||
cpx #$a
|
||||
bcc b1
|
||||
//SEG15 main::@return
|
||||
//SEG16 [7] return [ ]
|
||||
rts
|
||||
}
|
||||
|
||||
Removing instruction jmp b1
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
ASSEMBLER
|
||||
//SEG0 Global Constants & labels
|
||||
//SEG1 @begin
|
||||
//SEG2 [0] call main param-assignment [ ]
|
||||
//SEG3 [1] phi from @begin to main
|
||||
jsr main
|
||||
//SEG4 @end
|
||||
//SEG5 main
|
||||
main: {
|
||||
.const buf = $1100
|
||||
//SEG6 [2] phi from main to main::@1
|
||||
//SEG7 [2] phi (byte) main::i#2 = (byte) 5 -- xby=coby1
|
||||
ldx #5
|
||||
//SEG8 [2] phi from main::@1 to main::@1
|
||||
//SEG9 [2] phi (byte) main::i#2 = (byte) main::i#1 -- register_copy
|
||||
//SEG10 main::@1
|
||||
b1:
|
||||
//SEG11 [3] (byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2 [ main::i#2 main::$1 ] -- aby=xby_plus_coby1
|
||||
txa
|
||||
clc
|
||||
adc #2+2
|
||||
//SEG12 [4] *((const byte[16]) main::buf#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] -- cowo1_staridx_xby=aby
|
||||
sta buf,x
|
||||
//SEG13 [5] (byte) main::i#1 ← (byte) main::i#2 + (byte) 1 [ main::i#1 ] -- xby=xby_plus_1
|
||||
inx
|
||||
//SEG14 [6] if((byte) main::i#1<(byte) 10) goto main::@1 [ main::i#1 ] -- xby_lt_coby1_then_la1
|
||||
cpx #$a
|
||||
bcc b1
|
||||
//SEG15 main::@return
|
||||
//SEG16 [7] return [ ]
|
||||
rts
|
||||
}
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) main()
|
||||
(byte~) main::$1 reg byte a 22.0
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(byte[16]) main::buf
|
||||
(const byte[16]) main::buf#0 = (word) 4352
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 16.5
|
||||
(byte) main::i#2 reg byte x 14.666666666666666
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
reg byte a [ main::$1 ]
|
||||
|
||||
FINAL CODE
|
||||
//SEG0 Global Constants & labels
|
||||
//SEG1 @begin
|
||||
//SEG2 [0] call main param-assignment [ ]
|
||||
//SEG3 [1] phi from @begin to main
|
||||
jsr main
|
||||
//SEG4 @end
|
||||
//SEG5 main
|
||||
main: {
|
||||
.const buf = $1100
|
||||
//SEG6 [2] phi from main to main::@1
|
||||
//SEG7 [2] phi (byte) main::i#2 = (byte) 5 -- xby=coby1
|
||||
ldx #5
|
||||
//SEG8 [2] phi from main::@1 to main::@1
|
||||
//SEG9 [2] phi (byte) main::i#2 = (byte) main::i#1 -- register_copy
|
||||
//SEG10 main::@1
|
||||
b1:
|
||||
//SEG11 [3] (byte~) main::$1 ← (byte) main::i#2 + (byte) 2+(byte) 2 [ main::i#2 main::$1 ] -- aby=xby_plus_coby1
|
||||
txa
|
||||
clc
|
||||
adc #2+2
|
||||
//SEG12 [4] *((const byte[16]) main::buf#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] -- cowo1_staridx_xby=aby
|
||||
sta buf,x
|
||||
//SEG13 [5] (byte) main::i#1 ← (byte) main::i#2 + (byte) 1 [ main::i#1 ] -- xby=xby_plus_1
|
||||
inx
|
||||
//SEG14 [6] if((byte) main::i#1<(byte) 10) goto main::@1 [ main::i#1 ] -- xby_lt_coby1_then_la1
|
||||
cpx #$a
|
||||
bcc b1
|
||||
//SEG15 main::@return
|
||||
//SEG16 [7] return [ ]
|
||||
rts
|
||||
}
|
||||
|
14
src/main/java/dk/camelot64/kickc/test/ref/iterarray.sym
Normal file
14
src/main/java/dk/camelot64/kickc/test/ref/iterarray.sym
Normal file
@ -0,0 +1,14 @@
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(void()) main()
|
||||
(byte~) main::$1 reg byte a 22.0
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(byte[16]) main::buf
|
||||
(const byte[16]) main::buf#0 = (word) 4352
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 16.5
|
||||
(byte) main::i#2 reg byte x 14.666666666666666
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
reg byte a [ main::$1 ]
|
@ -1,10 +0,0 @@
|
||||
.const p = $1100
|
||||
ldx #5
|
||||
b1:
|
||||
txa
|
||||
clc
|
||||
adc #2+2
|
||||
sta p,x
|
||||
inx
|
||||
cpx #$a
|
||||
bcc b1
|
@ -1,10 +0,0 @@
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
[0] (byte) i#2 ← phi( @1/(byte) i#1 @begin/(byte) 5 ) [ i#2 ]
|
||||
[1] (byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2 [ i#2 $1 ]
|
||||
[2] *((const byte[16]) p#0 + (byte) i#2) ← (byte~) $1 [ i#2 ]
|
||||
[3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ]
|
||||
[4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ]
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
@ -1,579 +0,0 @@
|
||||
byte[16] p = $1100;
|
||||
byte i = 5;
|
||||
do {
|
||||
p[i] = 2+i+2;
|
||||
i = i+1;
|
||||
} while(i<10)
|
||||
|
||||
PROGRAM
|
||||
(byte[16]) p ← (word) 4352
|
||||
(byte) i ← (byte) 5
|
||||
@1:
|
||||
(byte~) $0 ← (byte) 2 + (byte) i
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p + (byte) i) ← (byte~) $1
|
||||
(byte~) $2 ← (byte) i + (byte) 1
|
||||
(byte) i ← (byte~) $2
|
||||
(boolean~) $3 ← (byte) i < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
|
||||
SYMBOLS
|
||||
(byte~) $0
|
||||
(byte~) $1
|
||||
(byte~) $2
|
||||
(boolean~) $3
|
||||
(label) @1
|
||||
(byte) i
|
||||
(byte[16]) p
|
||||
|
||||
INITIAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
(byte[16]) p ← (word) 4352
|
||||
(byte) i ← (byte) 5
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte~) $0 ← (byte) 2 + (byte) i
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p + (byte) i) ← (byte~) $1
|
||||
(byte~) $2 ← (byte) i + (byte) 1
|
||||
(byte) i ← (byte~) $2
|
||||
(boolean~) $3 ← (byte) i < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
Removing empty block @2
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
(byte[16]) p ← (word) 4352
|
||||
(byte) i ← (byte) 5
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte~) $0 ← (byte) 2 + (byte) i
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p + (byte) i) ← (byte~) $1
|
||||
(byte~) $2 ← (byte) i + (byte) 1
|
||||
(byte) i ← (byte~) $2
|
||||
(boolean~) $3 ← (byte) i < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
PROCEDURE MODIFY VARIABLE ANALYSIS
|
||||
|
||||
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL
|
||||
@begin: scope:[] from
|
||||
(byte[16]) p ← (word) 4352
|
||||
(byte) i ← (byte) 5
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte~) $0 ← (byte) 2 + (byte) i
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p + (byte) i) ← (byte~) $1
|
||||
(byte~) $2 ← (byte) i + (byte) 1
|
||||
(byte) i ← (byte~) $2
|
||||
(boolean~) $3 ← (byte) i < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
Completing Phi functions...
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte[16]) p#0 ← (word) 4352
|
||||
(byte) i#0 ← (byte) 5
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte[16]) p#1 ← phi( @1/(byte[16]) p#1 @begin/(byte[16]) p#0 )
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @begin/(byte) i#0 )
|
||||
(byte~) $0 ← (byte) 2 + (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p#1 + (byte) i#2) ← (byte~) $1
|
||||
(byte~) $2 ← (byte) i#2 + (byte) 1
|
||||
(byte) i#1 ← (byte~) $2
|
||||
(boolean~) $3 ← (byte) i#1 < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN
|
||||
@begin: scope:[] from
|
||||
(byte[16]) p#0 ← (word) 4352
|
||||
(byte) i#0 ← (byte) 5
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte[16]) p#1 ← phi( @1/(byte[16]) p#1 @begin/(byte[16]) p#0 )
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @begin/(byte) i#0 )
|
||||
(byte~) $0 ← (byte) 2 + (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p#1 + (byte) i#2) ← (byte~) $1
|
||||
(byte~) $2 ← (byte) i#2 + (byte) 1
|
||||
(byte) i#1 ← (byte~) $2
|
||||
(boolean~) $3 ← (byte) i#1 < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
INITIAL SSA SYMBOL TABLE
|
||||
(byte~) $0
|
||||
(byte~) $1
|
||||
(byte~) $2
|
||||
(boolean~) $3
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte) i
|
||||
(byte) i#0
|
||||
(byte) i#1
|
||||
(byte) i#2
|
||||
(byte[16]) p
|
||||
(byte[16]) p#0
|
||||
(byte[16]) p#1
|
||||
|
||||
Alias (byte) i#1 = (byte~) $2
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
(byte[16]) p#0 ← (word) 4352
|
||||
(byte) i#0 ← (byte) 5
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte[16]) p#1 ← phi( @1/(byte[16]) p#1 @begin/(byte[16]) p#0 )
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @begin/(byte) i#0 )
|
||||
(byte~) $0 ← (byte) 2 + (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p#1 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
(boolean~) $3 ← (byte) i#1 < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
Self Phi Eliminated (byte[16]) p#1
|
||||
Succesful SSA optimization Pass2SelfPhiElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
(byte[16]) p#0 ← (word) 4352
|
||||
(byte) i#0 ← (byte) 5
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte[16]) p#1 ← phi( @begin/(byte[16]) p#0 )
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @begin/(byte) i#0 )
|
||||
(byte~) $0 ← (byte) 2 + (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p#1 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
(boolean~) $3 ← (byte) i#1 < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
Simple Condition (boolean~) $3 if((byte) i#1<(byte) 10) goto @1
|
||||
Succesful SSA optimization Pass2ConditionalJumpSimplification
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
(byte[16]) p#0 ← (word) 4352
|
||||
(byte) i#0 ← (byte) 5
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte[16]) p#1 ← phi( @begin/(byte[16]) p#0 )
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @begin/(byte) i#0 )
|
||||
(byte~) $0 ← (byte) 2 + (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p#1 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
if((byte) i#1<(byte) 10) goto @1
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
Constant (const byte[16]) p#0 = 4352
|
||||
Constant (const byte) i#0 = 5
|
||||
Succesful SSA optimization Pass2ConstantIdentification
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte[16]) p#1 ← phi( @begin/(const byte[16]) p#0 )
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @begin/(const byte) i#0 )
|
||||
(byte~) $0 ← (byte) 2 + (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p#1 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
if((byte) i#1<(byte) 10) goto @1
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
Constant (const byte[16]) p#1 = p#0
|
||||
Succesful SSA optimization Pass2ConstantIdentification
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @begin/(const byte) i#0 )
|
||||
(byte~) $0 ← (byte) 2 + (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((const byte[16]) p#1 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
if((byte) i#1<(byte) 10) goto @1
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Consolidated constant in assignment $1
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Succesful SSA optimization Pass2ConstantAdditionElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @begin/(const byte) i#0 )
|
||||
(byte~) $0 ← (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2+(byte) 2
|
||||
*((const byte[16]) p#1 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
if((byte) i#1<(byte) 10) goto @1
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Alias (byte) i#2 = (byte~) $0
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @begin/(const byte) i#0 )
|
||||
(byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2
|
||||
*((const byte[16]) p#1 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
if((byte) i#1<(byte) 10) goto @1
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Constant inlined p#1 = (const byte[16]) p#0
|
||||
Constant inlined i#0 = (byte) 5
|
||||
Succesful SSA optimization Pass2ConstantInlining
|
||||
CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @begin/(byte) 5 )
|
||||
(byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2
|
||||
*((const byte[16]) p#0 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
if((byte) i#1<(byte) 10) goto @1
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(byte~) $1
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte) i
|
||||
(byte) i#1
|
||||
(byte) i#2
|
||||
(byte[16]) p
|
||||
(const byte[16]) p#0 = (word) 4352
|
||||
|
||||
Block Sequence Planned @begin @1 @end
|
||||
Added new block during phi lifting @3(between @1 and @1)
|
||||
Block Sequence Planned @begin @1 @end @3
|
||||
CONTROL FLOW GRAPH - PHI LIFTED
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
@1: scope:[] from @3 @begin
|
||||
(byte) i#2 ← phi( @3/(byte~) i#3 @begin/(byte) 5 )
|
||||
(byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2
|
||||
*((const byte[16]) p#0 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
if((byte) i#1<(byte) 10) goto @3
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
@3: scope:[] from @1
|
||||
(byte~) i#3 ← (byte) i#1
|
||||
to:@1
|
||||
|
||||
CALL GRAPH
|
||||
|
||||
Propagating live ranges...
|
||||
Propagating live ranges...
|
||||
CONTROL FLOW GRAPH - LIVE RANGES FOUND
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
@1: scope:[] from @3 @begin
|
||||
[0] (byte) i#2 ← phi( @3/(byte~) i#3 @begin/(byte) 5 ) [ i#2 ]
|
||||
[1] (byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2 [ i#2 $1 ]
|
||||
[2] *((const byte[16]) p#0 + (byte) i#2) ← (byte~) $1 [ i#2 ]
|
||||
[3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ]
|
||||
[4] if((byte) i#1<(byte) 10) goto @3 [ i#1 ]
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
@3: scope:[] from @1
|
||||
[5] (byte~) i#3 ← (byte) i#1 [ i#3 ]
|
||||
to:@1
|
||||
|
||||
Created 1 initial phi equivalence classes
|
||||
Coalesced [5] i#3 ← i#1
|
||||
Coalesced down to 1 phi equivalence classes
|
||||
Culled Empty Block (label) @3
|
||||
Block Sequence Planned @begin @1 @end
|
||||
Propagating live ranges...
|
||||
Propagating live ranges...
|
||||
CONTROL FLOW GRAPH - PHI MEM COALESCED
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
@1: scope:[] from @1 @begin
|
||||
[0] (byte) i#2 ← phi( @1/(byte) i#1 @begin/(byte) 5 ) [ i#2 ]
|
||||
[1] (byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2 [ i#2 $1 ]
|
||||
[2] *((const byte[16]) p#0 + (byte) i#2) ← (byte~) $1 [ i#2 ]
|
||||
[3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ]
|
||||
[4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ]
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
|
||||
DOMINATORS
|
||||
@begin dominated by @begin
|
||||
@1 dominated by @1 @begin
|
||||
@end dominated by @1 @end @begin
|
||||
|
||||
Found back edge: Loop head: @1 tails: @1 blocks: null
|
||||
Populated: Loop head: @1 tails: @1 blocks: @1
|
||||
NATURAL LOOPS
|
||||
Loop head: @1 tails: @1 blocks: @1
|
||||
|
||||
Found 1 loops in scope []
|
||||
Loop head: @1 tails: @1 blocks: @1
|
||||
NATURAL LOOPS WITH DEPTH
|
||||
Loop head: @1 tails: @1 blocks: @1 depth: 1
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte~) $1 22.0
|
||||
(byte) i
|
||||
(byte) i#1 16.5
|
||||
(byte) i#2 14.666666666666666
|
||||
(byte[16]) p
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ i#2 i#1 ]
|
||||
Added variable $1 to zero page equivalence class [ $1 ]
|
||||
Complete equivalence classes
|
||||
[ i#2 i#1 ]
|
||||
[ $1 ]
|
||||
Allocated zp ZP_BYTE:2 [ i#2 i#1 ]
|
||||
Allocated zp ZP_BYTE:3 [ $1 ]
|
||||
INITIAL ASM
|
||||
//SEG0 Global Constants & labels
|
||||
.const p = $1100
|
||||
.label _1 = 3
|
||||
.label i = 2
|
||||
//SEG1 @begin
|
||||
bbegin:
|
||||
//SEG2 [0] phi from @begin to @1
|
||||
b1_from_bbegin:
|
||||
//SEG3 [0] phi (byte) i#2 = (byte) 5 -- zpby1=coby1
|
||||
lda #5
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG4 [0] phi from @1 to @1
|
||||
b1_from_b1:
|
||||
//SEG5 [0] phi (byte) i#2 = (byte) i#1 -- register_copy
|
||||
jmp b1
|
||||
//SEG6 @1
|
||||
b1:
|
||||
//SEG7 [1] (byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2 [ i#2 $1 ] -- zpby1=zpby2_plus_coby1
|
||||
lda i
|
||||
clc
|
||||
adc #2+2
|
||||
sta _1
|
||||
//SEG8 [2] *((const byte[16]) p#0 + (byte) i#2) ← (byte~) $1 [ i#2 ] -- cowo1_staridx_zpby1=zpby2
|
||||
lda _1
|
||||
ldx i
|
||||
sta p,x
|
||||
//SEG9 [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] -- zpby1=zpby1_plus_1
|
||||
inc i
|
||||
//SEG10 [4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] -- zpby1_lt_coby1_then_la1
|
||||
lda i
|
||||
cmp #$a
|
||||
bcc b1_from_b1
|
||||
jmp bend
|
||||
//SEG11 @end
|
||||
bend:
|
||||
|
||||
Statement [1] (byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2 [ i#2 $1 ] always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ i#2 i#1 ]
|
||||
Statement [1] (byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2 [ i#2 $1 ] always clobbers reg byte a
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Potential registers zp ZP_BYTE:2 [ i#2 i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:3 [ $1 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [] 31.17: zp ZP_BYTE:2 [ i#2 i#1 ] 22: zp ZP_BYTE:3 [ $1 ]
|
||||
|
||||
Uplifting [] best 285 combination reg byte x [ i#2 i#1 ] reg byte a [ $1 ]
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
ASSEMBLER
|
||||
//SEG0 Global Constants & labels
|
||||
.const p = $1100
|
||||
//SEG1 @begin
|
||||
bbegin:
|
||||
//SEG2 [0] phi from @begin to @1
|
||||
b1_from_bbegin:
|
||||
//SEG3 [0] phi (byte) i#2 = (byte) 5 -- xby=coby1
|
||||
ldx #5
|
||||
jmp b1
|
||||
//SEG4 [0] phi from @1 to @1
|
||||
b1_from_b1:
|
||||
//SEG5 [0] phi (byte) i#2 = (byte) i#1 -- register_copy
|
||||
//SEG6 @1
|
||||
b1:
|
||||
//SEG7 [1] (byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2 [ i#2 $1 ] -- aby=xby_plus_coby1
|
||||
txa
|
||||
clc
|
||||
adc #2+2
|
||||
//SEG8 [2] *((const byte[16]) p#0 + (byte) i#2) ← (byte~) $1 [ i#2 ] -- cowo1_staridx_xby=aby
|
||||
sta p,x
|
||||
//SEG9 [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] -- xby=xby_plus_1
|
||||
inx
|
||||
//SEG10 [4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] -- xby_lt_coby1_then_la1
|
||||
cpx #$a
|
||||
bcc b1_from_b1
|
||||
//SEG11 @end
|
||||
bend:
|
||||
|
||||
Replacing label b1_from_b1 with b1
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1_from_b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
ASSEMBLER
|
||||
//SEG0 Global Constants & labels
|
||||
.const p = $1100
|
||||
//SEG1 @begin
|
||||
bbegin:
|
||||
//SEG2 [0] phi from @begin to @1
|
||||
//SEG3 [0] phi (byte) i#2 = (byte) 5 -- xby=coby1
|
||||
ldx #5
|
||||
jmp b1
|
||||
//SEG4 [0] phi from @1 to @1
|
||||
//SEG5 [0] phi (byte) i#2 = (byte) i#1 -- register_copy
|
||||
//SEG6 @1
|
||||
b1:
|
||||
//SEG7 [1] (byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2 [ i#2 $1 ] -- aby=xby_plus_coby1
|
||||
txa
|
||||
clc
|
||||
adc #2+2
|
||||
//SEG8 [2] *((const byte[16]) p#0 + (byte) i#2) ← (byte~) $1 [ i#2 ] -- cowo1_staridx_xby=aby
|
||||
sta p,x
|
||||
//SEG9 [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] -- xby=xby_plus_1
|
||||
inx
|
||||
//SEG10 [4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] -- xby_lt_coby1_then_la1
|
||||
cpx #$a
|
||||
bcc b1
|
||||
//SEG11 @end
|
||||
bend:
|
||||
|
||||
Removing instruction bbegin:
|
||||
Removing instruction bend:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
ASSEMBLER
|
||||
//SEG0 Global Constants & labels
|
||||
.const p = $1100
|
||||
//SEG1 @begin
|
||||
//SEG2 [0] phi from @begin to @1
|
||||
//SEG3 [0] phi (byte) i#2 = (byte) 5 -- xby=coby1
|
||||
ldx #5
|
||||
jmp b1
|
||||
//SEG4 [0] phi from @1 to @1
|
||||
//SEG5 [0] phi (byte) i#2 = (byte) i#1 -- register_copy
|
||||
//SEG6 @1
|
||||
b1:
|
||||
//SEG7 [1] (byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2 [ i#2 $1 ] -- aby=xby_plus_coby1
|
||||
txa
|
||||
clc
|
||||
adc #2+2
|
||||
//SEG8 [2] *((const byte[16]) p#0 + (byte) i#2) ← (byte~) $1 [ i#2 ] -- cowo1_staridx_xby=aby
|
||||
sta p,x
|
||||
//SEG9 [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] -- xby=xby_plus_1
|
||||
inx
|
||||
//SEG10 [4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] -- xby_lt_coby1_then_la1
|
||||
cpx #$a
|
||||
bcc b1
|
||||
//SEG11 @end
|
||||
|
||||
Removing instruction jmp b1
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
ASSEMBLER
|
||||
//SEG0 Global Constants & labels
|
||||
.const p = $1100
|
||||
//SEG1 @begin
|
||||
//SEG2 [0] phi from @begin to @1
|
||||
//SEG3 [0] phi (byte) i#2 = (byte) 5 -- xby=coby1
|
||||
ldx #5
|
||||
//SEG4 [0] phi from @1 to @1
|
||||
//SEG5 [0] phi (byte) i#2 = (byte) i#1 -- register_copy
|
||||
//SEG6 @1
|
||||
b1:
|
||||
//SEG7 [1] (byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2 [ i#2 $1 ] -- aby=xby_plus_coby1
|
||||
txa
|
||||
clc
|
||||
adc #2+2
|
||||
//SEG8 [2] *((const byte[16]) p#0 + (byte) i#2) ← (byte~) $1 [ i#2 ] -- cowo1_staridx_xby=aby
|
||||
sta p,x
|
||||
//SEG9 [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] -- xby=xby_plus_1
|
||||
inx
|
||||
//SEG10 [4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] -- xby_lt_coby1_then_la1
|
||||
cpx #$a
|
||||
bcc b1
|
||||
//SEG11 @end
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(byte~) $1 reg byte a 22.0
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte) i
|
||||
(byte) i#1 reg byte x 16.5
|
||||
(byte) i#2 reg byte x 14.666666666666666
|
||||
(byte[16]) p
|
||||
(const byte[16]) p#0 = (word) 4352
|
||||
|
||||
reg byte x [ i#2 i#1 ]
|
||||
reg byte a [ $1 ]
|
||||
|
||||
FINAL CODE
|
||||
//SEG0 Global Constants & labels
|
||||
.const p = $1100
|
||||
//SEG1 @begin
|
||||
//SEG2 [0] phi from @begin to @1
|
||||
//SEG3 [0] phi (byte) i#2 = (byte) 5 -- xby=coby1
|
||||
ldx #5
|
||||
//SEG4 [0] phi from @1 to @1
|
||||
//SEG5 [0] phi (byte) i#2 = (byte) i#1 -- register_copy
|
||||
//SEG6 @1
|
||||
b1:
|
||||
//SEG7 [1] (byte~) $1 ← (byte) i#2 + (byte) 2+(byte) 2 [ i#2 $1 ] -- aby=xby_plus_coby1
|
||||
txa
|
||||
clc
|
||||
adc #2+2
|
||||
//SEG8 [2] *((const byte[16]) p#0 + (byte) i#2) ← (byte~) $1 [ i#2 ] -- cowo1_staridx_xby=aby
|
||||
sta p,x
|
||||
//SEG9 [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] -- xby=xby_plus_1
|
||||
inx
|
||||
//SEG10 [4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] -- xby_lt_coby1_then_la1
|
||||
cpx #$a
|
||||
bcc b1
|
||||
//SEG11 @end
|
||||
|
@ -1,12 +0,0 @@
|
||||
(byte~) $1 reg byte a 22.0
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte) i
|
||||
(byte) i#1 reg byte x 16.5
|
||||
(byte) i#2 reg byte x 14.666666666666666
|
||||
(byte[16]) p
|
||||
(const byte[16]) p#0 = (word) 4352
|
||||
|
||||
reg byte x [ i#2 i#1 ]
|
||||
reg byte a [ $1 ]
|
Loading…
x
Reference in New Issue
Block a user