1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Added ifmin() for optimizing if() block sequence.

This commit is contained in:
jespergravgaard 2017-08-13 00:44:48 +02:00
parent 4741a2d22e
commit 7b30fa4f2c
7 changed files with 863 additions and 71 deletions

View File

@ -1,71 +0,0 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.icl.*;
import java.util.Arrays;
import java.util.List;
/*** Uplift one variable into the A register - and check if the program still works */
public class Pass3RegisterUpliftTest extends Pass2Base {
public Pass3RegisterUpliftTest(Program program) {
super(program);
}
/** Uplift variables to registers */
public void uplift() {
VariableRegisterWeights variableRegisterWeights = getProgram().getVariableRegisterWeights();
LiveRangeEquivalenceClassSet equivalenceClassSet = getProgram().getLiveRangeEquivalenceClassSet();
double maxWeight = 0.0;
LiveRangeEquivalenceClass maxEquivalenceClass = null;
// Find the live range equivalence class with the highest total weight
for (LiveRangeEquivalenceClass equivalenceClass : equivalenceClassSet.getEquivalenceClasses()) {
double totalWeight = 0.0;
List<VariableRef> vars = equivalenceClass.getVariables();
for (VariableRef var : vars) {
Double varWeight = variableRegisterWeights.getWeight(var);
totalWeight += varWeight;
}
if (maxWeight < totalWeight) {
maxEquivalenceClass = equivalenceClass;
maxWeight = totalWeight;
}
}
if (maxEquivalenceClass != null) {
getLog().append("Uplifting max weight " + maxWeight + " live range equivalence class " + maxEquivalenceClass);
// Try the A register first
List<RegisterAllocation.Register> registers =
Arrays.asList(
RegisterAllocation.getRegisterA(),
RegisterAllocation.getRegisterX(),
RegisterAllocation.getRegisterY());
for (RegisterAllocation.Register register : registers) {
attemptUplift(maxEquivalenceClass, register);
}
}
RegisterAllocation allocation = getProgram().getLiveRangeEquivalenceClassSet().createRegisterAllocation();
getProgram().setAllocation(allocation);
}
private void attemptUplift(LiveRangeEquivalenceClass equivalenceClass, RegisterAllocation.Register register) {
RegisterAllocation allocation = getProgram().getLiveRangeEquivalenceClassSet().createRegisterAllocation();
for (VariableRef var : equivalenceClass.getVariables()) {
allocation.setRegister(var, register);
}
getProgram().setAllocation(allocation);
new Pass4CodeGeneration(getProgram()).generate();
Pass4AssertNoCpuClobber clobber = new Pass4AssertNoCpuClobber(getProgram());
if (clobber.hasClobberProblem(false)) {
getLog().append("Uplift to " + register + " resulted in clobber.");
} else {
getLog().append("Uplift to " + register + " succesfull.");
}
}
}

View File

