diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index c5777854a..034fc4848 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -85,7 +85,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor()); - program.getScope().add(startProcedure); - final ProcedureCompilation startProcedureCompilation = program.createProcedureCompilation(startProcedure.getRef()); - final StatementSequence sequence = startProcedureCompilation.getStatementSequence(); - sequence.addStatement(new StatementProcedureBegin(startProcedure.getRef(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS)); - if(initCompilation!=null) - sequence.addStatement(new StatementCall(null, SymbolRef.INIT_PROC_NAME, new ArrayList<>(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS)); - sequence.addStatement(new StatementCall(null, SymbolRef.MAIN_PROC_NAME, new ArrayList<>(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS)); - sequence.addStatement(new StatementReturn(null, new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS)); - sequence.addStatement(new StatementProcedureEnd(startProcedure.getRef(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS)); + { + program.setStartProcedure(new ProcedureRef(SymbolRef.START_PROC_NAME)); + final Procedure startProcedure = new Procedure(SymbolRef.START_PROC_NAME, SymbolType.VOID, program.getScope(), Scope.SEGMENT_CODE_DEFAULT, Scope.SEGMENT_DATA_DEFAULT, Procedure.CallingConvention.PHI_CALL); + startProcedure.setParameters(new ArrayList<>()); + program.getScope().add(startProcedure); + final ProcedureCompilation startProcedureCompilation = program.createProcedureCompilation(startProcedure.getRef()); + final StatementSequence startSequence = startProcedureCompilation.getStatementSequence(); + startSequence.addStatement(new StatementProcedureBegin(startProcedure.getRef(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS)); + if(initCompilation != null) + startSequence.addStatement(new StatementCall(null, SymbolRef.INIT_PROC_NAME, new ArrayList<>(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS)); + startSequence.addStatement(new StatementCall(null, SymbolRef.MAIN_PROC_NAME, new ArrayList<>(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS)); + final Label startReturnLabel = startProcedure.addLabel(SymbolRef.PROCEXIT_BLOCK_NAME); + startSequence.addStatement(new StatementLabel(startReturnLabel.getRef(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS)); + startSequence.addStatement(new StatementReturn(null, new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS)); + startSequence.addStatement(new StatementProcedureEnd(startProcedure.getRef(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS)); + } } @@ -1026,7 +1033,14 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor(),getProgram() ); + Pass2EliminateUnusedBlocks.removeProcedure(procedure.getRef(), new HashSet<>(), getProgram()); optimized = true; } } @@ -40,16 +40,19 @@ public class PassNEliminateEmptyProcedure extends Pass2SsaOptimization { while(stmtIt.hasNext()) { Statement statement = stmtIt.next(); if(statement instanceof StatementCalling && ((StatementCalling) statement).getProcedure().equals(ref)) { - getLog().append("Removing call to empty procedure "+statement.toString(getProgram(), false)); + getLog().append("Removing call to empty procedure " + statement.toString(getProgram(), false)); stmtIt.remove(); } else if(statement instanceof StatementCallPrepare && ((StatementCallPrepare) statement).getProcedure().equals(ref)) { - getLog().append("Removing call to empty procedure "+statement.toString(getProgram(), false)); + getLog().append("Removing call to empty procedure " + statement.toString(getProgram(), false)); stmtIt.remove(); } else if(statement instanceof StatementCallFinalize && ((StatementCallFinalize) statement).getProcedure().equals(ref)) { - getLog().append("Removing call to empty procedure "+statement.toString(getProgram(), false)); + getLog().append("Removing call to empty procedure " + statement.toString(getProgram(), false)); stmtIt.remove(); } } + if(ref.getLabelRef().equals(block.getCallSuccessor())) { + block.setCallSuccessor(null); + } } } diff --git a/src/test/ref/arrays-init-kasm-0.cfg b/src/test/ref/arrays-init-kasm-0.cfg index 1de599f91..9bfe86442 100644 --- a/src/test/ref/arrays-init-kasm-0.cfg +++ b/src/test/ref/arrays-init-kasm-0.cfg @@ -1,17 +1,8 @@ -@begin: scope:[] from - [0] phi() - to:@1 -@1: scope:[] from @begin - [1] phi() - [2] call main - to:@end -@end: scope:[] from @1 - [3] phi() (void()) main() -main: scope:[main] from @1 - [4] *((const byte*) SCREEN) ← *((const byte*) SINTAB) +main: scope:[main] from + [0] *((const byte*) SCREEN) ← *((const byte*) SINTAB) to:main::@return main::@return: scope:[main] from main - [5] return + [1] return to:@return diff --git a/src/test/ref/arrays-init-kasm-0.log b/src/test/ref/arrays-init-kasm-0.log index a790d6535..096645cbb 100644 --- a/src/test/ref/arrays-init-kasm-0.log +++ b/src/test/ref/arrays-init-kasm-0.log @@ -1,30 +1,44 @@ CONTROL FLOW GRAPH SSA -@begin: scope:[] from - to:@1 + +(void()) _init() +_init: scope:[_init] from _start + to:_init::@return +_init::@return: scope:[_init] from _init + return + to:@return (void()) main() -main: scope:[main] from @1 +main: scope:[main] from _start::@1 *((const byte*) SCREEN + (number) 0) ← *((const byte*) SINTAB + (number) 0) to:main::@return main::@return: scope:[main] from main return to:@return -@1: scope:[] from @begin + +(void()) _start() +_start: scope:[_start] from + call _init + to:_start::@1 +_start::@1: scope:[_start] from _start call main - to:@2 -@2: scope:[] from @1 - to:@end -@end: scope:[] from @2 + to:_start::@2 +_start::@2: scope:[_start] from _start::@1 + to:_start::@return +_start::@return: scope:[_start] from _start::@2 + return + to:@return SYMBOL TABLE SSA -(label) @1 -(label) @2 -(label) @begin -(label) @end (const byte*) SCREEN = (byte*)(number) $400 (const byte*) SINTAB[(number) $100] = kickasm {{ .fill 256, 128 + 128*sin(i*2*PI/256) }} +(void()) _init() +(label) _init::@return +(void()) _start() +(label) _start::@1 +(label) _start::@2 +(label) _start::@return (void()) main() (label) main::@return @@ -38,40 +52,33 @@ Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) 0 Successful SSA optimization PassNFinalizeNumberTypeConversions -Simplifying expression containing zero SINTAB in [0] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) SINTAB + (byte) 0) -Simplifying expression containing zero SCREEN in [0] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) SINTAB) +Simplifying expression containing zero SINTAB in [1] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) SINTAB + (byte) 0) +Simplifying expression containing zero SCREEN in [1] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) SINTAB) Successful SSA optimization PassNSimplifyExpressionWithZero -Adding NOP phi() at start of @begin -Adding NOP phi() at start of @1 -Adding NOP phi() at start of @2 -Adding NOP phi() at start of @end +Removing call to empty procedure call _init +Removing unused procedure _init +Removing unused procedure block _init +Removing unused procedure block _init::@return +Successful SSA optimization PassNEliminateEmptyProcedure +Removing unused procedure _start +Removing unused procedure block _start +Removing unused procedure block _start::@1 +Removing unused procedure block _start::@2 +Removing unused procedure block _start::@return +Successful SSA optimization PassNEliminateEmptyStart CALL GRAPH -Calls in [] to main:2 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes -Culled Empty Block (label) @2 -Adding NOP phi() at start of @begin -Adding NOP phi() at start of @1 -Adding NOP phi() at start of @end FINAL CONTROL FLOW GRAPH -@begin: scope:[] from - [0] phi() - to:@1 -@1: scope:[] from @begin - [1] phi() - [2] call main - to:@end -@end: scope:[] from @1 - [3] phi() (void()) main() -main: scope:[main] from @1 - [4] *((const byte*) SCREEN) ← *((const byte*) SINTAB) +main: scope:[main] from + [0] *((const byte*) SCREEN) ← *((const byte*) SINTAB) to:main::@return main::@return: scope:[main] from main - [5] return + [1] return to:@return @@ -91,29 +98,15 @@ Target platform is c64basic / MOS6502X .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 - // @begin -__bbegin: - // [1] phi from @begin to @1 [phi:@begin->@1] -__b1_from___bbegin: - jmp __b1 - // @1 -__b1: - // [2] call main - jsr main - // [3] phi from @1 to @end [phi:@1->@end] -__bend_from___b1: - jmp __bend - // @end -__bend: // main main: { - // [4] *((const byte*) SCREEN) ← *((const byte*) SINTAB) -- _deref_pbuc1=_deref_pbuc2 + // [0] *((const byte*) SCREEN) ← *((const byte*) SINTAB) -- _deref_pbuc1=_deref_pbuc2 lda SINTAB sta SCREEN jmp __breturn // main::@return __breturn: - // [5] return + // [1] return rts } // File Data @@ -123,14 +116,14 @@ SINTAB: REGISTER UPLIFT POTENTIAL REGISTERS -Statement [4] *((const byte*) SCREEN) ← *((const byte*) SINTAB) [ ] ( main:2 [ ] { } ) always clobbers reg byte a +Statement [0] *((const byte*) SCREEN) ← *((const byte*) SINTAB) [ ] ( [ ] { } ) always clobbers reg byte a REGISTER UPLIFT SCOPES Uplift Scope [main] Uplift Scope [] -Uplifting [main] best 29 combination -Uplifting [] best 29 combination +Uplifting [main] best 17 combination +Uplifting [] best 17 combination ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -141,29 +134,15 @@ ASSEMBLER BEFORE OPTIMIZATION .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 - // @begin -__bbegin: - // [1] phi from @begin to @1 [phi:@begin->@1] -__b1_from___bbegin: - jmp __b1 - // @1 -__b1: - // [2] call main - jsr main - // [3] phi from @1 to @end [phi:@1->@end] -__bend_from___b1: - jmp __bend - // @end -__bend: // main main: { - // [4] *((const byte*) SCREEN) ← *((const byte*) SINTAB) -- _deref_pbuc1=_deref_pbuc2 + // [0] *((const byte*) SCREEN) ← *((const byte*) SINTAB) -- _deref_pbuc1=_deref_pbuc2 lda SINTAB sta SCREEN jmp __breturn // main::@return __breturn: - // [5] return + // [1] return rts } // File Data @@ -173,25 +152,12 @@ SINTAB: ASSEMBLER OPTIMIZATIONS -Removing instruction jmp __b1 -Removing instruction jmp __bend Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination -Removing instruction __b1_from___bbegin: -Removing instruction __b1: -Removing instruction __bend_from___b1: -Succesful ASM optimization Pass5RedundantLabelElimination -Removing instruction __bbegin: -Removing instruction __bend: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination -Removing instruction jsr main -Succesful ASM optimization Pass5SkipBegin FINAL SYMBOL TABLE -(label) @1 -(label) @begin -(label) @end (const byte*) SCREEN = (byte*) 1024 (const byte*) SINTAB[(number) $100] = kickasm {{ .fill 256, 128 + 128*sin(i*2*PI/256) }} @@ -211,21 +177,15 @@ Score: 14 .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 - // @begin - // [1] phi from @begin to @1 [phi:@begin->@1] - // @1 - // [2] call main - // [3] phi from @1 to @end [phi:@1->@end] - // @end // main main: { // SCREEN[0] = SINTAB[0] - // [4] *((const byte*) SCREEN) ← *((const byte*) SINTAB) -- _deref_pbuc1=_deref_pbuc2 + // [0] *((const byte*) SCREEN) ← *((const byte*) SINTAB) -- _deref_pbuc1=_deref_pbuc2 lda SINTAB sta SCREEN // main::@return // } - // [5] return + // [1] return rts } // File Data diff --git a/src/test/ref/arrays-init-kasm-0.sym b/src/test/ref/arrays-init-kasm-0.sym index 95ab889d1..dcdb4ebb4 100644 --- a/src/test/ref/arrays-init-kasm-0.sym +++ b/src/test/ref/arrays-init-kasm-0.sym @@ -1,6 +1,3 @@ -(label) @1 -(label) @begin -(label) @end (const byte*) SCREEN = (byte*) 1024 (const byte*) SINTAB[(number) $100] = kickasm {{ .fill 256, 128 + 128*sin(i*2*PI/256) }} diff --git a/src/test/ref/euclid-problem-2.cfg b/src/test/ref/euclid-problem-2.cfg index 7dd4dcdc8..631fb6273 100644 --- a/src/test/ref/euclid-problem-2.cfg +++ b/src/test/ref/euclid-problem-2.cfg @@ -1,64 +1,55 @@ -@begin: scope:[] from - [0] phi() - to:@1 -@1: scope:[] from @begin - [1] phi() - [2] call main - to:@end -@end: scope:[] from @1 - [3] phi() (void()) main() -main: scope:[main] from @1 - [4] phi() - [5] call euclid - [6] (byte) euclid::return#0 ← (byte) euclid::a#5 +main: scope:[main] from + [0] phi() + [1] call euclid + [2] (byte) euclid::return#0 ← (byte) euclid::a#5 to:main::@1 main::@1: scope:[main] from main - [7] (byte~) main::$0 ← (byte) euclid::return#0 - [8] *((const nomodify byte*) SCREEN) ← (byte~) main::$0 - [9] call euclid - [10] (byte) euclid::return#1 ← (byte) euclid::a#5 + [3] (byte~) main::$0 ← (byte) euclid::return#0 + [4] *((const nomodify byte*) SCREEN) ← (byte~) main::$0 + [5] call euclid + [6] (byte) euclid::return#1 ← (byte) euclid::a#5 to:main::@2 main::@2: scope:[main] from main::@1 - [11] (byte~) main::$1 ← (byte) euclid::return#1 - [12] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$1 - [13] call euclid - [14] (byte) euclid::return#2 ← (byte) euclid::a#5 + [7] (byte~) main::$1 ← (byte) euclid::return#1 + [8] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$1 + [9] call euclid + [10] (byte) euclid::return#2 ← (byte) euclid::a#5 to:main::@3 main::@3: scope:[main] from main::@2 - [15] (byte~) main::$2 ← (byte) euclid::return#2 - [16] *((const nomodify byte*) SCREEN+(byte) 2) ← (byte~) main::$2 - [17] call euclid - [18] (byte) euclid::return#3 ← (byte) euclid::a#5 + [11] (byte~) main::$2 ← (byte) euclid::return#2 + [12] *((const nomodify byte*) SCREEN+(byte) 2) ← (byte~) main::$2 + [13] call euclid + [14] (byte) euclid::return#3 ← (byte) euclid::a#5 to:main::@4 main::@4: scope:[main] from main::@3 - [19] (byte~) main::$3 ← (byte) euclid::return#3 - [20] *((const nomodify byte*) SCREEN+(byte) 3) ← (byte~) main::$3 + [15] (byte~) main::$3 ← (byte) euclid::return#3 + [16] *((const nomodify byte*) SCREEN+(byte) 3) ← (byte~) main::$3 to:main::@return main::@return: scope:[main] from main::@4 - [21] return + [17] return to:@return (byte()) euclid((byte) euclid::a , (byte) euclid::b) euclid: scope:[euclid] from main main::@1 main::@2 main::@3 - [22] (byte) euclid::b#9 ← phi( main/(byte) 2 main::@1/(byte) $45 main::@2/(byte) $9b main::@3/(byte) 3 ) - [22] (byte) euclid::a#10 ← phi( main/(byte) $80 main::@1/(byte) $a9 main::@2/(byte) $ff main::@3/(byte) $63 ) + [18] (byte) euclid::b#9 ← phi( main/(byte) 2 main::@1/(byte) $45 main::@2/(byte) $9b main::@3/(byte) 3 ) + [18] (byte) euclid::a#10 ← phi( main/(byte) $80 main::@1/(byte) $a9 main::@2/(byte) $ff main::@3/(byte) $63 ) to:euclid::@1 euclid::@1: scope:[euclid] from euclid euclid::@3 euclid::@4 - [23] (byte) euclid::b#5 ← phi( euclid/(byte) euclid::b#9 euclid::@3/(byte) euclid::b#5 euclid::@4/(byte) euclid::b#4 ) - [23] (byte) euclid::a#5 ← phi( euclid/(byte) euclid::a#10 euclid::@3/(byte) euclid::a#4 euclid::@4/(byte) euclid::a#5 ) - [24] if((byte) euclid::a#5!=(byte) euclid::b#5) goto euclid::@2 + [19] (byte) euclid::b#5 ← phi( euclid/(byte) euclid::b#9 euclid::@3/(byte) euclid::b#5 euclid::@4/(byte) euclid::b#4 ) + [19] (byte) euclid::a#5 ← phi( euclid/(byte) euclid::a#10 euclid::@3/(byte) euclid::a#4 euclid::@4/(byte) euclid::a#5 ) + [20] if((byte) euclid::a#5!=(byte) euclid::b#5) goto euclid::@2 to:euclid::@return euclid::@return: scope:[euclid] from euclid::@1 - [25] return + [21] return to:@return euclid::@2: scope:[euclid] from euclid::@1 - [26] if((byte) euclid::a#5>(byte) euclid::b#5) goto euclid::@3 + [22] if((byte) euclid::a#5>(byte) euclid::b#5) goto euclid::@3 to:euclid::@4 euclid::@4: scope:[euclid] from euclid::@2 - [27] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 + [23] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 to:euclid::@1 euclid::@3: scope:[euclid] from euclid::@2 - [28] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 + [24] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 to:euclid::@1 diff --git a/src/test/ref/euclid-problem-2.log b/src/test/ref/euclid-problem-2.log index 40582e9ba..c21654c22 100644 --- a/src/test/ref/euclid-problem-2.log +++ b/src/test/ref/euclid-problem-2.log @@ -1,60 +1,68 @@ +Does this handle main() / _start() correctly? CONTROL FLOW GRAPH SSA -@begin: scope:[] from + +(void()) _init() +_init: scope:[_init] from _start (byte) idx#0 ← (byte) 0 - to:@1 + to:_init::@return +_init::@return: scope:[_init] from _init + (byte) idx#10 ← phi( _init/(byte) idx#0 ) + (byte) idx#1 ← (byte) idx#10 + return + to:@return (void()) main() -main: scope:[main] from @1 - (byte) idx#13 ← phi( @1/(byte) idx#14 ) +main: scope:[main] from _start::@1 + (byte) idx#19 ← phi( _start::@1/(byte) idx#7 ) (byte) euclid::a#0 ← (number) $80 (byte) euclid::b#0 ← (number) 2 call euclid (byte) euclid::return#0 ← (byte) euclid::return#5 to:main::@1 main::@1: scope:[main] from main - (byte) idx#7 ← phi( main/(byte) idx#13 ) + (byte) idx#11 ← phi( main/(byte) idx#19 ) (byte) euclid::return#6 ← phi( main/(byte) euclid::return#0 ) (byte~) main::$0 ← (byte) euclid::return#6 - *((const nomodify byte*) SCREEN + (byte) idx#7) ← (byte~) main::$0 - (byte) idx#1 ← ++ (byte) idx#7 + *((const nomodify byte*) SCREEN + (byte) idx#11) ← (byte~) main::$0 + (byte) idx#2 ← ++ (byte) idx#11 (byte) euclid::a#1 ← (number) $a9 (byte) euclid::b#1 ← (number) $45 call euclid (byte) euclid::return#1 ← (byte) euclid::return#5 to:main::@2 main::@2: scope:[main] from main::@1 - (byte) idx#8 ← phi( main::@1/(byte) idx#1 ) + (byte) idx#12 ← phi( main::@1/(byte) idx#2 ) (byte) euclid::return#7 ← phi( main::@1/(byte) euclid::return#1 ) (byte~) main::$1 ← (byte) euclid::return#7 - *((const nomodify byte*) SCREEN + (byte) idx#8) ← (byte~) main::$1 - (byte) idx#2 ← ++ (byte) idx#8 + *((const nomodify byte*) SCREEN + (byte) idx#12) ← (byte~) main::$1 + (byte) idx#3 ← ++ (byte) idx#12 (byte) euclid::a#2 ← (number) $ff (byte) euclid::b#2 ← (number) $9b call euclid (byte) euclid::return#2 ← (byte) euclid::return#5 to:main::@3 main::@3: scope:[main] from main::@2 - (byte) idx#9 ← phi( main::@2/(byte) idx#2 ) + (byte) idx#13 ← phi( main::@2/(byte) idx#3 ) (byte) euclid::return#8 ← phi( main::@2/(byte) euclid::return#2 ) (byte~) main::$2 ← (byte) euclid::return#8 - *((const nomodify byte*) SCREEN + (byte) idx#9) ← (byte~) main::$2 - (byte) idx#3 ← ++ (byte) idx#9 + *((const nomodify byte*) SCREEN + (byte) idx#13) ← (byte~) main::$2 + (byte) idx#4 ← ++ (byte) idx#13 (byte) euclid::a#3 ← (number) $63 (byte) euclid::b#3 ← (number) 3 call euclid (byte) euclid::return#3 ← (byte) euclid::return#5 to:main::@4 main::@4: scope:[main] from main::@3 - (byte) idx#10 ← phi( main::@3/(byte) idx#3 ) + (byte) idx#14 ← phi( main::@3/(byte) idx#4 ) (byte) euclid::return#9 ← phi( main::@3/(byte) euclid::return#3 ) (byte~) main::$3 ← (byte) euclid::return#9 - *((const nomodify byte*) SCREEN + (byte) idx#10) ← (byte~) main::$3 - (byte) idx#4 ← ++ (byte) idx#10 + *((const nomodify byte*) SCREEN + (byte) idx#14) ← (byte~) main::$3 + (byte) idx#5 ← ++ (byte) idx#14 to:main::@return main::@return: scope:[main] from main::@4 - (byte) idx#11 ← phi( main::@4/(byte) idx#4 ) - (byte) idx#5 ← (byte) idx#11 + (byte) idx#15 ← phi( main::@4/(byte) idx#5 ) + (byte) idx#6 ← (byte) idx#15 return to:@return @@ -96,22 +104,35 @@ euclid::@return: scope:[euclid] from euclid::@3 (byte) euclid::return#5 ← (byte) euclid::return#10 return to:@return -@1: scope:[] from @begin - (byte) idx#14 ← phi( @begin/(byte) idx#0 ) + +(void()) _start() +_start: scope:[_start] from + (byte) idx#20 ← phi( ) + call _init + to:_start::@1 +_start::@1: scope:[_start] from _start + (byte) idx#16 ← phi( _start/(byte) idx#1 ) + (byte) idx#7 ← (byte) idx#16 call main - to:@2 -@2: scope:[] from @1 - (byte) idx#12 ← phi( @1/(byte) idx#5 ) - (byte) idx#6 ← (byte) idx#12 - to:@end -@end: scope:[] from @2 + to:_start::@2 +_start::@2: scope:[_start] from _start::@1 + (byte) idx#17 ← phi( _start::@1/(byte) idx#6 ) + (byte) idx#8 ← (byte) idx#17 + to:_start::@return +_start::@return: scope:[_start] from _start::@2 + (byte) idx#18 ← phi( _start::@2/(byte) idx#8 ) + (byte) idx#9 ← (byte) idx#18 + return + to:@return SYMBOL TABLE SSA -(label) @1 -(label) @2 -(label) @begin -(label) @end (const nomodify byte*) SCREEN = (byte*)(number) $400 +(void()) _init() +(label) _init::@return +(void()) _start() +(label) _start::@1 +(label) _start::@2 +(label) _start::@return (byte()) euclid((byte) euclid::a , (byte) euclid::b) (bool~) euclid::$0 (bool~) euclid::$1 @@ -166,7 +187,13 @@ SYMBOL TABLE SSA (byte) idx#12 (byte) idx#13 (byte) idx#14 +(byte) idx#15 +(byte) idx#16 +(byte) idx#17 +(byte) idx#18 +(byte) idx#19 (byte) idx#2 +(byte) idx#20 (byte) idx#3 (byte) idx#4 (byte) idx#5 @@ -185,6 +212,7 @@ SYMBOL TABLE SSA (label) main::@4 (label) main::@return +Does this handle main() / _start() correctly? Adding number conversion cast (unumber) $80 in (byte) euclid::a#0 ← (number) $80 Adding number conversion cast (unumber) 2 in (byte) euclid::b#0 ← (number) 2 Adding number conversion cast (unumber) $a9 in (byte) euclid::a#1 ← (number) $a9 @@ -222,27 +250,29 @@ Finalized unsigned number type (byte) $9b Finalized unsigned number type (byte) $63 Finalized unsigned number type (byte) 3 Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias idx#0 = idx#10 idx#1 Alias euclid::return#0 = euclid::return#6 -Alias idx#13 = idx#7 +Alias idx#11 = idx#19 Alias euclid::return#1 = euclid::return#7 -Alias idx#1 = idx#8 +Alias idx#12 = idx#2 Alias euclid::return#2 = euclid::return#8 -Alias idx#2 = idx#9 +Alias idx#13 = idx#3 Alias euclid::return#3 = euclid::return#9 -Alias idx#10 = idx#3 -Alias idx#11 = idx#4 idx#5 +Alias idx#14 = idx#4 +Alias idx#15 = idx#5 idx#6 Alias euclid::a#5 = euclid::a#6 euclid::a#7 euclid::return#4 euclid::a#8 euclid::a#9 euclid::return#10 euclid::return#5 Alias euclid::b#5 = euclid::b#6 euclid::b#7 euclid::b#8 Alias euclid::a#4 = euclid::$3 Alias euclid::b#4 = euclid::$2 -Alias idx#0 = idx#14 -Alias idx#12 = idx#6 +Alias idx#16 = idx#7 +Alias idx#17 = idx#8 idx#18 idx#9 Successful SSA optimization Pass2AliasElimination -Identical Phi Values (byte) idx#13 (byte) idx#0 -Identical Phi Values (byte) idx#12 (byte) idx#11 +Identical Phi Values (byte) idx#11 (byte) idx#16 +Identical Phi Values (byte) idx#16 (byte) idx#0 +Identical Phi Values (byte) idx#17 (byte) idx#15 Successful SSA optimization Pass2IdenticalPhiElimination -Simple Condition (bool~) euclid::$0 [34] if((byte) euclid::a#5!=(byte) euclid::b#5) goto euclid::@2 -Simple Condition (bool~) euclid::$1 [36] if((byte) euclid::a#5>(byte) euclid::b#5) goto euclid::@4 +Simple Condition (bool~) euclid::$0 [35] if((byte) euclid::a#5!=(byte) euclid::b#5) goto euclid::@2 +Simple Condition (bool~) euclid::$1 [37] if((byte) euclid::a#5>(byte) euclid::b#5) goto euclid::@4 Successful SSA optimization Pass2ConditionalJumpSimplification Constant (const byte) idx#0 = 0 Constant (const byte) euclid::a#0 = $80 @@ -254,21 +284,34 @@ Constant (const byte) euclid::b#2 = $9b Constant (const byte) euclid::a#3 = $63 Constant (const byte) euclid::b#3 = 3 Successful SSA optimization Pass2ConstantIdentification -Simplifying expression containing zero SCREEN in [7] *((const nomodify byte*) SCREEN + (const byte) idx#0) ← (byte~) main::$0 +Simplifying expression containing zero SCREEN in [8] *((const nomodify byte*) SCREEN + (const byte) idx#0) ← (byte~) main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused variable (byte) idx#11 and assignment [19] (byte) idx#11 ← ++ (byte) idx#10 +Eliminating unused variable (byte) idx#15 and assignment [20] (byte) idx#15 ← ++ (byte) idx#14 +Eliminating unused variable - keeping the phi block (byte) idx#20 Successful SSA optimization PassNEliminateUnusedVars -Constant right-side identified [4] (byte) idx#1 ← ++ (const byte) idx#0 +Removing call to empty procedure call _init +Removing unused procedure _init +Removing unused procedure block _init +Removing unused procedure block _init::@return +Successful SSA optimization PassNEliminateEmptyProcedure +Does this handle main() / _start() correctly? +Constant right-side identified [4] (byte) idx#12 ← ++ (const byte) idx#0 Successful SSA optimization Pass2ConstantRValueConsolidation -Constant (const byte) idx#1 = ++idx#0 +Constant (const byte) idx#12 = ++idx#0 Successful SSA optimization Pass2ConstantIdentification -Constant right-side identified [8] (byte) idx#2 ← ++ (const byte) idx#1 +Removing unused procedure _start +Removing unused procedure block _start +Removing unused procedure block _start::@1 +Removing unused procedure block _start::@2 +Removing unused procedure block _start::@return +Successful SSA optimization PassNEliminateEmptyStart +Constant right-side identified [8] (byte) idx#13 ← ++ (const byte) idx#12 Successful SSA optimization Pass2ConstantRValueConsolidation -Constant (const byte) idx#2 = ++idx#1 +Constant (const byte) idx#13 = ++idx#12 Successful SSA optimization Pass2ConstantIdentification -Constant right-side identified [12] (byte) idx#10 ← ++ (const byte) idx#2 +Constant right-side identified [12] (byte) idx#14 ← ++ (const byte) idx#13 Successful SSA optimization Pass2ConstantRValueConsolidation -Constant (const byte) idx#10 = ++idx#2 +Constant (const byte) idx#14 = ++idx#13 Successful SSA optimization Pass2ConstantIdentification Inlining constant with var siblings (const byte) euclid::a#0 Inlining constant with var siblings (const byte) euclid::b#0 @@ -279,20 +322,20 @@ Inlining constant with var siblings (const byte) euclid::b#2 Inlining constant with var siblings (const byte) euclid::a#3 Inlining constant with var siblings (const byte) euclid::b#3 Inlining constant with different constant siblings (const byte) idx#0 -Inlining constant with different constant siblings (const byte) idx#1 -Inlining constant with different constant siblings (const byte) idx#2 -Inlining constant with different constant siblings (const byte) idx#10 -Constant inlined idx#10 = ++++++(byte) 0 +Inlining constant with different constant siblings (const byte) idx#12 +Inlining constant with different constant siblings (const byte) idx#13 +Inlining constant with different constant siblings (const byte) idx#14 +Constant inlined idx#12 = ++(byte) 0 +Constant inlined idx#14 = ++++++(byte) 0 +Constant inlined idx#13 = ++++(byte) 0 Constant inlined euclid::b#0 = (byte) 2 Constant inlined euclid::a#1 = (byte) $a9 -Constant inlined idx#2 = ++++(byte) 0 Constant inlined euclid::a#0 = (byte) $80 Constant inlined euclid::b#2 = (byte) $9b Constant inlined euclid::a#3 = (byte) $63 Constant inlined idx#0 = (byte) 0 Constant inlined euclid::b#1 = (byte) $45 Constant inlined euclid::a#2 = (byte) $ff -Constant inlined idx#1 = ++(byte) 0 Constant inlined euclid::b#3 = (byte) 3 Successful SSA optimization Pass2ConstantInlining Consolidated array index constant in *(SCREEN+++0) @@ -306,121 +349,105 @@ Successful SSA optimization Pass2ConstantSimplification Simplifying constant integer increment ++1 Simplifying constant integer increment ++2 Successful SSA optimization Pass2ConstantSimplification -Adding NOP phi() at start of @begin -Adding NOP phi() at start of @1 -Adding NOP phi() at start of @2 -Adding NOP phi() at start of @end Adding NOP phi() at start of main Adding NOP phi() at start of euclid::@3 CALL GRAPH -Calls in [] to main:2 -Calls in [main] to euclid:6 euclid:10 euclid:14 euclid:18 +Calls in [main] to euclid:1 euclid:5 euclid:9 euclid:13 +Does this handle main() / _start() correctly? Created 4 initial phi equivalence classes -Coalesced [24] euclid::a#11 ← euclid::a#10 -Coalesced [25] euclid::b#10 ← euclid::b#9 -Coalesced (already) [32] euclid::a#13 ← euclid::a#5 -Coalesced [33] euclid::b#12 ← euclid::b#4 -Coalesced [35] euclid::a#12 ← euclid::a#4 -Coalesced (already) [36] euclid::b#11 ← euclid::b#5 +Coalesced [19] euclid::a#11 ← euclid::a#10 +Coalesced [20] euclid::b#10 ← euclid::b#9 +Coalesced (already) [27] euclid::a#13 ← euclid::a#5 +Coalesced [28] euclid::b#12 ← euclid::b#4 +Coalesced [30] euclid::a#12 ← euclid::a#4 +Coalesced (already) [31] euclid::b#11 ← euclid::b#5 Coalesced down to 2 phi equivalence classes -Culled Empty Block (label) @2 Culled Empty Block (label) euclid::@3 Renumbering block euclid::@4 to euclid::@3 Renumbering block euclid::@5 to euclid::@4 -Adding NOP phi() at start of @begin -Adding NOP phi() at start of @1 -Adding NOP phi() at start of @end Adding NOP phi() at start of main +Does this handle main() / _start() correctly? FINAL CONTROL FLOW GRAPH -@begin: scope:[] from - [0] phi() - to:@1 -@1: scope:[] from @begin - [1] phi() - [2] call main - to:@end -@end: scope:[] from @1 - [3] phi() (void()) main() -main: scope:[main] from @1 - [4] phi() - [5] call euclid - [6] (byte) euclid::return#0 ← (byte) euclid::a#5 +main: scope:[main] from + [0] phi() + [1] call euclid + [2] (byte) euclid::return#0 ← (byte) euclid::a#5 to:main::@1 main::@1: scope:[main] from main - [7] (byte~) main::$0 ← (byte) euclid::return#0 - [8] *((const nomodify byte*) SCREEN) ← (byte~) main::$0 - [9] call euclid - [10] (byte) euclid::return#1 ← (byte) euclid::a#5 + [3] (byte~) main::$0 ← (byte) euclid::return#0 + [4] *((const nomodify byte*) SCREEN) ← (byte~) main::$0 + [5] call euclid + [6] (byte) euclid::return#1 ← (byte) euclid::a#5 to:main::@2 main::@2: scope:[main] from main::@1 - [11] (byte~) main::$1 ← (byte) euclid::return#1 - [12] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$1 - [13] call euclid - [14] (byte) euclid::return#2 ← (byte) euclid::a#5 + [7] (byte~) main::$1 ← (byte) euclid::return#1 + [8] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$1 + [9] call euclid + [10] (byte) euclid::return#2 ← (byte) euclid::a#5 to:main::@3 main::@3: scope:[main] from main::@2 - [15] (byte~) main::$2 ← (byte) euclid::return#2 - [16] *((const nomodify byte*) SCREEN+(byte) 2) ← (byte~) main::$2 - [17] call euclid - [18] (byte) euclid::return#3 ← (byte) euclid::a#5 + [11] (byte~) main::$2 ← (byte) euclid::return#2 + [12] *((const nomodify byte*) SCREEN+(byte) 2) ← (byte~) main::$2 + [13] call euclid + [14] (byte) euclid::return#3 ← (byte) euclid::a#5 to:main::@4 main::@4: scope:[main] from main::@3 - [19] (byte~) main::$3 ← (byte) euclid::return#3 - [20] *((const nomodify byte*) SCREEN+(byte) 3) ← (byte~) main::$3 + [15] (byte~) main::$3 ← (byte) euclid::return#3 + [16] *((const nomodify byte*) SCREEN+(byte) 3) ← (byte~) main::$3 to:main::@return main::@return: scope:[main] from main::@4 - [21] return + [17] return to:@return (byte()) euclid((byte) euclid::a , (byte) euclid::b) euclid: scope:[euclid] from main main::@1 main::@2 main::@3 - [22] (byte) euclid::b#9 ← phi( main/(byte) 2 main::@1/(byte) $45 main::@2/(byte) $9b main::@3/(byte) 3 ) - [22] (byte) euclid::a#10 ← phi( main/(byte) $80 main::@1/(byte) $a9 main::@2/(byte) $ff main::@3/(byte) $63 ) + [18] (byte) euclid::b#9 ← phi( main/(byte) 2 main::@1/(byte) $45 main::@2/(byte) $9b main::@3/(byte) 3 ) + [18] (byte) euclid::a#10 ← phi( main/(byte) $80 main::@1/(byte) $a9 main::@2/(byte) $ff main::@3/(byte) $63 ) to:euclid::@1 euclid::@1: scope:[euclid] from euclid euclid::@3 euclid::@4 - [23] (byte) euclid::b#5 ← phi( euclid/(byte) euclid::b#9 euclid::@3/(byte) euclid::b#5 euclid::@4/(byte) euclid::b#4 ) - [23] (byte) euclid::a#5 ← phi( euclid/(byte) euclid::a#10 euclid::@3/(byte) euclid::a#4 euclid::@4/(byte) euclid::a#5 ) - [24] if((byte) euclid::a#5!=(byte) euclid::b#5) goto euclid::@2 + [19] (byte) euclid::b#5 ← phi( euclid/(byte) euclid::b#9 euclid::@3/(byte) euclid::b#5 euclid::@4/(byte) euclid::b#4 ) + [19] (byte) euclid::a#5 ← phi( euclid/(byte) euclid::a#10 euclid::@3/(byte) euclid::a#4 euclid::@4/(byte) euclid::a#5 ) + [20] if((byte) euclid::a#5!=(byte) euclid::b#5) goto euclid::@2 to:euclid::@return euclid::@return: scope:[euclid] from euclid::@1 - [25] return + [21] return to:@return euclid::@2: scope:[euclid] from euclid::@1 - [26] if((byte) euclid::a#5>(byte) euclid::b#5) goto euclid::@3 + [22] if((byte) euclid::a#5>(byte) euclid::b#5) goto euclid::@3 to:euclid::@4 euclid::@4: scope:[euclid] from euclid::@2 - [27] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 + [23] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 to:euclid::@1 euclid::@3: scope:[euclid] from euclid::@2 - [28] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 + [24] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 to:euclid::@1 VARIABLE REGISTER WEIGHTS (byte()) euclid((byte) euclid::a , (byte) euclid::b) (byte) euclid::a -(byte) euclid::a#10 101.0 -(byte) euclid::a#4 2002.0 -(byte) euclid::a#5 794.6666666666667 +(byte) euclid::a#10 11.0 +(byte) euclid::a#4 202.0 +(byte) euclid::a#5 80.66666666666666 (byte) euclid::b -(byte) euclid::b#4 2002.0 -(byte) euclid::b#5 1777.0 -(byte) euclid::b#9 101.0 +(byte) euclid::b#4 202.0 +(byte) euclid::b#5 179.5 +(byte) euclid::b#9 11.0 (byte) euclid::return -(byte) euclid::return#0 22.0 -(byte) euclid::return#1 22.0 -(byte) euclid::return#2 22.0 -(byte) euclid::return#3 22.0 +(byte) euclid::return#0 4.0 +(byte) euclid::return#1 4.0 +(byte) euclid::return#2 4.0 +(byte) euclid::return#3 4.0 (byte) idx (void()) main() -(byte~) main::$0 22.0 -(byte~) main::$1 22.0 -(byte~) main::$2 22.0 -(byte~) main::$3 22.0 +(byte~) main::$0 4.0 +(byte~) main::$1 4.0 +(byte~) main::$2 4.0 +(byte~) main::$3 4.0 Initial phi equivalence classes [ euclid::a#5 euclid::a#10 euclid::a#4 ] @@ -466,120 +493,104 @@ Target platform is c64basic / MOS6502X .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 - // @begin -__bbegin: - // [1] phi from @begin to @1 [phi:@begin->@1] -__b1_from___bbegin: - jmp __b1 - // @1 -__b1: - // [2] call main - // [4] phi from @1 to main [phi:@1->main] -main_from___b1: - jsr main - // [3] phi from @1 to @end [phi:@1->@end] -__bend_from___b1: - jmp __bend - // @end -__bend: // main main: { .label __0 = 5 .label __1 = 7 .label __2 = 9 .label __3 = $b - // [5] call euclid - // [22] phi from main to euclid [phi:main->euclid] + // [1] call euclid + // [18] phi from main to euclid [phi:main->euclid] euclid_from_main: - // [22] phi (byte) euclid::b#9 = (byte) 2 [phi:main->euclid#0] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::b#9 = (byte) 2 [phi:main->euclid#0] -- vbuz1=vbuc1 lda #2 sta.z euclid.b - // [22] phi (byte) euclid::a#10 = (byte) $80 [phi:main->euclid#1] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::a#10 = (byte) $80 [phi:main->euclid#1] -- vbuz1=vbuc1 lda #$80 sta.z euclid.a jsr euclid - // [6] (byte) euclid::return#0 ← (byte) euclid::a#5 -- vbuz1=vbuz2 + // [2] (byte) euclid::return#0 ← (byte) euclid::a#5 -- vbuz1=vbuz2 lda.z euclid.a sta.z euclid.return jmp __b1 // main::@1 __b1: - // [7] (byte~) main::$0 ← (byte) euclid::return#0 -- vbuz1=vbuz2 + // [3] (byte~) main::$0 ← (byte) euclid::return#0 -- vbuz1=vbuz2 lda.z euclid.return sta.z __0 - // [8] *((const nomodify byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuz1 + // [4] *((const nomodify byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuz1 lda.z __0 sta SCREEN - // [9] call euclid - // [22] phi from main::@1 to euclid [phi:main::@1->euclid] + // [5] call euclid + // [18] phi from main::@1 to euclid [phi:main::@1->euclid] euclid_from___b1: - // [22] phi (byte) euclid::b#9 = (byte) $45 [phi:main::@1->euclid#0] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::b#9 = (byte) $45 [phi:main::@1->euclid#0] -- vbuz1=vbuc1 lda #$45 sta.z euclid.b - // [22] phi (byte) euclid::a#10 = (byte) $a9 [phi:main::@1->euclid#1] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::a#10 = (byte) $a9 [phi:main::@1->euclid#1] -- vbuz1=vbuc1 lda #$a9 sta.z euclid.a jsr euclid - // [10] (byte) euclid::return#1 ← (byte) euclid::a#5 -- vbuz1=vbuz2 + // [6] (byte) euclid::return#1 ← (byte) euclid::a#5 -- vbuz1=vbuz2 lda.z euclid.a sta.z euclid.return_1 jmp __b2 // main::@2 __b2: - // [11] (byte~) main::$1 ← (byte) euclid::return#1 -- vbuz1=vbuz2 + // [7] (byte~) main::$1 ← (byte) euclid::return#1 -- vbuz1=vbuz2 lda.z euclid.return_1 sta.z __1 - // [12] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$1 -- _deref_pbuc1=vbuz1 + // [8] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$1 -- _deref_pbuc1=vbuz1 lda.z __1 sta SCREEN+1 - // [13] call euclid - // [22] phi from main::@2 to euclid [phi:main::@2->euclid] + // [9] call euclid + // [18] phi from main::@2 to euclid [phi:main::@2->euclid] euclid_from___b2: - // [22] phi (byte) euclid::b#9 = (byte) $9b [phi:main::@2->euclid#0] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::b#9 = (byte) $9b [phi:main::@2->euclid#0] -- vbuz1=vbuc1 lda #$9b sta.z euclid.b - // [22] phi (byte) euclid::a#10 = (byte) $ff [phi:main::@2->euclid#1] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::a#10 = (byte) $ff [phi:main::@2->euclid#1] -- vbuz1=vbuc1 lda #$ff sta.z euclid.a jsr euclid - // [14] (byte) euclid::return#2 ← (byte) euclid::a#5 -- vbuz1=vbuz2 + // [10] (byte) euclid::return#2 ← (byte) euclid::a#5 -- vbuz1=vbuz2 lda.z euclid.a sta.z euclid.return_2 jmp __b3 // main::@3 __b3: - // [15] (byte~) main::$2 ← (byte) euclid::return#2 -- vbuz1=vbuz2 + // [11] (byte~) main::$2 ← (byte) euclid::return#2 -- vbuz1=vbuz2 lda.z euclid.return_2 sta.z __2 - // [16] *((const nomodify byte*) SCREEN+(byte) 2) ← (byte~) main::$2 -- _deref_pbuc1=vbuz1 + // [12] *((const nomodify byte*) SCREEN+(byte) 2) ← (byte~) main::$2 -- _deref_pbuc1=vbuz1 lda.z __2 sta SCREEN+2 - // [17] call euclid - // [22] phi from main::@3 to euclid [phi:main::@3->euclid] + // [13] call euclid + // [18] phi from main::@3 to euclid [phi:main::@3->euclid] euclid_from___b3: - // [22] phi (byte) euclid::b#9 = (byte) 3 [phi:main::@3->euclid#0] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::b#9 = (byte) 3 [phi:main::@3->euclid#0] -- vbuz1=vbuc1 lda #3 sta.z euclid.b - // [22] phi (byte) euclid::a#10 = (byte) $63 [phi:main::@3->euclid#1] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::a#10 = (byte) $63 [phi:main::@3->euclid#1] -- vbuz1=vbuc1 lda #$63 sta.z euclid.a jsr euclid - // [18] (byte) euclid::return#3 ← (byte) euclid::a#5 -- vbuz1=vbuz2 + // [14] (byte) euclid::return#3 ← (byte) euclid::a#5 -- vbuz1=vbuz2 lda.z euclid.a sta.z euclid.return_3 jmp __b4 // main::@4 __b4: - // [19] (byte~) main::$3 ← (byte) euclid::return#3 -- vbuz1=vbuz2 + // [15] (byte~) main::$3 ← (byte) euclid::return#3 -- vbuz1=vbuz2 lda.z euclid.return_3 sta.z __3 - // [20] *((const nomodify byte*) SCREEN+(byte) 3) ← (byte~) main::$3 -- _deref_pbuc1=vbuz1 + // [16] *((const nomodify byte*) SCREEN+(byte) 3) ← (byte~) main::$3 -- _deref_pbuc1=vbuz1 lda.z __3 sta SCREEN+3 jmp __breturn // main::@return __breturn: - // [21] return + // [17] return rts } // euclid @@ -592,34 +603,34 @@ euclid: { .label return_3 = $a .label a = 2 .label b = 3 - // [23] phi from euclid euclid::@3 euclid::@4 to euclid::@1 [phi:euclid/euclid::@3/euclid::@4->euclid::@1] + // [19] phi from euclid euclid::@3 euclid::@4 to euclid::@1 [phi:euclid/euclid::@3/euclid::@4->euclid::@1] __b1_from_euclid: __b1_from___b3: __b1_from___b4: - // [23] phi (byte) euclid::b#5 = (byte) euclid::b#9 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#0] -- register_copy - // [23] phi (byte) euclid::a#5 = (byte) euclid::a#10 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#1] -- register_copy + // [19] phi (byte) euclid::b#5 = (byte) euclid::b#9 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#0] -- register_copy + // [19] phi (byte) euclid::a#5 = (byte) euclid::a#10 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#1] -- register_copy jmp __b1 // euclid::@1 __b1: - // [24] if((byte) euclid::a#5!=(byte) euclid::b#5) goto euclid::@2 -- vbuz1_neq_vbuz2_then_la1 + // [20] if((byte) euclid::a#5!=(byte) euclid::b#5) goto euclid::@2 -- vbuz1_neq_vbuz2_then_la1 lda.z a cmp.z b bne __b2 jmp __breturn // euclid::@return __breturn: - // [25] return + // [21] return rts // euclid::@2 __b2: - // [26] if((byte) euclid::a#5>(byte) euclid::b#5) goto euclid::@3 -- vbuz1_gt_vbuz2_then_la1 + // [22] if((byte) euclid::a#5>(byte) euclid::b#5) goto euclid::@3 -- vbuz1_gt_vbuz2_then_la1 lda.z b cmp.z a bcc __b3 jmp __b4 // euclid::@4 __b4: - // [27] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 -- vbuz1=vbuz1_minus_vbuz2 + // [23] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 -- vbuz1=vbuz1_minus_vbuz2 lda.z b sec sbc.z a @@ -627,7 +638,7 @@ euclid: { jmp __b1_from___b4 // euclid::@3 __b3: - // [28] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 -- vbuz1=vbuz1_minus_vbuz2 + // [24] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 -- vbuz1=vbuz1_minus_vbuz2 lda.z a sec sbc.z b @@ -637,12 +648,12 @@ euclid: { // File Data REGISTER UPLIFT POTENTIAL REGISTERS -Statement [27] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 [ euclid::a#5 euclid::b#4 ] ( main:2::euclid:5 [ euclid::a#5 euclid::b#4 ] { { euclid::return#0 = euclid::a#5 } } main:2::euclid:9 [ euclid::a#5 euclid::b#4 ] { { euclid::return#1 = euclid::a#5 } } main:2::euclid:13 [ euclid::a#5 euclid::b#4 ] { { euclid::return#2 = euclid::a#5 } } main:2::euclid:17 [ euclid::a#5 euclid::b#4 ] { { euclid::return#3 = euclid::a#5 } } ) always clobbers reg byte a +Statement [23] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 [ euclid::a#5 euclid::b#4 ] ( euclid:1 [ euclid::a#5 euclid::b#4 ] { { euclid::return#0 = euclid::a#5 } } euclid:5 [ euclid::a#5 euclid::b#4 ] { { euclid::return#1 = euclid::a#5 } } euclid:9 [ euclid::a#5 euclid::b#4 ] { { euclid::return#2 = euclid::a#5 } } euclid:13 [ euclid::a#5 euclid::b#4 ] { { euclid::return#3 = euclid::a#5 } } ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:2 [ euclid::a#5 euclid::a#10 euclid::a#4 ] -Statement [28] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 [ euclid::b#5 euclid::a#4 ] ( main:2::euclid:5 [ euclid::b#5 euclid::a#4 ] { { euclid::return#0 = euclid::a#5 } } main:2::euclid:9 [ euclid::b#5 euclid::a#4 ] { { euclid::return#1 = euclid::a#5 } } main:2::euclid:13 [ euclid::b#5 euclid::a#4 ] { { euclid::return#2 = euclid::a#5 } } main:2::euclid:17 [ euclid::b#5 euclid::a#4 ] { { euclid::return#3 = euclid::a#5 } } ) always clobbers reg byte a +Statement [24] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 [ euclid::b#5 euclid::a#4 ] ( euclid:1 [ euclid::b#5 euclid::a#4 ] { { euclid::return#0 = euclid::a#5 } } euclid:5 [ euclid::b#5 euclid::a#4 ] { { euclid::return#1 = euclid::a#5 } } euclid:9 [ euclid::b#5 euclid::a#4 ] { { euclid::return#2 = euclid::a#5 } } euclid:13 [ euclid::b#5 euclid::a#4 ] { { euclid::return#3 = euclid::a#5 } } ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:3 [ euclid::b#5 euclid::b#9 euclid::b#4 ] -Statement [27] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 [ euclid::a#5 euclid::b#4 ] ( main:2::euclid:5 [ euclid::a#5 euclid::b#4 ] { { euclid::return#0 = euclid::a#5 } } main:2::euclid:9 [ euclid::a#5 euclid::b#4 ] { { euclid::return#1 = euclid::a#5 } } main:2::euclid:13 [ euclid::a#5 euclid::b#4 ] { { euclid::return#2 = euclid::a#5 } } main:2::euclid:17 [ euclid::a#5 euclid::b#4 ] { { euclid::return#3 = euclid::a#5 } } ) always clobbers reg byte a -Statement [28] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 [ euclid::b#5 euclid::a#4 ] ( main:2::euclid:5 [ euclid::b#5 euclid::a#4 ] { { euclid::return#0 = euclid::a#5 } } main:2::euclid:9 [ euclid::b#5 euclid::a#4 ] { { euclid::return#1 = euclid::a#5 } } main:2::euclid:13 [ euclid::b#5 euclid::a#4 ] { { euclid::return#2 = euclid::a#5 } } main:2::euclid:17 [ euclid::b#5 euclid::a#4 ] { { euclid::return#3 = euclid::a#5 } } ) always clobbers reg byte a +Statement [23] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 [ euclid::a#5 euclid::b#4 ] ( euclid:1 [ euclid::a#5 euclid::b#4 ] { { euclid::return#0 = euclid::a#5 } } euclid:5 [ euclid::a#5 euclid::b#4 ] { { euclid::return#1 = euclid::a#5 } } euclid:9 [ euclid::a#5 euclid::b#4 ] { { euclid::return#2 = euclid::a#5 } } euclid:13 [ euclid::a#5 euclid::b#4 ] { { euclid::return#3 = euclid::a#5 } } ) always clobbers reg byte a +Statement [24] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 [ euclid::b#5 euclid::a#4 ] ( euclid:1 [ euclid::b#5 euclid::a#4 ] { { euclid::return#0 = euclid::a#5 } } euclid:5 [ euclid::b#5 euclid::a#4 ] { { euclid::return#1 = euclid::a#5 } } euclid:9 [ euclid::b#5 euclid::a#4 ] { { euclid::return#2 = euclid::a#5 } } euclid:13 [ euclid::b#5 euclid::a#4 ] { { euclid::return#3 = euclid::a#5 } } ) always clobbers reg byte a Potential registers zp[1]:2 [ euclid::a#5 euclid::a#10 euclid::a#4 ] : zp[1]:2 , reg byte x , reg byte y , Potential registers zp[1]:3 [ euclid::b#5 euclid::b#9 euclid::b#4 ] : zp[1]:3 , reg byte x , reg byte y , Potential registers zp[1]:4 [ euclid::return#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , @@ -655,21 +666,21 @@ Potential registers zp[1]:10 [ euclid::return#3 ] : zp[1]:10 , reg byte a , reg Potential registers zp[1]:11 [ main::$3 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [euclid] 3,880: zp[1]:3 [ euclid::b#5 euclid::b#9 euclid::b#4 ] 2,897.67: zp[1]:2 [ euclid::a#5 euclid::a#10 euclid::a#4 ] 22: zp[1]:4 [ euclid::return#0 ] 22: zp[1]:6 [ euclid::return#1 ] 22: zp[1]:8 [ euclid::return#2 ] 22: zp[1]:10 [ euclid::return#3 ] -Uplift Scope [main] 22: zp[1]:5 [ main::$0 ] 22: zp[1]:7 [ main::$1 ] 22: zp[1]:9 [ main::$2 ] 22: zp[1]:11 [ main::$3 ] +Uplift Scope [euclid] 392.5: zp[1]:3 [ euclid::b#5 euclid::b#9 euclid::b#4 ] 293.67: zp[1]:2 [ euclid::a#5 euclid::a#10 euclid::a#4 ] 4: zp[1]:4 [ euclid::return#0 ] 4: zp[1]:6 [ euclid::return#1 ] 4: zp[1]:8 [ euclid::return#2 ] 4: zp[1]:10 [ euclid::return#3 ] +Uplift Scope [main] 4: zp[1]:5 [ main::$0 ] 4: zp[1]:7 [ main::$1 ] 4: zp[1]:9 [ main::$2 ] 4: zp[1]:11 [ main::$3 ] Uplift Scope [] -Uplifting [euclid] best 625 combination reg byte x [ euclid::b#5 euclid::b#9 euclid::b#4 ] zp[1]:2 [ euclid::a#5 euclid::a#10 euclid::a#4 ] reg byte a [ euclid::return#0 ] reg byte a [ euclid::return#1 ] zp[1]:8 [ euclid::return#2 ] zp[1]:10 [ euclid::return#3 ] +Uplifting [euclid] best 613 combination reg byte x [ euclid::b#5 euclid::b#9 euclid::b#4 ] zp[1]:2 [ euclid::a#5 euclid::a#10 euclid::a#4 ] reg byte a [ euclid::return#0 ] reg byte a [ euclid::return#1 ] zp[1]:8 [ euclid::return#2 ] zp[1]:10 [ euclid::return#3 ] Limited combination testing to 100 combinations of 2304 possible. -Uplifting [main] best 601 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] reg byte a [ main::$2 ] reg byte a [ main::$3 ] +Uplifting [main] best 589 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] reg byte a [ main::$2 ] reg byte a [ main::$3 ] Limited combination testing to 100 combinations of 256 possible. -Uplifting [] best 601 combination +Uplifting [] best 589 combination Attempting to uplift remaining variables inzp[1]:2 [ euclid::a#5 euclid::a#10 euclid::a#4 ] -Uplifting [euclid] best 601 combination zp[1]:2 [ euclid::a#5 euclid::a#10 euclid::a#4 ] +Uplifting [euclid] best 589 combination zp[1]:2 [ euclid::a#5 euclid::a#10 euclid::a#4 ] Attempting to uplift remaining variables inzp[1]:8 [ euclid::return#2 ] -Uplifting [euclid] best 595 combination reg byte a [ euclid::return#2 ] +Uplifting [euclid] best 583 combination reg byte a [ euclid::return#2 ] Attempting to uplift remaining variables inzp[1]:10 [ euclid::return#3 ] -Uplifting [euclid] best 589 combination reg byte a [ euclid::return#3 ] +Uplifting [euclid] best 577 combination reg byte a [ euclid::return#3 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -681,96 +692,80 @@ ASSEMBLER BEFORE OPTIMIZATION .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 - // @begin -__bbegin: - // [1] phi from @begin to @1 [phi:@begin->@1] -__b1_from___bbegin: - jmp __b1 - // @1 -__b1: - // [2] call main - // [4] phi from @1 to main [phi:@1->main] -main_from___b1: - jsr main - // [3] phi from @1 to @end [phi:@1->@end] -__bend_from___b1: - jmp __bend - // @end -__bend: // main main: { - // [5] call euclid - // [22] phi from main to euclid [phi:main->euclid] + // [1] call euclid + // [18] phi from main to euclid [phi:main->euclid] euclid_from_main: - // [22] phi (byte) euclid::b#9 = (byte) 2 [phi:main->euclid#0] -- vbuxx=vbuc1 + // [18] phi (byte) euclid::b#9 = (byte) 2 [phi:main->euclid#0] -- vbuxx=vbuc1 ldx #2 - // [22] phi (byte) euclid::a#10 = (byte) $80 [phi:main->euclid#1] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::a#10 = (byte) $80 [phi:main->euclid#1] -- vbuz1=vbuc1 lda #$80 sta.z euclid.a jsr euclid - // [6] (byte) euclid::return#0 ← (byte) euclid::a#5 -- vbuaa=vbuz1 + // [2] (byte) euclid::return#0 ← (byte) euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a jmp __b1 // main::@1 __b1: - // [7] (byte~) main::$0 ← (byte) euclid::return#0 - // [8] *((const nomodify byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa + // [3] (byte~) main::$0 ← (byte) euclid::return#0 + // [4] *((const nomodify byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa sta SCREEN - // [9] call euclid - // [22] phi from main::@1 to euclid [phi:main::@1->euclid] + // [5] call euclid + // [18] phi from main::@1 to euclid [phi:main::@1->euclid] euclid_from___b1: - // [22] phi (byte) euclid::b#9 = (byte) $45 [phi:main::@1->euclid#0] -- vbuxx=vbuc1 + // [18] phi (byte) euclid::b#9 = (byte) $45 [phi:main::@1->euclid#0] -- vbuxx=vbuc1 ldx #$45 - // [22] phi (byte) euclid::a#10 = (byte) $a9 [phi:main::@1->euclid#1] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::a#10 = (byte) $a9 [phi:main::@1->euclid#1] -- vbuz1=vbuc1 lda #$a9 sta.z euclid.a jsr euclid - // [10] (byte) euclid::return#1 ← (byte) euclid::a#5 -- vbuaa=vbuz1 + // [6] (byte) euclid::return#1 ← (byte) euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a jmp __b2 // main::@2 __b2: - // [11] (byte~) main::$1 ← (byte) euclid::return#1 - // [12] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$1 -- _deref_pbuc1=vbuaa + // [7] (byte~) main::$1 ← (byte) euclid::return#1 + // [8] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$1 -- _deref_pbuc1=vbuaa sta SCREEN+1 - // [13] call euclid - // [22] phi from main::@2 to euclid [phi:main::@2->euclid] + // [9] call euclid + // [18] phi from main::@2 to euclid [phi:main::@2->euclid] euclid_from___b2: - // [22] phi (byte) euclid::b#9 = (byte) $9b [phi:main::@2->euclid#0] -- vbuxx=vbuc1 + // [18] phi (byte) euclid::b#9 = (byte) $9b [phi:main::@2->euclid#0] -- vbuxx=vbuc1 ldx #$9b - // [22] phi (byte) euclid::a#10 = (byte) $ff [phi:main::@2->euclid#1] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::a#10 = (byte) $ff [phi:main::@2->euclid#1] -- vbuz1=vbuc1 lda #$ff sta.z euclid.a jsr euclid - // [14] (byte) euclid::return#2 ← (byte) euclid::a#5 -- vbuaa=vbuz1 + // [10] (byte) euclid::return#2 ← (byte) euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a jmp __b3 // main::@3 __b3: - // [15] (byte~) main::$2 ← (byte) euclid::return#2 - // [16] *((const nomodify byte*) SCREEN+(byte) 2) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa + // [11] (byte~) main::$2 ← (byte) euclid::return#2 + // [12] *((const nomodify byte*) SCREEN+(byte) 2) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa sta SCREEN+2 - // [17] call euclid - // [22] phi from main::@3 to euclid [phi:main::@3->euclid] + // [13] call euclid + // [18] phi from main::@3 to euclid [phi:main::@3->euclid] euclid_from___b3: - // [22] phi (byte) euclid::b#9 = (byte) 3 [phi:main::@3->euclid#0] -- vbuxx=vbuc1 + // [18] phi (byte) euclid::b#9 = (byte) 3 [phi:main::@3->euclid#0] -- vbuxx=vbuc1 ldx #3 - // [22] phi (byte) euclid::a#10 = (byte) $63 [phi:main::@3->euclid#1] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::a#10 = (byte) $63 [phi:main::@3->euclid#1] -- vbuz1=vbuc1 lda #$63 sta.z euclid.a jsr euclid - // [18] (byte) euclid::return#3 ← (byte) euclid::a#5 -- vbuaa=vbuz1 + // [14] (byte) euclid::return#3 ← (byte) euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a jmp __b4 // main::@4 __b4: - // [19] (byte~) main::$3 ← (byte) euclid::return#3 - // [20] *((const nomodify byte*) SCREEN+(byte) 3) ← (byte~) main::$3 -- _deref_pbuc1=vbuaa + // [15] (byte~) main::$3 ← (byte) euclid::return#3 + // [16] *((const nomodify byte*) SCREEN+(byte) 3) ← (byte~) main::$3 -- _deref_pbuc1=vbuaa sta SCREEN+3 jmp __breturn // main::@return __breturn: - // [21] return + // [17] return rts } // euclid @@ -778,32 +773,32 @@ main: { // euclid(byte zp(2) a, byte register(X) b) euclid: { .label a = 2 - // [23] phi from euclid euclid::@3 euclid::@4 to euclid::@1 [phi:euclid/euclid::@3/euclid::@4->euclid::@1] + // [19] phi from euclid euclid::@3 euclid::@4 to euclid::@1 [phi:euclid/euclid::@3/euclid::@4->euclid::@1] __b1_from_euclid: __b1_from___b3: __b1_from___b4: - // [23] phi (byte) euclid::b#5 = (byte) euclid::b#9 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#0] -- register_copy - // [23] phi (byte) euclid::a#5 = (byte) euclid::a#10 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#1] -- register_copy + // [19] phi (byte) euclid::b#5 = (byte) euclid::b#9 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#0] -- register_copy + // [19] phi (byte) euclid::a#5 = (byte) euclid::a#10 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#1] -- register_copy jmp __b1 // euclid::@1 __b1: - // [24] if((byte) euclid::a#5!=(byte) euclid::b#5) goto euclid::@2 -- vbuz1_neq_vbuxx_then_la1 + // [20] if((byte) euclid::a#5!=(byte) euclid::b#5) goto euclid::@2 -- vbuz1_neq_vbuxx_then_la1 cpx.z a bne __b2 jmp __breturn // euclid::@return __breturn: - // [25] return + // [21] return rts // euclid::@2 __b2: - // [26] if((byte) euclid::a#5>(byte) euclid::b#5) goto euclid::@3 -- vbuz1_gt_vbuxx_then_la1 + // [22] if((byte) euclid::a#5>(byte) euclid::b#5) goto euclid::@3 -- vbuz1_gt_vbuxx_then_la1 cpx.z a bcc __b3 jmp __b4 // euclid::@4 __b4: - // [27] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 -- vbuxx=vbuxx_minus_vbuz1 + // [23] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 -- vbuxx=vbuxx_minus_vbuz1 txa sec sbc.z a @@ -811,7 +806,7 @@ euclid: { jmp __b1_from___b4 // euclid::@3 __b3: - // [28] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 -- vbuz1=vbuz1_minus_vbuxx + // [24] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 -- vbuz1=vbuz1_minus_vbuxx txa eor #$ff sec @@ -823,8 +818,6 @@ euclid: { ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 -Removing instruction jmp __bend -Removing instruction jmp __b1 Removing instruction jmp __b2 Removing instruction jmp __b3 Removing instruction jmp __b4 @@ -835,16 +828,10 @@ Removing instruction jmp __b4 Succesful ASM optimization Pass5NextJumpElimination Replacing label __b1_from___b4 with __b1 Replacing label __b1_from___b3 with __b1 -Removing instruction __b1_from___bbegin: -Removing instruction __b1: -Removing instruction main_from___b1: -Removing instruction __bend_from___b1: Removing instruction __b1_from_euclid: Removing instruction __b1_from___b3: Removing instruction __b1_from___b4: Succesful ASM optimization Pass5RedundantLabelElimination -Removing instruction __bbegin: -Removing instruction __bend: Removing instruction euclid_from_main: Removing instruction __b1: Removing instruction euclid_from___b1: @@ -857,13 +844,8 @@ Removing instruction __breturn: Removing instruction __breturn: Removing instruction __b4: Succesful ASM optimization Pass5UnusedLabelElimination -Removing instruction jsr main -Succesful ASM optimization Pass5SkipBegin FINAL SYMBOL TABLE -(label) @1 -(label) @begin -(label) @end (const nomodify byte*) SCREEN = (byte*) 1024 (byte()) euclid((byte) euclid::a , (byte) euclid::b) (label) euclid::@1 @@ -872,24 +854,24 @@ FINAL SYMBOL TABLE (label) euclid::@4 (label) euclid::@return (byte) euclid::a -(byte) euclid::a#10 a zp[1]:2 101.0 -(byte) euclid::a#4 a zp[1]:2 2002.0 -(byte) euclid::a#5 a zp[1]:2 794.6666666666667 +(byte) euclid::a#10 a zp[1]:2 11.0 +(byte) euclid::a#4 a zp[1]:2 202.0 +(byte) euclid::a#5 a zp[1]:2 80.66666666666666 (byte) euclid::b -(byte) euclid::b#4 reg byte x 2002.0 -(byte) euclid::b#5 reg byte x 1777.0 -(byte) euclid::b#9 reg byte x 101.0 +(byte) euclid::b#4 reg byte x 202.0 +(byte) euclid::b#5 reg byte x 179.5 +(byte) euclid::b#9 reg byte x 11.0 (byte) euclid::return -(byte) euclid::return#0 reg byte a 22.0 -(byte) euclid::return#1 reg byte a 22.0 -(byte) euclid::return#2 reg byte a 22.0 -(byte) euclid::return#3 reg byte a 22.0 +(byte) euclid::return#0 reg byte a 4.0 +(byte) euclid::return#1 reg byte a 4.0 +(byte) euclid::return#2 reg byte a 4.0 +(byte) euclid::return#3 reg byte a 4.0 (byte) idx (void()) main() -(byte~) main::$0 reg byte a 22.0 -(byte~) main::$1 reg byte a 22.0 -(byte~) main::$2 reg byte a 22.0 -(byte~) main::$3 reg byte a 22.0 +(byte~) main::$0 reg byte a 4.0 +(byte~) main::$1 reg byte a 4.0 +(byte~) main::$2 reg byte a 4.0 +(byte~) main::$3 reg byte a 4.0 (label) main::@1 (label) main::@2 (label) main::@3 @@ -920,86 +902,79 @@ Score: 472 .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 - // @begin - // [1] phi from @begin to @1 [phi:@begin->@1] - // @1 - // [2] call main - // [4] phi from @1 to main [phi:@1->main] - // [3] phi from @1 to @end [phi:@1->@end] - // @end // main main: { // euclid(128,2) - // [5] call euclid - // [22] phi from main to euclid [phi:main->euclid] - // [22] phi (byte) euclid::b#9 = (byte) 2 [phi:main->euclid#0] -- vbuxx=vbuc1 + // [1] call euclid + // [18] phi from main to euclid [phi:main->euclid] + // [18] phi (byte) euclid::b#9 = (byte) 2 [phi:main->euclid#0] -- vbuxx=vbuc1 ldx #2 - // [22] phi (byte) euclid::a#10 = (byte) $80 [phi:main->euclid#1] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::a#10 = (byte) $80 [phi:main->euclid#1] -- vbuz1=vbuc1 lda #$80 sta.z euclid.a jsr euclid // euclid(128,2) - // [6] (byte) euclid::return#0 ← (byte) euclid::a#5 -- vbuaa=vbuz1 + // [2] (byte) euclid::return#0 ← (byte) euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a // main::@1 - // [7] (byte~) main::$0 ← (byte) euclid::return#0 + // [3] (byte~) main::$0 ← (byte) euclid::return#0 // SCREEN[idx++] = euclid(128,2) - // [8] *((const nomodify byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa + // [4] *((const nomodify byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa sta SCREEN // euclid(169,69) - // [9] call euclid - // [22] phi from main::@1 to euclid [phi:main::@1->euclid] - // [22] phi (byte) euclid::b#9 = (byte) $45 [phi:main::@1->euclid#0] -- vbuxx=vbuc1 + // [5] call euclid + // [18] phi from main::@1 to euclid [phi:main::@1->euclid] + // [18] phi (byte) euclid::b#9 = (byte) $45 [phi:main::@1->euclid#0] -- vbuxx=vbuc1 ldx #$45 - // [22] phi (byte) euclid::a#10 = (byte) $a9 [phi:main::@1->euclid#1] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::a#10 = (byte) $a9 [phi:main::@1->euclid#1] -- vbuz1=vbuc1 lda #$a9 sta.z euclid.a jsr euclid // euclid(169,69) - // [10] (byte) euclid::return#1 ← (byte) euclid::a#5 -- vbuaa=vbuz1 + // [6] (byte) euclid::return#1 ← (byte) euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a // main::@2 - // [11] (byte~) main::$1 ← (byte) euclid::return#1 + // [7] (byte~) main::$1 ← (byte) euclid::return#1 // SCREEN[idx++] = euclid(169,69) - // [12] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$1 -- _deref_pbuc1=vbuaa + // [8] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$1 -- _deref_pbuc1=vbuaa sta SCREEN+1 // euclid(255,155) - // [13] call euclid - // [22] phi from main::@2 to euclid [phi:main::@2->euclid] - // [22] phi (byte) euclid::b#9 = (byte) $9b [phi:main::@2->euclid#0] -- vbuxx=vbuc1 + // [9] call euclid + // [18] phi from main::@2 to euclid [phi:main::@2->euclid] + // [18] phi (byte) euclid::b#9 = (byte) $9b [phi:main::@2->euclid#0] -- vbuxx=vbuc1 ldx #$9b - // [22] phi (byte) euclid::a#10 = (byte) $ff [phi:main::@2->euclid#1] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::a#10 = (byte) $ff [phi:main::@2->euclid#1] -- vbuz1=vbuc1 lda #$ff sta.z euclid.a jsr euclid // euclid(255,155) - // [14] (byte) euclid::return#2 ← (byte) euclid::a#5 -- vbuaa=vbuz1 + // [10] (byte) euclid::return#2 ← (byte) euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a // main::@3 - // [15] (byte~) main::$2 ← (byte) euclid::return#2 + // [11] (byte~) main::$2 ← (byte) euclid::return#2 // SCREEN[idx++] = euclid(255,155) - // [16] *((const nomodify byte*) SCREEN+(byte) 2) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa + // [12] *((const nomodify byte*) SCREEN+(byte) 2) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa sta SCREEN+2 // euclid(99,3) - // [17] call euclid - // [22] phi from main::@3 to euclid [phi:main::@3->euclid] - // [22] phi (byte) euclid::b#9 = (byte) 3 [phi:main::@3->euclid#0] -- vbuxx=vbuc1 + // [13] call euclid + // [18] phi from main::@3 to euclid [phi:main::@3->euclid] + // [18] phi (byte) euclid::b#9 = (byte) 3 [phi:main::@3->euclid#0] -- vbuxx=vbuc1 ldx #3 - // [22] phi (byte) euclid::a#10 = (byte) $63 [phi:main::@3->euclid#1] -- vbuz1=vbuc1 + // [18] phi (byte) euclid::a#10 = (byte) $63 [phi:main::@3->euclid#1] -- vbuz1=vbuc1 lda #$63 sta.z euclid.a jsr euclid // euclid(99,3) - // [18] (byte) euclid::return#3 ← (byte) euclid::a#5 -- vbuaa=vbuz1 + // [14] (byte) euclid::return#3 ← (byte) euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a // main::@4 - // [19] (byte~) main::$3 ← (byte) euclid::return#3 + // [15] (byte~) main::$3 ← (byte) euclid::return#3 // SCREEN[idx++] = euclid(99,3) - // [20] *((const nomodify byte*) SCREEN+(byte) 3) ← (byte~) main::$3 -- _deref_pbuc1=vbuaa + // [16] *((const nomodify byte*) SCREEN+(byte) 3) ← (byte~) main::$3 -- _deref_pbuc1=vbuaa sta SCREEN+3 // main::@return // } - // [21] return + // [17] return rts } // euclid @@ -1007,28 +982,28 @@ main: { // euclid(byte zp(2) a, byte register(X) b) euclid: { .label a = 2 - // [23] phi from euclid euclid::@3 euclid::@4 to euclid::@1 [phi:euclid/euclid::@3/euclid::@4->euclid::@1] - // [23] phi (byte) euclid::b#5 = (byte) euclid::b#9 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#0] -- register_copy - // [23] phi (byte) euclid::a#5 = (byte) euclid::a#10 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#1] -- register_copy + // [19] phi from euclid euclid::@3 euclid::@4 to euclid::@1 [phi:euclid/euclid::@3/euclid::@4->euclid::@1] + // [19] phi (byte) euclid::b#5 = (byte) euclid::b#9 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#0] -- register_copy + // [19] phi (byte) euclid::a#5 = (byte) euclid::a#10 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#1] -- register_copy // euclid::@1 __b1: // while (a!=b) - // [24] if((byte) euclid::a#5!=(byte) euclid::b#5) goto euclid::@2 -- vbuz1_neq_vbuxx_then_la1 + // [20] if((byte) euclid::a#5!=(byte) euclid::b#5) goto euclid::@2 -- vbuz1_neq_vbuxx_then_la1 cpx.z a bne __b2 // euclid::@return // } - // [25] return + // [21] return rts // euclid::@2 __b2: // if(a>b) - // [26] if((byte) euclid::a#5>(byte) euclid::b#5) goto euclid::@3 -- vbuz1_gt_vbuxx_then_la1 + // [22] if((byte) euclid::a#5>(byte) euclid::b#5) goto euclid::@3 -- vbuz1_gt_vbuxx_then_la1 cpx.z a bcc __b3 // euclid::@4 // b = b-a - // [27] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 -- vbuxx=vbuxx_minus_vbuz1 + // [23] (byte) euclid::b#4 ← (byte) euclid::b#5 - (byte) euclid::a#5 -- vbuxx=vbuxx_minus_vbuz1 txa sec sbc.z a @@ -1037,7 +1012,7 @@ euclid: { // euclid::@3 __b3: // a = a-b - // [28] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 -- vbuz1=vbuz1_minus_vbuxx + // [24] (byte) euclid::a#4 ← (byte) euclid::a#5 - (byte) euclid::b#5 -- vbuz1=vbuz1_minus_vbuxx txa eor #$ff sec diff --git a/src/test/ref/euclid-problem-2.sym b/src/test/ref/euclid-problem-2.sym index 3aaebc0a9..c6ae1762b 100644 --- a/src/test/ref/euclid-problem-2.sym +++ b/src/test/ref/euclid-problem-2.sym @@ -1,6 +1,3 @@ -(label) @1 -(label) @begin -(label) @end (const nomodify byte*) SCREEN = (byte*) 1024 (byte()) euclid((byte) euclid::a , (byte) euclid::b) (label) euclid::@1 @@ -9,24 +6,24 @@ (label) euclid::@4 (label) euclid::@return (byte) euclid::a -(byte) euclid::a#10 a zp[1]:2 101.0 -(byte) euclid::a#4 a zp[1]:2 2002.0 -(byte) euclid::a#5 a zp[1]:2 794.6666666666667 +(byte) euclid::a#10 a zp[1]:2 11.0 +(byte) euclid::a#4 a zp[1]:2 202.0 +(byte) euclid::a#5 a zp[1]:2 80.66666666666666 (byte) euclid::b -(byte) euclid::b#4 reg byte x 2002.0 -(byte) euclid::b#5 reg byte x 1777.0 -(byte) euclid::b#9 reg byte x 101.0 +(byte) euclid::b#4 reg byte x 202.0 +(byte) euclid::b#5 reg byte x 179.5 +(byte) euclid::b#9 reg byte x 11.0 (byte) euclid::return -(byte) euclid::return#0 reg byte a 22.0 -(byte) euclid::return#1 reg byte a 22.0 -(byte) euclid::return#2 reg byte a 22.0 -(byte) euclid::return#3 reg byte a 22.0 +(byte) euclid::return#0 reg byte a 4.0 +(byte) euclid::return#1 reg byte a 4.0 +(byte) euclid::return#2 reg byte a 4.0 +(byte) euclid::return#3 reg byte a 4.0 (byte) idx (void()) main() -(byte~) main::$0 reg byte a 22.0 -(byte~) main::$1 reg byte a 22.0 -(byte~) main::$2 reg byte a 22.0 -(byte~) main::$3 reg byte a 22.0 +(byte~) main::$0 reg byte a 4.0 +(byte~) main::$1 reg byte a 4.0 +(byte~) main::$2 reg byte a 4.0 +(byte~) main::$3 reg byte a 4.0 (label) main::@1 (label) main::@2 (label) main::@3 diff --git a/src/test/ref/static-init-code-0.cfg b/src/test/ref/static-init-code-0.cfg index 1d73ee33e..266bfbe95 100644 --- a/src/test/ref/static-init-code-0.cfg +++ b/src/test/ref/static-init-code-0.cfg @@ -1,26 +1,31 @@ -__stackcall (void()) _start() +(void()) _start() _start: scope:[_start] from [0] phi() - [1] callexecute _init - [2] call main + [1] call _init to:_start::@1 _start::@1: scope:[_start] from _start - [3] return + [2] phi() + [3] call main + to:_start::@return +_start::@return: scope:[_start] from _start::@1 + [4] return to:@return (void()) main() -main: scope:[main] from _start - [4] *((const nomodify byte*) SCREEN) ← (volatile byte) c1 - [5] *((const nomodify byte*) SCREEN+(byte) 1) ← (volatile byte) c2 +main: scope:[main] from _start::@1 + [5] *((const nomodify byte*) SCREEN) ← (volatile byte) c1 + [6] *((const nomodify byte*) SCREEN+(byte) 1) ← (volatile byte) c2 to:main::@return main::@return: scope:[main] from main - [6] return + [7] return to:@return -__stackcall (void()) _init() -_init: scope:[_init] from - [7] (volatile byte) c1 ← (byte) 'o' - [8] (volatile byte) c2 ← (byte) 'k' - [9] return +(void()) _init() +_init: scope:[_init] from _start + [8] (volatile byte) c1 ← (byte) 'o' + [9] (volatile byte) c2 ← (byte) 'k' + to:_init::@return +_init::@return: scope:[_init] from _init + [10] return to:@return diff --git a/src/test/ref/static-init-code-0.log b/src/test/ref/static-init-code-0.log index 0ba9ed9da..b790874de 100644 --- a/src/test/ref/static-init-code-0.log +++ b/src/test/ref/static-init-code-0.log @@ -1,17 +1,18 @@ Resolved forward reference c2 to (volatile byte) c2 -Calling convention STACK_CALL adding prepare/execute/finalize for call _init CONTROL FLOW GRAPH SSA -__stackcall (void()) _init() -_init: scope:[_init] from +(void()) _init() +_init: scope:[_init] from _start (volatile byte) c1 ← (byte) 'o' (volatile byte) c2 ← (byte) 'k' + to:_init::@return +_init::@return: scope:[_init] from _init return to:@return (void()) main() -main: scope:[main] from _start +main: scope:[main] from _start::@1 *((const nomodify byte*) SCREEN + (number) 0) ← (volatile byte) c1 *((const nomodify byte*) SCREEN + (number) 1) ← (volatile byte) c2 to:main::@return @@ -19,20 +20,27 @@ main::@return: scope:[main] from main return to:@return -__stackcall (void()) _start() +(void()) _start() _start: scope:[_start] from - callexecute _init - call main + call _init to:_start::@1 _start::@1: scope:[_start] from _start + call main + to:_start::@2 +_start::@2: scope:[_start] from _start::@1 + to:_start::@return +_start::@return: scope:[_start] from _start::@2 return to:@return SYMBOL TABLE SSA (const nomodify byte*) SCREEN = (byte*)(number) $400 -__stackcall (void()) _init() -__stackcall (void()) _start() +(void()) _init() +(label) _init::@return +(void()) _start() (label) _start::@1 +(label) _start::@2 +(label) _start::@return (volatile byte) c1 loadstore (volatile byte) c2 loadstore (void()) main() @@ -53,47 +61,58 @@ Successful SSA optimization PassNSimplifyExpressionWithZero Consolidated array index constant in *(SCREEN+1) Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of _start +Adding NOP phi() at start of _start::@1 +Adding NOP phi() at start of _start::@2 CALL GRAPH -Calls in [_start] to _init:1 main:2 +Calls in [_start] to _init:1 main:3 +Does this handle main() / _start() correctly? Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) _start::@2 Adding NOP phi() at start of _start +Adding NOP phi() at start of _start::@1 +Does this handle main() / _start() correctly? FINAL CONTROL FLOW GRAPH -__stackcall (void()) _start() +(void()) _start() _start: scope:[_start] from [0] phi() - [1] callexecute _init - [2] call main + [1] call _init to:_start::@1 _start::@1: scope:[_start] from _start - [3] return + [2] phi() + [3] call main + to:_start::@return +_start::@return: scope:[_start] from _start::@1 + [4] return to:@return (void()) main() -main: scope:[main] from _start - [4] *((const nomodify byte*) SCREEN) ← (volatile byte) c1 - [5] *((const nomodify byte*) SCREEN+(byte) 1) ← (volatile byte) c2 +main: scope:[main] from _start::@1 + [5] *((const nomodify byte*) SCREEN) ← (volatile byte) c1 + [6] *((const nomodify byte*) SCREEN+(byte) 1) ← (volatile byte) c2 to:main::@return main::@return: scope:[main] from main - [6] return + [7] return to:@return -__stackcall (void()) _init() -_init: scope:[_init] from - [7] (volatile byte) c1 ← (byte) 'o' - [8] (volatile byte) c2 ← (byte) 'k' - [9] return +(void()) _init() +_init: scope:[_init] from _start + [8] (volatile byte) c1 ← (byte) 'o' + [9] (volatile byte) c2 ← (byte) 'k' + to:_init::@return +_init::@return: scope:[_init] from _init + [10] return to:@return VARIABLE REGISTER WEIGHTS -__stackcall (void()) _init() -__stackcall (void()) _start() -(volatile byte) c1 loadstore 22.0 -(volatile byte) c2 loadstore 11.0 +(void()) _init() +(void()) _start() +(volatile byte) c1 loadstore 4.4 +(volatile byte) c2 loadstore 4.4 (void()) main() Initial phi equivalence classes @@ -121,67 +140,75 @@ Target platform is c64basic / MOS6502X .label c2 = 3 // _start _start: { - // [1] callexecute _init -- jsr + // [1] call _init jsr _init - // [2] call main - jsr main + // [2] phi from _start to _start::@1 [phi:_start->_start::@1] + __b1_from__start: jmp __b1 // _start::@1 __b1: - // [3] return + // [3] call main + jsr main + jmp __breturn + // _start::@return + __breturn: + // [4] return rts } // main main: { - // [4] *((const nomodify byte*) SCREEN) ← (volatile byte) c1 -- _deref_pbuc1=vbuz1 + // [5] *((const nomodify byte*) SCREEN) ← (volatile byte) c1 -- _deref_pbuc1=vbuz1 lda.z c1 sta SCREEN - // [5] *((const nomodify byte*) SCREEN+(byte) 1) ← (volatile byte) c2 -- _deref_pbuc1=vbuz1 + // [6] *((const nomodify byte*) SCREEN+(byte) 1) ← (volatile byte) c2 -- _deref_pbuc1=vbuz1 lda.z c2 sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [6] return + // [7] return rts } // _init _init: { - // [7] (volatile byte) c1 ← (byte) 'o' -- vbuz1=vbuc1 + // [8] (volatile byte) c1 ← (byte) 'o' -- vbuz1=vbuc1 // Initialize a volatile ZP-variable (will be done in the initializer) lda #'o' sta.z c1 - // [8] (volatile byte) c2 ← (byte) 'k' -- vbuz1=vbuc1 + // [9] (volatile byte) c2 ← (byte) 'k' -- vbuz1=vbuc1 // Initialize another volatile ZP-variable (will be done in the initializer) lda #'k' sta.z c2 - // [9] return + jmp __breturn + // _init::@return + __breturn: + // [10] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS -Statement [4] *((const nomodify byte*) SCREEN) ← (volatile byte) c1 [ c2 ] ( ) always clobbers reg byte a -Statement [5] *((const nomodify byte*) SCREEN+(byte) 1) ← (volatile byte) c2 [ ] ( ) always clobbers reg byte a -Statement [7] (volatile byte) c1 ← (byte) 'o' [ ] ( ) always clobbers reg byte a -Statement [8] (volatile byte) c2 ← (byte) 'k' [ ] ( ) always clobbers reg byte a +Statement [5] *((const nomodify byte*) SCREEN) ← (volatile byte) c1 [ c2 ] ( main:3 [ c2 ] { } ) always clobbers reg byte a +Statement [6] *((const nomodify byte*) SCREEN+(byte) 1) ← (volatile byte) c2 [ ] ( main:3 [ ] { } ) always clobbers reg byte a +Statement [8] (volatile byte) c1 ← (byte) 'o' [ c1 ] ( _init:1 [ c1 ] { } ) always clobbers reg byte a +Statement [9] (volatile byte) c2 ← (byte) 'k' [ c1 c2 ] ( _init:1 [ c1 c2 ] { } ) always clobbers reg byte a Potential registers zp[1]:2 [ c1 ] : zp[1]:2 , Potential registers zp[1]:3 [ c2 ] : zp[1]:3 , REGISTER UPLIFT SCOPES -Uplift Scope [] 22: zp[1]:2 [ c1 ] 11: zp[1]:3 [ c2 ] +Uplift Scope [] 4.4: zp[1]:2 [ c1 ] 4.4: zp[1]:3 [ c2 ] Uplift Scope [_init] Uplift Scope [main] Uplift Scope [_start] -Uplifting [] best 60 combination zp[1]:2 [ c1 ] zp[1]:3 [ c2 ] -Uplifting [_init] best 60 combination -Uplifting [main] best 60 combination -Uplifting [_start] best 60 combination +Uplifting [] best 66 combination zp[1]:2 [ c1 ] zp[1]:3 [ c2 ] +Uplifting [_init] best 66 combination +Uplifting [main] best 66 combination +Uplifting [_start] best 66 combination Attempting to uplift remaining variables inzp[1]:2 [ c1 ] -Uplifting [] best 60 combination zp[1]:2 [ c1 ] +Uplifting [] best 66 combination zp[1]:2 [ c1 ] Attempting to uplift remaining variables inzp[1]:3 [ c2 ] -Uplifting [] best 60 combination zp[1]:3 [ c2 ] +Uplifting [] best 66 combination zp[1]:3 [ c2 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -198,41 +225,49 @@ ASSEMBLER BEFORE OPTIMIZATION .label c2 = 3 // _start _start: { - // [1] callexecute _init -- jsr + // [1] call _init jsr _init - // [2] call main - jsr main + // [2] phi from _start to _start::@1 [phi:_start->_start::@1] + __b1_from__start: jmp __b1 // _start::@1 __b1: - // [3] return + // [3] call main + jsr main + jmp __breturn + // _start::@return + __breturn: + // [4] return rts } // main main: { - // [4] *((const nomodify byte*) SCREEN) ← (volatile byte) c1 -- _deref_pbuc1=vbuz1 + // [5] *((const nomodify byte*) SCREEN) ← (volatile byte) c1 -- _deref_pbuc1=vbuz1 lda.z c1 sta SCREEN - // [5] *((const nomodify byte*) SCREEN+(byte) 1) ← (volatile byte) c2 -- _deref_pbuc1=vbuz1 + // [6] *((const nomodify byte*) SCREEN+(byte) 1) ← (volatile byte) c2 -- _deref_pbuc1=vbuz1 lda.z c2 sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [6] return + // [7] return rts } // _init _init: { - // [7] (volatile byte) c1 ← (byte) 'o' -- vbuz1=vbuc1 + // [8] (volatile byte) c1 ← (byte) 'o' -- vbuz1=vbuc1 // Initialize a volatile ZP-variable (will be done in the initializer) lda #'o' sta.z c1 - // [8] (volatile byte) c2 ← (byte) 'k' -- vbuz1=vbuc1 + // [9] (volatile byte) c2 ← (byte) 'k' -- vbuz1=vbuc1 // Initialize another volatile ZP-variable (will be done in the initializer) lda #'k' sta.z c2 - // [9] return + jmp __breturn + // _init::@return + __breturn: + // [10] return rts } // File Data @@ -240,18 +275,26 @@ _init: { ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __b1_from__start: +Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction __b1: Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE (const nomodify byte*) SCREEN = (byte*) 1024 -__stackcall (void()) _init() -__stackcall (void()) _start() +(void()) _init() +(label) _init::@return +(void()) _start() (label) _start::@1 -(volatile byte) c1 loadstore zp[1]:2 22.0 -(volatile byte) c2 loadstore zp[1]:3 11.0 +(label) _start::@return +(volatile byte) c1 loadstore zp[1]:2 4.4 +(volatile byte) c2 loadstore zp[1]:3 4.4 (void()) main() (label) main::@return @@ -276,42 +319,45 @@ Score: 54 .label c2 = 3 // _start _start: { - // [1] callexecute _init -- jsr + // [1] call _init jsr _init - // [2] call main - jsr main + // [2] phi from _start to _start::@1 [phi:_start->_start::@1] // _start::@1 - // [3] return + // [3] call main + jsr main + // _start::@return + // [4] return rts } // main main: { // SCREEN[0] = c1 - // [4] *((const nomodify byte*) SCREEN) ← (volatile byte) c1 -- _deref_pbuc1=vbuz1 + // [5] *((const nomodify byte*) SCREEN) ← (volatile byte) c1 -- _deref_pbuc1=vbuz1 lda.z c1 sta SCREEN // SCREEN[1] = c2 - // [5] *((const nomodify byte*) SCREEN+(byte) 1) ← (volatile byte) c2 -- _deref_pbuc1=vbuz1 + // [6] *((const nomodify byte*) SCREEN+(byte) 1) ← (volatile byte) c2 -- _deref_pbuc1=vbuz1 lda.z c2 sta SCREEN+1 // main::@return // } - // [6] return + // [7] return rts } // _init _init: { // c1 = 'o' - // [7] (volatile byte) c1 ← (byte) 'o' -- vbuz1=vbuc1 + // [8] (volatile byte) c1 ← (byte) 'o' -- vbuz1=vbuc1 // Initialize a volatile ZP-variable (will be done in the initializer) lda #'o' sta.z c1 // c2 = 'k' - // [8] (volatile byte) c2 ← (byte) 'k' -- vbuz1=vbuc1 + // [9] (volatile byte) c2 ← (byte) 'k' -- vbuz1=vbuc1 // Initialize another volatile ZP-variable (will be done in the initializer) lda #'k' sta.z c2 - // [9] return + // _init::@return + // [10] return rts } // File Data diff --git a/src/test/ref/static-init-code-0.sym b/src/test/ref/static-init-code-0.sym index 3a13898d7..3374f83a6 100644 --- a/src/test/ref/static-init-code-0.sym +++ b/src/test/ref/static-init-code-0.sym @@ -1,9 +1,11 @@ (const nomodify byte*) SCREEN = (byte*) 1024 -__stackcall (void()) _init() -__stackcall (void()) _start() +(void()) _init() +(label) _init::@return +(void()) _start() (label) _start::@1 -(volatile byte) c1 loadstore zp[1]:2 22.0 -(volatile byte) c2 loadstore zp[1]:3 11.0 +(label) _start::@return +(volatile byte) c1 loadstore zp[1]:2 4.4 +(volatile byte) c2 loadstore zp[1]:3 4.4 (void()) main() (label) main::@return diff --git a/src/test/ref/static-init-code-1.log b/src/test/ref/static-init-code-1.log index 72440b685..10126d6e7 100644 --- a/src/test/ref/static-init-code-1.log +++ b/src/test/ref/static-init-code-1.log @@ -10,18 +10,21 @@ main::@return: scope:[main] from main return to:@return -__stackcall (void()) _start() +(void()) _start() _start: scope:[_start] from call main to:_start::@1 _start::@1: scope:[_start] from _start + to:_start::@return +_start::@return: scope:[_start] from _start::@1 return to:@return SYMBOL TABLE SSA (const nomodify byte*) SCREEN = (byte*)(number) $400 -__stackcall (void()) _start() +(void()) _start() (label) _start::@1 +(label) _start::@return (void()) main() (label) main::@return @@ -37,6 +40,11 @@ Finalized unsigned number type (byte) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions Simplifying expression containing zero SCREEN in [0] *((const nomodify byte*) SCREEN + (byte) 0) ← (byte) 'o' Successful SSA optimization PassNSimplifyExpressionWithZero +Removing unused procedure _start +Removing unused procedure block _start +Removing unused procedure block _start::@1 +Removing unused procedure block _start::@return +Successful SSA optimization PassNEliminateEmptyStart Consolidated array index constant in *(SCREEN+1) Successful SSA optimization Pass2ConstantAdditionElimination CALL GRAPH @@ -90,8 +98,8 @@ main: { // File Data REGISTER UPLIFT POTENTIAL REGISTERS -Statement [0] *((const nomodify byte*) SCREEN) ← (byte) 'o' [ ] ( ) always clobbers reg byte a -Statement [1] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte) 'k' [ ] ( ) always clobbers reg byte a +Statement [0] *((const nomodify byte*) SCREEN) ← (byte) 'o' [ ] ( [ ] { } ) always clobbers reg byte a +Statement [1] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte) 'k' [ ] ( [ ] { } ) always clobbers reg byte a REGISTER UPLIFT SCOPES Uplift Scope [main] diff --git a/src/test/ref/static-init-code-2.asm b/src/test/ref/static-init-code-2.asm new file mode 100644 index 000000000..e6d8a6b0a --- /dev/null +++ b/src/test/ref/static-init-code-2.asm @@ -0,0 +1,18 @@ +// Tests static initialization code +// No initializer code should be needed (since all values are constant) +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const c1 = 'o' + .const c2 = 'k' + .label SCREEN = $400 +main: { + // SCREEN[0] = c1 + lda #c1 + sta SCREEN + // SCREEN[1] = c2 + lda #c2 + sta SCREEN+1 + // } + rts +} diff --git a/src/test/ref/static-init-code-2.cfg b/src/test/ref/static-init-code-2.cfg new file mode 100644 index 000000000..9c52558cd --- /dev/null +++ b/src/test/ref/static-init-code-2.cfg @@ -0,0 +1,9 @@ + +(void()) main() +main: scope:[main] from + [0] *((const nomodify byte*) SCREEN) ← (const byte) c1 + [1] *((const nomodify byte*) SCREEN+(byte) 1) ← (const byte) c2 + to:main::@return +main::@return: scope:[main] from main + [2] return + to:@return diff --git a/src/test/ref/static-init-code-2.log b/src/test/ref/static-init-code-2.log new file mode 100644 index 000000000..6820550f8 --- /dev/null +++ b/src/test/ref/static-init-code-2.log @@ -0,0 +1,207 @@ + +CONTROL FLOW GRAPH SSA + +(void()) _init() +_init: scope:[_init] from _start + to:_init::@return +_init::@return: scope:[_init] from _init + return + to:@return + +(void()) main() +main: scope:[main] from _start::@1 + *((const nomodify byte*) SCREEN + (number) 0) ← (const byte) c1 + *((const nomodify byte*) SCREEN + (number) 1) ← (const byte) c2 + to:main::@return +main::@return: scope:[main] from main + return + to:@return + +(void()) _start() +_start: scope:[_start] from + call _init + to:_start::@1 +_start::@1: scope:[_start] from _start + call main + to:_start::@2 +_start::@2: scope:[_start] from _start::@1 + to:_start::@return +_start::@return: scope:[_start] from _start::@2 + return + to:@return + +SYMBOL TABLE SSA +(const nomodify byte*) SCREEN = (byte*)(number) $400 +(void()) _init() +(label) _init::@return +(void()) _start() +(label) _start::@1 +(label) _start::@2 +(label) _start::@return +(const byte) c1 = (byte) 'o' +(const byte) c2 = (byte) 'k' +(void()) main() +(label) main::@return + +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) SCREEN + (number) 0) ← (const byte) c1 +Adding number conversion cast (unumber) 1 in *((const nomodify byte*) SCREEN + (number) 1) ← (const byte) c2 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant pointer cast (byte*) 1024 +Simplifying constant integer cast 0 +Simplifying constant integer cast 1 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 1 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Simplifying expression containing zero SCREEN in [1] *((const nomodify byte*) SCREEN + (byte) 0) ← (const byte) c1 +Successful SSA optimization PassNSimplifyExpressionWithZero +Removing call to empty procedure call _init +Removing unused procedure _init +Removing unused procedure block _init +Removing unused procedure block _init::@return +Successful SSA optimization PassNEliminateEmptyProcedure +Removing unused procedure _start +Removing unused procedure block _start +Removing unused procedure block _start::@1 +Removing unused procedure block _start::@2 +Removing unused procedure block _start::@return +Successful SSA optimization PassNEliminateEmptyStart +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination +CALL GRAPH + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes + +FINAL CONTROL FLOW GRAPH + +(void()) main() +main: scope:[main] from + [0] *((const nomodify byte*) SCREEN) ← (const byte) c1 + [1] *((const nomodify byte*) SCREEN+(byte) 1) ← (const byte) c2 + to:main::@return +main::@return: scope:[main] from main + [2] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(void()) main() + +Initial phi equivalence classes +Complete equivalence classes + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Tests static initialization code +// No initializer code should be needed (since all values are constant) + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .const c1 = 'o' + .const c2 = 'k' + .label SCREEN = $400 + // main +main: { + // [0] *((const nomodify byte*) SCREEN) ← (const byte) c1 -- _deref_pbuc1=vbuc2 + lda #c1 + sta SCREEN + // [1] *((const nomodify byte*) SCREEN+(byte) 1) ← (const byte) c2 -- _deref_pbuc1=vbuc2 + lda #c2 + sta SCREEN+1 + jmp __breturn + // main::@return + __breturn: + // [2] return + rts +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [0] *((const nomodify byte*) SCREEN) ← (const byte) c1 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [1] *((const nomodify byte*) SCREEN+(byte) 1) ← (const byte) c2 [ ] ( [ ] { } ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [] + +Uplifting [main] best 21 combination +Uplifting [] best 21 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Tests static initialization code +// No initializer code should be needed (since all values are constant) + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .const c1 = 'o' + .const c2 = 'k' + .label SCREEN = $400 + // main +main: { + // [0] *((const nomodify byte*) SCREEN) ← (const byte) c1 -- _deref_pbuc1=vbuc2 + lda #c1 + sta SCREEN + // [1] *((const nomodify byte*) SCREEN+(byte) 1) ← (const byte) c2 -- _deref_pbuc1=vbuc2 + lda #c2 + sta SCREEN+1 + jmp __breturn + // main::@return + __breturn: + // [2] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(const nomodify byte*) SCREEN = (byte*) 1024 +(const byte) c1 = (byte) 'o' +(const byte) c2 = (byte) 'k' +(void()) main() +(label) main::@return + + + +FINAL ASSEMBLER +Score: 18 + + // File Comments +// Tests static initialization code +// No initializer code should be needed (since all values are constant) + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .const c1 = 'o' + .const c2 = 'k' + .label SCREEN = $400 + // main +main: { + // SCREEN[0] = c1 + // [0] *((const nomodify byte*) SCREEN) ← (const byte) c1 -- _deref_pbuc1=vbuc2 + lda #c1 + sta SCREEN + // SCREEN[1] = c2 + // [1] *((const nomodify byte*) SCREEN+(byte) 1) ← (const byte) c2 -- _deref_pbuc1=vbuc2 + lda #c2 + sta SCREEN+1 + // main::@return + // } + // [2] return + rts +} + // File Data + diff --git a/src/test/ref/static-init-code-2.sym b/src/test/ref/static-init-code-2.sym new file mode 100644 index 000000000..c2e4c537d --- /dev/null +++ b/src/test/ref/static-init-code-2.sym @@ -0,0 +1,6 @@ +(const nomodify byte*) SCREEN = (byte*) 1024 +(const byte) c1 = (byte) 'o' +(const byte) c2 = (byte) 'k' +(void()) main() +(label) main::@return +