@ -84,6 +84,10 @@ public class TestCompilationOutput extends TestCase {
compileAndCompare("modglobalmin");
}
public void testIfMin() throws IOException, URISyntaxException {
compileAndCompare("ifmin");
}
public void testUseUninitialized() throws IOException, URISyntaxException {
String filename = "useuninitialized";
compileAndCompare(filename);

View File

@ -0,0 +1,13 @@
// Minimal if() test
byte* SCREEN = $0400;
main();
void main() {
byte i=0;
do {
if(i<50) {
*SCREEN = i;
}
} while(++i<100)
}

View File

@ -0,0 +1,15 @@
jsr main
main: {
ldx #$0
b1:
cpx #$32
bcc b2
b3:
inx
cpx #$64
bcc b1
rts
b2:
stx $400
jmp b3
}

View File

@ -0,0 +1,20 @@
@begin: scope:[] from
[0] 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
[1] (byte) main::i#2 ← phi( main/(byte) 0 main::@3/(byte) main::i#1 ) [ main::i#2 ]
[2] if((byte) main::i#2<(byte) 50) goto main::@2 [ main::i#2 ]
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
[3] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ]
[4] if((byte) main::i#1<(byte) 100) goto main::@1 [ main::i#1 ]
to:main::@return
main::@return: scope:[main] from main::@3
[5] return [ ]
to:@return
main::@2: scope:[main] from main::@1
[6] *((word) 1024) ← (byte) main::i#2 [ main::i#2 ]
to:main::@3

View File

@ -0,0 +1,798 @@
// Minimal if() test
byte* SCREEN = $0400;
main();
void main() {
byte i=0;
do {
if(i<50) {
*SCREEN = i;
}
} while(++i<100)
}
Adding pre/post-modifier (byte) main::i ← ++ (byte) main::i
PROGRAM
(byte*) SCREEN ← (word) 1024
(void~) $0 ← call main
proc (void()) main()
(byte) main::i ← (byte) 0
main::@1:
(boolean~) main::$0 ← (byte) main::i < (byte) 50
if((boolean~) main::$0) goto main::@2
goto main::@3
main::@2:
*((byte*) SCREEN) ← (byte) main::i
main::@3:
(byte) main::i ← ++ (byte) main::i
(boolean~) main::$1 ← (byte) main::i < (byte) 100
if((boolean~) main::$1) goto main::@1
main::@return:
return
endproc // main()
SYMBOLS
(void~) $0
(byte*) SCREEN
(void()) main()
(boolean~) main::$0
(boolean~) main::$1
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(byte) main::i
INITIAL CONTROL FLOW GRAPH
@begin: scope:[] from
(byte*) SCREEN ← (word) 1024
(void~) $0 ← call main
to:@1
main: scope:[main] from
(byte) main::i ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@3
(boolean~) main::$0 ← (byte) main::i < (byte) 50
if((boolean~) main::$0) goto main::@2
to:main::@4
main::@2: scope:[main] from main::@1 main::@5
*((byte*) SCREEN) ← (byte) main::i
to:main::@3
main::@4: scope:[main] from main::@1
to:main::@3
main::@3: scope:[main] from main::@2 main::@4
(byte) main::i ← ++ (byte) main::i
(boolean~) main::$1 ← (byte) main::i < (byte) 100
if((boolean~) main::$1) goto main::@1
to:main::@6
main::@5: scope:[main] from
to:main::@2
main::@6: scope:[main] from main::@3
to:main::@return
main::@return: scope:[main] from main::@6
return
to:@return
@1: scope:[] from @begin
to:@end
@end: scope:[] from @1
Removing empty block main::@4
Removing empty block main::@5
Removing empty block main::@6
Removing empty block @1
CONTROL FLOW GRAPH
@begin: scope:[] from
(byte*) SCREEN ← (word) 1024
(void~) $0 ← call main
to:@end
main: scope:[main] from
(byte) main::i ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@3
(boolean~) main::$0 ← (byte) main::i < (byte) 50
if((boolean~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
*((byte*) SCREEN) ← (byte) main::i
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte) main::i ← ++ (byte) main::i
(boolean~) main::$1 ← (byte) main::i < (byte) 100
if((boolean~) main::$1) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@end: scope:[] from @begin
PROCEDURE MODIFY VARIABLE ANALYSIS
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL
@begin: scope:[] from
(byte*) SCREEN ← (word) 1024
call main param-assignment
to:@2
@2: scope:[] from @begin
to:@end
main: scope:[main] from @begin
(byte) main::i ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@3
(boolean~) main::$0 ← (byte) main::i < (byte) 50
if((boolean~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
*((byte*) SCREEN) ← (byte) main::i
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte) main::i ← ++ (byte) main::i
(boolean~) main::$1 ← (byte) main::i < (byte) 100
if((boolean~) main::$1) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@end: scope:[] from @2
Completing Phi functions...
Completing Phi functions...
Completing Phi functions...
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte*) SCREEN#0 ← (word) 1024
call main param-assignment
to:@2
@2: scope:[] from @begin
to:@end
main: scope:[main] from @begin
(byte*) SCREEN#3 ← phi( @begin/(byte*) SCREEN#0 )
(byte) main::i#0 ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@3
(byte*) SCREEN#2 ← phi( main/(byte*) SCREEN#3 main::@3/(byte*) SCREEN#4 )
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@3/(byte) main::i#1 )
(boolean~) main::$0 ← (byte) main::i#2 < (byte) 50
if((boolean~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
(byte*) SCREEN#1 ← phi( main::@1/(byte*) SCREEN#2 )
(byte) main::i#3 ← phi( main::@1/(byte) main::i#2 )
*((byte*) SCREEN#1) ← (byte) main::i#3
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte*) SCREEN#4 ← phi( main::@1/(byte*) SCREEN#2 main::@2/(byte*) SCREEN#1 )
(byte) main::i#4 ← phi( main::@1/(byte) main::i#2 main::@2/(byte) main::i#3 )
(byte) main::i#1 ← ++ (byte) main::i#4
(boolean~) main::$1 ← (byte) main::i#1 < (byte) 100
if((boolean~) main::$1) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@end: scope:[] from @2
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN
@begin: scope:[] from
(byte*) SCREEN#0 ← (word) 1024
call main param-assignment
to:@2
@2: scope:[] from @begin
to:@end
main: scope:[main] from @begin
(byte*) SCREEN#3 ← phi( @begin/(byte*) SCREEN#0 )
(byte) main::i#0 ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@3
(byte*) SCREEN#2 ← phi( main/(byte*) SCREEN#3 main::@3/(byte*) SCREEN#4 )
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@3/(byte) main::i#1 )
(boolean~) main::$0 ← (byte) main::i#2 < (byte) 50
if((boolean~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
(byte*) SCREEN#1 ← phi( main::@1/(byte*) SCREEN#2 )
(byte) main::i#3 ← phi( main::@1/(byte) main::i#2 )
*((byte*) SCREEN#1) ← (byte) main::i#3
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte*) SCREEN#4 ← phi( main::@1/(byte*) SCREEN#2 main::@2/(byte*) SCREEN#1 )
(byte) main::i#4 ← phi( main::@1/(byte) main::i#2 main::@2/(byte) main::i#3 )
(byte) main::i#1 ← ++ (byte) main::i#4
(boolean~) main::$1 ← (byte) main::i#1 < (byte) 100
if((boolean~) main::$1) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@end: scope:[] from @2
Culled Empty Block (label) @2
Succesful SSA optimization Pass2CullEmptyBlocks
CONTROL FLOW GRAPH
@begin: scope:[] from
(byte*) SCREEN#0 ← (word) 1024
call main param-assignment
to:@end
main: scope:[main] from @begin
(byte*) SCREEN#3 ← phi( @begin/(byte*) SCREEN#0 )
(byte) main::i#0 ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@3
(byte*) SCREEN#2 ← phi( main/(byte*) SCREEN#3 main::@3/(byte*) SCREEN#4 )
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@3/(byte) main::i#1 )
(boolean~) main::$0 ← (byte) main::i#2 < (byte) 50
if((boolean~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
(byte*) SCREEN#1 ← phi( main::@1/(byte*) SCREEN#2 )
(byte) main::i#3 ← phi( main::@1/(byte) main::i#2 )
*((byte*) SCREEN#1) ← (byte) main::i#3
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte*) SCREEN#4 ← phi( main::@1/(byte*) SCREEN#2 main::@2/(byte*) SCREEN#1 )
(byte) main::i#4 ← phi( main::@1/(byte) main::i#2 main::@2/(byte) main::i#3 )
(byte) main::i#1 ← ++ (byte) main::i#4
(boolean~) main::$1 ← (byte) main::i#1 < (byte) 100
if((boolean~) main::$1) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@end: scope:[] from @begin
Constant (byte*) SCREEN#0 (word) 1024
Constant (byte) main::i#0 (byte) 0
Succesful SSA optimization Pass2ConstantPropagation
CONTROL FLOW GRAPH
@begin: scope:[] from
call main param-assignment
to:@end
main: scope:[main] from @begin
(byte*) SCREEN#3 ← phi( @begin/(word) 1024 )
to:main::@1
main::@1: scope:[main] from main main::@3
(byte*) SCREEN#2 ← phi( main/(byte*) SCREEN#3 main::@3/(byte*) SCREEN#4 )
(byte) main::i#2 ← phi( main/(byte) 0 main::@3/(byte) main::i#1 )
(boolean~) main::$0 ← (byte) main::i#2 < (byte) 50
if((boolean~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
(byte*) SCREEN#1 ← phi( main::@1/(byte*) SCREEN#2 )
(byte) main::i#3 ← phi( main::@1/(byte) main::i#2 )
*((byte*) SCREEN#1) ← (byte) main::i#3
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte*) SCREEN#4 ← phi( main::@1/(byte*) SCREEN#2 main::@2/(byte*) SCREEN#1 )
(byte) main::i#4 ← phi( main::@1/(byte) main::i#2 main::@2/(byte) main::i#3 )
(byte) main::i#1 ← ++ (byte) main::i#4
(boolean~) main::$1 ← (byte) main::i#1 < (byte) 100
if((boolean~) main::$1) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@end: scope:[] from @begin
Alias (byte) main::i#2 = (byte) main::i#3
Alias (byte*) SCREEN#1 = (byte*) SCREEN#2
Succesful SSA optimization Pass2AliasElimination
CONTROL FLOW GRAPH
@begin: scope:[] from
call main param-assignment
to:@end
main: scope:[main] from @begin
(byte*) SCREEN#3 ← phi( @begin/(word) 1024 )
to:main::@1
main::@1: scope:[main] from main main::@3
(byte*) SCREEN#1 ← phi( main/(byte*) SCREEN#3 main::@3/(byte*) SCREEN#4 )
(byte) main::i#2 ← phi( main/(byte) 0 main::@3/(byte) main::i#1 )
(boolean~) main::$0 ← (byte) main::i#2 < (byte) 50
if((boolean~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
*((byte*) SCREEN#1) ← (byte) main::i#2
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte*) SCREEN#4 ← phi( main::@1/(byte*) SCREEN#1 main::@2/(byte*) SCREEN#1 )
(byte) main::i#4 ← phi( main::@1/(byte) main::i#2 main::@2/(byte) main::i#2 )
(byte) main::i#1 ← ++ (byte) main::i#4
(boolean~) main::$1 ← (byte) main::i#1 < (byte) 100
if((boolean~) main::$1) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@end: scope:[] from @begin
Redundant Phi (byte*) SCREEN#3 (word) 1024
Redundant Phi (byte) main::i#4 (byte) main::i#2
Redundant Phi (byte*) SCREEN#4 (byte*) SCREEN#1
Succesful SSA optimization Pass2RedundantPhiElimination
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::@3
(byte*) SCREEN#1 ← phi( main/(word) 1024 main::@3/(byte*) SCREEN#1 )
(byte) main::i#2 ← phi( main/(byte) 0 main::@3/(byte) main::i#1 )
(boolean~) main::$0 ← (byte) main::i#2 < (byte) 50
if((boolean~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
*((byte*) SCREEN#1) ← (byte) main::i#2
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte) main::i#1 ← ++ (byte) main::i#2
(boolean~) main::$1 ← (byte) main::i#1 < (byte) 100
if((boolean~) main::$1) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@end: scope:[] from @begin
Self Phi Eliminated (byte*) SCREEN#1
Succesful SSA optimization Pass2SelfPhiElimination
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::@3
(byte*) SCREEN#1 ← phi( main/(word) 1024 )
(byte) main::i#2 ← phi( main/(byte) 0 main::@3/(byte) main::i#1 )
(boolean~) main::$0 ← (byte) main::i#2 < (byte) 50
if((boolean~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
*((byte*) SCREEN#1) ← (byte) main::i#2
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte) main::i#1 ← ++ (byte) main::i#2
(boolean~) main::$1 ← (byte) main::i#1 < (byte) 100
if((boolean~) main::$1) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@end: scope:[] from @begin
Simple Condition (boolean~) main::$0 if((byte) main::i#2<(byte) 50) goto main::@2
Simple Condition (boolean~) main::$1 if((byte) main::i#1<(byte) 100) goto main::@1
Succesful SSA optimization Pass2ConditionalJumpSimplification
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::@3
(byte*) SCREEN#1 ← phi( main/(word) 1024 )
(byte) main::i#2 ← phi( main/(byte) 0 main::@3/(byte) main::i#1 )
if((byte) main::i#2<(byte) 50) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
*((byte*) SCREEN#1) ← (byte) main::i#2
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte) main::i#1 ← ++ (byte) main::i#2
if((byte) main::i#1<(byte) 100) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@end: scope:[] from @begin
Constant (byte*) SCREEN#1 (word) 1024
Succesful SSA optimization Pass2ConstantPropagation
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::@3
(byte) main::i#2 ← phi( main/(byte) 0 main::@3/(byte) main::i#1 )
if((byte) main::i#2<(byte) 50) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
*((word) 1024) ← (byte) main::i#2
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte) main::i#1 ← ++ (byte) main::i#2
if((byte) main::i#1<(byte) 100) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@end: scope:[] from @begin
Block Sequence Planned @begin @end main main::@1 main::@3 main::@return main::@2
Added new block during phi lifting main::@7(between main::@3 and main::@1)
Block Sequence Planned @begin @end main main::@1 main::@3 main::@return main::@7 main::@2
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::@7
(byte) main::i#2 ← phi( main/(byte) 0 main::@7/(byte~) main::i#5 )
if((byte) main::i#2<(byte) 50) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte) main::i#1 ← ++ (byte) main::i#2
if((byte) main::i#1<(byte) 100) goto main::@7
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
main::@7: scope:[main] from main::@3
(byte~) main::i#5 ← (byte) main::i#1
to:main::@1
main::@2: scope:[main] from main::@1
*((word) 1024) ← (byte) main::i#2
to:main::@3
Propagating live ranges...
CONTROL FLOW GRAPH - LIVE RANGES
@begin: scope:[] from
[0] 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::@7
[1] (byte) main::i#2 ← phi( main/(byte) 0 main::@7/(byte~) main::i#5 ) [ main::i#2 ]
[2] if((byte) main::i#2<(byte) 50) goto main::@2 [ main::i#2 ]
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
[3] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ]
[4] if((byte) main::i#1<(byte) 100) goto main::@7 [ main::i#1 ]
to:main::@return
main::@return: scope:[main] from main::@3
[5] return [ ]
to:@return
main::@7: scope:[main] from main::@3
[6] (byte~) main::i#5 ← (byte) main::i#1 [ main::i#5 ]
to:main::@1
main::@2: scope:[main] from main::@1
[7] *((word) 1024) ← (byte) main::i#2 [ main::i#2 ]
to:main::@3
Created 1 initial phi equivalence classes
Coalesced [6] main::i#5 ← main::i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) main::@7
Block Sequence Planned @begin @end main main::@1 main::@3 main::@return main::@2
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
to:main::@1
main::@1: scope:[main] from main main::@3
[1] (byte) main::i#2 ← phi( main/(byte) 0 main::@3/(byte) main::i#1 ) [ main::i#2 ]
[2] if((byte) main::i#2<(byte) 50) goto main::@2 [ main::i#2 ]
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
[3] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ]
[4] if((byte) main::i#1<(byte) 100) goto main::@1 [ main::i#1 ]
to:main::@return
main::@return: scope:[main] from main::@3
[5] return [ ]
to:@return
main::@2: scope:[main] from main::@1
[6] *((word) 1024) ← (byte) main::i#2 [ main::i#2 ]
to:main::@3
CALL GRAPH
Calls in [] to 0:main
DOMINATORS
@begin dominated by @begin
@end dominated by @end @begin
main dominated by @begin main
main::@1 dominated by @begin main::@1 main
main::@3 dominated by @begin main::@1 main::@3 main
main::@return dominated by main::@return @begin main::@1 main::@3 main
main::@2 dominated by @begin main::@2 main::@1 main
Found back edge: Loop head: main::@1 tails: main::@3 blocks: null
Populated: Loop head: main::@1 tails: main::@3 blocks: main::@3 main::@1 main::@2
NATURAL LOOPS
Loop head: main::@1 tails: main::@3 blocks: main::@3 main::@1 main::@2
Found 0 loops in scope []
Found 1 loops in scope [main]
Loop head: main::@1 tails: main::@3 blocks: main::@3 main::@1 main::@2
NATURAL LOOPS WITH DEPTH
Loop head: main::@1 tails: main::@3 blocks: main::@3 main::@1 main::@2 depth: 1
VARIABLE REGISTER WEIGHTS
(byte*) SCREEN
(void()) main()
(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 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
Allocated zp byte:2 to zp byte:2 [ main::i#2 main::i#1 ]
INITIAL ASM
//SEG0 @begin
bbegin:
//SEG1 [0] call main param-assignment [ ]
jsr main
jmp bend
//SEG2 @end
bend:
//SEG3 main
main: {
//SEG4 [1] phi from main to main::@1
b1_from_main:
//SEG5 [1] phi (byte) main::i#2 = (byte) 0 -- zpby1=coby1
lda #$0
sta $2
jmp b1
//SEG6 [1] phi from main::@3 to main::@1
b1_from_b3:
//SEG7 [1] phi (byte) main::i#2 = (byte) main::i#1 -- register_copy
jmp b1
//SEG8 main::@1
b1:
//SEG9 [2] if((byte) main::i#2<(byte) 50) goto main::@2 [ main::i#2 ] -- zpby1_lt_coby1_then_la1
lda $2
cmp #$32
bcc b2
jmp b3
//SEG10 main::@3
b3:
//SEG11 [3] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] -- zpby1=_inc_zpby1
inc $2
//SEG12 [4] if((byte) main::i#1<(byte) 100) goto main::@1 [ main::i#1 ] -- zpby1_lt_coby1_then_la1
lda $2
cmp #$64
bcc b1_from_b3
jmp breturn
//SEG13 main::@return
breturn:
//SEG14 [5] return [ ]
rts
//SEG15 main::@2
b2:
//SEG16 [6] *((word) 1024) ← (byte) main::i#2 [ main::i#2 ] -- _star_cowo1=zpby1
lda $2
sta $400
jmp b3
}
REGISTER UPLIFT POTENTIAL REGISTERS
Potential registers zp byte:2 [ main::i#2 main::i#1 ] : zp byte:2 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 31.17: zp byte:2 [ main::i#2 main::i#1 ]
Uplift Scope []
Uplifting [main] best 335 combination reg byte x [ main::i#2 main::i#1 ]
Uplifting [] best 335 combination
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp b3
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
ASSEMBLER
//SEG0 @begin
bbegin:
//SEG1 [0] call main param-assignment [ ]
jsr main
//SEG2 @end
bend:
//SEG3 main
main: {
//SEG4 [1] phi from main to main::@1
b1_from_main:
//SEG5 [1] phi (byte) main::i#2 = (byte) 0 -- xby=coby1
ldx #$0
jmp b1
//SEG6 [1] phi from main::@3 to main::@1
b1_from_b3:
//SEG7 [1] phi (byte) main::i#2 = (byte) main::i#1 -- register_copy
//SEG8 main::@1
b1:
//SEG9 [2] if((byte) main::i#2<(byte) 50) goto main::@2 [ main::i#2 ] -- xby_lt_coby1_then_la1
cpx #$32
bcc b2
//SEG10 main::@3
b3:
//SEG11 [3] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] -- xby=_inc_xby
inx
//SEG12 [4] if((byte) main::i#1<(byte) 100) goto main::@1 [ main::i#1 ] -- xby_lt_coby1_then_la1
cpx #$64
bcc b1_from_b3
//SEG13 main::@return
breturn:
//SEG14 [5] return [ ]
rts
//SEG15 main::@2
b2:
//SEG16 [6] *((word) 1024) ← (byte) main::i#2 [ main::i#2 ] -- _star_cowo1=xby
stx $400
jmp b3
}
Replacing label b1_from_b3 with b1
Removing instruction b1_from_b3:
Succesful ASM optimization Pass5RedundantLabelElimination
ASSEMBLER
//SEG0 @begin
bbegin:
//SEG1 [0] call main param-assignment [ ]
jsr main
//SEG2 @end
bend:
//SEG3 main
main: {
//SEG4 [1] phi from main to main::@1
b1_from_main:
//SEG5 [1] phi (byte) main::i#2 = (byte) 0 -- xby=coby1
ldx #$0
jmp b1
//SEG6 [1] phi from main::@3 to main::@1
//SEG7 [1] phi (byte) main::i#2 = (byte) main::i#1 -- register_copy
//SEG8 main::@1
b1:
//SEG9 [2] if((byte) main::i#2<(byte) 50) goto main::@2 [ main::i#2 ] -- xby_lt_coby1_then_la1
cpx #$32
bcc b2
//SEG10 main::@3
b3:
//SEG11 [3] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] -- xby=_inc_xby
inx
//SEG12 [4] if((byte) main::i#1<(byte) 100) goto main::@1 [ main::i#1 ] -- xby_lt_coby1_then_la1
cpx #$64
bcc b1
//SEG13 main::@return
breturn:
//SEG14 [5] return [ ]
rts
//SEG15 main::@2
b2:
//SEG16 [6] *((word) 1024) ← (byte) main::i#2 [ main::i#2 ] -- _star_cowo1=xby
stx $400
jmp b3
}
Removing instruction bbegin:
Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
ASSEMBLER
//SEG0 @begin
//SEG1 [0] call main param-assignment [ ]
jsr main
//SEG2 @end
//SEG3 main
main: {
//SEG4 [1] phi from main to main::@1
//SEG5 [1] phi (byte) main::i#2 = (byte) 0 -- xby=coby1
ldx #$0
jmp b1
//SEG6 [1] phi from main::@3 to main::@1
//SEG7 [1] phi (byte) main::i#2 = (byte) main::i#1 -- register_copy
//SEG8 main::@1
b1:
//SEG9 [2] if((byte) main::i#2<(byte) 50) goto main::@2 [ main::i#2 ] -- xby_lt_coby1_then_la1
cpx #$32
bcc b2
//SEG10 main::@3
b3:
//SEG11 [3] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] -- xby=_inc_xby
inx
//SEG12 [4] if((byte) main::i#1<(byte) 100) goto main::@1 [ main::i#1 ] -- xby_lt_coby1_then_la1
cpx #$64
bcc b1
//SEG13 main::@return
//SEG14 [5] return [ ]
rts
//SEG15 main::@2
b2:
//SEG16 [6] *((word) 1024) ← (byte) main::i#2 [ main::i#2 ] -- _star_cowo1=xby
stx $400
jmp b3
}
Removing instruction jmp b1
Succesful ASM optimization Pass5NextJumpElimination
ASSEMBLER
//SEG0 @begin
//SEG1 [0] call main param-assignment [ ]
jsr main
//SEG2 @end
//SEG3 main
main: {
//SEG4 [1] phi from main to main::@1
//SEG5 [1] phi (byte) main::i#2 = (byte) 0 -- xby=coby1
ldx #$0
//SEG6 [1] phi from main::@3 to main::@1
//SEG7 [1] phi (byte) main::i#2 = (byte) main::i#1 -- register_copy
//SEG8 main::@1
b1:
//SEG9 [2] if((byte) main::i#2<(byte) 50) goto main::@2 [ main::i#2 ] -- xby_lt_coby1_then_la1
cpx #$32
bcc b2
//SEG10 main::@3
b3:
//SEG11 [3] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] -- xby=_inc_xby
inx
//SEG12 [4] if((byte) main::i#1<(byte) 100) goto main::@1 [ main::i#1 ] -- xby_lt_coby1_then_la1
cpx #$64
bcc b1
//SEG13 main::@return
//SEG14 [5] return [ ]
rts
//SEG15 main::@2
b2:
//SEG16 [6] *((word) 1024) ← (byte) main::i#2 [ main::i#2 ] -- _star_cowo1=xby
stx $400
jmp b3
}
FINAL SYMBOL TABLE
(label) @begin
(label) @end
(byte*) SCREEN
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(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 ]
FINAL CODE
//SEG0 @begin
//SEG1 [0] call main param-assignment [ ]
jsr main
//SEG2 @end
//SEG3 main
main: {
//SEG4 [1] phi from main to main::@1
//SEG5 [1] phi (byte) main::i#2 = (byte) 0 -- xby=coby1
ldx #$0
//SEG6 [1] phi from main::@3 to main::@1
//SEG7 [1] phi (byte) main::i#2 = (byte) main::i#1 -- register_copy
//SEG8 main::@1
b1:
//SEG9 [2] if((byte) main::i#2<(byte) 50) goto main::@2 [ main::i#2 ] -- xby_lt_coby1_then_la1
cpx #$32
bcc b2
//SEG10 main::@3
b3:
//SEG11 [3] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] -- xby=_inc_xby
inx
//SEG12 [4] if((byte) main::i#1<(byte) 100) goto main::@1 [ main::i#1 ] -- xby_lt_coby1_then_la1
cpx #$64
bcc b1
//SEG13 main::@return
//SEG14 [5] return [ ]
rts
//SEG15 main::@2
b2:
//SEG16 [6] *((word) 1024) ← (byte) main::i#2 [ main::i#2 ] -- _star_cowo1=xby
stx $400
jmp b3
}

View File

@ -0,0 +1,13 @@
(label) @begin
(label) @end
(byte*) SCREEN
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(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 ]