diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1CallStack.java b/src/main/java/dk/camelot64/kickc/passes/Pass1CallStack.java index 38cfa7b4e..9fdcdb20b 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1CallStack.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1CallStack.java @@ -53,6 +53,20 @@ public class Pass1CallStack extends Pass2SsaOptimization { if(createStackBase) CallingConventionStack.getStackBaseConstant(getScope()); + // Set variables modified in STACK_CALL procedures to load/store + for(Procedure procedure : getScope().getAllProcedures(true)) { + if(Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) { + Set modifiedVars = getProgram().getProcedureModifiedVars().getModifiedVars(procedure.getRef()); + for(VariableRef modifiedVar : modifiedVars) { + final Variable variable = getScope().getVariable(modifiedVar); + if(variable.isKindPhiMaster()) { + getLog().append("Converting PHI-variable modified inside __stackcall procedure "+procedure.getFullName()+"() to load/store "+variable.toString(getProgram())); + variable.setKind(Variable.Kind.LOAD_STORE); + } + } + } + } + // Transform STACK_CALL calls to call-prepare, call-execute, call-finalize for(ControlFlowBlock block : getGraph().getAllBlocks()) { ListIterator stmtIt = block.getStatements().listIterator(); diff --git a/src/test/kc/procedure-callingconvention-stack-10.kc b/src/test/kc/procedure-callingconvention-stack-10.kc index 0362a6677..d2ff78ed0 100644 --- a/src/test/kc/procedure-callingconvention-stack-10.kc +++ b/src/test/kc/procedure-callingconvention-stack-10.kc @@ -2,7 +2,6 @@ // Returning and passing struct values #pragma calling(__stackcall) -#pragma var_model(ma_zp) const char* SCREEN = 0x0400; char idx = 0; diff --git a/src/test/kc/procedure-callingconvention-stack-11.kc b/src/test/kc/procedure-callingconvention-stack-11.kc index ffefcd363..276582bcf 100644 --- a/src/test/kc/procedure-callingconvention-stack-11.kc +++ b/src/test/kc/procedure-callingconvention-stack-11.kc @@ -2,7 +2,6 @@ // Returning and passing struct of struct values #pragma calling(__stackcall) -#pragma var_model(ma_zp) const char* SCREEN = 0x0400; char idx = 0; diff --git a/src/test/kc/procedure-callingconvention-stack-12.kc b/src/test/kc/procedure-callingconvention-stack-12.kc index 2530d35ae..ae4e564d5 100644 --- a/src/test/kc/procedure-callingconvention-stack-12.kc +++ b/src/test/kc/procedure-callingconvention-stack-12.kc @@ -2,7 +2,6 @@ // Test that comments are handled correctly #pragma calling(__stackcall) -#pragma var_model(ma_zp) const char* SCREEN = 0x0400; char idx = 0; diff --git a/src/test/kc/procedure-callingconvention-stack-7.kc b/src/test/kc/procedure-callingconvention-stack-7.kc index 8abccdd7f..1f4e0aa63 100644 --- a/src/test/kc/procedure-callingconvention-stack-7.kc +++ b/src/test/kc/procedure-callingconvention-stack-7.kc @@ -2,7 +2,6 @@ // Illustrates live ranges for main::val and printline::i #pragma calling(__stackcall) -#pragma var_model(ma_zp) const char* SCREEN = 0x0400; diff --git a/src/test/kc/procedure-callingconvention-stack-8.kc b/src/test/kc/procedure-callingconvention-stack-8.kc index 4f07b5483..beb18b357 100644 --- a/src/test/kc/procedure-callingconvention-stack-8.kc +++ b/src/test/kc/procedure-callingconvention-stack-8.kc @@ -2,7 +2,6 @@ // Illustrates live ranges for printline::i and global variable val #pragma calling(__stackcall) -#pragma var_model(ma_zp) const char* SCREEN = 0x0400; diff --git a/src/test/kc/procedure-callingconvention-stack-9.kc b/src/test/kc/procedure-callingconvention-stack-9.kc index eaf323837..368ce875c 100644 --- a/src/test/kc/procedure-callingconvention-stack-9.kc +++ b/src/test/kc/procedure-callingconvention-stack-9.kc @@ -2,7 +2,6 @@ // Illustrates live range problem with function variable printother::i and global variable val #pragma calling(__stackcall) -#pragma var_model(ma_zp) const char* SCREEN = 0x0400; diff --git a/src/test/ref/procedure-callingconvention-stack-10.asm b/src/test/ref/procedure-callingconvention-stack-10.asm index d056fd49d..d2adbf741 100644 --- a/src/test/ref/procedure-callingconvention-stack-10.asm +++ b/src/test/ref/procedure-callingconvention-stack-10.asm @@ -4,9 +4,9 @@ :BasicUpstart(__bbegin) .pc = $80d "Program" .label SCREEN = $400 - .const OFFSET_STRUCT_POINT_Y = 1 .const STACK_BASE = $103 - .label idx = 2 + .const OFFSET_STRUCT_POINT_Y = 1 + .label idx = 3 __bbegin: // idx = 0 lda #0 @@ -39,20 +39,14 @@ print: { // } rts } -// get(byte register(X) i) get: { .const OFFSET_STACK_I = 0 - .label p = 6 tsx lda STACK_BASE+OFFSET_STACK_I,x tax // i/2 txa lsr - // p = { i, i/2 } - stx.z p - sta p+OFFSET_STRUCT_POINT_Y - // return p; tay // } txa @@ -64,9 +58,7 @@ get: { rts } main: { - .label i = 3 - .label p = 4 - // i=0 + .label i = 2 lda #0 sta.z i __b1: @@ -82,16 +74,15 @@ main: { pha pha jsr get + // p = get(i) + pla + tay pla tax - pla - // p = get(i) - stx.z p - sta p+OFFSET_STRUCT_POINT_Y // print(p) - txa + tya pha - lda p+OFFSET_STRUCT_POINT_Y + txa pha jsr print pla diff --git a/src/test/ref/procedure-callingconvention-stack-10.cfg b/src/test/ref/procedure-callingconvention-stack-10.cfg index edd6c0543..ddd16f59e 100644 --- a/src/test/ref/procedure-callingconvention-stack-10.cfg +++ b/src/test/ref/procedure-callingconvention-stack-10.cfg @@ -23,40 +23,35 @@ print::@return: scope:[print] from print __stackcall (struct Point()) get((byte) get::i) get: scope:[get] from - [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) - [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 - [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 - [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 - [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) - [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) + [11] (byte) get::return_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) + [12] (byte) get::return_y#0 ← (byte) get::return_x#0 >> (byte) 1 to:get::@return get::@return: scope:[get] from get - [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 - [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 - [19] return + [13] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 + [14] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 + [15] return to:@return __stackcall (void()) main() main: scope:[main] from - [20] (byte) main::i ← (byte) 0 + [16] phi() to:main::@1 main::@1: scope:[main] from main main::@2 - [21] if((byte) main::i<(byte) 5) goto main::@2 + [17] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 ) + [18] if((byte) main::i#2<(byte) 5) goto main::@2 to:main::@return main::@return: scope:[main] from main::@1 - [22] return + [19] return to:@return main::@2: scope:[main] from main::@1 - [23] stackpush(byte) ← (byte) main::i + [20] stackpush(byte) ← (byte) main::i#2 sideeffect stackpushbytes((number) 1) - [25] callexecute get - [26] (byte~) main::$1_x ← stackpull(byte) - [27] (byte~) main::$1_y ← stackpull(byte) - [28] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x - [29] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y - [30] stackpush(byte) ← *((byte*)&(struct Point) main::p) - [31] stackpush(byte) ← *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) - [32] callexecute print + [22] callexecute get + [23] (byte) main::p_x#0 ← stackpull(byte) + [24] (byte) main::p_y#0 ← stackpull(byte) + [25] stackpush(byte) ← (byte) main::p_x#0 + [26] stackpush(byte) ← (byte) main::p_y#0 + [27] callexecute print sideeffect stackpullbytes((number) 2) - [34] (byte) main::i ← ++ (byte) main::i + [29] (byte) main::i#1 ← ++ (byte) main::i#2 to:main::@1 diff --git a/src/test/ref/procedure-callingconvention-stack-10.log b/src/test/ref/procedure-callingconvention-stack-10.log index 6fcf68698..453ddac00 100644 --- a/src/test/ref/procedure-callingconvention-stack-10.log +++ b/src/test/ref/procedure-callingconvention-stack-10.log @@ -1,24 +1,30 @@ Created struct value member variable (byte~) main::$1_x Created struct value member variable (byte~) main::$1_y Converted struct value to member variables (struct Point~) main::$1 +Created struct value member variable (byte) main::p_x +Created struct value member variable (byte) main::p_y +Converted struct value to member variables (struct Point) main::p Created struct value member variable (byte) get::return_x Created struct value member variable (byte) get::return_y Converted struct value to member variables (struct Point) get::return +Created struct value member variable (byte) get::p_x +Created struct value member variable (byte) get::p_y +Converted struct value to member variables (struct Point) get::p Created struct value member variable (byte) print::p_x Created struct value member variable (byte) print::p_y Converted struct value to member variables (struct Point) print::p Converted procedure struct value parameter to member unwinding __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) Converted procedure call LValue to member unwinding { (byte~) main::$1_x, (byte~) main::$1_y } ← call get (byte) main::i Unwinding value copy (struct Point) main::p ← (struct Point~) main::$1 -Adding value simple copy *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_x -Adding value simple copy *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -Converted procedure struct value parameter to member unwinding in call (void~) main::$2 ← call print *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) +Adding value simple copy (byte) main::p_x ← (byte~) main::$1_x +Adding value simple copy (byte) main::p_y ← (byte~) main::$1_y +Converted procedure struct value parameter to member unwinding in call (void~) main::$2 ← call print (byte) main::p_x (byte) main::p_y Unwinding value copy (struct Point) get::p ← (struct Point){ (byte) get::i, (number~) get::$0 } -Adding value simple copy *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::i -Adding value simple copy *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (number~) get::$0 +Adding value simple copy (byte) get::p_x ← (byte) get::i +Adding value simple copy (byte) get::p_y ← (number~) get::$0 Unwinding value copy (struct Point) get::return ← (struct Point) get::p -Adding value simple copy (byte) get::return_x ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X) -Adding value simple copy (byte) get::return_y ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) +Adding value simple copy (byte) get::return_x ← (byte) get::p_x +Adding value simple copy (byte) get::return_y ← (byte) get::p_y Converted procedure struct return value to member unwinding return { (byte) get::return_x, (byte) get::return_y } Unwinding value copy (struct Point) print::p ← param((struct Point) print::p) Adding value simple copy (byte) print::p_x ← param((byte) print::p_x) @@ -33,8 +39,9 @@ Culled Empty Block (label) main::@6 Culled Empty Block (label) @1 Culled Empty Block (label) get::@1 Culled Empty Block (label) @2 +Converting PHI-variable modified inside __stackcall procedure main() to load/store (byte) idx Calling convention STACK_CALL adding prepare/execute/finalize for { (byte~) main::$1_x, (byte~) main::$1_y } ← call get (byte) main::i -Calling convention STACK_CALL adding prepare/execute/finalize for call print *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) +Calling convention STACK_CALL adding prepare/execute/finalize for call print (byte) main::p_x (byte) main::p_y Calling convention STACK_CALL adding prepare/execute/finalize for call main Calling convention STACK_CALL replacing param((byte) get::i) with stackidx(byte,(const byte) get::OFFSET_STACK_I) Calling convention STACK_CALL replacing param((byte) print::p_x) with stackidx(byte,(const byte) print::OFFSET_STACK_P_X) @@ -44,8 +51,8 @@ Calling convention STACK_CALL adding stack return stackidx(byte,get::OFFSET_STAC Calling convention STACK_CALL adding stack pull main::$1_x ← stackpull(byte) Calling convention STACK_CALL adding stack pull main::$1_y ← stackpull(byte) Calling convention STACK_CALL adding stack push stackpush(byte) ← main::i -Calling convention STACK_CALL adding stack push stackpush(byte) ← *((byte*)&main::p+OFFSET_STRUCT_POINT_X) -Calling convention STACK_CALL adding stack push stackpush(byte) ← *((byte*)&main::p+OFFSET_STRUCT_POINT_Y) +Calling convention STACK_CALL adding stack push stackpush(byte) ← main::p_x +Calling convention STACK_CALL adding stack push stackpush(byte) ← main::p_y CONTROL FLOW GRAPH SSA @begin: scope:[] from @@ -54,26 +61,27 @@ CONTROL FLOW GRAPH SSA __stackcall (void()) main() main: scope:[main] from - (byte) main::i ← (byte) 0 + (byte) main::i#0 ← (byte) 0 to:main::@1 main::@1: scope:[main] from main main::@2 - (bool~) main::$0 ← (byte) main::i < (number) 5 + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#1 ) + (bool~) main::$0 ← (byte) main::i#2 < (number) 5 if((bool~) main::$0) goto main::@2 to:main::@return main::@2: scope:[main] from main::@1 - stackpush(byte) ← (byte) main::i + (byte) main::i#3 ← phi( main::@1/(byte) main::i#2 ) + stackpush(byte) ← (byte) main::i#3 sideeffect stackpushbytes((number) 1) callexecute get (byte~) main::$1_x ← stackpull(byte) (byte~) main::$1_y ← stackpull(byte) - *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_x - *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y - (struct Point) main::p ← struct-unwound {*((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)} - stackpush(byte) ← *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) - stackpush(byte) ← *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) + (byte) main::p_x#0 ← (byte~) main::$1_x + (byte) main::p_y#0 ← (byte~) main::$1_y + stackpush(byte) ← (byte) main::p_x#0 + stackpush(byte) ← (byte) main::p_y#0 callexecute print sideeffect stackpullbytes((number) 2) - (byte) main::i ← ++ (byte) main::i + (byte) main::i#1 ← ++ (byte) main::i#3 to:main::@1 main::@return: scope:[main] from main::@1 return @@ -83,11 +91,10 @@ __stackcall (struct Point()) get((byte) get::i) get: scope:[get] from (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) (number~) get::$0 ← (byte) get::i#0 / (number) 2 - *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::i#0 - *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (number~) get::$0 - (struct Point) get::p ← struct-unwound {*((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y)} - (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X) - (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) + (byte) get::p_x#0 ← (byte) get::i#0 + (byte) get::p_y#0 ← (number~) get::$0 + (byte) get::return_x#0 ← (byte) get::p_x#0 + (byte) get::return_y#0 ← (byte) get::p_y#0 (struct Point) get::return#0 ← struct-unwound {(byte) get::return_x#0, (byte) get::return_y#0} to:get::@return get::@return: scope:[get] from get @@ -121,8 +128,8 @@ SYMBOL TABLE SSA (label) @end (const byte) OFFSET_STRUCT_POINT_X = (byte) 0 (const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 -(byte) Point::x loadstore -(byte) Point::y loadstore +(byte) Point::x +(byte) Point::y (const byte*) SCREEN = (byte*)(number) $400 (const word) STACK_BASE = (word) $103 __stackcall (struct Point()) get((byte) get::i) @@ -132,7 +139,10 @@ __stackcall (struct Point()) get((byte) get::i) (const byte) get::OFFSET_STACK_RETURN = (byte) 0 (byte) get::i (byte) get::i#0 -(struct Point) get::p loadstore +(byte) get::p_x +(byte) get::p_x#0 +(byte) get::p_y +(byte) get::p_y#0 (struct Point) get::return (struct Point) get::return#0 (byte) get::return_x @@ -149,8 +159,15 @@ __stackcall (void()) main() (label) main::@1 (label) main::@2 (label) main::@return -(byte) main::i loadstore -(struct Point) main::p loadstore +(byte) main::i +(byte) main::i#0 +(byte) main::i#1 +(byte) main::i#2 +(byte) main::i#3 +(byte) main::p_x +(byte) main::p_x#0 +(byte) main::p_y +(byte) main::p_y#0 __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) (label) print::@return (const byte) print::OFFSET_STACK_P_X = (byte) 1 @@ -160,7 +177,7 @@ __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) (byte) print::p_y (byte) print::p_y#0 -Adding number conversion cast (unumber) 5 in (bool~) main::$0 ← (byte) main::i < (number) 5 +Adding number conversion cast (unumber) 5 in (bool~) main::$0 ← (byte) main::i#2 < (number) 5 Adding number conversion cast (unumber) 2 in (number~) get::$0 ← (byte) get::i#0 / (number) 2 Adding number conversion cast (unumber) get::$0 in (number~) get::$0 ← (byte) get::i#0 / (unumber)(number) 2 Successful SSA optimization PassNAddNumberTypeConversions @@ -172,38 +189,43 @@ Finalized unsigned number type (byte) 5 Finalized unsigned number type (byte) 2 Successful SSA optimization PassNFinalizeNumberTypeConversions Inferred type updated to byte in (unumber~) get::$0 ← (byte) get::i#0 / (byte) 2 -Alias (byte) get::return_x#0 = (byte) get::return_x#1 -Alias (byte) get::return_y#0 = (byte) get::return_y#1 +Alias (byte) main::i#2 = (byte) main::i#3 +Alias (byte) main::p_x#0 = (byte~) main::$1_x +Alias (byte) main::p_y#0 = (byte~) main::$1_y +Alias (byte) get::return_x#0 = (byte) get::p_x#0 (byte) get::i#0 (byte) get::return_x#1 +Alias (byte) get::return_y#0 = (byte) get::p_y#0 (byte~) get::$0 (byte) get::return_y#1 Successful SSA optimization Pass2AliasElimination -Simple Condition (bool~) main::$0 [3] if((byte) main::i<(byte) 5) goto main::@2 +Simple Condition (bool~) main::$0 [4] if((byte) main::i#2<(byte) 5) goto main::@2 Successful SSA optimization Pass2ConditionalJumpSimplification -Removing C-classic struct-unwound assignment [11] (struct Point) main::p ← struct-unwound {*((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)} -Removing C-classic struct-unwound assignment [22] (struct Point) get::p ← struct-unwound {*((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y)} -Simplifying constant evaluating to zero (const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_X in [26] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::return_x#0 +Constant (const byte) main::i#0 = 0 +Successful SSA optimization Pass2ConstantIdentification +Simplifying constant evaluating to zero (const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_X in [19] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::return_x#0 Successful SSA optimization PassNSimplifyConstantZero -Simplifying expression containing zero (byte*)&main::p in [9] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_x -Simplifying expression containing zero (byte*)&main::p in [12] stackpush(byte) ← *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) -Simplifying expression containing zero (byte*)&get::p in [20] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::i#0 -Simplifying expression containing zero (byte*)&get::p in [23] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X) -Simplifying expression containing zero OFFSET_STRUCT_POINT_Y in [27] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 +Simplifying expression containing zero OFFSET_STRUCT_POINT_Y in [20] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused variable (struct Point) get::return#0 and assignment [22] (struct Point) get::return#0 ← struct-unwound {(byte) get::return_x#0, (byte) get::return_y#0} +Eliminating unused variable (struct Point) get::return#0 and assignment [16] (struct Point) get::return#0 ← struct-unwound {(byte) get::return_x#0, (byte) get::return_y#0} Eliminating unused constant (const byte) get::OFFSET_STACK_RETURN Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X Successful SSA optimization PassNEliminateUnusedVars -Rewriting division to use shift [17] (byte~) get::$0 ← (byte) get::i#0 / (byte) 2 +Rewriting division to use shift [15] (byte) get::return_y#0 ← (byte) get::return_x#0 / (byte) 2 Successful SSA optimization Pass2MultiplyToShiftRewriting +Inlining constant with var siblings (const byte) main::i#0 +Constant inlined main::i#0 = (byte) 0 +Successful SSA optimization Pass2ConstantInlining Adding NOP phi() at start of @3 Adding NOP phi() at start of @end +Adding NOP phi() at start of main CALL GRAPH Calls in [] to main:2 -Calls in [main] to get:25 print:32 +Calls in [main] to get:22 print:27 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes +Created 1 initial phi equivalence classes +Coalesced [30] main::i#4 ← main::i#1 +Coalesced down to 1 phi equivalence classes Renumbering block @3 to @1 Adding NOP phi() at start of @1 Adding NOP phi() at start of @end +Adding NOP phi() at start of main FINAL CONTROL FLOW GRAPH @begin: scope:[] from @@ -231,66 +253,63 @@ print::@return: scope:[print] from print __stackcall (struct Point()) get((byte) get::i) get: scope:[get] from - [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) - [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 - [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 - [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 - [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) - [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) + [11] (byte) get::return_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) + [12] (byte) get::return_y#0 ← (byte) get::return_x#0 >> (byte) 1 to:get::@return get::@return: scope:[get] from get - [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 - [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 - [19] return + [13] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 + [14] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 + [15] return to:@return __stackcall (void()) main() main: scope:[main] from - [20] (byte) main::i ← (byte) 0 + [16] phi() to:main::@1 main::@1: scope:[main] from main main::@2 - [21] if((byte) main::i<(byte) 5) goto main::@2 + [17] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 ) + [18] if((byte) main::i#2<(byte) 5) goto main::@2 to:main::@return main::@return: scope:[main] from main::@1 - [22] return + [19] return to:@return main::@2: scope:[main] from main::@1 - [23] stackpush(byte) ← (byte) main::i + [20] stackpush(byte) ← (byte) main::i#2 sideeffect stackpushbytes((number) 1) - [25] callexecute get - [26] (byte~) main::$1_x ← stackpull(byte) - [27] (byte~) main::$1_y ← stackpull(byte) - [28] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x - [29] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y - [30] stackpush(byte) ← *((byte*)&(struct Point) main::p) - [31] stackpush(byte) ← *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) - [32] callexecute print + [22] callexecute get + [23] (byte) main::p_x#0 ← stackpull(byte) + [24] (byte) main::p_y#0 ← stackpull(byte) + [25] stackpush(byte) ← (byte) main::p_x#0 + [26] stackpush(byte) ← (byte) main::p_y#0 + [27] callexecute print sideeffect stackpullbytes((number) 2) - [34] (byte) main::i ← ++ (byte) main::i + [29] (byte) main::i#1 ← ++ (byte) main::i#2 to:main::@1 null depth in calling loop Loop head: main::@1 tails: main::@2 blocks: main::@2 main::@1 in scope print null depth in calling loop Loop head: main::@1 tails: main::@2 blocks: main::@2 main::@1 in scope get VARIABLE REGISTER WEIGHTS -(byte) Point::x loadstore -(byte) Point::y loadstore +(byte) Point::x +(byte) Point::y __stackcall (struct Point()) get((byte) get::i) -(byte~) get::$0 2.0 (byte) get::i -(byte) get::i#0 3.0 -(struct Point) get::p loadstore +(byte) get::p_x +(byte) get::p_y (struct Point) get::return (byte) get::return_x -(byte) get::return_x#0 2.0 +(byte) get::return_x#0 3.0 (byte) get::return_y (byte) get::return_y#0 2.0 -(byte) idx loadstore 0.6086956521739131 +(byte) idx loadstore 0.6363636363636365 __stackcall (void()) main() -(byte~) main::$1_x 11.0 -(byte~) main::$1_y 11.0 -(byte) main::i loadstore 3.2857142857142856 -(struct Point) main::p loadstore +(byte) main::i +(byte) main::i#1 22.0 +(byte) main::i#2 4.0 +(byte) main::p_x +(byte) main::p_x#0 11.0 +(byte) main::p_y +(byte) main::p_y#0 11.0 __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) (byte) print::p_x (byte) print::p_x#0 2.0 @@ -298,43 +317,31 @@ __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) (byte) print::p_y#0 1.3333333333333333 Initial phi equivalence classes +[ main::i#2 main::i#1 ] Added variable idx to live range equivalence class [ idx ] Added variable print::p_x#0 to live range equivalence class [ print::p_x#0 ] Added variable print::p_y#0 to live range equivalence class [ print::p_y#0 ] -Added variable get::i#0 to live range equivalence class [ get::i#0 ] -Added variable get::$0 to live range equivalence class [ get::$0 ] Added variable get::return_x#0 to live range equivalence class [ get::return_x#0 ] Added variable get::return_y#0 to live range equivalence class [ get::return_y#0 ] -Added variable main::i to live range equivalence class [ main::i ] -Added variable main::$1_x to live range equivalence class [ main::$1_x ] -Added variable main::$1_y to live range equivalence class [ main::$1_y ] -Added variable main::p to live range equivalence class [ main::p ] -Added variable get::p to live range equivalence class [ get::p ] +Added variable main::p_x#0 to live range equivalence class [ main::p_x#0 ] +Added variable main::p_y#0 to live range equivalence class [ main::p_y#0 ] Complete equivalence classes +[ main::i#2 main::i#1 ] [ idx ] [ print::p_x#0 ] [ print::p_y#0 ] -[ get::i#0 ] -[ get::$0 ] [ get::return_x#0 ] [ get::return_y#0 ] -[ main::i ] -[ main::$1_x ] -[ main::$1_y ] -[ main::p ] -[ get::p ] -Allocated zp[1]:2 [ idx ] -Allocated zp[1]:3 [ print::p_x#0 ] -Allocated zp[1]:4 [ print::p_y#0 ] -Allocated zp[1]:5 [ get::i#0 ] -Allocated zp[1]:6 [ get::$0 ] -Allocated zp[1]:7 [ get::return_x#0 ] -Allocated zp[1]:8 [ get::return_y#0 ] -Allocated zp[1]:9 [ main::i ] -Allocated zp[1]:10 [ main::$1_x ] -Allocated zp[1]:11 [ main::$1_y ] -Allocated zp[2]:12 [ main::p ] -Allocated zp[2]:14 [ get::p ] +[ main::p_x#0 ] +[ main::p_y#0 ] +Allocated zp[1]:2 [ main::i#2 main::i#1 ] +Allocated zp[1]:3 [ idx ] +Allocated zp[1]:4 [ print::p_x#0 ] +Allocated zp[1]:5 [ print::p_y#0 ] +Allocated zp[1]:6 [ get::return_x#0 ] +Allocated zp[1]:7 [ get::return_y#0 ] +Allocated zp[1]:8 [ main::p_x#0 ] +Allocated zp[1]:9 [ main::p_y#0 ] INITIAL ASM Target platform is c64basic / MOS6502X @@ -347,9 +354,9 @@ Target platform is c64basic / MOS6502X .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 - .const OFFSET_STRUCT_POINT_Y = 1 .const STACK_BASE = $103 - .label idx = 2 + .const OFFSET_STRUCT_POINT_Y = 1 + .label idx = 3 // @begin __bbegin: // [0] (byte) idx ← (byte) 0 -- vbuz1=vbuc1 @@ -368,12 +375,12 @@ __bend_from___b1: // @end __bend: // print -// print(byte zp(3) p_x, byte zp(4) p_y) +// print(byte zp(4) p_x, byte zp(5) p_y) print: { .const OFFSET_STACK_P_X = 1 .const OFFSET_STACK_P_Y = 0 - .label p_x = 3 - .label p_y = 4 + .label p_x = 4 + .label p_y = 5 // [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_P_X,x @@ -401,184 +408,159 @@ print: { rts } // get -// get(byte zp(5) i) get: { .const OFFSET_STACK_I = 0 - .label __0 = 6 - .label p = $e - .label i = 5 - .label return_x = 7 - .label return_y = 8 - // [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuz1=_stackidxbyte_vbuc1 + .label return_x = 6 + .label return_y = 7 + // [11] (byte) get::return_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_I,x - sta.z i - // [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuz1=vbuz2_ror_1 - lda.z i - lsr - sta.z __0 - // [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuz1 - lda.z i - sta.z p - // [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuz1 - lda.z __0 - sta p+OFFSET_STRUCT_POINT_Y - // [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuz1=_deref_pbuc1 - lda.z p sta.z return_x - // [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1 - lda p+OFFSET_STRUCT_POINT_Y + // [12] (byte) get::return_y#0 ← (byte) get::return_x#0 >> (byte) 1 -- vbuz1=vbuz2_ror_1 + lda.z return_x + lsr sta.z return_y jmp __breturn // get::@return __breturn: - // [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 -- _stackidxbyte_vbuc1=vbuz1 + // [13] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return_x tsx sta STACK_BASE+0,x - // [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 -- _stackidxbyte_vbuc1=vbuz1 + // [14] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return_y tsx sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x - // [19] return + // [15] return rts } // main main: { - .label i = 9 - .label p = $c - .label __1_x = $a - .label __1_y = $b - // [20] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + .label p_x = 8 + .label p_y = 9 + .label i = 2 + // [17] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [17] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // main::@1 __b1: - // [21] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + // [18] if((byte) main::i#2<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #5 bcc __b2 jmp __breturn // main::@return __breturn: - // [22] return + // [19] return rts // main::@2 __b2: - // [23] stackpush(byte) ← (byte) main::i -- _stackpushbyte_=vbuz1 + // [20] stackpush(byte) ← (byte) main::i#2 -- _stackpushbyte_=vbuz1 lda.z i pha // sideeffect stackpushbytes((number) 1) -- _stackpushbyte_1 pha - // [25] callexecute get -- jsr + // [22] callexecute get -- jsr jsr get - // [26] (byte~) main::$1_x ← stackpull(byte) -- vbuz1=_stackpullbyte_ + // [23] (byte) main::p_x#0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla - sta.z __1_x - // [27] (byte~) main::$1_y ← stackpull(byte) -- vbuz1=_stackpullbyte_ + sta.z p_x + // [24] (byte) main::p_y#0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla - sta.z __1_y - // [28] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuz1 - lda.z __1_x - sta.z p - // [29] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuz1 - lda.z __1_y - sta p+OFFSET_STRUCT_POINT_Y - // [30] stackpush(byte) ← *((byte*)&(struct Point) main::p) -- _stackpushbyte_=_deref_pbuc1 - lda.z p + sta.z p_y + // [25] stackpush(byte) ← (byte) main::p_x#0 -- _stackpushbyte_=vbuz1 + lda.z p_x pha - // [31] stackpush(byte) ← *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) -- _stackpushbyte_=_deref_pbuc1 - lda p+OFFSET_STRUCT_POINT_Y + // [26] stackpush(byte) ← (byte) main::p_y#0 -- _stackpushbyte_=vbuz1 + lda.z p_y pha - // [32] callexecute print -- jsr + // [27] callexecute print -- jsr jsr print // sideeffect stackpullbytes((number) 2) -- _stackpullbyte_2 pla pla - // [34] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [29] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 inc.z i + // [17] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + __b1_from___b2: + // [17] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy jmp __b1 } // File Data REGISTER UPLIFT POTENTIAL REGISTERS -Statement [0] (byte) idx ← (byte) 0 [ idx get::p main::p ] ( [ idx get::p main::p ] ) always clobbers reg byte a -Statement [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) [ idx print::p_x#0 ] ( main:2::print:32 [ get::p main::i main::p idx print::p_x#0 ] ) always clobbers reg byte a reg byte x -Statement [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) [ idx print::p_x#0 print::p_y#0 ] ( main:2::print:32 [ get::p main::i main::p idx print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a reg byte x -Removing always clobbered register reg byte a as potential for zp[1]:3 [ print::p_x#0 ] -Removing always clobbered register reg byte x as potential for zp[1]:3 [ print::p_x#0 ] -Statement [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 [ idx print::p_y#0 ] ( main:2::print:32 [ get::p main::i main::p idx print::p_y#0 ] ) always clobbers reg byte a reg byte y -Removing always clobbered register reg byte a as potential for zp[1]:4 [ print::p_y#0 ] -Removing always clobbered register reg byte y as potential for zp[1]:4 [ print::p_y#0 ] -Statement [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 [ idx ] ( main:2::print:32 [ get::p main::i main::p idx ] ) always clobbers reg byte a reg byte y -Statement [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::i#0 get::p ] ( main:2::get:25 [ idx main::i main::p get::i#0 get::p ] ) always clobbers reg byte a reg byte x -Statement [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 [ get::i#0 get::$0 get::p ] ( main:2::get:25 [ idx main::i main::p get::i#0 get::$0 get::p ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp[1]:5 [ get::i#0 ] -Statement [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 [ get::p get::return_y#0 ] ( main:2::get:25 [ idx main::i main::p get::p get::return_y#0 ] ) always clobbers reg byte x -Removing always clobbered register reg byte x as potential for zp[1]:8 [ get::return_y#0 ] -Statement [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 [ get::p ] ( main:2::get:25 [ idx main::i main::p get::p ] ) always clobbers reg byte x -Statement [20] (byte) main::i ← (byte) 0 [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a -Statement [21] if((byte) main::i<(byte) 5) goto main::@2 [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a -Statement [23] stackpush(byte) ← (byte) main::i [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a -Statement [26] (byte~) main::$1_x ← stackpull(byte) [ idx get::p main::i main::$1_x main::p ] ( main:2 [ idx get::p main::i main::$1_x main::p ] ) always clobbers reg byte a -Statement [27] (byte~) main::$1_y ← stackpull(byte) [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp[1]:10 [ main::$1_x ] -Statement [30] stackpush(byte) ← *((byte*)&(struct Point) main::p) [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a -Statement [31] stackpush(byte) ← *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a +Statement [0] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a +Statement [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) [ idx print::p_x#0 ] ( main:2::print:27 [ main::i#2 idx print::p_x#0 ] ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ] +Removing always clobbered register reg byte x as potential for zp[1]:2 [ main::i#2 main::i#1 ] +Statement [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) [ idx print::p_x#0 print::p_y#0 ] ( main:2::print:27 [ main::i#2 idx print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:4 [ print::p_x#0 ] +Removing always clobbered register reg byte x as potential for zp[1]:4 [ print::p_x#0 ] +Statement [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 [ idx print::p_y#0 ] ( main:2::print:27 [ main::i#2 idx print::p_y#0 ] ) always clobbers reg byte a reg byte y +Removing always clobbered register reg byte y as potential for zp[1]:2 [ main::i#2 main::i#1 ] +Removing always clobbered register reg byte a as potential for zp[1]:5 [ print::p_y#0 ] +Removing always clobbered register reg byte y as potential for zp[1]:5 [ print::p_y#0 ] +Statement [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 [ idx ] ( main:2::print:27 [ main::i#2 idx ] ) always clobbers reg byte a reg byte y +Statement [11] (byte) get::return_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::return_x#0 ] ( main:2::get:22 [ idx main::i#2 get::return_x#0 ] ) always clobbers reg byte a reg byte x +Statement [12] (byte) get::return_y#0 ← (byte) get::return_x#0 >> (byte) 1 [ get::return_x#0 get::return_y#0 ] ( main:2::get:22 [ idx main::i#2 get::return_x#0 get::return_y#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:6 [ get::return_x#0 ] +Statement [13] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 [ get::return_y#0 ] ( main:2::get:22 [ idx main::i#2 get::return_y#0 ] ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:7 [ get::return_y#0 ] +Removing always clobbered register reg byte x as potential for zp[1]:7 [ get::return_y#0 ] +Statement [14] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 [ ] ( main:2::get:22 [ idx main::i#2 ] ) always clobbers reg byte a reg byte x +Statement [18] if((byte) main::i#2<(byte) 5) goto main::@2 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a +Statement [20] stackpush(byte) ← (byte) main::i#2 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a +Statement [23] (byte) main::p_x#0 ← stackpull(byte) [ idx main::i#2 main::p_x#0 ] ( main:2 [ idx main::i#2 main::p_x#0 ] ) always clobbers reg byte a +Statement [24] (byte) main::p_y#0 ← stackpull(byte) [ idx main::i#2 main::p_x#0 main::p_y#0 ] ( main:2 [ idx main::i#2 main::p_x#0 main::p_y#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:8 [ main::p_x#0 ] +Statement [25] stackpush(byte) ← (byte) main::p_x#0 [ idx main::i#2 main::p_y#0 ] ( main:2 [ idx main::i#2 main::p_y#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:9 [ main::p_y#0 ] +Statement [26] stackpush(byte) ← (byte) main::p_y#0 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a Statement sideeffect stackpullbytes((number) 2) always clobbers reg byte a -Statement [0] (byte) idx ← (byte) 0 [ idx get::p main::p ] ( [ idx get::p main::p ] ) always clobbers reg byte a -Statement [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) [ idx print::p_x#0 ] ( main:2::print:32 [ get::p main::i main::p idx print::p_x#0 ] ) always clobbers reg byte a reg byte x -Statement [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) [ idx print::p_x#0 print::p_y#0 ] ( main:2::print:32 [ get::p main::i main::p idx print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a reg byte x -Statement [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 [ idx print::p_y#0 ] ( main:2::print:32 [ get::p main::i main::p idx print::p_y#0 ] ) always clobbers reg byte a reg byte y -Statement [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 [ idx ] ( main:2::print:32 [ get::p main::i main::p idx ] ) always clobbers reg byte a reg byte y -Statement [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::i#0 get::p ] ( main:2::get:25 [ idx main::i main::p get::i#0 get::p ] ) always clobbers reg byte a reg byte x -Statement [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 [ get::i#0 get::$0 get::p ] ( main:2::get:25 [ idx main::i main::p get::i#0 get::$0 get::p ] ) always clobbers reg byte a -Statement [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 [ get::p get::return_y#0 ] ( main:2::get:25 [ idx main::i main::p get::p get::return_y#0 ] ) always clobbers reg byte x -Statement [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 [ get::p ] ( main:2::get:25 [ idx main::i main::p get::p ] ) always clobbers reg byte x -Statement [20] (byte) main::i ← (byte) 0 [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a -Statement [21] if((byte) main::i<(byte) 5) goto main::@2 [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a -Statement [23] stackpush(byte) ← (byte) main::i [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a -Statement [26] (byte~) main::$1_x ← stackpull(byte) [ idx get::p main::i main::$1_x main::p ] ( main:2 [ idx get::p main::i main::$1_x main::p ] ) always clobbers reg byte a -Statement [27] (byte~) main::$1_y ← stackpull(byte) [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [30] stackpush(byte) ← *((byte*)&(struct Point) main::p) [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a -Statement [31] stackpush(byte) ← *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a +Statement [0] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a +Statement [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) [ idx print::p_x#0 ] ( main:2::print:27 [ main::i#2 idx print::p_x#0 ] ) always clobbers reg byte a reg byte x +Statement [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) [ idx print::p_x#0 print::p_y#0 ] ( main:2::print:27 [ main::i#2 idx print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a reg byte x +Statement [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 [ idx print::p_y#0 ] ( main:2::print:27 [ main::i#2 idx print::p_y#0 ] ) always clobbers reg byte a reg byte y +Statement [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 [ idx ] ( main:2::print:27 [ main::i#2 idx ] ) always clobbers reg byte a reg byte y +Statement [11] (byte) get::return_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::return_x#0 ] ( main:2::get:22 [ idx main::i#2 get::return_x#0 ] ) always clobbers reg byte a reg byte x +Statement [12] (byte) get::return_y#0 ← (byte) get::return_x#0 >> (byte) 1 [ get::return_x#0 get::return_y#0 ] ( main:2::get:22 [ idx main::i#2 get::return_x#0 get::return_y#0 ] ) always clobbers reg byte a +Statement [13] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 [ get::return_y#0 ] ( main:2::get:22 [ idx main::i#2 get::return_y#0 ] ) always clobbers reg byte a reg byte x +Statement [14] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 [ ] ( main:2::get:22 [ idx main::i#2 ] ) always clobbers reg byte a reg byte x +Statement [18] if((byte) main::i#2<(byte) 5) goto main::@2 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a +Statement [20] stackpush(byte) ← (byte) main::i#2 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a +Statement [23] (byte) main::p_x#0 ← stackpull(byte) [ idx main::i#2 main::p_x#0 ] ( main:2 [ idx main::i#2 main::p_x#0 ] ) always clobbers reg byte a +Statement [24] (byte) main::p_y#0 ← stackpull(byte) [ idx main::i#2 main::p_x#0 main::p_y#0 ] ( main:2 [ idx main::i#2 main::p_x#0 main::p_y#0 ] ) always clobbers reg byte a +Statement [25] stackpush(byte) ← (byte) main::p_x#0 [ idx main::i#2 main::p_y#0 ] ( main:2 [ idx main::i#2 main::p_y#0 ] ) always clobbers reg byte a +Statement [26] stackpush(byte) ← (byte) main::p_y#0 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a Statement sideeffect stackpullbytes((number) 2) always clobbers reg byte a -Potential registers zp[1]:2 [ idx ] : zp[1]:2 , -Potential registers zp[1]:3 [ print::p_x#0 ] : zp[1]:3 , reg byte y , -Potential registers zp[1]:4 [ print::p_y#0 ] : zp[1]:4 , reg byte x , -Potential registers zp[1]:5 [ get::i#0 ] : zp[1]:5 , reg byte x , reg byte y , -Potential registers zp[1]:6 [ get::$0 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , -Potential registers zp[1]:7 [ get::return_x#0 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , -Potential registers zp[1]:8 [ get::return_y#0 ] : zp[1]:8 , reg byte a , reg byte y , -Potential registers zp[1]:9 [ main::i ] : zp[1]:9 , -Potential registers zp[1]:10 [ main::$1_x ] : zp[1]:10 , reg byte x , reg byte y , -Potential registers zp[1]:11 [ main::$1_y ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , -Potential registers zp[2]:12 [ main::p ] : zp[2]:12 , -Potential registers zp[2]:14 [ get::p ] : zp[2]:14 , +Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , +Potential registers zp[1]:3 [ idx ] : zp[1]:3 , +Potential registers zp[1]:4 [ print::p_x#0 ] : zp[1]:4 , reg byte y , +Potential registers zp[1]:5 [ print::p_y#0 ] : zp[1]:5 , reg byte x , +Potential registers zp[1]:6 [ get::return_x#0 ] : zp[1]:6 , reg byte x , reg byte y , +Potential registers zp[1]:7 [ get::return_y#0 ] : zp[1]:7 , reg byte y , +Potential registers zp[1]:8 [ main::p_x#0 ] : zp[1]:8 , reg byte x , reg byte y , +Potential registers zp[1]:9 [ main::p_y#0 ] : zp[1]:9 , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] 11: zp[1]:10 [ main::$1_x ] 11: zp[1]:11 [ main::$1_y ] 3.29: zp[1]:9 [ main::i ] 0: zp[2]:12 [ main::p ] -Uplift Scope [get] 3: zp[1]:5 [ get::i#0 ] 2: zp[1]:6 [ get::$0 ] 2: zp[1]:7 [ get::return_x#0 ] 2: zp[1]:8 [ get::return_y#0 ] 0: zp[2]:14 [ get::p ] -Uplift Scope [print] 2: zp[1]:3 [ print::p_x#0 ] 1.33: zp[1]:4 [ print::p_y#0 ] -Uplift Scope [] 0.61: zp[1]:2 [ idx ] +Uplift Scope [main] 26: zp[1]:2 [ main::i#2 main::i#1 ] 11: zp[1]:8 [ main::p_x#0 ] 11: zp[1]:9 [ main::p_y#0 ] +Uplift Scope [get] 3: zp[1]:6 [ get::return_x#0 ] 2: zp[1]:7 [ get::return_y#0 ] +Uplift Scope [print] 2: zp[1]:4 [ print::p_x#0 ] 1.33: zp[1]:5 [ print::p_y#0 ] +Uplift Scope [] 0.64: zp[1]:3 [ idx ] Uplift Scope [Point] -Uplifting [main] best 937 combination reg byte x [ main::$1_x ] reg byte a [ main::$1_y ] zp[1]:9 [ main::i ] zp[2]:12 [ main::p ] -Uplifting [get] best 922 combination reg byte x [ get::i#0 ] reg byte a [ get::$0 ] reg byte x [ get::return_x#0 ] zp[1]:8 [ get::return_y#0 ] zp[2]:14 [ get::p ] -Limited combination testing to 100 combinations of 144 possible. -Uplifting [print] best 918 combination reg byte y [ print::p_x#0 ] reg byte x [ print::p_y#0 ] -Uplifting [] best 918 combination zp[1]:2 [ idx ] -Uplifting [Point] best 918 combination -Attempting to uplift remaining variables inzp[1]:9 [ main::i ] -Uplifting [main] best 918 combination zp[1]:9 [ main::i ] -Attempting to uplift remaining variables inzp[1]:8 [ get::return_y#0 ] -Uplifting [get] best 914 combination reg byte y [ get::return_y#0 ] -Attempting to uplift remaining variables inzp[1]:2 [ idx ] -Uplifting [] best 914 combination zp[1]:2 [ idx ] -Allocated (was zp[1]:9) zp[1]:3 [ main::i ] -Allocated (was zp[2]:12) zp[2]:4 [ main::p ] -Allocated (was zp[2]:14) zp[2]:6 [ get::p ] +Uplifting [main] best 903 combination zp[1]:2 [ main::i#2 main::i#1 ] reg byte y [ main::p_x#0 ] reg byte x [ main::p_y#0 ] +Uplifting [get] best 898 combination reg byte x [ get::return_x#0 ] reg byte y [ get::return_y#0 ] +Uplifting [print] best 894 combination reg byte y [ print::p_x#0 ] reg byte x [ print::p_y#0 ] +Uplifting [] best 894 combination zp[1]:3 [ idx ] +Uplifting [Point] best 894 combination +Attempting to uplift remaining variables inzp[1]:2 [ main::i#2 main::i#1 ] +Uplifting [main] best 894 combination zp[1]:2 [ main::i#2 main::i#1 ] +Attempting to uplift remaining variables inzp[1]:3 [ idx ] +Uplifting [] best 894 combination zp[1]:3 [ idx ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -590,9 +572,9 @@ ASSEMBLER BEFORE OPTIMIZATION .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 - .const OFFSET_STRUCT_POINT_Y = 1 .const STACK_BASE = $103 - .label idx = 2 + .const OFFSET_STRUCT_POINT_Y = 1 + .label idx = 3 // @begin __bbegin: // [0] (byte) idx ← (byte) 0 -- vbuz1=vbuc1 @@ -642,89 +624,81 @@ print: { rts } // get -// get(byte register(X) i) get: { .const OFFSET_STACK_I = 0 - .label p = 6 - // [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1 + // [11] (byte) get::return_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_I,x tax - // [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuaa=vbuxx_ror_1 + // [12] (byte) get::return_y#0 ← (byte) get::return_x#0 >> (byte) 1 -- vbuyy=vbuxx_ror_1 txa lsr - // [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuxx - stx.z p - // [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuaa - sta p+OFFSET_STRUCT_POINT_Y - // [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuxx=_deref_pbuc1 - ldx.z p - // [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=_deref_pbuc1 - ldy p+OFFSET_STRUCT_POINT_Y + tay jmp __breturn // get::@return __breturn: - // [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 -- _stackidxbyte_vbuc1=vbuxx + // [13] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 -- _stackidxbyte_vbuc1=vbuxx txa tsx sta STACK_BASE+0,x - // [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 -- _stackidxbyte_vbuc1=vbuyy + // [14] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 -- _stackidxbyte_vbuc1=vbuyy tya tsx sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x - // [19] return + // [15] return rts } // main main: { - .label i = 3 - .label p = 4 - // [20] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + .label i = 2 + // [17] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [17] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // main::@1 __b1: - // [21] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + // [18] if((byte) main::i#2<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #5 bcc __b2 jmp __breturn // main::@return __breturn: - // [22] return + // [19] return rts // main::@2 __b2: - // [23] stackpush(byte) ← (byte) main::i -- _stackpushbyte_=vbuz1 + // [20] stackpush(byte) ← (byte) main::i#2 -- _stackpushbyte_=vbuz1 lda.z i pha // sideeffect stackpushbytes((number) 1) -- _stackpushbyte_1 pha - // [25] callexecute get -- jsr + // [22] callexecute get -- jsr jsr get - // [26] (byte~) main::$1_x ← stackpull(byte) -- vbuxx=_stackpullbyte_ + // [23] (byte) main::p_x#0 ← stackpull(byte) -- vbuyy=_stackpullbyte_ + pla + tay + // [24] (byte) main::p_y#0 ← stackpull(byte) -- vbuxx=_stackpullbyte_ pla tax - // [27] (byte~) main::$1_y ← stackpull(byte) -- vbuaa=_stackpullbyte_ - pla - // [28] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuxx - stx.z p - // [29] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuaa - sta p+OFFSET_STRUCT_POINT_Y - // [30] stackpush(byte) ← *((byte*)&(struct Point) main::p) -- _stackpushbyte_=_deref_pbuc1 - lda.z p + // [25] stackpush(byte) ← (byte) main::p_x#0 -- _stackpushbyte_=vbuyy + tya pha - // [31] stackpush(byte) ← *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) -- _stackpushbyte_=_deref_pbuc1 - lda p+OFFSET_STRUCT_POINT_Y + // [26] stackpush(byte) ← (byte) main::p_y#0 -- _stackpushbyte_=vbuxx + txa pha - // [32] callexecute print -- jsr + // [27] callexecute print -- jsr jsr print // sideeffect stackpullbytes((number) 2) -- _stackpullbyte_2 pla pla - // [34] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [29] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 inc.z i + // [17] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + __b1_from___b2: + // [17] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy jmp __b1 } // File Data @@ -737,10 +711,6 @@ Removing instruction jmp __breturn Removing instruction jmp __b1 Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination -Removing instruction ldx.z p -Replacing instruction ldy p+OFFSET_STRUCT_POINT_Y with TAY -Replacing instruction lda.z p with TXA -Succesful ASM optimization Pass5UnnecesaryLoadElimination Removing instruction __b1_from___bbegin: Removing instruction __bend_from___b1: Succesful ASM optimization Pass5RedundantLabelElimination @@ -748,7 +718,9 @@ Removing instruction __b1: Removing instruction __bend: Removing instruction __breturn: Removing instruction __breturn: +Removing instruction __b1_from_main: Removing instruction __breturn: +Removing instruction __b1_from___b2: Succesful ASM optimization Pass5UnusedLabelElimination Adding RTS to root block Succesful ASM optimization Pass5AddMainRts @@ -758,31 +730,33 @@ FINAL SYMBOL TABLE (label) @begin (label) @end (const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 -(byte) Point::x loadstore -(byte) Point::y loadstore +(byte) Point::x +(byte) Point::y (const byte*) SCREEN = (byte*) 1024 (const word) STACK_BASE = (word) $103 __stackcall (struct Point()) get((byte) get::i) -(byte~) get::$0 reg byte a 2.0 (label) get::@return (const byte) get::OFFSET_STACK_I = (byte) 0 (byte) get::i -(byte) get::i#0 reg byte x 3.0 -(struct Point) get::p loadstore zp[2]:6 +(byte) get::p_x +(byte) get::p_y (struct Point) get::return (byte) get::return_x -(byte) get::return_x#0 reg byte x 2.0 +(byte) get::return_x#0 reg byte x 3.0 (byte) get::return_y (byte) get::return_y#0 reg byte y 2.0 -(byte) idx loadstore zp[1]:2 0.6086956521739131 +(byte) idx loadstore zp[1]:3 0.6363636363636365 __stackcall (void()) main() -(byte~) main::$1_x reg byte x 11.0 -(byte~) main::$1_y reg byte a 11.0 (label) main::@1 (label) main::@2 (label) main::@return -(byte) main::i loadstore zp[1]:3 3.2857142857142856 -(struct Point) main::p loadstore zp[2]:4 +(byte) main::i +(byte) main::i#1 i zp[1]:2 22.0 +(byte) main::i#2 i zp[1]:2 4.0 +(byte) main::p_x +(byte) main::p_x#0 reg byte y 11.0 +(byte) main::p_y +(byte) main::p_y#0 reg byte x 11.0 __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) (label) print::@return (const byte) print::OFFSET_STACK_P_X = (byte) 1 @@ -792,22 +766,18 @@ __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) (byte) print::p_y (byte) print::p_y#0 reg byte x 1.3333333333333333 -zp[1]:2 [ idx ] +zp[1]:2 [ main::i#2 main::i#1 ] +zp[1]:3 [ idx ] reg byte y [ print::p_x#0 ] reg byte x [ print::p_y#0 ] -reg byte x [ get::i#0 ] -reg byte a [ get::$0 ] reg byte x [ get::return_x#0 ] reg byte y [ get::return_y#0 ] -zp[1]:3 [ main::i ] -reg byte x [ main::$1_x ] -reg byte a [ main::$1_y ] -zp[2]:4 [ main::p ] -zp[2]:6 [ get::p ] +reg byte y [ main::p_x#0 ] +reg byte x [ main::p_y#0 ] FINAL ASSEMBLER -Score: 860 +Score: 828 // File Comments // Test a procedure with calling convention stack @@ -818,9 +788,9 @@ Score: 860 .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 - .const OFFSET_STRUCT_POINT_Y = 1 .const STACK_BASE = $103 - .label idx = 2 + .const OFFSET_STRUCT_POINT_Y = 1 + .label idx = 3 // @begin __bbegin: // idx = 0 @@ -870,94 +840,82 @@ print: { rts } // get -// get(byte register(X) i) get: { .const OFFSET_STACK_I = 0 - .label p = 6 - // [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1 + // [11] (byte) get::return_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_I,x tax // i/2 - // [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuaa=vbuxx_ror_1 + // [12] (byte) get::return_y#0 ← (byte) get::return_x#0 >> (byte) 1 -- vbuyy=vbuxx_ror_1 txa lsr - // p = { i, i/2 } - // [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuxx - stx.z p - // [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuaa - sta p+OFFSET_STRUCT_POINT_Y - // return p; - // [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuxx=_deref_pbuc1 - // [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=_deref_pbuc1 tay // get::@return // } - // [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 -- _stackidxbyte_vbuc1=vbuxx + // [13] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 -- _stackidxbyte_vbuc1=vbuxx txa tsx sta STACK_BASE+0,x - // [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 -- _stackidxbyte_vbuc1=vbuyy + // [14] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 -- _stackidxbyte_vbuc1=vbuyy tya tsx sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x - // [19] return + // [15] return rts } // main main: { - .label i = 3 - .label p = 4 - // i=0 - // [20] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + .label i = 2 + // [17] phi from main to main::@1 [phi:main->main::@1] + // [17] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 lda #0 sta.z i // main::@1 __b1: // for(char i=0;i<5;i++) - // [21] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + // [18] if((byte) main::i#2<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #5 bcc __b2 // main::@return // } - // [22] return + // [19] return rts // main::@2 __b2: // get(i) - // [23] stackpush(byte) ← (byte) main::i -- _stackpushbyte_=vbuz1 + // [20] stackpush(byte) ← (byte) main::i#2 -- _stackpushbyte_=vbuz1 lda.z i pha // sideeffect stackpushbytes((number) 1) -- _stackpushbyte_1 pha - // [25] callexecute get -- jsr + // [22] callexecute get -- jsr jsr get - // [26] (byte~) main::$1_x ← stackpull(byte) -- vbuxx=_stackpullbyte_ + // p = get(i) + // [23] (byte) main::p_x#0 ← stackpull(byte) -- vbuyy=_stackpullbyte_ + pla + tay + // [24] (byte) main::p_y#0 ← stackpull(byte) -- vbuxx=_stackpullbyte_ pla tax - // [27] (byte~) main::$1_y ← stackpull(byte) -- vbuaa=_stackpullbyte_ - pla - // p = get(i) - // [28] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuxx - stx.z p - // [29] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuaa - sta p+OFFSET_STRUCT_POINT_Y // print(p) - // [30] stackpush(byte) ← *((byte*)&(struct Point) main::p) -- _stackpushbyte_=_deref_pbuc1 + // [25] stackpush(byte) ← (byte) main::p_x#0 -- _stackpushbyte_=vbuyy + tya + pha + // [26] stackpush(byte) ← (byte) main::p_y#0 -- _stackpushbyte_=vbuxx txa pha - // [31] stackpush(byte) ← *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) -- _stackpushbyte_=_deref_pbuc1 - lda p+OFFSET_STRUCT_POINT_Y - pha - // [32] callexecute print -- jsr + // [27] callexecute print -- jsr jsr print // sideeffect stackpullbytes((number) 2) -- _stackpullbyte_2 pla pla // for(char i=0;i<5;i++) - // [34] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [29] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 inc.z i + // [17] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + // [17] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy jmp __b1 } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-10.sym b/src/test/ref/procedure-callingconvention-stack-10.sym index 326231d1d..e87adfdb3 100644 --- a/src/test/ref/procedure-callingconvention-stack-10.sym +++ b/src/test/ref/procedure-callingconvention-stack-10.sym @@ -2,31 +2,33 @@ (label) @begin (label) @end (const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 -(byte) Point::x loadstore -(byte) Point::y loadstore +(byte) Point::x +(byte) Point::y (const byte*) SCREEN = (byte*) 1024 (const word) STACK_BASE = (word) $103 __stackcall (struct Point()) get((byte) get::i) -(byte~) get::$0 reg byte a 2.0 (label) get::@return (const byte) get::OFFSET_STACK_I = (byte) 0 (byte) get::i -(byte) get::i#0 reg byte x 3.0 -(struct Point) get::p loadstore zp[2]:6 +(byte) get::p_x +(byte) get::p_y (struct Point) get::return (byte) get::return_x -(byte) get::return_x#0 reg byte x 2.0 +(byte) get::return_x#0 reg byte x 3.0 (byte) get::return_y (byte) get::return_y#0 reg byte y 2.0 -(byte) idx loadstore zp[1]:2 0.6086956521739131 +(byte) idx loadstore zp[1]:3 0.6363636363636365 __stackcall (void()) main() -(byte~) main::$1_x reg byte x 11.0 -(byte~) main::$1_y reg byte a 11.0 (label) main::@1 (label) main::@2 (label) main::@return -(byte) main::i loadstore zp[1]:3 3.2857142857142856 -(struct Point) main::p loadstore zp[2]:4 +(byte) main::i +(byte) main::i#1 i zp[1]:2 22.0 +(byte) main::i#2 i zp[1]:2 4.0 +(byte) main::p_x +(byte) main::p_x#0 reg byte y 11.0 +(byte) main::p_y +(byte) main::p_y#0 reg byte x 11.0 __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) (label) print::@return (const byte) print::OFFSET_STACK_P_X = (byte) 1 @@ -36,15 +38,11 @@ __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) (byte) print::p_y (byte) print::p_y#0 reg byte x 1.3333333333333333 -zp[1]:2 [ idx ] +zp[1]:2 [ main::i#2 main::i#1 ] +zp[1]:3 [ idx ] reg byte y [ print::p_x#0 ] reg byte x [ print::p_y#0 ] -reg byte x [ get::i#0 ] -reg byte a [ get::$0 ] reg byte x [ get::return_x#0 ] reg byte y [ get::return_y#0 ] -zp[1]:3 [ main::i ] -reg byte x [ main::$1_x ] -reg byte a [ main::$1_y ] -zp[2]:4 [ main::p ] -zp[2]:6 [ get::p ] +reg byte y [ main::p_x#0 ] +reg byte x [ main::p_y#0 ] diff --git a/src/test/ref/procedure-callingconvention-stack-11.asm b/src/test/ref/procedure-callingconvention-stack-11.asm index 578d774ca..e521ab309 100644 --- a/src/test/ref/procedure-callingconvention-stack-11.asm +++ b/src/test/ref/procedure-callingconvention-stack-11.asm @@ -4,24 +4,24 @@ :BasicUpstart(__bbegin) .pc = $80d "Program" .label SCREEN = $400 + .const STACK_BASE = $103 .const OFFSET_STRUCT_POINT_Y = 1 .const OFFSET_STRUCT_VECTOR_P2 = 2 - .const STACK_BASE = $103 - .label idx = 2 + .label idx = 3 __bbegin: // idx = 0 lda #0 sta.z idx jsr main rts -// print(byte register(Y) v_p1_x, byte zp(3) v_p1_y, byte zp(4) v_p2_x, byte register(X) v_p2_y) +// print(byte register(Y) v_p1_x, byte zp(4) v_p1_y, byte zp(5) v_p2_x, byte register(X) v_p2_y) print: { .const OFFSET_STACK_V_P1_X = 3 .const OFFSET_STACK_V_P1_Y = 2 .const OFFSET_STACK_V_P2_X = 1 .const OFFSET_STACK_V_P2_Y = 0 - .label v_p1_y = 3 - .label v_p2_x = 4 + .label v_p1_y = 4 + .label v_p2_x = 5 // } tsx lda STACK_BASE+OFFSET_STACK_V_P1_X,x @@ -68,51 +68,33 @@ print: { // } rts } -// get(byte register(Y) i) get: { .const OFFSET_STACK_I = 0 - .label __0 = 3 - .label __2 = 4 - .label v = $10 - .label return_p2_x = 6 - .label return_p2_y = 7 + .label return_p1_y = 4 + .label return_p2_y = 5 tsx lda STACK_BASE+OFFSET_STACK_I,x - tay - // i/2 - tya - lsr - sta.z __0 - // i+1 - tya tax - inx + // i/2 + txa + lsr + sta.z return_p1_y + // i+1 + txa + tay + iny // i*2 - tya + txa asl - sta.z __2 - // v = { {i, i/2}, {i+1, i*2} } - sty.z v - lda.z __0 - sta v+OFFSET_STRUCT_POINT_Y - stx v+OFFSET_STRUCT_VECTOR_P2 - lda.z __2 - sta v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y - // return v; - ldx.z v - ldy v+OFFSET_STRUCT_POINT_Y - lda v+OFFSET_STRUCT_VECTOR_P2 - sta.z return_p2_x - lda v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y sta.z return_p2_y // } txa tsx sta STACK_BASE+0,x - tya + lda.z return_p1_y tsx sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x - lda.z return_p2_x + tya tsx sta STACK_BASE+OFFSET_STRUCT_VECTOR_P2,x lda.z return_p2_y @@ -121,11 +103,9 @@ get: { rts } main: { - .label i = 5 - .label v = $c - .label __1_p2_x = 6 - .label __1_p2_y = 7 - // i=0 + .label v_p2_x = 4 + .label v_p2_y = 5 + .label i = 2 lda #0 sta.z i __b1: @@ -143,29 +123,23 @@ main: { pha pha jsr get + // v = get(i) pla tay pla tax pla - sta.z __1_p2_x + sta.z v_p2_x pla - sta.z __1_p2_y - // v = get(i) - sty.z v - stx v+OFFSET_STRUCT_POINT_Y - lda.z __1_p2_x - sta v+OFFSET_STRUCT_VECTOR_P2 - lda.z __1_p2_y - sta v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y + sta.z v_p2_y // print(v) tya pha txa pha - lda v+OFFSET_STRUCT_VECTOR_P2 + lda.z v_p2_x pha - lda v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y + lda.z v_p2_y pha jsr print tsx diff --git a/src/test/ref/procedure-callingconvention-stack-11.cfg b/src/test/ref/procedure-callingconvention-stack-11.cfg index 629d6ba32..5bc2accbd 100644 --- a/src/test/ref/procedure-callingconvention-stack-11.cfg +++ b/src/test/ref/procedure-callingconvention-stack-11.cfg @@ -31,54 +31,43 @@ print::@return: scope:[print] from print __stackcall (struct Vector()) get((byte) get::i) get: scope:[get] from - [19] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) - [20] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 - [21] (byte~) get::$1 ← (byte) get::i#0 + (byte) 1 - [22] (byte~) get::$2 ← (byte) get::i#0 << (byte) 1 - [23] *((byte*)(struct Point*)&(struct Vector) get::v) ← (byte) get::i#0 - [24] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 - [25] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte~) get::$1 - [26] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$2 - [27] (byte) get::return_p1_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v) - [28] (byte) get::return_p1_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_POINT_Y) - [29] (byte) get::return_p2_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2) - [30] (byte) get::return_p2_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) + [19] (byte) get::return_p1_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) + [20] (byte) get::return_p1_y#0 ← (byte) get::return_p1_x#0 >> (byte) 1 + [21] (byte) get::return_p2_x#0 ← (byte) get::return_p1_x#0 + (byte) 1 + [22] (byte) get::return_p2_y#0 ← (byte) get::return_p1_x#0 << (byte) 1 to:get::@return get::@return: scope:[get] from get - [31] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 - [32] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 - [33] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 - [34] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 - [35] return + [23] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 + [24] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 + [25] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 + [26] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 + [27] return to:@return __stackcall (void()) main() main: scope:[main] from - [36] (byte) main::i ← (byte) 0 + [28] phi() to:main::@1 main::@1: scope:[main] from main main::@2 - [37] if((byte) main::i<(byte) 5) goto main::@2 + [29] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 ) + [30] if((byte) main::i#2<(byte) 5) goto main::@2 to:main::@return main::@return: scope:[main] from main::@1 - [38] return + [31] return to:@return main::@2: scope:[main] from main::@1 - [39] stackpush(byte) ← (byte) main::i + [32] stackpush(byte) ← (byte) main::i#2 sideeffect stackpushbytes((number) 3) - [41] callexecute get - [42] (byte~) main::$1_p1_x ← stackpull(byte) - [43] (byte~) main::$1_p1_y ← stackpull(byte) - [44] (byte~) main::$1_p2_x ← stackpull(byte) - [45] (byte~) main::$1_p2_y ← stackpull(byte) - [46] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte~) main::$1_p1_x - [47] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p1_y - [48] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte~) main::$1_p2_x - [49] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p2_y - [50] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v) - [51] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) - [52] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) - [53] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) - [54] callexecute print + [34] callexecute get + [35] (byte) main::v_p1_x#0 ← stackpull(byte) + [36] (byte) main::v_p1_y#0 ← stackpull(byte) + [37] (byte) main::v_p2_x#0 ← stackpull(byte) + [38] (byte) main::v_p2_y#0 ← stackpull(byte) + [39] stackpush(byte) ← (byte) main::v_p1_x#0 + [40] stackpush(byte) ← (byte) main::v_p1_y#0 + [41] stackpush(byte) ← (byte) main::v_p2_x#0 + [42] stackpush(byte) ← (byte) main::v_p2_y#0 + [43] callexecute print sideeffect stackpullbytes((number) 4) - [56] (byte) main::i ← ++ (byte) main::i + [45] (byte) main::i#1 ← ++ (byte) main::i#2 to:main::@1 diff --git a/src/test/ref/procedure-callingconvention-stack-11.log b/src/test/ref/procedure-callingconvention-stack-11.log index 178d42d09..4ebadd2df 100644 --- a/src/test/ref/procedure-callingconvention-stack-11.log +++ b/src/test/ref/procedure-callingconvention-stack-11.log @@ -1,9 +1,15 @@ Created struct value member variable (struct Point~) main::$1_p1 Created struct value member variable (struct Point~) main::$1_p2 Converted struct value to member variables (struct Vector~) main::$1 +Created struct value member variable (struct Point) main::v_p1 +Created struct value member variable (struct Point) main::v_p2 +Converted struct value to member variables (struct Vector) main::v Created struct value member variable (struct Point) get::return_p1 Created struct value member variable (struct Point) get::return_p2 Converted struct value to member variables (struct Vector) get::return +Created struct value member variable (struct Point) get::v_p1 +Created struct value member variable (struct Point) get::v_p2 +Converted struct value to member variables (struct Vector) get::v Created struct value member variable (struct Point) print::v_p1 Created struct value member variable (struct Point) print::v_p2 Converted struct value to member variables (struct Vector) print::v @@ -13,12 +19,24 @@ Converted struct value to member variables (struct Point~) main::$1_p1 Created struct value member variable (byte~) main::$1_p2_x Created struct value member variable (byte~) main::$1_p2_y Converted struct value to member variables (struct Point~) main::$1_p2 +Created struct value member variable (byte) main::v_p1_x +Created struct value member variable (byte) main::v_p1_y +Converted struct value to member variables (struct Point) main::v_p1 +Created struct value member variable (byte) main::v_p2_x +Created struct value member variable (byte) main::v_p2_y +Converted struct value to member variables (struct Point) main::v_p2 Created struct value member variable (byte) get::return_p1_x Created struct value member variable (byte) get::return_p1_y Converted struct value to member variables (struct Point) get::return_p1 Created struct value member variable (byte) get::return_p2_x Created struct value member variable (byte) get::return_p2_y Converted struct value to member variables (struct Point) get::return_p2 +Created struct value member variable (byte) get::v_p1_x +Created struct value member variable (byte) get::v_p1_y +Converted struct value to member variables (struct Point) get::v_p1 +Created struct value member variable (byte) get::v_p2_x +Created struct value member variable (byte) get::v_p2_y +Converted struct value to member variables (struct Point) get::v_p2 Created struct value member variable (byte) print::v_p1_x Created struct value member variable (byte) print::v_p1_y Converted struct value to member variables (struct Point) print::v_p1 @@ -29,26 +47,26 @@ Converted procedure struct value parameter to member unwinding __stackcall (void Converted procedure call LValue to member unwinding { { (byte~) main::$1_p1_x, (byte~) main::$1_p1_y }, { (byte~) main::$1_p2_x, (byte~) main::$1_p2_y } } ← call get (byte) main::i Unwinding value copy (struct Vector) main::v ← (struct Vector~) main::$1 Unwinding value copy (struct Vector) main::v ← (struct Vector~) main::$1 -Adding value simple copy *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_p1_x -Adding value simple copy *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p1_y +Adding value simple copy (byte) main::v_p1_x ← (byte~) main::$1_p1_x +Adding value simple copy (byte) main::v_p1_y ← (byte~) main::$1_p1_y Unwinding value copy (struct Vector) main::v ← (struct Vector~) main::$1 -Adding value simple copy *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_p2_x -Adding value simple copy *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p2_y -Converted procedure struct value parameter to member unwinding in call (void~) main::$2 ← call print *((struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1) *((struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) +Adding value simple copy (byte) main::v_p2_x ← (byte~) main::$1_p2_x +Adding value simple copy (byte) main::v_p2_y ← (byte~) main::$1_p2_y +Converted procedure struct value parameter to member unwinding in call (void~) main::$2 ← call print (struct Point) main::v_p1 (struct Point) main::v_p2 Unwinding value copy (struct Vector) get::v ← (struct Vector){ (struct Point){ (byte) get::i, (number~) get::$0 }, (struct Point){ (number~) get::$1, (number~) get::$2 } } Unwinding value copy (struct Vector) get::v ← (struct Vector){ (struct Point){ (byte) get::i, (number~) get::$0 }, (struct Point){ (number~) get::$1, (number~) get::$2 } } -Adding value simple copy *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::i -Adding value simple copy *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) ← (number~) get::$0 +Adding value simple copy (byte) get::v_p1_x ← (byte) get::i +Adding value simple copy (byte) get::v_p1_y ← (number~) get::$0 Unwinding value copy (struct Vector) get::v ← (struct Vector){ (struct Point){ (byte) get::i, (number~) get::$0 }, (struct Point){ (number~) get::$1, (number~) get::$2 } } -Adding value simple copy *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) ← (number~) get::$1 -Adding value simple copy *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (number~) get::$2 +Adding value simple copy (byte) get::v_p2_x ← (number~) get::$1 +Adding value simple copy (byte) get::v_p2_y ← (number~) get::$2 Unwinding value copy (struct Vector) get::return ← (struct Vector) get::v Unwinding value copy (struct Vector) get::return ← (struct Vector) get::v -Adding value simple copy (byte) get::return_p1_x ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) -Adding value simple copy (byte) get::return_p1_y ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) +Adding value simple copy (byte) get::return_p1_x ← (byte) get::v_p1_x +Adding value simple copy (byte) get::return_p1_y ← (byte) get::v_p1_y Unwinding value copy (struct Vector) get::return ← (struct Vector) get::v -Adding value simple copy (byte) get::return_p2_x ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) -Adding value simple copy (byte) get::return_p2_y ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) +Adding value simple copy (byte) get::return_p2_x ← (byte) get::v_p2_x +Adding value simple copy (byte) get::return_p2_y ← (byte) get::v_p2_y Converted procedure struct return value to member unwinding return { { (byte) get::return_p1_x, (byte) get::return_p1_y }, { (byte) get::return_p2_x, (byte) get::return_p2_y } } Unwinding value copy (struct Vector) print::v ← param((struct Vector) print::v) Unwinding value copy (struct Vector) print::v ← param((struct Vector) print::v) @@ -62,7 +80,7 @@ Replacing struct member reference (struct Vector) print::v.p1.y with member unwi Replacing struct member reference (struct Vector) print::v.p2.x with member unwinding reference (byte) print::v_p2_x Replacing struct member reference (struct Vector) print::v.p2.y with member unwinding reference (byte) print::v_p2_y Converted procedure struct value parameter to member unwinding __stackcall (void()) print((byte) print::v_p1_x , (byte) print::v_p1_y , (byte) print::v_p2_x , (byte) print::v_p2_y) -Converted procedure struct value parameter to member unwinding in call (void~) main::$2 ← call print *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) +Converted procedure struct value parameter to member unwinding in call (void~) main::$2 ← call print (byte) main::v_p1_x (byte) main::v_p1_y (byte) main::v_p2_x (byte) main::v_p2_y Eliminating unused variable with no statement (struct Vector~) main::$1 Eliminating unused variable with no statement (struct Point~) main::$1_p1 Eliminating unused variable with no statement (struct Point~) main::$1_p2 @@ -73,8 +91,9 @@ Culled Empty Block (label) main::@6 Culled Empty Block (label) @1 Culled Empty Block (label) get::@1 Culled Empty Block (label) @2 +Converting PHI-variable modified inside __stackcall procedure main() to load/store (byte) idx Calling convention STACK_CALL adding prepare/execute/finalize for { { (byte~) main::$1_p1_x, (byte~) main::$1_p1_y }, { (byte~) main::$1_p2_x, (byte~) main::$1_p2_y } } ← call get (byte) main::i -Calling convention STACK_CALL adding prepare/execute/finalize for call print *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) +Calling convention STACK_CALL adding prepare/execute/finalize for call print (byte) main::v_p1_x (byte) main::v_p1_y (byte) main::v_p2_x (byte) main::v_p2_y Calling convention STACK_CALL adding prepare/execute/finalize for call main Calling convention STACK_CALL replacing param((byte) get::i) with stackidx(byte,(const byte) get::OFFSET_STACK_I) Calling convention STACK_CALL replacing param((byte) print::v_p1_x) with stackidx(byte,(const byte) print::OFFSET_STACK_V_P1_X) @@ -90,10 +109,10 @@ Calling convention STACK_CALL adding stack pull main::$1_p1_y ← stackpull(byte Calling convention STACK_CALL adding stack pull main::$1_p2_x ← stackpull(byte) Calling convention STACK_CALL adding stack pull main::$1_p2_y ← stackpull(byte) Calling convention STACK_CALL adding stack push stackpush(byte) ← main::i -Calling convention STACK_CALL adding stack push stackpush(byte) ← *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P1+OFFSET_STRUCT_POINT_X) -Calling convention STACK_CALL adding stack push stackpush(byte) ← *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P1+OFFSET_STRUCT_POINT_Y) -Calling convention STACK_CALL adding stack push stackpush(byte) ← *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_X) -Calling convention STACK_CALL adding stack push stackpush(byte) ← *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y) +Calling convention STACK_CALL adding stack push stackpush(byte) ← main::v_p1_x +Calling convention STACK_CALL adding stack push stackpush(byte) ← main::v_p1_y +Calling convention STACK_CALL adding stack push stackpush(byte) ← main::v_p2_x +Calling convention STACK_CALL adding stack push stackpush(byte) ← main::v_p2_y CONTROL FLOW GRAPH SSA @begin: scope:[] from @@ -102,32 +121,33 @@ CONTROL FLOW GRAPH SSA __stackcall (void()) main() main: scope:[main] from - (byte) main::i ← (byte) 0 + (byte) main::i#0 ← (byte) 0 to:main::@1 main::@1: scope:[main] from main main::@2 - (bool~) main::$0 ← (byte) main::i < (number) 5 + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#1 ) + (bool~) main::$0 ← (byte) main::i#2 < (number) 5 if((bool~) main::$0) goto main::@2 to:main::@return main::@2: scope:[main] from main::@1 - stackpush(byte) ← (byte) main::i + (byte) main::i#3 ← phi( main::@1/(byte) main::i#2 ) + stackpush(byte) ← (byte) main::i#3 sideeffect stackpushbytes((number) 3) callexecute get (byte~) main::$1_p1_x ← stackpull(byte) (byte~) main::$1_p1_y ← stackpull(byte) (byte~) main::$1_p2_x ← stackpull(byte) (byte~) main::$1_p2_y ← stackpull(byte) - *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_p1_x - *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p1_y - *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_p2_x - *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p2_y - (struct Vector) main::v ← struct-unwound {*((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y), *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y)} - stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) - stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) - stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) - stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) + (byte) main::v_p1_x#0 ← (byte~) main::$1_p1_x + (byte) main::v_p1_y#0 ← (byte~) main::$1_p1_y + (byte) main::v_p2_x#0 ← (byte~) main::$1_p2_x + (byte) main::v_p2_y#0 ← (byte~) main::$1_p2_y + stackpush(byte) ← (byte) main::v_p1_x#0 + stackpush(byte) ← (byte) main::v_p1_y#0 + stackpush(byte) ← (byte) main::v_p2_x#0 + stackpush(byte) ← (byte) main::v_p2_y#0 callexecute print sideeffect stackpullbytes((number) 4) - (byte) main::i ← ++ (byte) main::i + (byte) main::i#1 ← ++ (byte) main::i#3 to:main::@1 main::@return: scope:[main] from main::@1 return @@ -139,15 +159,14 @@ get: scope:[get] from (number~) get::$0 ← (byte) get::i#0 / (number) 2 (number~) get::$1 ← (byte) get::i#0 + (number) 1 (number~) get::$2 ← (byte) get::i#0 * (number) 2 - *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::i#0 - *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) ← (number~) get::$0 - *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) ← (number~) get::$1 - *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (number~) get::$2 - (struct Vector) get::v ← struct-unwound {*((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y), *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y)} - (byte) get::return_p1_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) - (byte) get::return_p1_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) - (byte) get::return_p2_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) - (byte) get::return_p2_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) + (byte) get::v_p1_x#0 ← (byte) get::i#0 + (byte) get::v_p1_y#0 ← (number~) get::$0 + (byte) get::v_p2_x#0 ← (number~) get::$1 + (byte) get::v_p2_y#0 ← (number~) get::$2 + (byte) get::return_p1_x#0 ← (byte) get::v_p1_x#0 + (byte) get::return_p1_y#0 ← (byte) get::v_p1_y#0 + (byte) get::return_p2_x#0 ← (byte) get::v_p2_x#0 + (byte) get::return_p2_y#0 ← (byte) get::v_p2_y#0 (struct Vector) get::return#0 ← struct-unwound {(byte) get::return_p1_x#0, (byte) get::return_p1_y#0, (byte) get::return_p2_x#0, (byte) get::return_p2_y#0} to:get::@return get::@return: scope:[get] from get @@ -195,12 +214,12 @@ SYMBOL TABLE SSA (const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 (const byte) OFFSET_STRUCT_VECTOR_P1 = (byte) 0 (const byte) OFFSET_STRUCT_VECTOR_P2 = (byte) 2 -(byte) Point::x loadstore -(byte) Point::y loadstore +(byte) Point::x +(byte) Point::y (const byte*) SCREEN = (byte*)(number) $400 (const word) STACK_BASE = (word) $103 -(struct Point) Vector::p1 loadstore -(struct Point) Vector::p2 loadstore +(struct Point) Vector::p1 +(struct Point) Vector::p2 __stackcall (struct Vector()) get((byte) get::i) (number~) get::$0 (number~) get::$1 @@ -226,7 +245,16 @@ __stackcall (struct Vector()) get((byte) get::i) (byte) get::return_p2_y (byte) get::return_p2_y#0 (byte) get::return_p2_y#1 -(struct Vector) get::v loadstore +(struct Point) get::v_p1 +(byte) get::v_p1_x +(byte) get::v_p1_x#0 +(byte) get::v_p1_y +(byte) get::v_p1_y#0 +(struct Point) get::v_p2 +(byte) get::v_p2_x +(byte) get::v_p2_x#0 +(byte) get::v_p2_y +(byte) get::v_p2_y#0 (byte) idx loadstore __stackcall (void()) main() (bool~) main::$0 @@ -237,8 +265,21 @@ __stackcall (void()) main() (label) main::@1 (label) main::@2 (label) main::@return -(byte) main::i loadstore -(struct Vector) main::v loadstore +(byte) main::i +(byte) main::i#0 +(byte) main::i#1 +(byte) main::i#2 +(byte) main::i#3 +(struct Point) main::v_p1 +(byte) main::v_p1_x +(byte) main::v_p1_x#0 +(byte) main::v_p1_y +(byte) main::v_p1_y#0 +(struct Point) main::v_p2 +(byte) main::v_p2_x +(byte) main::v_p2_x#0 +(byte) main::v_p2_y +(byte) main::v_p2_y#0 __stackcall (void()) print((byte) print::v_p1_x , (byte) print::v_p1_y , (byte) print::v_p2_x , (byte) print::v_p2_y) (label) print::@return (const byte) print::OFFSET_STACK_V_P1_X = (byte) 3 @@ -256,7 +297,7 @@ __stackcall (void()) print((byte) print::v_p1_x , (byte) print::v_p1_y , (byte) (byte) print::v_p2_y (byte) print::v_p2_y#0 -Adding number conversion cast (unumber) 5 in (bool~) main::$0 ← (byte) main::i < (number) 5 +Adding number conversion cast (unumber) 5 in (bool~) main::$0 ← (byte) main::i#2 < (number) 5 Adding number conversion cast (unumber) 2 in (number~) get::$0 ← (byte) get::i#0 / (number) 2 Adding number conversion cast (unumber) get::$0 in (number~) get::$0 ← (byte) get::i#0 / (unumber)(number) 2 Adding number conversion cast (unumber) 1 in (number~) get::$1 ← (byte) get::i#0 + (number) 1 @@ -278,59 +319,54 @@ Successful SSA optimization PassNFinalizeNumberTypeConversions Inferred type updated to byte in (unumber~) get::$0 ← (byte) get::i#0 / (byte) 2 Inferred type updated to byte in (unumber~) get::$1 ← (byte) get::i#0 + (byte) 1 Inferred type updated to byte in (unumber~) get::$2 ← (byte) get::i#0 * (byte) 2 -Alias (byte) get::return_p1_x#0 = (byte) get::return_p1_x#1 -Alias (byte) get::return_p1_y#0 = (byte) get::return_p1_y#1 -Alias (byte) get::return_p2_x#0 = (byte) get::return_p2_x#1 -Alias (byte) get::return_p2_y#0 = (byte) get::return_p2_y#1 +Alias (byte) main::i#2 = (byte) main::i#3 +Alias (byte) main::v_p1_x#0 = (byte~) main::$1_p1_x +Alias (byte) main::v_p1_y#0 = (byte~) main::$1_p1_y +Alias (byte) main::v_p2_x#0 = (byte~) main::$1_p2_x +Alias (byte) main::v_p2_y#0 = (byte~) main::$1_p2_y +Alias (byte) get::return_p1_x#0 = (byte) get::v_p1_x#0 (byte) get::i#0 (byte) get::return_p1_x#1 +Alias (byte) get::return_p1_y#0 = (byte) get::v_p1_y#0 (byte~) get::$0 (byte) get::return_p1_y#1 +Alias (byte) get::return_p2_x#0 = (byte) get::v_p2_x#0 (byte~) get::$1 (byte) get::return_p2_x#1 +Alias (byte) get::return_p2_y#0 = (byte) get::v_p2_y#0 (byte~) get::$2 (byte) get::return_p2_y#1 Successful SSA optimization Pass2AliasElimination -Simple Condition (bool~) main::$0 [3] if((byte) main::i<(byte) 5) goto main::@2 +Simple Condition (bool~) main::$0 [4] if((byte) main::i#2<(byte) 5) goto main::@2 Successful SSA optimization Pass2ConditionalJumpSimplification -Removing C-classic struct-unwound assignment [15] (struct Vector) main::v ← struct-unwound {*((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y), *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y)} -Removing C-classic struct-unwound assignment [32] (struct Vector) get::v ← struct-unwound {*((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y), *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y)} -Simplifying constant evaluating to zero (const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X in [38] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::return_p1_x#0 -Simplifying constant evaluating to zero (const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P1 in [39] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 +Constant (const byte) main::i#0 = 0 +Successful SSA optimization Pass2ConstantIdentification +Simplifying constant evaluating to zero (const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X in [25] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::return_p1_x#0 +Simplifying constant evaluating to zero (const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P1 in [26] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 Successful SSA optimization PassNSimplifyConstantZero -Simplifying expression containing zero (byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P1 in [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_p1_x -Simplifying expression containing zero (struct Point*)&main::v in [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1) ← (byte~) main::$1_p1_x -Simplifying expression containing zero (struct Point*)&main::v in [12] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p1_y -Simplifying expression containing zero (byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P2 in [13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_p2_x -Simplifying expression containing zero (byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P1 in [16] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) -Simplifying expression containing zero (struct Point*)&main::v in [16] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1) -Simplifying expression containing zero (struct Point*)&main::v in [17] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) -Simplifying expression containing zero (byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P2 in [18] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) -Simplifying expression containing zero (byte*)(struct Point*)&get::v+OFFSET_STRUCT_VECTOR_P1 in [28] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::i#0 -Simplifying expression containing zero (struct Point*)&get::v in [28] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1) ← (byte) get::i#0 -Simplifying expression containing zero (struct Point*)&get::v in [29] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -Simplifying expression containing zero (byte*)(struct Point*)&get::v+OFFSET_STRUCT_VECTOR_P2 in [30] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) get::$1 -Simplifying expression containing zero (byte*)(struct Point*)&get::v+OFFSET_STRUCT_VECTOR_P1 in [33] (byte) get::return_p1_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_X) -Simplifying expression containing zero (struct Point*)&get::v in [33] (byte) get::return_p1_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1) -Simplifying expression containing zero (struct Point*)&get::v in [34] (byte) get::return_p1_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P1+(const byte) OFFSET_STRUCT_POINT_Y) -Simplifying expression containing zero (byte*)(struct Point*)&get::v+OFFSET_STRUCT_VECTOR_P2 in [35] (byte) get::return_p2_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) -Simplifying expression containing zero OFFSET_STRUCT_POINT_Y in [39] stackidx(byte,(byte) 0+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 -Simplifying expression containing zero get::OFFSET_STACK_RETURN+OFFSET_STRUCT_VECTOR_P2 in [40] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::return_p2_x#0 -Simplifying expression containing zero OFFSET_STRUCT_VECTOR_P2 in [41] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 +Simplifying expression containing zero OFFSET_STRUCT_POINT_Y in [26] stackidx(byte,(byte) 0+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 +Simplifying expression containing zero get::OFFSET_STACK_RETURN+OFFSET_STRUCT_VECTOR_P2 in [27] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::return_p2_x#0 +Simplifying expression containing zero OFFSET_STRUCT_VECTOR_P2 in [28] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 Successful SSA optimization PassNSimplifyExpressionWithZero -Simplifying expression containing zero OFFSET_STRUCT_VECTOR_P2 in [40] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 +Simplifying expression containing zero OFFSET_STRUCT_VECTOR_P2 in [27] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused variable (struct Vector) get::return#0 and assignment [34] (struct Vector) get::return#0 ← struct-unwound {(byte) get::return_p1_x#0, (byte) get::return_p1_y#0, (byte) get::return_p2_x#0, (byte) get::return_p2_y#0} +Eliminating unused variable (struct Vector) get::return#0 and assignment [22] (struct Vector) get::return#0 ← struct-unwound {(byte) get::return_p1_x#0, (byte) get::return_p1_y#0, (byte) get::return_p2_x#0, (byte) get::return_p2_y#0} Eliminating unused constant (const byte) get::OFFSET_STACK_RETURN Eliminating unused constant (const byte) OFFSET_STRUCT_VECTOR_P1 Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X Successful SSA optimization PassNEliminateUnusedVars -Rewriting division to use shift [23] (byte~) get::$0 ← (byte) get::i#0 / (byte) 2 -Rewriting multiplication to use shift [25] (byte~) get::$2 ← (byte) get::i#0 * (byte) 2 +Rewriting division to use shift [19] (byte) get::return_p1_y#0 ← (byte) get::return_p1_x#0 / (byte) 2 +Rewriting multiplication to use shift [21] (byte) get::return_p2_y#0 ← (byte) get::return_p1_x#0 * (byte) 2 Successful SSA optimization Pass2MultiplyToShiftRewriting +Inlining constant with var siblings (const byte) main::i#0 +Constant inlined main::i#0 = (byte) 0 +Successful SSA optimization Pass2ConstantInlining Adding NOP phi() at start of @3 Adding NOP phi() at start of @end +Adding NOP phi() at start of main CALL GRAPH Calls in [] to main:2 -Calls in [main] to get:41 print:54 +Calls in [main] to get:34 print:43 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes +Created 1 initial phi equivalence classes +Coalesced [46] main::i#4 ← main::i#1 +Coalesced down to 1 phi equivalence classes Renumbering block @3 to @1 Adding NOP phi() at start of @1 Adding NOP phi() at start of @end +Adding NOP phi() at start of main FINAL CONTROL FLOW GRAPH @begin: scope:[] from @@ -366,76 +402,61 @@ print::@return: scope:[print] from print __stackcall (struct Vector()) get((byte) get::i) get: scope:[get] from - [19] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) - [20] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 - [21] (byte~) get::$1 ← (byte) get::i#0 + (byte) 1 - [22] (byte~) get::$2 ← (byte) get::i#0 << (byte) 1 - [23] *((byte*)(struct Point*)&(struct Vector) get::v) ← (byte) get::i#0 - [24] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 - [25] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte~) get::$1 - [26] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$2 - [27] (byte) get::return_p1_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v) - [28] (byte) get::return_p1_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_POINT_Y) - [29] (byte) get::return_p2_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2) - [30] (byte) get::return_p2_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) + [19] (byte) get::return_p1_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) + [20] (byte) get::return_p1_y#0 ← (byte) get::return_p1_x#0 >> (byte) 1 + [21] (byte) get::return_p2_x#0 ← (byte) get::return_p1_x#0 + (byte) 1 + [22] (byte) get::return_p2_y#0 ← (byte) get::return_p1_x#0 << (byte) 1 to:get::@return get::@return: scope:[get] from get - [31] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 - [32] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 - [33] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 - [34] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 - [35] return + [23] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 + [24] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 + [25] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 + [26] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 + [27] return to:@return __stackcall (void()) main() main: scope:[main] from - [36] (byte) main::i ← (byte) 0 + [28] phi() to:main::@1 main::@1: scope:[main] from main main::@2 - [37] if((byte) main::i<(byte) 5) goto main::@2 + [29] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 ) + [30] if((byte) main::i#2<(byte) 5) goto main::@2 to:main::@return main::@return: scope:[main] from main::@1 - [38] return + [31] return to:@return main::@2: scope:[main] from main::@1 - [39] stackpush(byte) ← (byte) main::i + [32] stackpush(byte) ← (byte) main::i#2 sideeffect stackpushbytes((number) 3) - [41] callexecute get - [42] (byte~) main::$1_p1_x ← stackpull(byte) - [43] (byte~) main::$1_p1_y ← stackpull(byte) - [44] (byte~) main::$1_p2_x ← stackpull(byte) - [45] (byte~) main::$1_p2_y ← stackpull(byte) - [46] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte~) main::$1_p1_x - [47] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p1_y - [48] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte~) main::$1_p2_x - [49] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p2_y - [50] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v) - [51] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) - [52] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) - [53] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) - [54] callexecute print + [34] callexecute get + [35] (byte) main::v_p1_x#0 ← stackpull(byte) + [36] (byte) main::v_p1_y#0 ← stackpull(byte) + [37] (byte) main::v_p2_x#0 ← stackpull(byte) + [38] (byte) main::v_p2_y#0 ← stackpull(byte) + [39] stackpush(byte) ← (byte) main::v_p1_x#0 + [40] stackpush(byte) ← (byte) main::v_p1_y#0 + [41] stackpush(byte) ← (byte) main::v_p2_x#0 + [42] stackpush(byte) ← (byte) main::v_p2_y#0 + [43] callexecute print sideeffect stackpullbytes((number) 4) - [56] (byte) main::i ← ++ (byte) main::i + [45] (byte) main::i#1 ← ++ (byte) main::i#2 to:main::@1 null depth in calling loop Loop head: main::@1 tails: main::@2 blocks: main::@2 main::@1 in scope print null depth in calling loop Loop head: main::@1 tails: main::@2 blocks: main::@2 main::@1 in scope get VARIABLE REGISTER WEIGHTS -(byte) Point::x loadstore -(byte) Point::y loadstore -(struct Point) Vector::p1 loadstore -(struct Point) Vector::p2 loadstore +(byte) Point::x +(byte) Point::y +(struct Point) Vector::p1 +(struct Point) Vector::p2 __stackcall (struct Vector()) get((byte) get::i) -(byte~) get::$0 1.0 -(byte~) get::$1 1.0 -(byte~) get::$2 1.0 (byte) get::i -(byte) get::i#0 2.5 (struct Vector) get::return (struct Point) get::return_p1 (byte) get::return_p1_x -(byte) get::return_p1_x#0 1.0 +(byte) get::return_p1_x#0 2.5 (byte) get::return_p1_y (byte) get::return_p1_y#0 1.0 (struct Point) get::return_p2 @@ -443,15 +464,27 @@ __stackcall (struct Vector()) get((byte) get::i) (byte) get::return_p2_x#0 1.0 (byte) get::return_p2_y (byte) get::return_p2_y#0 1.0 -(struct Vector) get::v loadstore -(byte) idx loadstore 0.8648648648648649 +(struct Point) get::v_p1 +(byte) get::v_p1_x +(byte) get::v_p1_y +(struct Point) get::v_p2 +(byte) get::v_p2_x +(byte) get::v_p2_y +(byte) idx loadstore 0.9411764705882354 __stackcall (void()) main() -(byte~) main::$1_p1_x 5.5 -(byte~) main::$1_p1_y 5.5 -(byte~) main::$1_p2_x 5.5 -(byte~) main::$1_p2_y 5.5 -(byte) main::i loadstore 2.3000000000000003 -(struct Vector) main::v loadstore +(byte) main::i +(byte) main::i#1 22.0 +(byte) main::i#2 2.933333333333333 +(struct Point) main::v_p1 +(byte) main::v_p1_x +(byte) main::v_p1_x#0 5.5 +(byte) main::v_p1_y +(byte) main::v_p1_y#0 5.5 +(struct Point) main::v_p2 +(byte) main::v_p2_x +(byte) main::v_p2_x#0 5.5 +(byte) main::v_p2_y +(byte) main::v_p2_y#0 5.5 __stackcall (void()) print((byte) print::v_p1_x , (byte) print::v_p1_y , (byte) print::v_p2_x , (byte) print::v_p2_y) (struct Point) print::v_p1 (byte) print::v_p1_x @@ -465,73 +498,49 @@ __stackcall (void()) print((byte) print::v_p1_x , (byte) print::v_p1_y , (byte) (byte) print::v_p2_y#0 0.5714285714285714 Initial phi equivalence classes +[ main::i#2 main::i#1 ] Added variable idx to live range equivalence class [ idx ] Added variable print::v_p1_x#0 to live range equivalence class [ print::v_p1_x#0 ] Added variable print::v_p1_y#0 to live range equivalence class [ print::v_p1_y#0 ] Added variable print::v_p2_x#0 to live range equivalence class [ print::v_p2_x#0 ] Added variable print::v_p2_y#0 to live range equivalence class [ print::v_p2_y#0 ] -Added variable get::i#0 to live range equivalence class [ get::i#0 ] -Added variable get::$0 to live range equivalence class [ get::$0 ] -Added variable get::$1 to live range equivalence class [ get::$1 ] -Added variable get::$2 to live range equivalence class [ get::$2 ] Added variable get::return_p1_x#0 to live range equivalence class [ get::return_p1_x#0 ] Added variable get::return_p1_y#0 to live range equivalence class [ get::return_p1_y#0 ] Added variable get::return_p2_x#0 to live range equivalence class [ get::return_p2_x#0 ] Added variable get::return_p2_y#0 to live range equivalence class [ get::return_p2_y#0 ] -Added variable main::i to live range equivalence class [ main::i ] -Added variable main::$1_p1_x to live range equivalence class [ main::$1_p1_x ] -Added variable main::$1_p1_y to live range equivalence class [ main::$1_p1_y ] -Added variable main::$1_p2_x to live range equivalence class [ main::$1_p2_x ] -Added variable main::$1_p2_y to live range equivalence class [ main::$1_p2_y ] -Added variable Vector::p1 to live range equivalence class [ Vector::p1 ] -Added variable Vector::p2 to live range equivalence class [ Vector::p2 ] -Added variable main::v to live range equivalence class [ main::v ] -Added variable get::v to live range equivalence class [ get::v ] +Added variable main::v_p1_x#0 to live range equivalence class [ main::v_p1_x#0 ] +Added variable main::v_p1_y#0 to live range equivalence class [ main::v_p1_y#0 ] +Added variable main::v_p2_x#0 to live range equivalence class [ main::v_p2_x#0 ] +Added variable main::v_p2_y#0 to live range equivalence class [ main::v_p2_y#0 ] Complete equivalence classes +[ main::i#2 main::i#1 ] [ idx ] [ print::v_p1_x#0 ] [ print::v_p1_y#0 ] [ print::v_p2_x#0 ] [ print::v_p2_y#0 ] -[ get::i#0 ] -[ get::$0 ] -[ get::$1 ] -[ get::$2 ] [ get::return_p1_x#0 ] [ get::return_p1_y#0 ] [ get::return_p2_x#0 ] [ get::return_p2_y#0 ] -[ main::i ] -[ main::$1_p1_x ] -[ main::$1_p1_y ] -[ main::$1_p2_x ] -[ main::$1_p2_y ] -[ Vector::p1 ] -[ Vector::p2 ] -[ main::v ] -[ get::v ] -Allocated zp[1]:2 [ idx ] -Allocated zp[1]:3 [ print::v_p1_x#0 ] -Allocated zp[1]:4 [ print::v_p1_y#0 ] -Allocated zp[1]:5 [ print::v_p2_x#0 ] -Allocated zp[1]:6 [ print::v_p2_y#0 ] -Allocated zp[1]:7 [ get::i#0 ] -Allocated zp[1]:8 [ get::$0 ] -Allocated zp[1]:9 [ get::$1 ] -Allocated zp[1]:10 [ get::$2 ] -Allocated zp[1]:11 [ get::return_p1_x#0 ] -Allocated zp[1]:12 [ get::return_p1_y#0 ] -Allocated zp[1]:13 [ get::return_p2_x#0 ] -Allocated zp[1]:14 [ get::return_p2_y#0 ] -Allocated zp[1]:15 [ main::i ] -Allocated zp[1]:16 [ main::$1_p1_x ] -Allocated zp[1]:17 [ main::$1_p1_y ] -Allocated zp[1]:18 [ main::$1_p2_x ] -Allocated zp[1]:19 [ main::$1_p2_y ] -Allocated zp[2]:20 [ Vector::p1 ] -Allocated zp[2]:22 [ Vector::p2 ] -Allocated zp[4]:24 [ main::v ] -Allocated zp[4]:28 [ get::v ] +[ main::v_p1_x#0 ] +[ main::v_p1_y#0 ] +[ main::v_p2_x#0 ] +[ main::v_p2_y#0 ] +Allocated zp[1]:2 [ main::i#2 main::i#1 ] +Allocated zp[1]:3 [ idx ] +Allocated zp[1]:4 [ print::v_p1_x#0 ] +Allocated zp[1]:5 [ print::v_p1_y#0 ] +Allocated zp[1]:6 [ print::v_p2_x#0 ] +Allocated zp[1]:7 [ print::v_p2_y#0 ] +Allocated zp[1]:8 [ get::return_p1_x#0 ] +Allocated zp[1]:9 [ get::return_p1_y#0 ] +Allocated zp[1]:10 [ get::return_p2_x#0 ] +Allocated zp[1]:11 [ get::return_p2_y#0 ] +Allocated zp[1]:12 [ main::v_p1_x#0 ] +Allocated zp[1]:13 [ main::v_p1_y#0 ] +Allocated zp[1]:14 [ main::v_p2_x#0 ] +Allocated zp[1]:15 [ main::v_p2_y#0 ] INITIAL ASM Target platform is c64basic / MOS6502X @@ -544,10 +553,10 @@ Target platform is c64basic / MOS6502X .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 + .const STACK_BASE = $103 .const OFFSET_STRUCT_POINT_Y = 1 .const OFFSET_STRUCT_VECTOR_P2 = 2 - .const STACK_BASE = $103 - .label idx = 2 + .label idx = 3 // @begin __bbegin: // [0] (byte) idx ← (byte) 0 -- vbuz1=vbuc1 @@ -566,16 +575,16 @@ __bend_from___b1: // @end __bend: // print -// print(byte zp(3) v_p1_x, byte zp(4) v_p1_y, byte zp(5) v_p2_x, byte zp(6) v_p2_y) +// print(byte zp(4) v_p1_x, byte zp(5) v_p1_y, byte zp(6) v_p2_x, byte zp(7) v_p2_y) print: { .const OFFSET_STACK_V_P1_X = 3 .const OFFSET_STACK_V_P1_Y = 2 .const OFFSET_STACK_V_P2_X = 1 .const OFFSET_STACK_V_P2_Y = 0 - .label v_p1_x = 3 - .label v_p1_y = 4 - .label v_p2_x = 5 - .label v_p2_y = 6 + .label v_p1_x = 4 + .label v_p1_y = 5 + .label v_p2_x = 6 + .label v_p2_y = 7 // [4] (byte) print::v_p1_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P1_X) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_V_P1_X,x @@ -629,317 +638,257 @@ print: { rts } // get -// get(byte zp(7) i) get: { .const OFFSET_STACK_I = 0 - .label __0 = 8 - .label __1 = 9 - .label __2 = $a - .label v = $1c - .label i = 7 - .label return_p1_x = $b - .label return_p1_y = $c - .label return_p2_x = $d - .label return_p2_y = $e - // [19] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuz1=_stackidxbyte_vbuc1 + .label return_p1_x = 8 + .label return_p1_y = 9 + .label return_p2_x = $a + .label return_p2_y = $b + // [19] (byte) get::return_p1_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_I,x - sta.z i - // [20] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuz1=vbuz2_ror_1 - lda.z i - lsr - sta.z __0 - // [21] (byte~) get::$1 ← (byte) get::i#0 + (byte) 1 -- vbuz1=vbuz2_plus_1 - ldy.z i - iny - sty.z __1 - // [22] (byte~) get::$2 ← (byte) get::i#0 << (byte) 1 -- vbuz1=vbuz2_rol_1 - lda.z i - asl - sta.z __2 - // [23] *((byte*)(struct Point*)&(struct Vector) get::v) ← (byte) get::i#0 -- _deref_pbuc1=vbuz1 - lda.z i - sta.z v - // [24] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuz1 - lda.z __0 - sta v+OFFSET_STRUCT_POINT_Y - // [25] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte~) get::$1 -- _deref_pbuc1=vbuz1 - lda.z __1 - sta v+OFFSET_STRUCT_VECTOR_P2 - // [26] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$2 -- _deref_pbuc1=vbuz1 - lda.z __2 - sta v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y - // [27] (byte) get::return_p1_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v) -- vbuz1=_deref_pbuc1 - lda.z v sta.z return_p1_x - // [28] (byte) get::return_p1_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1 - lda v+OFFSET_STRUCT_POINT_Y + // [20] (byte) get::return_p1_y#0 ← (byte) get::return_p1_x#0 >> (byte) 1 -- vbuz1=vbuz2_ror_1 + lda.z return_p1_x + lsr sta.z return_p1_y - // [29] (byte) get::return_p2_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2) -- vbuz1=_deref_pbuc1 - lda v+OFFSET_STRUCT_VECTOR_P2 - sta.z return_p2_x - // [30] (byte) get::return_p2_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1 - lda v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y + // [21] (byte) get::return_p2_x#0 ← (byte) get::return_p1_x#0 + (byte) 1 -- vbuz1=vbuz2_plus_1 + ldy.z return_p1_x + iny + sty.z return_p2_x + // [22] (byte) get::return_p2_y#0 ← (byte) get::return_p1_x#0 << (byte) 1 -- vbuz1=vbuz2_rol_1 + lda.z return_p1_x + asl sta.z return_p2_y jmp __breturn // get::@return __breturn: - // [31] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 -- _stackidxbyte_vbuc1=vbuz1 + // [23] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return_p1_x tsx sta STACK_BASE+0,x - // [32] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 -- _stackidxbyte_vbuc1=vbuz1 + // [24] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return_p1_y tsx sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x - // [33] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 -- _stackidxbyte_vbuc1=vbuz1 + // [25] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return_p2_x tsx sta STACK_BASE+OFFSET_STRUCT_VECTOR_P2,x - // [34] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 -- _stackidxbyte_vbuc1=vbuz1 + // [26] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return_p2_y tsx sta STACK_BASE+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y,x - // [35] return + // [27] return rts } // main main: { - .label i = $f - .label v = $18 - .label __1_p1_x = $10 - .label __1_p1_y = $11 - .label __1_p2_x = $12 - .label __1_p2_y = $13 - // [36] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + .label v_p1_x = $c + .label v_p1_y = $d + .label v_p2_x = $e + .label v_p2_y = $f + .label i = 2 + // [29] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [29] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // main::@1 __b1: - // [37] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + // [30] if((byte) main::i#2<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #5 bcc __b2 jmp __breturn // main::@return __breturn: - // [38] return + // [31] return rts // main::@2 __b2: - // [39] stackpush(byte) ← (byte) main::i -- _stackpushbyte_=vbuz1 + // [32] stackpush(byte) ← (byte) main::i#2 -- _stackpushbyte_=vbuz1 lda.z i pha // sideeffect stackpushbytes((number) 3) -- _stackpushbyte_3 pha pha pha - // [41] callexecute get -- jsr + // [34] callexecute get -- jsr jsr get - // [42] (byte~) main::$1_p1_x ← stackpull(byte) -- vbuz1=_stackpullbyte_ + // [35] (byte) main::v_p1_x#0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla - sta.z __1_p1_x - // [43] (byte~) main::$1_p1_y ← stackpull(byte) -- vbuz1=_stackpullbyte_ + sta.z v_p1_x + // [36] (byte) main::v_p1_y#0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla - sta.z __1_p1_y - // [44] (byte~) main::$1_p2_x ← stackpull(byte) -- vbuz1=_stackpullbyte_ + sta.z v_p1_y + // [37] (byte) main::v_p2_x#0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla - sta.z __1_p2_x - // [45] (byte~) main::$1_p2_y ← stackpull(byte) -- vbuz1=_stackpullbyte_ + sta.z v_p2_x + // [38] (byte) main::v_p2_y#0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla - sta.z __1_p2_y - // [46] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte~) main::$1_p1_x -- _deref_pbuc1=vbuz1 - lda.z __1_p1_x - sta.z v - // [47] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p1_y -- _deref_pbuc1=vbuz1 - lda.z __1_p1_y - sta v+OFFSET_STRUCT_POINT_Y - // [48] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte~) main::$1_p2_x -- _deref_pbuc1=vbuz1 - lda.z __1_p2_x - sta v+OFFSET_STRUCT_VECTOR_P2 - // [49] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p2_y -- _deref_pbuc1=vbuz1 - lda.z __1_p2_y - sta v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y - // [50] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _stackpushbyte_=_deref_pbuc1 - lda.z v + sta.z v_p2_y + // [39] stackpush(byte) ← (byte) main::v_p1_x#0 -- _stackpushbyte_=vbuz1 + lda.z v_p1_x pha - // [51] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _stackpushbyte_=_deref_pbuc1 - lda v+OFFSET_STRUCT_POINT_Y + // [40] stackpush(byte) ← (byte) main::v_p1_y#0 -- _stackpushbyte_=vbuz1 + lda.z v_p1_y pha - // [52] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) -- _stackpushbyte_=_deref_pbuc1 - lda v+OFFSET_STRUCT_VECTOR_P2 + // [41] stackpush(byte) ← (byte) main::v_p2_x#0 -- _stackpushbyte_=vbuz1 + lda.z v_p2_x pha - // [53] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) -- _stackpushbyte_=_deref_pbuc1 - lda v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y + // [42] stackpush(byte) ← (byte) main::v_p2_y#0 -- _stackpushbyte_=vbuz1 + lda.z v_p2_y pha - // [54] callexecute print -- jsr + // [43] callexecute print -- jsr jsr print // sideeffect stackpullbytes((number) 4) -- _stackpullbyte_4 tsx txa axs #-4 txs - // [56] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [45] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 inc.z i + // [29] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + __b1_from___b2: + // [29] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy jmp __b1 } // File Data REGISTER UPLIFT POTENTIAL REGISTERS -Statement [0] (byte) idx ← (byte) 0 [ idx get::v main::v ] ( [ idx get::v main::v ] ) always clobbers reg byte a -Statement [4] (byte) print::v_p1_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P1_X) [ idx print::v_p1_x#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p1_x#0 ] ) always clobbers reg byte a reg byte x -Statement [5] (byte) print::v_p1_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P1_Y) [ idx print::v_p1_x#0 print::v_p1_y#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p1_x#0 print::v_p1_y#0 ] ) always clobbers reg byte a reg byte x -Removing always clobbered register reg byte a as potential for zp[1]:3 [ print::v_p1_x#0 ] -Removing always clobbered register reg byte x as potential for zp[1]:3 [ print::v_p1_x#0 ] -Statement [6] (byte) print::v_p2_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P2_X) [ idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 ] ) always clobbers reg byte a reg byte x -Removing always clobbered register reg byte a as potential for zp[1]:4 [ print::v_p1_y#0 ] -Removing always clobbered register reg byte x as potential for zp[1]:4 [ print::v_p1_y#0 ] -Statement [7] (byte) print::v_p2_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P2_Y) [ idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ) always clobbers reg byte a reg byte x -Removing always clobbered register reg byte a as potential for zp[1]:5 [ print::v_p2_x#0 ] -Removing always clobbered register reg byte x as potential for zp[1]:5 [ print::v_p2_x#0 ] -Statement [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p1_x#0 [ idx print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ) always clobbers reg byte a reg byte y -Removing always clobbered register reg byte y as potential for zp[1]:4 [ print::v_p1_y#0 ] -Removing always clobbered register reg byte y as potential for zp[1]:5 [ print::v_p2_x#0 ] -Removing always clobbered register reg byte a as potential for zp[1]:6 [ print::v_p2_y#0 ] -Removing always clobbered register reg byte y as potential for zp[1]:6 [ print::v_p2_y#0 ] -Statement [10] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p1_y#0 [ idx print::v_p2_x#0 print::v_p2_y#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p2_x#0 print::v_p2_y#0 ] ) always clobbers reg byte a reg byte y -Statement [12] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p2_x#0 [ idx print::v_p2_y#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p2_y#0 ] ) always clobbers reg byte a reg byte y -Statement [14] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p2_y#0 [ idx ] ( main:2::print:54 [ get::v main::i main::v idx ] ) always clobbers reg byte a reg byte y -Statement [16] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' [ idx ] ( main:2::print:54 [ get::v main::i main::v idx ] ) always clobbers reg byte a reg byte y -Statement [19] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::i#0 get::v ] ( main:2::get:41 [ idx main::i main::v get::i#0 get::v ] ) always clobbers reg byte a reg byte x -Statement [20] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 [ get::i#0 get::$0 get::v ] ( main:2::get:41 [ idx main::i main::v get::i#0 get::$0 get::v ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp[1]:7 [ get::i#0 ] -Statement [22] (byte~) get::$2 ← (byte) get::i#0 << (byte) 1 [ get::i#0 get::$0 get::$1 get::$2 get::v ] ( main:2::get:41 [ idx main::i main::v get::i#0 get::$0 get::$1 get::$2 get::v ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp[1]:8 [ get::$0 ] -Removing always clobbered register reg byte a as potential for zp[1]:9 [ get::$1 ] -Statement [31] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 [ get::v get::return_p1_y#0 get::return_p2_x#0 get::return_p2_y#0 ] ( main:2::get:41 [ idx main::i main::v get::v get::return_p1_y#0 get::return_p2_x#0 get::return_p2_y#0 ] ) always clobbers reg byte x -Removing always clobbered register reg byte x as potential for zp[1]:12 [ get::return_p1_y#0 ] -Removing always clobbered register reg byte x as potential for zp[1]:13 [ get::return_p2_x#0 ] -Removing always clobbered register reg byte x as potential for zp[1]:14 [ get::return_p2_y#0 ] -Statement [32] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 [ get::v get::return_p2_x#0 get::return_p2_y#0 ] ( main:2::get:41 [ idx main::i main::v get::v get::return_p2_x#0 get::return_p2_y#0 ] ) always clobbers reg byte x -Statement [33] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 [ get::v get::return_p2_y#0 ] ( main:2::get:41 [ idx main::i main::v get::v get::return_p2_y#0 ] ) always clobbers reg byte x -Statement [34] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 [ get::v ] ( main:2::get:41 [ idx main::i main::v get::v ] ) always clobbers reg byte x -Statement [36] (byte) main::i ← (byte) 0 [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a -Statement [37] if((byte) main::i<(byte) 5) goto main::@2 [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a -Statement [39] stackpush(byte) ← (byte) main::i [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a -Statement [42] (byte~) main::$1_p1_x ← stackpull(byte) [ idx get::v main::i main::$1_p1_x main::v ] ( main:2 [ idx get::v main::i main::$1_p1_x main::v ] ) always clobbers reg byte a -Statement [43] (byte~) main::$1_p1_y ← stackpull(byte) [ idx get::v main::i main::$1_p1_x main::$1_p1_y main::v ] ( main:2 [ idx get::v main::i main::$1_p1_x main::$1_p1_y main::v ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp[1]:16 [ main::$1_p1_x ] -Statement [44] (byte~) main::$1_p2_x ← stackpull(byte) [ idx get::v main::i main::$1_p1_x main::$1_p1_y main::$1_p2_x main::v ] ( main:2 [ idx get::v main::i main::$1_p1_x main::$1_p1_y main::$1_p2_x main::v ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp[1]:17 [ main::$1_p1_y ] -Statement [45] (byte~) main::$1_p2_y ← stackpull(byte) [ idx get::v main::i main::$1_p1_x main::$1_p1_y main::$1_p2_x main::$1_p2_y main::v ] ( main:2 [ idx get::v main::i main::$1_p1_x main::$1_p1_y main::$1_p2_x main::$1_p2_y main::v ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp[1]:18 [ main::$1_p2_x ] -Statement [50] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v) [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a -Statement [51] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a -Statement [52] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a -Statement [53] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a +Statement [0] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a +Statement [4] (byte) print::v_p1_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P1_X) [ idx print::v_p1_x#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p1_x#0 ] ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ] +Removing always clobbered register reg byte x as potential for zp[1]:2 [ main::i#2 main::i#1 ] +Statement [5] (byte) print::v_p1_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P1_Y) [ idx print::v_p1_x#0 print::v_p1_y#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p1_x#0 print::v_p1_y#0 ] ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:4 [ print::v_p1_x#0 ] +Removing always clobbered register reg byte x as potential for zp[1]:4 [ print::v_p1_x#0 ] +Statement [6] (byte) print::v_p2_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P2_X) [ idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 ] ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:5 [ print::v_p1_y#0 ] +Removing always clobbered register reg byte x as potential for zp[1]:5 [ print::v_p1_y#0 ] +Statement [7] (byte) print::v_p2_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P2_Y) [ idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:6 [ print::v_p2_x#0 ] +Removing always clobbered register reg byte x as potential for zp[1]:6 [ print::v_p2_x#0 ] +Statement [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p1_x#0 [ idx print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ) always clobbers reg byte a reg byte y +Removing always clobbered register reg byte y as potential for zp[1]:2 [ main::i#2 main::i#1 ] +Removing always clobbered register reg byte y as potential for zp[1]:5 [ print::v_p1_y#0 ] +Removing always clobbered register reg byte y as potential for zp[1]:6 [ print::v_p2_x#0 ] +Removing always clobbered register reg byte a as potential for zp[1]:7 [ print::v_p2_y#0 ] +Removing always clobbered register reg byte y as potential for zp[1]:7 [ print::v_p2_y#0 ] +Statement [10] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p1_y#0 [ idx print::v_p2_x#0 print::v_p2_y#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p2_x#0 print::v_p2_y#0 ] ) always clobbers reg byte a reg byte y +Statement [12] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p2_x#0 [ idx print::v_p2_y#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p2_y#0 ] ) always clobbers reg byte a reg byte y +Statement [14] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p2_y#0 [ idx ] ( main:2::print:43 [ main::i#2 idx ] ) always clobbers reg byte a reg byte y +Statement [16] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' [ idx ] ( main:2::print:43 [ main::i#2 idx ] ) always clobbers reg byte a reg byte y +Statement [19] (byte) get::return_p1_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::return_p1_x#0 ] ( main:2::get:34 [ idx main::i#2 get::return_p1_x#0 ] ) always clobbers reg byte a reg byte x +Statement [20] (byte) get::return_p1_y#0 ← (byte) get::return_p1_x#0 >> (byte) 1 [ get::return_p1_x#0 get::return_p1_y#0 ] ( main:2::get:34 [ idx main::i#2 get::return_p1_x#0 get::return_p1_y#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:8 [ get::return_p1_x#0 ] +Statement [22] (byte) get::return_p2_y#0 ← (byte) get::return_p1_x#0 << (byte) 1 [ get::return_p1_x#0 get::return_p1_y#0 get::return_p2_x#0 get::return_p2_y#0 ] ( main:2::get:34 [ idx main::i#2 get::return_p1_x#0 get::return_p1_y#0 get::return_p2_x#0 get::return_p2_y#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:9 [ get::return_p1_y#0 ] +Removing always clobbered register reg byte a as potential for zp[1]:10 [ get::return_p2_x#0 ] +Statement [23] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 [ get::return_p1_y#0 get::return_p2_x#0 get::return_p2_y#0 ] ( main:2::get:34 [ idx main::i#2 get::return_p1_y#0 get::return_p2_x#0 get::return_p2_y#0 ] ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte x as potential for zp[1]:9 [ get::return_p1_y#0 ] +Removing always clobbered register reg byte x as potential for zp[1]:10 [ get::return_p2_x#0 ] +Removing always clobbered register reg byte a as potential for zp[1]:11 [ get::return_p2_y#0 ] +Removing always clobbered register reg byte x as potential for zp[1]:11 [ get::return_p2_y#0 ] +Statement [24] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 [ get::return_p2_x#0 get::return_p2_y#0 ] ( main:2::get:34 [ idx main::i#2 get::return_p2_x#0 get::return_p2_y#0 ] ) always clobbers reg byte a reg byte x +Statement [25] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 [ get::return_p2_y#0 ] ( main:2::get:34 [ idx main::i#2 get::return_p2_y#0 ] ) always clobbers reg byte a reg byte x +Statement [26] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 [ ] ( main:2::get:34 [ idx main::i#2 ] ) always clobbers reg byte a reg byte x +Statement [30] if((byte) main::i#2<(byte) 5) goto main::@2 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a +Statement [32] stackpush(byte) ← (byte) main::i#2 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a +Statement [35] (byte) main::v_p1_x#0 ← stackpull(byte) [ idx main::i#2 main::v_p1_x#0 ] ( main:2 [ idx main::i#2 main::v_p1_x#0 ] ) always clobbers reg byte a +Statement [36] (byte) main::v_p1_y#0 ← stackpull(byte) [ idx main::i#2 main::v_p1_x#0 main::v_p1_y#0 ] ( main:2 [ idx main::i#2 main::v_p1_x#0 main::v_p1_y#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:12 [ main::v_p1_x#0 ] +Statement [37] (byte) main::v_p2_x#0 ← stackpull(byte) [ idx main::i#2 main::v_p1_x#0 main::v_p1_y#0 main::v_p2_x#0 ] ( main:2 [ idx main::i#2 main::v_p1_x#0 main::v_p1_y#0 main::v_p2_x#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:13 [ main::v_p1_y#0 ] +Statement [38] (byte) main::v_p2_y#0 ← stackpull(byte) [ idx main::i#2 main::v_p1_x#0 main::v_p1_y#0 main::v_p2_x#0 main::v_p2_y#0 ] ( main:2 [ idx main::i#2 main::v_p1_x#0 main::v_p1_y#0 main::v_p2_x#0 main::v_p2_y#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:14 [ main::v_p2_x#0 ] +Statement [39] stackpush(byte) ← (byte) main::v_p1_x#0 [ idx main::i#2 main::v_p1_y#0 main::v_p2_x#0 main::v_p2_y#0 ] ( main:2 [ idx main::i#2 main::v_p1_y#0 main::v_p2_x#0 main::v_p2_y#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:15 [ main::v_p2_y#0 ] +Statement [40] stackpush(byte) ← (byte) main::v_p1_y#0 [ idx main::i#2 main::v_p2_x#0 main::v_p2_y#0 ] ( main:2 [ idx main::i#2 main::v_p2_x#0 main::v_p2_y#0 ] ) always clobbers reg byte a +Statement [41] stackpush(byte) ← (byte) main::v_p2_x#0 [ idx main::i#2 main::v_p2_y#0 ] ( main:2 [ idx main::i#2 main::v_p2_y#0 ] ) always clobbers reg byte a +Statement [42] stackpush(byte) ← (byte) main::v_p2_y#0 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a Statement sideeffect stackpullbytes((number) 4) always clobbers reg byte a reg byte x -Statement [0] (byte) idx ← (byte) 0 [ idx get::v main::v ] ( [ idx get::v main::v ] ) always clobbers reg byte a -Statement [4] (byte) print::v_p1_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P1_X) [ idx print::v_p1_x#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p1_x#0 ] ) always clobbers reg byte a reg byte x -Statement [5] (byte) print::v_p1_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P1_Y) [ idx print::v_p1_x#0 print::v_p1_y#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p1_x#0 print::v_p1_y#0 ] ) always clobbers reg byte a reg byte x -Statement [6] (byte) print::v_p2_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P2_X) [ idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 ] ) always clobbers reg byte a reg byte x -Statement [7] (byte) print::v_p2_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P2_Y) [ idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ) always clobbers reg byte a reg byte x -Statement [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p1_x#0 [ idx print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ) always clobbers reg byte a reg byte y -Statement [10] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p1_y#0 [ idx print::v_p2_x#0 print::v_p2_y#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p2_x#0 print::v_p2_y#0 ] ) always clobbers reg byte a reg byte y -Statement [12] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p2_x#0 [ idx print::v_p2_y#0 ] ( main:2::print:54 [ get::v main::i main::v idx print::v_p2_y#0 ] ) always clobbers reg byte a reg byte y -Statement [14] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p2_y#0 [ idx ] ( main:2::print:54 [ get::v main::i main::v idx ] ) always clobbers reg byte a reg byte y -Statement [16] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' [ idx ] ( main:2::print:54 [ get::v main::i main::v idx ] ) always clobbers reg byte a reg byte y -Statement [19] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::i#0 get::v ] ( main:2::get:41 [ idx main::i main::v get::i#0 get::v ] ) always clobbers reg byte a reg byte x -Statement [20] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 [ get::i#0 get::$0 get::v ] ( main:2::get:41 [ idx main::i main::v get::i#0 get::$0 get::v ] ) always clobbers reg byte a -Statement [22] (byte~) get::$2 ← (byte) get::i#0 << (byte) 1 [ get::i#0 get::$0 get::$1 get::$2 get::v ] ( main:2::get:41 [ idx main::i main::v get::i#0 get::$0 get::$1 get::$2 get::v ] ) always clobbers reg byte a -Statement [31] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 [ get::v get::return_p1_y#0 get::return_p2_x#0 get::return_p2_y#0 ] ( main:2::get:41 [ idx main::i main::v get::v get::return_p1_y#0 get::return_p2_x#0 get::return_p2_y#0 ] ) always clobbers reg byte x -Statement [32] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 [ get::v get::return_p2_x#0 get::return_p2_y#0 ] ( main:2::get:41 [ idx main::i main::v get::v get::return_p2_x#0 get::return_p2_y#0 ] ) always clobbers reg byte x -Statement [33] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 [ get::v get::return_p2_y#0 ] ( main:2::get:41 [ idx main::i main::v get::v get::return_p2_y#0 ] ) always clobbers reg byte x -Statement [34] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 [ get::v ] ( main:2::get:41 [ idx main::i main::v get::v ] ) always clobbers reg byte x -Statement [36] (byte) main::i ← (byte) 0 [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a -Statement [37] if((byte) main::i<(byte) 5) goto main::@2 [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a -Statement [39] stackpush(byte) ← (byte) main::i [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a -Statement [42] (byte~) main::$1_p1_x ← stackpull(byte) [ idx get::v main::i main::$1_p1_x main::v ] ( main:2 [ idx get::v main::i main::$1_p1_x main::v ] ) always clobbers reg byte a -Statement [43] (byte~) main::$1_p1_y ← stackpull(byte) [ idx get::v main::i main::$1_p1_x main::$1_p1_y main::v ] ( main:2 [ idx get::v main::i main::$1_p1_x main::$1_p1_y main::v ] ) always clobbers reg byte a -Statement [44] (byte~) main::$1_p2_x ← stackpull(byte) [ idx get::v main::i main::$1_p1_x main::$1_p1_y main::$1_p2_x main::v ] ( main:2 [ idx get::v main::i main::$1_p1_x main::$1_p1_y main::$1_p2_x main::v ] ) always clobbers reg byte a -Statement [45] (byte~) main::$1_p2_y ← stackpull(byte) [ idx get::v main::i main::$1_p1_x main::$1_p1_y main::$1_p2_x main::$1_p2_y main::v ] ( main:2 [ idx get::v main::i main::$1_p1_x main::$1_p1_y main::$1_p2_x main::$1_p2_y main::v ] ) always clobbers reg byte a -Statement [50] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v) [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a -Statement [51] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a -Statement [52] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a -Statement [53] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::v main::i main::v ] ( main:2 [ idx get::v main::i main::v ] ) always clobbers reg byte a +Statement [0] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a +Statement [4] (byte) print::v_p1_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P1_X) [ idx print::v_p1_x#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p1_x#0 ] ) always clobbers reg byte a reg byte x +Statement [5] (byte) print::v_p1_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P1_Y) [ idx print::v_p1_x#0 print::v_p1_y#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p1_x#0 print::v_p1_y#0 ] ) always clobbers reg byte a reg byte x +Statement [6] (byte) print::v_p2_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P2_X) [ idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 ] ) always clobbers reg byte a reg byte x +Statement [7] (byte) print::v_p2_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P2_Y) [ idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p1_x#0 print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ) always clobbers reg byte a reg byte x +Statement [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p1_x#0 [ idx print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p1_y#0 print::v_p2_x#0 print::v_p2_y#0 ] ) always clobbers reg byte a reg byte y +Statement [10] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p1_y#0 [ idx print::v_p2_x#0 print::v_p2_y#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p2_x#0 print::v_p2_y#0 ] ) always clobbers reg byte a reg byte y +Statement [12] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p2_x#0 [ idx print::v_p2_y#0 ] ( main:2::print:43 [ main::i#2 idx print::v_p2_y#0 ] ) always clobbers reg byte a reg byte y +Statement [14] *((const byte*) SCREEN + (byte) idx) ← (byte) print::v_p2_y#0 [ idx ] ( main:2::print:43 [ main::i#2 idx ] ) always clobbers reg byte a reg byte y +Statement [16] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' [ idx ] ( main:2::print:43 [ main::i#2 idx ] ) always clobbers reg byte a reg byte y +Statement [19] (byte) get::return_p1_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::return_p1_x#0 ] ( main:2::get:34 [ idx main::i#2 get::return_p1_x#0 ] ) always clobbers reg byte a reg byte x +Statement [20] (byte) get::return_p1_y#0 ← (byte) get::return_p1_x#0 >> (byte) 1 [ get::return_p1_x#0 get::return_p1_y#0 ] ( main:2::get:34 [ idx main::i#2 get::return_p1_x#0 get::return_p1_y#0 ] ) always clobbers reg byte a +Statement [22] (byte) get::return_p2_y#0 ← (byte) get::return_p1_x#0 << (byte) 1 [ get::return_p1_x#0 get::return_p1_y#0 get::return_p2_x#0 get::return_p2_y#0 ] ( main:2::get:34 [ idx main::i#2 get::return_p1_x#0 get::return_p1_y#0 get::return_p2_x#0 get::return_p2_y#0 ] ) always clobbers reg byte a +Statement [23] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 [ get::return_p1_y#0 get::return_p2_x#0 get::return_p2_y#0 ] ( main:2::get:34 [ idx main::i#2 get::return_p1_y#0 get::return_p2_x#0 get::return_p2_y#0 ] ) always clobbers reg byte a reg byte x +Statement [24] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 [ get::return_p2_x#0 get::return_p2_y#0 ] ( main:2::get:34 [ idx main::i#2 get::return_p2_x#0 get::return_p2_y#0 ] ) always clobbers reg byte a reg byte x +Statement [25] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 [ get::return_p2_y#0 ] ( main:2::get:34 [ idx main::i#2 get::return_p2_y#0 ] ) always clobbers reg byte a reg byte x +Statement [26] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 [ ] ( main:2::get:34 [ idx main::i#2 ] ) always clobbers reg byte a reg byte x +Statement [30] if((byte) main::i#2<(byte) 5) goto main::@2 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a +Statement [32] stackpush(byte) ← (byte) main::i#2 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a +Statement [35] (byte) main::v_p1_x#0 ← stackpull(byte) [ idx main::i#2 main::v_p1_x#0 ] ( main:2 [ idx main::i#2 main::v_p1_x#0 ] ) always clobbers reg byte a +Statement [36] (byte) main::v_p1_y#0 ← stackpull(byte) [ idx main::i#2 main::v_p1_x#0 main::v_p1_y#0 ] ( main:2 [ idx main::i#2 main::v_p1_x#0 main::v_p1_y#0 ] ) always clobbers reg byte a +Statement [37] (byte) main::v_p2_x#0 ← stackpull(byte) [ idx main::i#2 main::v_p1_x#0 main::v_p1_y#0 main::v_p2_x#0 ] ( main:2 [ idx main::i#2 main::v_p1_x#0 main::v_p1_y#0 main::v_p2_x#0 ] ) always clobbers reg byte a +Statement [38] (byte) main::v_p2_y#0 ← stackpull(byte) [ idx main::i#2 main::v_p1_x#0 main::v_p1_y#0 main::v_p2_x#0 main::v_p2_y#0 ] ( main:2 [ idx main::i#2 main::v_p1_x#0 main::v_p1_y#0 main::v_p2_x#0 main::v_p2_y#0 ] ) always clobbers reg byte a +Statement [39] stackpush(byte) ← (byte) main::v_p1_x#0 [ idx main::i#2 main::v_p1_y#0 main::v_p2_x#0 main::v_p2_y#0 ] ( main:2 [ idx main::i#2 main::v_p1_y#0 main::v_p2_x#0 main::v_p2_y#0 ] ) always clobbers reg byte a +Statement [40] stackpush(byte) ← (byte) main::v_p1_y#0 [ idx main::i#2 main::v_p2_x#0 main::v_p2_y#0 ] ( main:2 [ idx main::i#2 main::v_p2_x#0 main::v_p2_y#0 ] ) always clobbers reg byte a +Statement [41] stackpush(byte) ← (byte) main::v_p2_x#0 [ idx main::i#2 main::v_p2_y#0 ] ( main:2 [ idx main::i#2 main::v_p2_y#0 ] ) always clobbers reg byte a +Statement [42] stackpush(byte) ← (byte) main::v_p2_y#0 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a Statement sideeffect stackpullbytes((number) 4) always clobbers reg byte a reg byte x -Potential registers zp[1]:2 [ idx ] : zp[1]:2 , -Potential registers zp[1]:3 [ print::v_p1_x#0 ] : zp[1]:3 , reg byte y , -Potential registers zp[1]:4 [ print::v_p1_y#0 ] : zp[1]:4 , -Potential registers zp[1]:5 [ print::v_p2_x#0 ] : zp[1]:5 , -Potential registers zp[1]:6 [ print::v_p2_y#0 ] : zp[1]:6 , reg byte x , -Potential registers zp[1]:7 [ get::i#0 ] : zp[1]:7 , reg byte x , reg byte y , -Potential registers zp[1]:8 [ get::$0 ] : zp[1]:8 , reg byte x , reg byte y , -Potential registers zp[1]:9 [ get::$1 ] : zp[1]:9 , reg byte x , reg byte y , -Potential registers zp[1]:10 [ get::$2 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , -Potential registers zp[1]:11 [ get::return_p1_x#0 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , -Potential registers zp[1]:12 [ get::return_p1_y#0 ] : zp[1]:12 , reg byte a , reg byte y , -Potential registers zp[1]:13 [ get::return_p2_x#0 ] : zp[1]:13 , reg byte a , reg byte y , -Potential registers zp[1]:14 [ get::return_p2_y#0 ] : zp[1]:14 , reg byte a , reg byte y , -Potential registers zp[1]:15 [ main::i ] : zp[1]:15 , -Potential registers zp[1]:16 [ main::$1_p1_x ] : zp[1]:16 , reg byte x , reg byte y , -Potential registers zp[1]:17 [ main::$1_p1_y ] : zp[1]:17 , reg byte x , reg byte y , -Potential registers zp[1]:18 [ main::$1_p2_x ] : zp[1]:18 , reg byte x , reg byte y , -Potential registers zp[1]:19 [ main::$1_p2_y ] : zp[1]:19 , reg byte a , reg byte x , reg byte y , -Potential registers zp[2]:20 [ Vector::p1 ] : zp[2]:20 , -Potential registers zp[2]:22 [ Vector::p2 ] : zp[2]:22 , -Potential registers zp[4]:24 [ main::v ] : zp[4]:24 , -Potential registers zp[4]:28 [ get::v ] : zp[4]:28 , +Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , +Potential registers zp[1]:3 [ idx ] : zp[1]:3 , +Potential registers zp[1]:4 [ print::v_p1_x#0 ] : zp[1]:4 , reg byte y , +Potential registers zp[1]:5 [ print::v_p1_y#0 ] : zp[1]:5 , +Potential registers zp[1]:6 [ print::v_p2_x#0 ] : zp[1]:6 , +Potential registers zp[1]:7 [ print::v_p2_y#0 ] : zp[1]:7 , reg byte x , +Potential registers zp[1]:8 [ get::return_p1_x#0 ] : zp[1]:8 , reg byte x , reg byte y , +Potential registers zp[1]:9 [ get::return_p1_y#0 ] : zp[1]:9 , reg byte y , +Potential registers zp[1]:10 [ get::return_p2_x#0 ] : zp[1]:10 , reg byte y , +Potential registers zp[1]:11 [ get::return_p2_y#0 ] : zp[1]:11 , reg byte y , +Potential registers zp[1]:12 [ main::v_p1_x#0 ] : zp[1]:12 , reg byte x , reg byte y , +Potential registers zp[1]:13 [ main::v_p1_y#0 ] : zp[1]:13 , reg byte x , reg byte y , +Potential registers zp[1]:14 [ main::v_p2_x#0 ] : zp[1]:14 , reg byte x , reg byte y , +Potential registers zp[1]:15 [ main::v_p2_y#0 ] : zp[1]:15 , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] 5.5: zp[1]:16 [ main::$1_p1_x ] 5.5: zp[1]:17 [ main::$1_p1_y ] 5.5: zp[1]:18 [ main::$1_p2_x ] 5.5: zp[1]:19 [ main::$1_p2_y ] 2.3: zp[1]:15 [ main::i ] 0: zp[4]:24 [ main::v ] -Uplift Scope [get] 2.5: zp[1]:7 [ get::i#0 ] 1: zp[1]:8 [ get::$0 ] 1: zp[1]:9 [ get::$1 ] 1: zp[1]:10 [ get::$2 ] 1: zp[1]:11 [ get::return_p1_x#0 ] 1: zp[1]:12 [ get::return_p1_y#0 ] 1: zp[1]:13 [ get::return_p2_x#0 ] 1: zp[1]:14 [ get::return_p2_y#0 ] 0: zp[4]:28 [ get::v ] -Uplift Scope [print] 1: zp[1]:3 [ print::v_p1_x#0 ] 0.8: zp[1]:4 [ print::v_p1_y#0 ] 0.67: zp[1]:5 [ print::v_p2_x#0 ] 0.57: zp[1]:6 [ print::v_p2_y#0 ] -Uplift Scope [] 0.86: zp[1]:2 [ idx ] +Uplift Scope [main] 24.93: zp[1]:2 [ main::i#2 main::i#1 ] 5.5: zp[1]:12 [ main::v_p1_x#0 ] 5.5: zp[1]:13 [ main::v_p1_y#0 ] 5.5: zp[1]:14 [ main::v_p2_x#0 ] 5.5: zp[1]:15 [ main::v_p2_y#0 ] +Uplift Scope [get] 2.5: zp[1]:8 [ get::return_p1_x#0 ] 1: zp[1]:9 [ get::return_p1_y#0 ] 1: zp[1]:10 [ get::return_p2_x#0 ] 1: zp[1]:11 [ get::return_p2_y#0 ] +Uplift Scope [print] 1: zp[1]:4 [ print::v_p1_x#0 ] 0.8: zp[1]:5 [ print::v_p1_y#0 ] 0.67: zp[1]:6 [ print::v_p2_x#0 ] 0.57: zp[1]:7 [ print::v_p2_y#0 ] +Uplift Scope [] 0.94: zp[1]:3 [ idx ] Uplift Scope [Point] -Uplift Scope [Vector] 0: zp[2]:20 [ Vector::p1 ] 0: zp[2]:22 [ Vector::p2 ] +Uplift Scope [Vector] -Uplifting [main] best 1566 combination reg byte y [ main::$1_p1_x ] reg byte x [ main::$1_p1_y ] zp[1]:18 [ main::$1_p2_x ] zp[1]:19 [ main::$1_p2_y ] zp[1]:15 [ main::i ] zp[4]:24 [ main::v ] -Limited combination testing to 100 combinations of 108 possible. -Uplifting [get] best 1555 combination reg byte y [ get::i#0 ] zp[1]:8 [ get::$0 ] reg byte x [ get::$1 ] zp[1]:10 [ get::$2 ] zp[1]:11 [ get::return_p1_x#0 ] zp[1]:12 [ get::return_p1_y#0 ] zp[1]:13 [ get::return_p2_x#0 ] zp[1]:14 [ get::return_p2_y#0 ] zp[4]:28 [ get::v ] -Limited combination testing to 100 combinations of 11664 possible. -Uplifting [print] best 1551 combination reg byte y [ print::v_p1_x#0 ] zp[1]:4 [ print::v_p1_y#0 ] zp[1]:5 [ print::v_p2_x#0 ] reg byte x [ print::v_p2_y#0 ] -Uplifting [] best 1551 combination zp[1]:2 [ idx ] -Uplifting [Point] best 1551 combination -Uplifting [Vector] best 1551 combination zp[2]:20 [ Vector::p1 ] zp[2]:22 [ Vector::p2 ] -Attempting to uplift remaining variables inzp[1]:18 [ main::$1_p2_x ] -Uplifting [main] best 1551 combination zp[1]:18 [ main::$1_p2_x ] -Attempting to uplift remaining variables inzp[1]:19 [ main::$1_p2_y ] -Uplifting [main] best 1551 combination zp[1]:19 [ main::$1_p2_y ] -Attempting to uplift remaining variables inzp[1]:15 [ main::i ] -Uplifting [main] best 1551 combination zp[1]:15 [ main::i ] -Attempting to uplift remaining variables inzp[1]:8 [ get::$0 ] -Uplifting [get] best 1551 combination zp[1]:8 [ get::$0 ] -Attempting to uplift remaining variables inzp[1]:10 [ get::$2 ] -Uplifting [get] best 1551 combination zp[1]:10 [ get::$2 ] -Attempting to uplift remaining variables inzp[1]:11 [ get::return_p1_x#0 ] -Uplifting [get] best 1547 combination reg byte x [ get::return_p1_x#0 ] -Attempting to uplift remaining variables inzp[1]:12 [ get::return_p1_y#0 ] -Uplifting [get] best 1543 combination reg byte y [ get::return_p1_y#0 ] -Attempting to uplift remaining variables inzp[1]:13 [ get::return_p2_x#0 ] -Uplifting [get] best 1543 combination zp[1]:13 [ get::return_p2_x#0 ] -Attempting to uplift remaining variables inzp[1]:14 [ get::return_p2_y#0 ] -Uplifting [get] best 1543 combination zp[1]:14 [ get::return_p2_y#0 ] -Attempting to uplift remaining variables inzp[1]:2 [ idx ] -Uplifting [] best 1543 combination zp[1]:2 [ idx ] -Attempting to uplift remaining variables inzp[1]:4 [ print::v_p1_y#0 ] -Uplifting [print] best 1543 combination zp[1]:4 [ print::v_p1_y#0 ] -Attempting to uplift remaining variables inzp[1]:5 [ print::v_p2_x#0 ] -Uplifting [print] best 1543 combination zp[1]:5 [ print::v_p2_x#0 ] -Coalescing zero page register [ zp[1]:8 [ get::$0 ] ] with [ zp[1]:4 [ print::v_p1_y#0 ] ] -Coalescing zero page register [ zp[1]:10 [ get::$2 ] ] with [ zp[1]:5 [ print::v_p2_x#0 ] ] -Coalescing zero page register [ zp[1]:18 [ main::$1_p2_x ] ] with [ zp[1]:13 [ get::return_p2_x#0 ] ] -Coalescing zero page register [ zp[1]:19 [ main::$1_p2_y ] ] with [ zp[1]:14 [ get::return_p2_y#0 ] ] -Allocated (was zp[1]:8) zp[1]:3 [ get::$0 print::v_p1_y#0 ] -Allocated (was zp[1]:10) zp[1]:4 [ get::$2 print::v_p2_x#0 ] -Allocated (was zp[1]:15) zp[1]:5 [ main::i ] -Allocated (was zp[1]:18) zp[1]:6 [ main::$1_p2_x get::return_p2_x#0 ] -Allocated (was zp[1]:19) zp[1]:7 [ main::$1_p2_y get::return_p2_y#0 ] -Allocated (was zp[2]:20) zp[2]:8 [ Vector::p1 ] -Allocated (was zp[2]:22) zp[2]:10 [ Vector::p2 ] -Allocated (was zp[4]:24) zp[4]:12 [ main::v ] -Allocated (was zp[4]:28) zp[4]:16 [ get::v ] +Uplifting [main] best 1324 combination zp[1]:2 [ main::i#2 main::i#1 ] reg byte y [ main::v_p1_x#0 ] reg byte x [ main::v_p1_y#0 ] zp[1]:14 [ main::v_p2_x#0 ] zp[1]:15 [ main::v_p2_y#0 ] +Uplifting [get] best 1317 combination reg byte x [ get::return_p1_x#0 ] zp[1]:9 [ get::return_p1_y#0 ] reg byte y [ get::return_p2_x#0 ] zp[1]:11 [ get::return_p2_y#0 ] +Uplifting [print] best 1313 combination reg byte y [ print::v_p1_x#0 ] zp[1]:5 [ print::v_p1_y#0 ] zp[1]:6 [ print::v_p2_x#0 ] reg byte x [ print::v_p2_y#0 ] +Uplifting [] best 1313 combination zp[1]:3 [ idx ] +Uplifting [Point] best 1313 combination +Uplifting [Vector] best 1313 combination +Attempting to uplift remaining variables inzp[1]:2 [ main::i#2 main::i#1 ] +Uplifting [main] best 1313 combination zp[1]:2 [ main::i#2 main::i#1 ] +Attempting to uplift remaining variables inzp[1]:14 [ main::v_p2_x#0 ] +Uplifting [main] best 1313 combination zp[1]:14 [ main::v_p2_x#0 ] +Attempting to uplift remaining variables inzp[1]:15 [ main::v_p2_y#0 ] +Uplifting [main] best 1313 combination zp[1]:15 [ main::v_p2_y#0 ] +Attempting to uplift remaining variables inzp[1]:9 [ get::return_p1_y#0 ] +Uplifting [get] best 1313 combination zp[1]:9 [ get::return_p1_y#0 ] +Attempting to uplift remaining variables inzp[1]:11 [ get::return_p2_y#0 ] +Uplifting [get] best 1313 combination zp[1]:11 [ get::return_p2_y#0 ] +Attempting to uplift remaining variables inzp[1]:3 [ idx ] +Uplifting [] best 1313 combination zp[1]:3 [ idx ] +Attempting to uplift remaining variables inzp[1]:5 [ print::v_p1_y#0 ] +Uplifting [print] best 1313 combination zp[1]:5 [ print::v_p1_y#0 ] +Attempting to uplift remaining variables inzp[1]:6 [ print::v_p2_x#0 ] +Uplifting [print] best 1313 combination zp[1]:6 [ print::v_p2_x#0 ] +Coalescing zero page register [ zp[1]:9 [ get::return_p1_y#0 ] ] with [ zp[1]:5 [ print::v_p1_y#0 ] ] +Coalescing zero page register [ zp[1]:11 [ get::return_p2_y#0 ] ] with [ zp[1]:6 [ print::v_p2_x#0 ] ] +Coalescing zero page register [ zp[1]:14 [ main::v_p2_x#0 ] ] with [ zp[1]:9 [ get::return_p1_y#0 print::v_p1_y#0 ] ] +Coalescing zero page register [ zp[1]:15 [ main::v_p2_y#0 ] ] with [ zp[1]:11 [ get::return_p2_y#0 print::v_p2_x#0 ] ] +Allocated (was zp[1]:14) zp[1]:4 [ main::v_p2_x#0 get::return_p1_y#0 print::v_p1_y#0 ] +Allocated (was zp[1]:15) zp[1]:5 [ main::v_p2_y#0 get::return_p2_y#0 print::v_p2_x#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -951,10 +900,10 @@ ASSEMBLER BEFORE OPTIMIZATION .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 + .const STACK_BASE = $103 .const OFFSET_STRUCT_POINT_Y = 1 .const OFFSET_STRUCT_VECTOR_P2 = 2 - .const STACK_BASE = $103 - .label idx = 2 + .label idx = 3 // @begin __bbegin: // [0] (byte) idx ← (byte) 0 -- vbuz1=vbuc1 @@ -973,14 +922,14 @@ __bend_from___b1: // @end __bend: // print -// print(byte register(Y) v_p1_x, byte zp(3) v_p1_y, byte zp(4) v_p2_x, byte register(X) v_p2_y) +// print(byte register(Y) v_p1_x, byte zp(4) v_p1_y, byte zp(5) v_p2_x, byte register(X) v_p2_y) print: { .const OFFSET_STACK_V_P1_X = 3 .const OFFSET_STACK_V_P1_Y = 2 .const OFFSET_STACK_V_P2_X = 1 .const OFFSET_STACK_V_P2_Y = 0 - .label v_p1_y = 3 - .label v_p2_x = 4 + .label v_p1_y = 4 + .label v_p2_x = 5 // [4] (byte) print::v_p1_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P1_X) -- vbuyy=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_V_P1_X,x @@ -1034,147 +983,117 @@ print: { rts } // get -// get(byte register(Y) i) get: { .const OFFSET_STACK_I = 0 - .label __0 = 3 - .label __2 = 4 - .label v = $10 - .label return_p2_x = 6 - .label return_p2_y = 7 - // [19] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuyy=_stackidxbyte_vbuc1 + .label return_p1_y = 4 + .label return_p2_y = 5 + // [19] (byte) get::return_p1_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_I,x - tay - // [20] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuz1=vbuyy_ror_1 - tya - lsr - sta.z __0 - // [21] (byte~) get::$1 ← (byte) get::i#0 + (byte) 1 -- vbuxx=vbuyy_plus_1 - tya tax - inx - // [22] (byte~) get::$2 ← (byte) get::i#0 << (byte) 1 -- vbuz1=vbuyy_rol_1 - tya + // [20] (byte) get::return_p1_y#0 ← (byte) get::return_p1_x#0 >> (byte) 1 -- vbuz1=vbuxx_ror_1 + txa + lsr + sta.z return_p1_y + // [21] (byte) get::return_p2_x#0 ← (byte) get::return_p1_x#0 + (byte) 1 -- vbuyy=vbuxx_plus_1 + txa + tay + iny + // [22] (byte) get::return_p2_y#0 ← (byte) get::return_p1_x#0 << (byte) 1 -- vbuz1=vbuxx_rol_1 + txa asl - sta.z __2 - // [23] *((byte*)(struct Point*)&(struct Vector) get::v) ← (byte) get::i#0 -- _deref_pbuc1=vbuyy - sty.z v - // [24] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuz1 - lda.z __0 - sta v+OFFSET_STRUCT_POINT_Y - // [25] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte~) get::$1 -- _deref_pbuc1=vbuxx - stx v+OFFSET_STRUCT_VECTOR_P2 - // [26] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$2 -- _deref_pbuc1=vbuz1 - lda.z __2 - sta v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y - // [27] (byte) get::return_p1_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v) -- vbuxx=_deref_pbuc1 - ldx.z v - // [28] (byte) get::return_p1_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=_deref_pbuc1 - ldy v+OFFSET_STRUCT_POINT_Y - // [29] (byte) get::return_p2_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2) -- vbuz1=_deref_pbuc1 - lda v+OFFSET_STRUCT_VECTOR_P2 - sta.z return_p2_x - // [30] (byte) get::return_p2_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1 - lda v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y sta.z return_p2_y jmp __breturn // get::@return __breturn: - // [31] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 -- _stackidxbyte_vbuc1=vbuxx + // [23] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 -- _stackidxbyte_vbuc1=vbuxx txa tsx sta STACK_BASE+0,x - // [32] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 -- _stackidxbyte_vbuc1=vbuyy - tya + // [24] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 -- _stackidxbyte_vbuc1=vbuz1 + lda.z return_p1_y tsx sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x - // [33] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 -- _stackidxbyte_vbuc1=vbuz1 - lda.z return_p2_x + // [25] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 -- _stackidxbyte_vbuc1=vbuyy + tya tsx sta STACK_BASE+OFFSET_STRUCT_VECTOR_P2,x - // [34] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 -- _stackidxbyte_vbuc1=vbuz1 + // [26] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return_p2_y tsx sta STACK_BASE+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y,x - // [35] return + // [27] return rts } // main main: { - .label i = 5 - .label v = $c - .label __1_p2_x = 6 - .label __1_p2_y = 7 - // [36] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + .label v_p2_x = 4 + .label v_p2_y = 5 + .label i = 2 + // [29] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [29] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // main::@1 __b1: - // [37] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + // [30] if((byte) main::i#2<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #5 bcc __b2 jmp __breturn // main::@return __breturn: - // [38] return + // [31] return rts // main::@2 __b2: - // [39] stackpush(byte) ← (byte) main::i -- _stackpushbyte_=vbuz1 + // [32] stackpush(byte) ← (byte) main::i#2 -- _stackpushbyte_=vbuz1 lda.z i pha // sideeffect stackpushbytes((number) 3) -- _stackpushbyte_3 pha pha pha - // [41] callexecute get -- jsr + // [34] callexecute get -- jsr jsr get - // [42] (byte~) main::$1_p1_x ← stackpull(byte) -- vbuyy=_stackpullbyte_ + // [35] (byte) main::v_p1_x#0 ← stackpull(byte) -- vbuyy=_stackpullbyte_ pla tay - // [43] (byte~) main::$1_p1_y ← stackpull(byte) -- vbuxx=_stackpullbyte_ + // [36] (byte) main::v_p1_y#0 ← stackpull(byte) -- vbuxx=_stackpullbyte_ pla tax - // [44] (byte~) main::$1_p2_x ← stackpull(byte) -- vbuz1=_stackpullbyte_ + // [37] (byte) main::v_p2_x#0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla - sta.z __1_p2_x - // [45] (byte~) main::$1_p2_y ← stackpull(byte) -- vbuz1=_stackpullbyte_ + sta.z v_p2_x + // [38] (byte) main::v_p2_y#0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla - sta.z __1_p2_y - // [46] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte~) main::$1_p1_x -- _deref_pbuc1=vbuyy - sty.z v - // [47] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p1_y -- _deref_pbuc1=vbuxx - stx v+OFFSET_STRUCT_POINT_Y - // [48] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte~) main::$1_p2_x -- _deref_pbuc1=vbuz1 - lda.z __1_p2_x - sta v+OFFSET_STRUCT_VECTOR_P2 - // [49] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p2_y -- _deref_pbuc1=vbuz1 - lda.z __1_p2_y - sta v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y - // [50] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _stackpushbyte_=_deref_pbuc1 - lda.z v + sta.z v_p2_y + // [39] stackpush(byte) ← (byte) main::v_p1_x#0 -- _stackpushbyte_=vbuyy + tya pha - // [51] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _stackpushbyte_=_deref_pbuc1 - lda v+OFFSET_STRUCT_POINT_Y + // [40] stackpush(byte) ← (byte) main::v_p1_y#0 -- _stackpushbyte_=vbuxx + txa pha - // [52] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) -- _stackpushbyte_=_deref_pbuc1 - lda v+OFFSET_STRUCT_VECTOR_P2 + // [41] stackpush(byte) ← (byte) main::v_p2_x#0 -- _stackpushbyte_=vbuz1 + lda.z v_p2_x pha - // [53] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) -- _stackpushbyte_=_deref_pbuc1 - lda v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y + // [42] stackpush(byte) ← (byte) main::v_p2_y#0 -- _stackpushbyte_=vbuz1 + lda.z v_p2_y pha - // [54] callexecute print -- jsr + // [43] callexecute print -- jsr jsr print // sideeffect stackpullbytes((number) 4) -- _stackpullbyte_4 tsx txa axs #-4 txs - // [56] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [45] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 inc.z i + // [29] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + __b1_from___b2: + // [29] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy jmp __b1 } // File Data @@ -1187,8 +1106,6 @@ Removing instruction jmp __breturn Removing instruction jmp __b1 Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination -Replacing instruction lda.z v with TYA -Replacing instruction lda v+OFFSET_STRUCT_POINT_Y with TXA Removing instruction __b1_from___bbegin: Removing instruction __bend_from___b1: Succesful ASM optimization Pass5RedundantLabelElimination @@ -1196,7 +1113,9 @@ Removing instruction __b1: Removing instruction __bend: Removing instruction __breturn: Removing instruction __breturn: +Removing instruction __b1_from_main: Removing instruction __breturn: +Removing instruction __b1_from___b2: Succesful ASM optimization Pass5UnusedLabelElimination Adding RTS to root block Succesful ASM optimization Pass5AddMainRts @@ -1207,43 +1126,51 @@ FINAL SYMBOL TABLE (label) @end (const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 (const byte) OFFSET_STRUCT_VECTOR_P2 = (byte) 2 -(byte) Point::x loadstore -(byte) Point::y loadstore +(byte) Point::x +(byte) Point::y (const byte*) SCREEN = (byte*) 1024 (const word) STACK_BASE = (word) $103 -(struct Point) Vector::p1 loadstore zp[2]:8 -(struct Point) Vector::p2 loadstore zp[2]:10 +(struct Point) Vector::p1 +(struct Point) Vector::p2 __stackcall (struct Vector()) get((byte) get::i) -(byte~) get::$0 zp[1]:3 1.0 -(byte~) get::$1 reg byte x 1.0 -(byte~) get::$2 zp[1]:4 1.0 (label) get::@return (const byte) get::OFFSET_STACK_I = (byte) 0 (byte) get::i -(byte) get::i#0 reg byte y 2.5 (struct Vector) get::return (struct Point) get::return_p1 (byte) get::return_p1_x -(byte) get::return_p1_x#0 reg byte x 1.0 +(byte) get::return_p1_x#0 reg byte x 2.5 (byte) get::return_p1_y -(byte) get::return_p1_y#0 reg byte y 1.0 +(byte) get::return_p1_y#0 return_p1_y zp[1]:4 1.0 (struct Point) get::return_p2 (byte) get::return_p2_x -(byte) get::return_p2_x#0 return_p2_x zp[1]:6 1.0 +(byte) get::return_p2_x#0 reg byte y 1.0 (byte) get::return_p2_y -(byte) get::return_p2_y#0 return_p2_y zp[1]:7 1.0 -(struct Vector) get::v loadstore zp[4]:16 -(byte) idx loadstore zp[1]:2 0.8648648648648649 +(byte) get::return_p2_y#0 return_p2_y zp[1]:5 1.0 +(struct Point) get::v_p1 +(byte) get::v_p1_x +(byte) get::v_p1_y +(struct Point) get::v_p2 +(byte) get::v_p2_x +(byte) get::v_p2_y +(byte) idx loadstore zp[1]:3 0.9411764705882354 __stackcall (void()) main() -(byte~) main::$1_p1_x reg byte y 5.5 -(byte~) main::$1_p1_y reg byte x 5.5 -(byte~) main::$1_p2_x zp[1]:6 5.5 -(byte~) main::$1_p2_y zp[1]:7 5.5 (label) main::@1 (label) main::@2 (label) main::@return -(byte) main::i loadstore zp[1]:5 2.3000000000000003 -(struct Vector) main::v loadstore zp[4]:12 +(byte) main::i +(byte) main::i#1 i zp[1]:2 22.0 +(byte) main::i#2 i zp[1]:2 2.933333333333333 +(struct Point) main::v_p1 +(byte) main::v_p1_x +(byte) main::v_p1_x#0 reg byte y 5.5 +(byte) main::v_p1_y +(byte) main::v_p1_y#0 reg byte x 5.5 +(struct Point) main::v_p2 +(byte) main::v_p2_x +(byte) main::v_p2_x#0 v_p2_x zp[1]:4 5.5 +(byte) main::v_p2_y +(byte) main::v_p2_y#0 v_p2_y zp[1]:5 5.5 __stackcall (void()) print((byte) print::v_p1_x , (byte) print::v_p1_y , (byte) print::v_p2_x , (byte) print::v_p2_y) (label) print::@return (const byte) print::OFFSET_STACK_V_P1_X = (byte) 3 @@ -1254,35 +1181,27 @@ __stackcall (void()) print((byte) print::v_p1_x , (byte) print::v_p1_y , (byte) (byte) print::v_p1_x (byte) print::v_p1_x#0 reg byte y 1.0 (byte) print::v_p1_y -(byte) print::v_p1_y#0 v_p1_y zp[1]:3 0.8 +(byte) print::v_p1_y#0 v_p1_y zp[1]:4 0.8 (struct Point) print::v_p2 (byte) print::v_p2_x -(byte) print::v_p2_x#0 v_p2_x zp[1]:4 0.6666666666666666 +(byte) print::v_p2_x#0 v_p2_x zp[1]:5 0.6666666666666666 (byte) print::v_p2_y (byte) print::v_p2_y#0 reg byte x 0.5714285714285714 -zp[1]:2 [ idx ] +zp[1]:2 [ main::i#2 main::i#1 ] +zp[1]:3 [ idx ] reg byte y [ print::v_p1_x#0 ] reg byte x [ print::v_p2_y#0 ] -reg byte y [ get::i#0 ] -zp[1]:3 [ get::$0 print::v_p1_y#0 ] -reg byte x [ get::$1 ] -zp[1]:4 [ get::$2 print::v_p2_x#0 ] reg byte x [ get::return_p1_x#0 ] -reg byte y [ get::return_p1_y#0 ] -zp[1]:5 [ main::i ] -reg byte y [ main::$1_p1_x ] -reg byte x [ main::$1_p1_y ] -zp[1]:6 [ main::$1_p2_x get::return_p2_x#0 ] -zp[1]:7 [ main::$1_p2_y get::return_p2_y#0 ] -zp[2]:8 [ Vector::p1 ] -zp[2]:10 [ Vector::p2 ] -zp[4]:12 [ main::v ] -zp[4]:16 [ get::v ] +reg byte y [ get::return_p2_x#0 ] +reg byte y [ main::v_p1_x#0 ] +reg byte x [ main::v_p1_y#0 ] +zp[1]:4 [ main::v_p2_x#0 get::return_p1_y#0 print::v_p1_y#0 ] +zp[1]:5 [ main::v_p2_y#0 get::return_p2_y#0 print::v_p2_x#0 ] FINAL ASSEMBLER -Score: 1474 +Score: 1247 // File Comments // Test a procedure with calling convention stack @@ -1293,10 +1212,10 @@ Score: 1474 .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 + .const STACK_BASE = $103 .const OFFSET_STRUCT_POINT_Y = 1 .const OFFSET_STRUCT_VECTOR_P2 = 2 - .const STACK_BASE = $103 - .label idx = 2 + .label idx = 3 // @begin __bbegin: // idx = 0 @@ -1311,14 +1230,14 @@ __bbegin: // [3] phi from @1 to @end [phi:@1->@end] // @end // print -// print(byte register(Y) v_p1_x, byte zp(3) v_p1_y, byte zp(4) v_p2_x, byte register(X) v_p2_y) +// print(byte register(Y) v_p1_x, byte zp(4) v_p1_y, byte zp(5) v_p2_x, byte register(X) v_p2_y) print: { .const OFFSET_STACK_V_P1_X = 3 .const OFFSET_STACK_V_P1_Y = 2 .const OFFSET_STACK_V_P2_X = 1 .const OFFSET_STACK_V_P2_Y = 0 - .label v_p1_y = 3 - .label v_p2_x = 4 + .label v_p1_y = 4 + .label v_p2_x = 5 // } // [4] (byte) print::v_p1_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_V_P1_X) -- vbuyy=_stackidxbyte_vbuc1 tsx @@ -1382,146 +1301,109 @@ print: { rts } // get -// get(byte register(Y) i) get: { .const OFFSET_STACK_I = 0 - .label __0 = 3 - .label __2 = 4 - .label v = $10 - .label return_p2_x = 6 - .label return_p2_y = 7 - // [19] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuyy=_stackidxbyte_vbuc1 + .label return_p1_y = 4 + .label return_p2_y = 5 + // [19] (byte) get::return_p1_x#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_I,x - tay - // i/2 - // [20] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuz1=vbuyy_ror_1 - tya - lsr - sta.z __0 - // i+1 - // [21] (byte~) get::$1 ← (byte) get::i#0 + (byte) 1 -- vbuxx=vbuyy_plus_1 - tya tax - inx + // i/2 + // [20] (byte) get::return_p1_y#0 ← (byte) get::return_p1_x#0 >> (byte) 1 -- vbuz1=vbuxx_ror_1 + txa + lsr + sta.z return_p1_y + // i+1 + // [21] (byte) get::return_p2_x#0 ← (byte) get::return_p1_x#0 + (byte) 1 -- vbuyy=vbuxx_plus_1 + txa + tay + iny // i*2 - // [22] (byte~) get::$2 ← (byte) get::i#0 << (byte) 1 -- vbuz1=vbuyy_rol_1 - tya + // [22] (byte) get::return_p2_y#0 ← (byte) get::return_p1_x#0 << (byte) 1 -- vbuz1=vbuxx_rol_1 + txa asl - sta.z __2 - // v = { {i, i/2}, {i+1, i*2} } - // [23] *((byte*)(struct Point*)&(struct Vector) get::v) ← (byte) get::i#0 -- _deref_pbuc1=vbuyy - sty.z v - // [24] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuz1 - lda.z __0 - sta v+OFFSET_STRUCT_POINT_Y - // [25] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte~) get::$1 -- _deref_pbuc1=vbuxx - stx v+OFFSET_STRUCT_VECTOR_P2 - // [26] *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$2 -- _deref_pbuc1=vbuz1 - lda.z __2 - sta v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y - // return v; - // [27] (byte) get::return_p1_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v) -- vbuxx=_deref_pbuc1 - ldx.z v - // [28] (byte) get::return_p1_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=_deref_pbuc1 - ldy v+OFFSET_STRUCT_POINT_Y - // [29] (byte) get::return_p2_x#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2) -- vbuz1=_deref_pbuc1 - lda v+OFFSET_STRUCT_VECTOR_P2 - sta.z return_p2_x - // [30] (byte) get::return_p2_y#0 ← *((byte*)(struct Point*)&(struct Vector) get::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1 - lda v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y sta.z return_p2_y // get::@return // } - // [31] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 -- _stackidxbyte_vbuc1=vbuxx + // [23] stackidx(byte,(byte) 0) ← (byte) get::return_p1_x#0 -- _stackidxbyte_vbuc1=vbuxx txa tsx sta STACK_BASE+0,x - // [32] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 -- _stackidxbyte_vbuc1=vbuyy - tya + // [24] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p1_y#0 -- _stackidxbyte_vbuc1=vbuz1 + lda.z return_p1_y tsx sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x - // [33] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 -- _stackidxbyte_vbuc1=vbuz1 - lda.z return_p2_x + // [25] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte) get::return_p2_x#0 -- _stackidxbyte_vbuc1=vbuyy + tya tsx sta STACK_BASE+OFFSET_STRUCT_VECTOR_P2,x - // [34] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 -- _stackidxbyte_vbuc1=vbuz1 + // [26] stackidx(byte,(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_p2_y#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return_p2_y tsx sta STACK_BASE+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y,x - // [35] return + // [27] return rts } // main main: { - .label i = 5 - .label v = $c - .label __1_p2_x = 6 - .label __1_p2_y = 7 - // i=0 - // [36] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + .label v_p2_x = 4 + .label v_p2_y = 5 + .label i = 2 + // [29] phi from main to main::@1 [phi:main->main::@1] + // [29] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 lda #0 sta.z i // main::@1 __b1: // for(char i=0;i<5;i++) - // [37] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + // [30] if((byte) main::i#2<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #5 bcc __b2 // main::@return // } - // [38] return + // [31] return rts // main::@2 __b2: // get(i) - // [39] stackpush(byte) ← (byte) main::i -- _stackpushbyte_=vbuz1 + // [32] stackpush(byte) ← (byte) main::i#2 -- _stackpushbyte_=vbuz1 lda.z i pha // sideeffect stackpushbytes((number) 3) -- _stackpushbyte_3 pha pha pha - // [41] callexecute get -- jsr + // [34] callexecute get -- jsr jsr get - // [42] (byte~) main::$1_p1_x ← stackpull(byte) -- vbuyy=_stackpullbyte_ + // v = get(i) + // [35] (byte) main::v_p1_x#0 ← stackpull(byte) -- vbuyy=_stackpullbyte_ pla tay - // [43] (byte~) main::$1_p1_y ← stackpull(byte) -- vbuxx=_stackpullbyte_ + // [36] (byte) main::v_p1_y#0 ← stackpull(byte) -- vbuxx=_stackpullbyte_ pla tax - // [44] (byte~) main::$1_p2_x ← stackpull(byte) -- vbuz1=_stackpullbyte_ + // [37] (byte) main::v_p2_x#0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla - sta.z __1_p2_x - // [45] (byte~) main::$1_p2_y ← stackpull(byte) -- vbuz1=_stackpullbyte_ + sta.z v_p2_x + // [38] (byte) main::v_p2_y#0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla - sta.z __1_p2_y - // v = get(i) - // [46] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte~) main::$1_p1_x -- _deref_pbuc1=vbuyy - sty.z v - // [47] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p1_y -- _deref_pbuc1=vbuxx - stx v+OFFSET_STRUCT_POINT_Y - // [48] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) ← (byte~) main::$1_p2_x -- _deref_pbuc1=vbuz1 - lda.z __1_p2_x - sta v+OFFSET_STRUCT_VECTOR_P2 - // [49] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_p2_y -- _deref_pbuc1=vbuz1 - lda.z __1_p2_y - sta v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y + sta.z v_p2_y // print(v) - // [50] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _stackpushbyte_=_deref_pbuc1 + // [39] stackpush(byte) ← (byte) main::v_p1_x#0 -- _stackpushbyte_=vbuyy tya pha - // [51] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _stackpushbyte_=_deref_pbuc1 + // [40] stackpush(byte) ← (byte) main::v_p1_y#0 -- _stackpushbyte_=vbuxx txa pha - // [52] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2) -- _stackpushbyte_=_deref_pbuc1 - lda v+OFFSET_STRUCT_VECTOR_P2 + // [41] stackpush(byte) ← (byte) main::v_p2_x#0 -- _stackpushbyte_=vbuz1 + lda.z v_p2_x pha - // [53] stackpush(byte) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_P2+(const byte) OFFSET_STRUCT_POINT_Y) -- _stackpushbyte_=_deref_pbuc1 - lda v+OFFSET_STRUCT_VECTOR_P2+OFFSET_STRUCT_POINT_Y + // [42] stackpush(byte) ← (byte) main::v_p2_y#0 -- _stackpushbyte_=vbuz1 + lda.z v_p2_y pha - // [54] callexecute print -- jsr + // [43] callexecute print -- jsr jsr print // sideeffect stackpullbytes((number) 4) -- _stackpullbyte_4 tsx @@ -1529,8 +1411,10 @@ main: { axs #-4 txs // for(char i=0;i<5;i++) - // [56] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [45] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 inc.z i + // [29] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + // [29] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy jmp __b1 } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-11.sym b/src/test/ref/procedure-callingconvention-stack-11.sym index c9708abc4..f5bda7e34 100644 --- a/src/test/ref/procedure-callingconvention-stack-11.sym +++ b/src/test/ref/procedure-callingconvention-stack-11.sym @@ -3,43 +3,51 @@ (label) @end (const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 (const byte) OFFSET_STRUCT_VECTOR_P2 = (byte) 2 -(byte) Point::x loadstore -(byte) Point::y loadstore +(byte) Point::x +(byte) Point::y (const byte*) SCREEN = (byte*) 1024 (const word) STACK_BASE = (word) $103 -(struct Point) Vector::p1 loadstore zp[2]:8 -(struct Point) Vector::p2 loadstore zp[2]:10 +(struct Point) Vector::p1 +(struct Point) Vector::p2 __stackcall (struct Vector()) get((byte) get::i) -(byte~) get::$0 zp[1]:3 1.0 -(byte~) get::$1 reg byte x 1.0 -(byte~) get::$2 zp[1]:4 1.0 (label) get::@return (const byte) get::OFFSET_STACK_I = (byte) 0 (byte) get::i -(byte) get::i#0 reg byte y 2.5 (struct Vector) get::return (struct Point) get::return_p1 (byte) get::return_p1_x -(byte) get::return_p1_x#0 reg byte x 1.0 +(byte) get::return_p1_x#0 reg byte x 2.5 (byte) get::return_p1_y -(byte) get::return_p1_y#0 reg byte y 1.0 +(byte) get::return_p1_y#0 return_p1_y zp[1]:4 1.0 (struct Point) get::return_p2 (byte) get::return_p2_x -(byte) get::return_p2_x#0 return_p2_x zp[1]:6 1.0 +(byte) get::return_p2_x#0 reg byte y 1.0 (byte) get::return_p2_y -(byte) get::return_p2_y#0 return_p2_y zp[1]:7 1.0 -(struct Vector) get::v loadstore zp[4]:16 -(byte) idx loadstore zp[1]:2 0.8648648648648649 +(byte) get::return_p2_y#0 return_p2_y zp[1]:5 1.0 +(struct Point) get::v_p1 +(byte) get::v_p1_x +(byte) get::v_p1_y +(struct Point) get::v_p2 +(byte) get::v_p2_x +(byte) get::v_p2_y +(byte) idx loadstore zp[1]:3 0.9411764705882354 __stackcall (void()) main() -(byte~) main::$1_p1_x reg byte y 5.5 -(byte~) main::$1_p1_y reg byte x 5.5 -(byte~) main::$1_p2_x zp[1]:6 5.5 -(byte~) main::$1_p2_y zp[1]:7 5.5 (label) main::@1 (label) main::@2 (label) main::@return -(byte) main::i loadstore zp[1]:5 2.3000000000000003 -(struct Vector) main::v loadstore zp[4]:12 +(byte) main::i +(byte) main::i#1 i zp[1]:2 22.0 +(byte) main::i#2 i zp[1]:2 2.933333333333333 +(struct Point) main::v_p1 +(byte) main::v_p1_x +(byte) main::v_p1_x#0 reg byte y 5.5 +(byte) main::v_p1_y +(byte) main::v_p1_y#0 reg byte x 5.5 +(struct Point) main::v_p2 +(byte) main::v_p2_x +(byte) main::v_p2_x#0 v_p2_x zp[1]:4 5.5 +(byte) main::v_p2_y +(byte) main::v_p2_y#0 v_p2_y zp[1]:5 5.5 __stackcall (void()) print((byte) print::v_p1_x , (byte) print::v_p1_y , (byte) print::v_p2_x , (byte) print::v_p2_y) (label) print::@return (const byte) print::OFFSET_STACK_V_P1_X = (byte) 3 @@ -50,28 +58,20 @@ __stackcall (void()) print((byte) print::v_p1_x , (byte) print::v_p1_y , (byte) (byte) print::v_p1_x (byte) print::v_p1_x#0 reg byte y 1.0 (byte) print::v_p1_y -(byte) print::v_p1_y#0 v_p1_y zp[1]:3 0.8 +(byte) print::v_p1_y#0 v_p1_y zp[1]:4 0.8 (struct Point) print::v_p2 (byte) print::v_p2_x -(byte) print::v_p2_x#0 v_p2_x zp[1]:4 0.6666666666666666 +(byte) print::v_p2_x#0 v_p2_x zp[1]:5 0.6666666666666666 (byte) print::v_p2_y (byte) print::v_p2_y#0 reg byte x 0.5714285714285714 -zp[1]:2 [ idx ] +zp[1]:2 [ main::i#2 main::i#1 ] +zp[1]:3 [ idx ] reg byte y [ print::v_p1_x#0 ] reg byte x [ print::v_p2_y#0 ] -reg byte y [ get::i#0 ] -zp[1]:3 [ get::$0 print::v_p1_y#0 ] -reg byte x [ get::$1 ] -zp[1]:4 [ get::$2 print::v_p2_x#0 ] reg byte x [ get::return_p1_x#0 ] -reg byte y [ get::return_p1_y#0 ] -zp[1]:5 [ main::i ] -reg byte y [ main::$1_p1_x ] -reg byte x [ main::$1_p1_y ] -zp[1]:6 [ main::$1_p2_x get::return_p2_x#0 ] -zp[1]:7 [ main::$1_p2_y get::return_p2_y#0 ] -zp[2]:8 [ Vector::p1 ] -zp[2]:10 [ Vector::p2 ] -zp[4]:12 [ main::v ] -zp[4]:16 [ get::v ] +reg byte y [ get::return_p2_x#0 ] +reg byte y [ main::v_p1_x#0 ] +reg byte x [ main::v_p1_y#0 ] +zp[1]:4 [ main::v_p2_x#0 get::return_p1_y#0 print::v_p1_y#0 ] +zp[1]:5 [ main::v_p2_y#0 get::return_p2_y#0 print::v_p2_x#0 ] diff --git a/src/test/ref/procedure-callingconvention-stack-12.asm b/src/test/ref/procedure-callingconvention-stack-12.asm index d42fd20e1..ed9071ea6 100644 --- a/src/test/ref/procedure-callingconvention-stack-12.asm +++ b/src/test/ref/procedure-callingconvention-stack-12.asm @@ -16,7 +16,6 @@ __bbegin: print: { .const OFFSET_STACK_STR = 1 .const OFFSET_STACK_SPACING = 0 - .label c = 6 .label str = 2 .label spacing = 5 // } @@ -48,13 +47,10 @@ print: { bne !+ inc.z str+1 !: - // c=0 - lda #0 - sta.z c + ldx #0 __b3: // for(char c=0;cprint::@3] + __b3_from___b2: + // [12] phi (byte) print::c#2 = (byte) 0 [phi:print::@2->print::@3#0] -- vbuz1=vbuc1 lda #0 sta.z c jmp __b3 // print::@3 __b3: - // [13] if((byte) print::c<(byte) print::spacing#0) goto print::@4 -- vbuz1_lt_vbuz2_then_la1 + // [13] if((byte) print::c#2<(byte) print::spacing#0) goto print::@4 -- vbuz1_lt_vbuz2_then_la1 lda.z c cmp.z spacing bcc __b4 @@ -340,8 +358,11 @@ print: { sta SCREEN,y // [15] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 inc.z idx - // [16] (byte) print::c ← ++ (byte) print::c -- vbuz1=_inc_vbuz1 + // [16] (byte) print::c#1 ← ++ (byte) print::c#2 -- vbuz1=_inc_vbuz1 inc.z c + // [12] phi from print::@4 to print::@3 [phi:print::@4->print::@3] + __b3_from___b4: + // [12] phi (byte) print::c#2 = (byte) print::c#1 [phi:print::@4->print::@3#0] -- register_copy jmp __b3 } // main @@ -395,13 +416,13 @@ Statement [0] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg b Statement [4] (byte*) print::str#0 ← stackidx(byte*,(const byte) print::OFFSET_STACK_STR) [ idx print::str#0 ] ( main:2::print:19 [ idx print::str#0 ] main:2::print:23 [ idx print::str#0 ] ) always clobbers reg byte a reg byte x Statement [5] (byte) print::spacing#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_SPACING) [ idx print::str#0 print::spacing#0 ] ( main:2::print:19 [ idx print::str#0 print::spacing#0 ] main:2::print:23 [ idx print::str#0 print::spacing#0 ] ) always clobbers reg byte a reg byte x Statement [7] if((byte) 0!=*((byte*) print::str#2)) goto print::@2 [ idx print::spacing#0 print::str#2 ] ( main:2::print:19 [ idx print::spacing#0 print::str#2 ] main:2::print:23 [ idx print::spacing#0 print::str#2 ] ) always clobbers reg byte a reg byte y -Removing always clobbered register reg byte a as potential for zp[1]:5 [ print::spacing#0 ] -Removing always clobbered register reg byte y as potential for zp[1]:5 [ print::spacing#0 ] +Removing always clobbered register reg byte a as potential for zp[1]:6 [ print::spacing#0 ] +Removing always clobbered register reg byte y as potential for zp[1]:6 [ print::spacing#0 ] Statement [9] *((const byte*) SCREEN + (byte) idx) ← *((byte*) print::str#2) [ idx print::spacing#0 print::str#2 ] ( main:2::print:19 [ idx print::spacing#0 print::str#2 ] main:2::print:23 [ idx print::spacing#0 print::str#2 ] ) always clobbers reg byte a reg byte x reg byte y -Removing always clobbered register reg byte x as potential for zp[1]:5 [ print::spacing#0 ] -Statement [12] (byte) print::c ← (byte) 0 [ idx print::spacing#0 print::str#1 print::c ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c ] ) always clobbers reg byte a -Statement [13] if((byte) print::c<(byte) print::spacing#0) goto print::@4 [ idx print::spacing#0 print::str#1 print::c ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c ] ) always clobbers reg byte a -Statement [14] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' [ idx print::spacing#0 print::str#1 print::c ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c ] ) always clobbers reg byte a reg byte y +Removing always clobbered register reg byte x as potential for zp[1]:6 [ print::spacing#0 ] +Statement [14] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' [ idx print::spacing#0 print::str#1 print::c#2 ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c#2 ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c#2 ] ) always clobbers reg byte a reg byte y +Removing always clobbered register reg byte a as potential for zp[1]:4 [ print::c#2 print::c#1 ] +Removing always clobbered register reg byte y as potential for zp[1]:4 [ print::c#2 print::c#1 ] Statement [17] stackpush(byte*) ← (const byte*) main::str [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a Statement [18] stackpush(byte) ← (byte) 1 [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a Statement sideeffect stackpullbytes((number) 3) always clobbers reg byte a reg byte x @@ -413,9 +434,7 @@ Statement [4] (byte*) print::str#0 ← stackidx(byte*,(const byte) print::OFFSET Statement [5] (byte) print::spacing#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_SPACING) [ idx print::str#0 print::spacing#0 ] ( main:2::print:19 [ idx print::str#0 print::spacing#0 ] main:2::print:23 [ idx print::str#0 print::spacing#0 ] ) always clobbers reg byte a reg byte x Statement [7] if((byte) 0!=*((byte*) print::str#2)) goto print::@2 [ idx print::spacing#0 print::str#2 ] ( main:2::print:19 [ idx print::spacing#0 print::str#2 ] main:2::print:23 [ idx print::spacing#0 print::str#2 ] ) always clobbers reg byte a reg byte y Statement [9] *((const byte*) SCREEN + (byte) idx) ← *((byte*) print::str#2) [ idx print::spacing#0 print::str#2 ] ( main:2::print:19 [ idx print::spacing#0 print::str#2 ] main:2::print:23 [ idx print::spacing#0 print::str#2 ] ) always clobbers reg byte a reg byte x reg byte y -Statement [12] (byte) print::c ← (byte) 0 [ idx print::spacing#0 print::str#1 print::c ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c ] ) always clobbers reg byte a -Statement [13] if((byte) print::c<(byte) print::spacing#0) goto print::@4 [ idx print::spacing#0 print::str#1 print::c ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c ] ) always clobbers reg byte a -Statement [14] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' [ idx print::spacing#0 print::str#1 print::c ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c ] ) always clobbers reg byte a reg byte y +Statement [14] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' [ idx print::spacing#0 print::str#1 print::c#2 ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c#2 ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c#2 ] ) always clobbers reg byte a reg byte y Statement [17] stackpush(byte*) ← (const byte*) main::str [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a Statement [18] stackpush(byte) ← (byte) 1 [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a Statement sideeffect stackpullbytes((number) 3) always clobbers reg byte a reg byte x @@ -423,24 +442,24 @@ Statement [21] stackpush(byte*) ← (const byte*) main::str1 [ idx ] ( main:2 [ Statement [22] stackpush(byte) ← (byte) 2 [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a Statement sideeffect stackpullbytes((number) 3) always clobbers reg byte a reg byte x Potential registers zp[2]:2 [ print::str#2 print::str#0 print::str#1 ] : zp[2]:2 , -Potential registers zp[1]:4 [ idx ] : zp[1]:4 , -Potential registers zp[1]:5 [ print::spacing#0 ] : zp[1]:5 , -Potential registers zp[1]:6 [ print::c ] : zp[1]:6 , +Potential registers zp[1]:4 [ print::c#2 print::c#1 ] : zp[1]:4 , reg byte x , +Potential registers zp[1]:5 [ idx ] : zp[1]:5 , +Potential registers zp[1]:6 [ print::spacing#0 ] : zp[1]:6 , REGISTER UPLIFT SCOPES -Uplift Scope [print] 62.8: zp[1]:6 [ print::c ] 54.67: zp[2]:2 [ print::str#2 print::str#0 print::str#1 ] 9.36: zp[1]:5 [ print::spacing#0 ] -Uplift Scope [] 16.1: zp[1]:4 [ idx ] +Uplift Scope [print] 277.75: zp[1]:4 [ print::c#2 print::c#1 ] 54.67: zp[2]:2 [ print::str#2 print::str#0 print::str#1 ] 9.36: zp[1]:6 [ print::spacing#0 ] +Uplift Scope [] 16.1: zp[1]:5 [ idx ] Uplift Scope [main] -Uplifting [print] best 4156 combination zp[1]:6 [ print::c ] zp[2]:2 [ print::str#2 print::str#0 print::str#1 ] zp[1]:5 [ print::spacing#0 ] -Uplifting [] best 4156 combination zp[1]:4 [ idx ] -Uplifting [main] best 4156 combination -Attempting to uplift remaining variables inzp[1]:6 [ print::c ] -Uplifting [print] best 4156 combination zp[1]:6 [ print::c ] -Attempting to uplift remaining variables inzp[1]:4 [ idx ] -Uplifting [] best 4156 combination zp[1]:4 [ idx ] -Attempting to uplift remaining variables inzp[1]:5 [ print::spacing#0 ] -Uplifting [print] best 4156 combination zp[1]:5 [ print::spacing#0 ] +Uplifting [print] best 3976 combination reg byte x [ print::c#2 print::c#1 ] zp[2]:2 [ print::str#2 print::str#0 print::str#1 ] zp[1]:6 [ print::spacing#0 ] +Uplifting [] best 3976 combination zp[1]:5 [ idx ] +Uplifting [main] best 3976 combination +Attempting to uplift remaining variables inzp[1]:5 [ idx ] +Uplifting [] best 3976 combination zp[1]:5 [ idx ] +Attempting to uplift remaining variables inzp[1]:6 [ print::spacing#0 ] +Uplifting [print] best 3976 combination zp[1]:6 [ print::spacing#0 ] +Allocated (was zp[1]:5) zp[1]:4 [ idx ] +Allocated (was zp[1]:6) zp[1]:5 [ print::spacing#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -476,7 +495,6 @@ __bend: print: { .const OFFSET_STACK_STR = 1 .const OFFSET_STACK_SPACING = 0 - .label c = 6 .label str = 2 .label spacing = 5 // [4] (byte*) print::str#0 ← stackidx(byte*,(const byte) print::OFFSET_STACK_STR) -- pbuz1=_stackidxptr_vbuc1 @@ -520,15 +538,15 @@ print: { bne !+ inc.z str+1 !: - // [12] (byte) print::c ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z c + // [12] phi from print::@2 to print::@3 [phi:print::@2->print::@3] + __b3_from___b2: + // [12] phi (byte) print::c#2 = (byte) 0 [phi:print::@2->print::@3#0] -- vbuxx=vbuc1 + ldx #0 jmp __b3 // print::@3 __b3: - // [13] if((byte) print::c<(byte) print::spacing#0) goto print::@4 -- vbuz1_lt_vbuz2_then_la1 - lda.z c - cmp.z spacing + // [13] if((byte) print::c#2<(byte) print::spacing#0) goto print::@4 -- vbuxx_lt_vbuz1_then_la1 + cpx.z spacing bcc __b4 jmp __b1_from___b3 // print::@4 @@ -539,8 +557,11 @@ print: { sta SCREEN,y // [15] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 inc.z idx - // [16] (byte) print::c ← ++ (byte) print::c -- vbuz1=_inc_vbuz1 - inc.z c + // [16] (byte) print::c#1 ← ++ (byte) print::c#2 -- vbuxx=_inc_vbuxx + inx + // [12] phi from print::@4 to print::@3 [phi:print::@4->print::@3] + __b3_from___b4: + // [12] phi (byte) print::c#2 = (byte) print::c#1 [phi:print::@4->print::@3#0] -- register_copy jmp __b3 } // main @@ -606,6 +627,8 @@ Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction __b1: Removing instruction __bend: Removing instruction __breturn: +Removing instruction __b3_from___b2: +Removing instruction __b3_from___b4: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination Adding RTS to root block @@ -630,7 +653,9 @@ __stackcall (void()) print((byte*) print::str , (byte) print::spacing) (label) print::@return (const byte) print::OFFSET_STACK_SPACING = (byte) 0 (const byte) print::OFFSET_STACK_STR = (byte) 1 -(byte) print::c loadstore zp[1]:6 62.8 +(byte) print::c +(byte) print::c#1 reg byte x 202.0 +(byte) print::c#2 reg byte x 75.75 (byte) print::spacing (byte) print::spacing#0 spacing zp[1]:5 9.363636363636363 (byte*) print::str @@ -639,13 +664,13 @@ __stackcall (void()) print((byte*) print::str , (byte) print::spacing) (byte*) print::str#2 str zp[2]:2 34.0 zp[2]:2 [ print::str#2 print::str#0 print::str#1 ] +reg byte x [ print::c#2 print::c#1 ] zp[1]:4 [ idx ] zp[1]:5 [ print::spacing#0 ] -zp[1]:6 [ print::c ] FINAL ASSEMBLER -Score: 4063 +Score: 3613 // File Comments // Test a procedure with calling convention stack @@ -676,7 +701,6 @@ __bbegin: print: { .const OFFSET_STACK_STR = 1 .const OFFSET_STACK_SPACING = 0 - .label c = 6 .label str = 2 .label spacing = 5 // } @@ -720,16 +744,14 @@ print: { bne !+ inc.z str+1 !: - // c=0 - // [12] (byte) print::c ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z c + // [12] phi from print::@2 to print::@3 [phi:print::@2->print::@3] + // [12] phi (byte) print::c#2 = (byte) 0 [phi:print::@2->print::@3#0] -- vbuxx=vbuc1 + ldx #0 // print::@3 __b3: // for(char c=0;cprint::@3] + // [12] phi (byte) print::c#2 = (byte) print::c#1 [phi:print::@4->print::@3#0] -- register_copy jmp __b3 } // main diff --git a/src/test/ref/procedure-callingconvention-stack-12.sym b/src/test/ref/procedure-callingconvention-stack-12.sym index 4bcb1f17d..e4c6c7374 100644 --- a/src/test/ref/procedure-callingconvention-stack-12.sym +++ b/src/test/ref/procedure-callingconvention-stack-12.sym @@ -16,7 +16,9 @@ __stackcall (void()) print((byte*) print::str , (byte) print::spacing) (label) print::@return (const byte) print::OFFSET_STACK_SPACING = (byte) 0 (const byte) print::OFFSET_STACK_STR = (byte) 1 -(byte) print::c loadstore zp[1]:6 62.8 +(byte) print::c +(byte) print::c#1 reg byte x 202.0 +(byte) print::c#2 reg byte x 75.75 (byte) print::spacing (byte) print::spacing#0 spacing zp[1]:5 9.363636363636363 (byte*) print::str @@ -25,6 +27,6 @@ __stackcall (void()) print((byte*) print::str , (byte) print::spacing) (byte*) print::str#2 str zp[2]:2 34.0 zp[2]:2 [ print::str#2 print::str#0 print::str#1 ] +reg byte x [ print::c#2 print::c#1 ] zp[1]:4 [ idx ] zp[1]:5 [ print::spacing#0 ] -zp[1]:6 [ print::c ] diff --git a/src/test/ref/procedure-callingconvention-stack-4.asm b/src/test/ref/procedure-callingconvention-stack-4.asm index 5fc35e565..d64ce4a1f 100644 --- a/src/test/ref/procedure-callingconvention-stack-4.asm +++ b/src/test/ref/procedure-callingconvention-stack-4.asm @@ -1,16 +1,24 @@ // Test a procedure with calling convention stack // A slightly more complex call .pc = $801 "Basic" -:BasicUpstart(main) +:BasicUpstart(__bbegin) .pc = $80d "Program" .label SCREEN = $400 .const STACK_BASE = $103 + .label i = 3 +__bbegin: + // i = 0 + lda #0 + sta.z i + jsr main + rts main: { - ldy #0 + .label a = 2 + lda #0 + sta.z a __b1: // v = a+1 - tya - tax + ldx.z a inx // plus('0', v) lda #'0' @@ -22,29 +30,32 @@ main: { // w = plus('0', v) pla // w+a - sty.z $ff clc - adc.z $ff + adc.z a // SCREEN[i] = w+a - sta SCREEN + ldy.z i + sta SCREEN,y // for(char a:0..1) - iny - cpy #2 + inc.z a + lda #2 + cmp.z a bne __b1 // } rts } -// plus(byte zp(2) a, byte register(A) b) +// plus(byte zp(4) a, byte register(A) b) plus: { .const OFFSET_STACK_A = 1 .const OFFSET_STACK_B = 0 .const OFFSET_STACK_RETURN = 1 - .label a = 2 + .label a = 4 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a tsx lda STACK_BASE+OFFSET_STACK_B,x + // i++; + inc.z i // return a+b; clc adc.z a diff --git a/src/test/ref/procedure-callingconvention-stack-4.cfg b/src/test/ref/procedure-callingconvention-stack-4.cfg index 9fdd7d0a7..0001247c9 100644 --- a/src/test/ref/procedure-callingconvention-stack-4.cfg +++ b/src/test/ref/procedure-callingconvention-stack-4.cfg @@ -1,5 +1,5 @@ @begin: scope:[] from - [0] phi() + [0] (byte) i ← (byte) 0 to:@1 @1: scope:[] from @begin [1] phi() @@ -21,7 +21,7 @@ main::@1: scope:[main] from main main::@1 sideeffect stackpullbytes((number) 1) [11] (byte) main::w#0 ← stackpull(byte) [12] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 - [13] *((const byte*) SCREEN) ← (byte~) main::$2 + [13] *((const byte*) SCREEN + (byte) i) ← (byte~) main::$2 [14] (byte) main::a#1 ← ++ (byte) main::a#2 [15] if((byte) main::a#1!=(byte) 2) goto main::@1 to:main::@return @@ -33,9 +33,10 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from [17] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [18] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) - [19] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 + [19] (byte) i ← ++ (byte) i + [20] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus - [20] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 - [21] return + [21] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 + [22] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-4.log b/src/test/ref/procedure-callingconvention-stack-4.log index f495a8a00..f9adccd64 100644 --- a/src/test/ref/procedure-callingconvention-stack-4.log +++ b/src/test/ref/procedure-callingconvention-stack-4.log @@ -1,6 +1,7 @@ Culled Empty Block (label) main::@2 Culled Empty Block (label) @1 Culled Empty Block (label) plus::@1 +Converting PHI-variable modified inside __stackcall procedure plus() to load/store (byte) i Calling convention STACK_CALL adding prepare/execute/finalize for (byte~) main::$1 ← call plus (byte) '0' (byte) main::v Calling convention STACK_CALL replacing param((byte) plus::a) with stackidx(byte,(const byte) plus::OFFSET_STACK_A) Calling convention STACK_CALL replacing param((byte) plus::b) with stackidx(byte,(const byte) plus::OFFSET_STACK_B) @@ -11,16 +12,14 @@ Calling convention STACK_CALL adding stack push stackpush(byte) ← main::v CONTROL FLOW GRAPH SSA @begin: scope:[] from - (byte) i#0 ← (byte) 0 + (byte) i ← (byte) 0 to:@2 (void()) main() main: scope:[main] from @2 - (byte) i#8 ← phi( @2/(byte) i#9 ) (byte) main::a#0 ← (byte) 0 to:main::@1 main::@1: scope:[main] from main main::@1 - (byte) i#4 ← phi( main/(byte) i#8 main::@1/(byte) i#4 ) (byte) main::a#2 ← phi( main/(byte) main::a#0 main::@1/(byte) main::a#1 ) (number~) main::$0 ← (byte) main::a#2 + (number) 1 (byte) main::v#0 ← (number~) main::$0 @@ -31,23 +30,20 @@ main::@1: scope:[main] from main main::@1 (byte~) main::$1 ← stackpull(byte) (byte) main::w#0 ← (byte~) main::$1 (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 - *((const byte*) SCREEN + (byte) i#4) ← (byte~) main::$2 + *((const byte*) SCREEN + (byte) i) ← (byte~) main::$2 (byte) main::a#1 ← (byte) main::a#2 + rangenext(0,1) (bool~) main::$3 ← (byte) main::a#1 != rangelast(0,1) if((bool~) main::$3) goto main::@1 to:main::@return main::@return: scope:[main] from main::@1 - (byte) i#5 ← phi( main::@1/(byte) i#4 ) - (byte) i#1 ← (byte) i#5 return to:@return __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - (byte) i#6 ← phi( ) (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) - (byte) i#2 ← ++ (byte) i#6 + (byte) i ← ++ (byte) i (byte~) plus::$0 ← (byte) plus::a#0 + (byte) plus::b#0 (byte) plus::return#0 ← (byte~) plus::$0 to:plus::@return @@ -57,12 +53,9 @@ plus::@return: scope:[plus] from plus return to:@return @2: scope:[] from @begin - (byte) i#9 ← phi( @begin/(byte) i#0 ) call main to:@3 @3: scope:[] from @2 - (byte) i#7 ← phi( @2/(byte) i#1 ) - (byte) i#3 ← (byte) i#7 to:@end @end: scope:[] from @3 @@ -73,17 +66,7 @@ SYMBOL TABLE SSA (label) @end (const byte*) SCREEN = (byte*)(number) $400 (const word) STACK_BASE = (word) $103 -(byte) i -(byte) i#0 -(byte) i#1 -(byte) i#2 -(byte) i#3 -(byte) i#4 -(byte) i#5 -(byte) i#6 -(byte) i#7 -(byte) i#8 -(byte) i#9 +(byte) i loadstore (void()) main() (number~) main::$0 (byte~) main::$1 @@ -124,29 +107,14 @@ Successful SSA optimization PassNFinalizeNumberTypeConversions Inferred type updated to byte in (unumber~) main::$0 ← (byte) main::a#2 + (byte) 1 Alias (byte) main::v#0 = (byte~) main::$0 Alias (byte) main::w#0 = (byte~) main::$1 -Alias (byte) i#1 = (byte) i#5 (byte) i#4 Alias (byte) plus::return#0 = (byte~) plus::$0 (byte) plus::return#1 -Alias (byte) i#0 = (byte) i#9 -Alias (byte) i#3 = (byte) i#7 Successful SSA optimization Pass2AliasElimination -Identical Phi Values (byte) i#8 (byte) i#0 -Identical Phi Values (byte) i#1 (byte) i#8 -Identical Phi Values (byte) i#3 (byte) i#1 -Successful SSA optimization Pass2IdenticalPhiElimination -Simple Condition (bool~) main::$3 [14] if((byte) main::a#1!=rangelast(0,1)) goto main::@1 +Simple Condition (bool~) main::$3 [13] if((byte) main::a#1!=rangelast(0,1)) goto main::@1 Successful SSA optimization Pass2ConditionalJumpSimplification -Constant (const byte) i#0 = 0 Constant (const byte) main::a#0 = 0 Successful SSA optimization Pass2ConstantIdentification -Resolved ranged next value [12] main::a#1 ← ++ main::a#2 to ++ -Resolved ranged comparison value [14] if(main::a#1!=rangelast(0,1)) goto main::@1 to (number) 2 -Simplifying expression containing zero SCREEN in [11] *((const byte*) SCREEN + (const byte) i#0) ← (byte~) main::$2 -Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused variable (byte) i#2 and assignment [15] (byte) i#2 ← ++ (byte) i#6 -Eliminating unused constant (const byte) i#0 -Successful SSA optimization PassNEliminateUnusedVars -Eliminating unused variable - keeping the phi block (byte) i#6 -Successful SSA optimization PassNEliminateUnusedVars +Resolved ranged next value [11] main::a#1 ← ++ main::a#2 to ++ +Resolved ranged comparison value [13] if(main::a#1!=rangelast(0,1)) goto main::@1 to (number) 2 Adding number conversion cast (unumber) 2 in if((byte) main::a#1!=(number) 2) goto main::@1 Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant integer cast 2 @@ -157,7 +125,6 @@ Inlining constant with var siblings (const byte) main::a#0 Constant inlined main::a#0 = (byte) 0 Successful SSA optimization Pass2ConstantInlining Added new block during phi lifting main::@3(between main::@1 and main::@1) -Adding NOP phi() at start of @begin Adding NOP phi() at start of @2 Adding NOP phi() at start of @3 Adding NOP phi() at start of @end @@ -172,14 +139,13 @@ Coalesced down to 1 phi equivalence classes Culled Empty Block (label) @3 Culled Empty Block (label) main::@3 Renumbering block @2 to @1 -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 FINAL CONTROL FLOW GRAPH @begin: scope:[] from - [0] phi() + [0] (byte) i ← (byte) 0 to:@1 @1: scope:[] from @begin [1] phi() @@ -201,7 +167,7 @@ main::@1: scope:[main] from main main::@1 sideeffect stackpullbytes((number) 1) [11] (byte) main::w#0 ← stackpull(byte) [12] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 - [13] *((const byte*) SCREEN) ← (byte~) main::$2 + [13] *((const byte*) SCREEN + (byte) i) ← (byte~) main::$2 [14] (byte) main::a#1 ← ++ (byte) main::a#2 [15] if((byte) main::a#1!=(byte) 2) goto main::@1 to:main::@return @@ -213,16 +179,17 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from [17] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [18] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) - [19] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 + [19] (byte) i ← ++ (byte) i + [20] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus - [20] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 - [21] return + [21] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 + [22] return to:@return VARIABLE REGISTER WEIGHTS -(byte) i +(byte) i loadstore 0.85 (void()) main() (byte~) main::$2 22.0 (byte) main::a @@ -234,14 +201,15 @@ VARIABLE REGISTER WEIGHTS (byte) main::w#0 22.0 __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (byte) plus::a -(byte) plus::a#0 2.0 +(byte) plus::a#0 1.3333333333333333 (byte) plus::b -(byte) plus::b#0 4.0 +(byte) plus::b#0 2.0 (byte) plus::return (byte) plus::return#0 4.0 Initial phi equivalence classes [ main::a#2 main::a#1 ] +Added variable i to live range equivalence class [ i ] Added variable main::v#0 to live range equivalence class [ main::v#0 ] Added variable main::w#0 to live range equivalence class [ main::w#0 ] Added variable main::$2 to live range equivalence class [ main::$2 ] @@ -250,6 +218,7 @@ Added variable plus::b#0 to live range equivalence class [ plus::b#0 ] Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] Complete equivalence classes [ main::a#2 main::a#1 ] +[ i ] [ main::v#0 ] [ main::w#0 ] [ main::$2 ] @@ -257,12 +226,13 @@ Complete equivalence classes [ plus::b#0 ] [ plus::return#0 ] Allocated zp[1]:2 [ main::a#2 main::a#1 ] -Allocated zp[1]:3 [ main::v#0 ] -Allocated zp[1]:4 [ main::w#0 ] -Allocated zp[1]:5 [ main::$2 ] -Allocated zp[1]:6 [ plus::a#0 ] -Allocated zp[1]:7 [ plus::b#0 ] -Allocated zp[1]:8 [ plus::return#0 ] +Allocated zp[1]:3 [ i ] +Allocated zp[1]:4 [ main::v#0 ] +Allocated zp[1]:5 [ main::w#0 ] +Allocated zp[1]:6 [ main::$2 ] +Allocated zp[1]:7 [ plus::a#0 ] +Allocated zp[1]:8 [ plus::b#0 ] +Allocated zp[1]:9 [ plus::return#0 ] INITIAL ASM Target platform is c64basic / MOS6502X @@ -276,8 +246,12 @@ Target platform is c64basic / MOS6502X // Global Constants & labels .label SCREEN = $400 .const STACK_BASE = $103 + .label i = 3 // @begin __bbegin: + // [0] (byte) i ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z i // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 @@ -294,9 +268,9 @@ __bend_from___b1: __bend: // main main: { - .label __2 = 5 - .label v = 3 - .label w = 4 + .label __2 = 6 + .label v = 4 + .label w = 5 .label a = 2 // [5] phi from main to main::@1 [phi:main->main::@1] __b1_from_main: @@ -332,9 +306,10 @@ main: { clc adc.z a sta.z __2 - // [13] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuz1 + // [13] *((const byte*) SCREEN + (byte) i) ← (byte~) main::$2 -- pbuc1_derefidx_vbuz1=vbuz2 lda.z __2 - sta SCREEN + ldy.z i + sta SCREEN,y // [14] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuz1=_inc_vbuz1 inc.z a // [15] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 @@ -348,14 +323,14 @@ main: { rts } // plus -// plus(byte zp(6) a, byte zp(7) b) +// plus(byte zp(7) a, byte zp(8) b) plus: { .const OFFSET_STACK_A = 1 .const OFFSET_STACK_B = 0 .const OFFSET_STACK_RETURN = 1 - .label a = 6 - .label b = 7 - .label return = 8 + .label a = 7 + .label b = 8 + .label return = 9 // [17] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x @@ -364,7 +339,9 @@ plus: { tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b - // [19] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3 + // [19] (byte) i ← ++ (byte) i -- vbuz1=_inc_vbuz1 + inc.z i + // [20] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3 lda.z a clc adc.z b @@ -372,58 +349,69 @@ plus: { jmp __breturn // plus::@return __breturn: - // [20] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1 + // [21] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return tsx sta STACK_BASE+OFFSET_STACK_RETURN,x - // [21] return + // [22] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS -Statement [7] stackpush(byte) ← (byte) '0' [ main::a#2 main::v#0 ] ( main:2 [ main::a#2 main::v#0 ] ) always clobbers reg byte a +Statement [0] (byte) i ← (byte) 0 [ i ] ( [ i ] ) always clobbers reg byte a +Statement [7] stackpush(byte) ← (byte) '0' [ i main::a#2 main::v#0 ] ( main:2 [ i main::a#2 main::v#0 ] ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::a#2 main::a#1 ] -Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::v#0 ] -Statement [8] stackpush(byte) ← (byte) main::v#0 [ main::a#2 ] ( main:2 [ main::a#2 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:4 [ main::v#0 ] +Statement [8] stackpush(byte) ← (byte) main::v#0 [ i main::a#2 ] ( main:2 [ i main::a#2 ] ) always clobbers reg byte a Statement sideeffect stackpullbytes((number) 1) always clobbers reg byte a -Statement [11] (byte) main::w#0 ← stackpull(byte) [ main::a#2 main::w#0 ] ( main:2 [ main::a#2 main::w#0 ] ) always clobbers reg byte a -Statement [12] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ main::a#2 main::$2 ] ( main:2 [ main::a#2 main::$2 ] ) always clobbers reg byte a -Statement [17] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:9 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (byte) main::w#0 ← stackpull(byte) [ i main::a#2 main::w#0 ] ( main:2 [ i main::a#2 main::w#0 ] ) always clobbers reg byte a +Statement [12] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ i main::a#2 main::$2 ] ( main:2 [ i main::a#2 main::$2 ] ) always clobbers reg byte a +Statement [13] *((const byte*) SCREEN + (byte) i) ← (byte~) main::$2 [ i main::a#2 ] ( main:2 [ i main::a#2 ] ) always clobbers reg byte y +Removing always clobbered register reg byte y as potential for zp[1]:2 [ main::a#2 main::a#1 ] +Statement [17] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ i plus::a#0 ] ( main:2::plus:9 [ main::a#2 i plus::a#0 ] ) always clobbers reg byte a reg byte x Removing always clobbered register reg byte x as potential for zp[1]:2 [ main::a#2 main::a#1 ] -Statement [18] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:9 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x -Removing always clobbered register reg byte a as potential for zp[1]:6 [ plus::a#0 ] -Removing always clobbered register reg byte x as potential for zp[1]:6 [ plus::a#0 ] -Statement [19] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:9 [ main::a#2 plus::return#0 ] ) always clobbers reg byte a -Statement [20] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:9 [ main::a#2 ] ) always clobbers reg byte x -Statement [7] stackpush(byte) ← (byte) '0' [ main::a#2 main::v#0 ] ( main:2 [ main::a#2 main::v#0 ] ) always clobbers reg byte a -Statement [8] stackpush(byte) ← (byte) main::v#0 [ main::a#2 ] ( main:2 [ main::a#2 ] ) always clobbers reg byte a +Statement [18] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ i plus::a#0 plus::b#0 ] ( main:2::plus:9 [ main::a#2 i plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:7 [ plus::a#0 ] +Removing always clobbered register reg byte x as potential for zp[1]:7 [ plus::a#0 ] +Statement [20] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ i plus::return#0 ] ( main:2::plus:9 [ main::a#2 i plus::return#0 ] ) always clobbers reg byte a +Statement [21] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ i ] ( main:2::plus:9 [ main::a#2 i ] ) always clobbers reg byte x +Statement [0] (byte) i ← (byte) 0 [ i ] ( [ i ] ) always clobbers reg byte a +Statement [7] stackpush(byte) ← (byte) '0' [ i main::a#2 main::v#0 ] ( main:2 [ i main::a#2 main::v#0 ] ) always clobbers reg byte a +Statement [8] stackpush(byte) ← (byte) main::v#0 [ i main::a#2 ] ( main:2 [ i main::a#2 ] ) always clobbers reg byte a Statement sideeffect stackpullbytes((number) 1) always clobbers reg byte a -Statement [11] (byte) main::w#0 ← stackpull(byte) [ main::a#2 main::w#0 ] ( main:2 [ main::a#2 main::w#0 ] ) always clobbers reg byte a -Statement [12] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ main::a#2 main::$2 ] ( main:2 [ main::a#2 main::$2 ] ) always clobbers reg byte a -Statement [17] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:9 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [18] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:9 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x -Statement [19] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:9 [ main::a#2 plus::return#0 ] ) always clobbers reg byte a -Statement [20] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:9 [ main::a#2 ] ) always clobbers reg byte x -Potential registers zp[1]:2 [ main::a#2 main::a#1 ] : zp[1]:2 , reg byte y , -Potential registers zp[1]:3 [ main::v#0 ] : zp[1]:3 , reg byte x , reg byte y , -Potential registers zp[1]:4 [ main::w#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , -Potential registers zp[1]:5 [ main::$2 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , -Potential registers zp[1]:6 [ plus::a#0 ] : zp[1]:6 , reg byte y , -Potential registers zp[1]:7 [ plus::b#0 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , -Potential registers zp[1]:8 [ plus::return#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Statement [11] (byte) main::w#0 ← stackpull(byte) [ i main::a#2 main::w#0 ] ( main:2 [ i main::a#2 main::w#0 ] ) always clobbers reg byte a +Statement [12] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ i main::a#2 main::$2 ] ( main:2 [ i main::a#2 main::$2 ] ) always clobbers reg byte a +Statement [13] *((const byte*) SCREEN + (byte) i) ← (byte~) main::$2 [ i main::a#2 ] ( main:2 [ i main::a#2 ] ) always clobbers reg byte y +Statement [15] if((byte) main::a#1!=(byte) 2) goto main::@1 [ i main::a#1 ] ( main:2 [ i main::a#1 ] ) always clobbers reg byte a +Statement [17] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ i plus::a#0 ] ( main:2::plus:9 [ main::a#2 i plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [18] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ i plus::a#0 plus::b#0 ] ( main:2::plus:9 [ main::a#2 i plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [20] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ i plus::return#0 ] ( main:2::plus:9 [ main::a#2 i plus::return#0 ] ) always clobbers reg byte a +Statement [21] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ i ] ( main:2::plus:9 [ main::a#2 i ] ) always clobbers reg byte x +Potential registers zp[1]:2 [ main::a#2 main::a#1 ] : zp[1]:2 , +Potential registers zp[1]:3 [ i ] : zp[1]:3 , +Potential registers zp[1]:4 [ main::v#0 ] : zp[1]:4 , reg byte x , reg byte y , +Potential registers zp[1]:5 [ main::w#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:6 [ main::$2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ plus::a#0 ] : zp[1]:7 , reg byte y , +Potential registers zp[1]:8 [ plus::b#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:9 [ plus::return#0 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] 22: zp[1]:4 [ main::w#0 ] 22: zp[1]:5 [ main::$2 ] 21.39: zp[1]:2 [ main::a#2 main::a#1 ] 11: zp[1]:3 [ main::v#0 ] -Uplift Scope [plus] 4: zp[1]:7 [ plus::b#0 ] 4: zp[1]:8 [ plus::return#0 ] 2: zp[1]:6 [ plus::a#0 ] -Uplift Scope [] +Uplift Scope [main] 22: zp[1]:5 [ main::w#0 ] 22: zp[1]:6 [ main::$2 ] 21.39: zp[1]:2 [ main::a#2 main::a#1 ] 11: zp[1]:4 [ main::v#0 ] +Uplift Scope [plus] 4: zp[1]:9 [ plus::return#0 ] 2: zp[1]:8 [ plus::b#0 ] 1.33: zp[1]:7 [ plus::a#0 ] +Uplift Scope [] 0.85: zp[1]:3 [ i ] -Uplifting [main] best 661 combination reg byte a [ main::w#0 ] reg byte a [ main::$2 ] reg byte y [ main::a#2 main::a#1 ] reg byte x [ main::v#0 ] -Uplifting [plus] best 649 combination reg byte a [ plus::b#0 ] reg byte a [ plus::return#0 ] zp[1]:6 [ plus::a#0 ] -Uplifting [] best 649 combination -Attempting to uplift remaining variables inzp[1]:6 [ plus::a#0 ] -Uplifting [plus] best 649 combination zp[1]:6 [ plus::a#0 ] -Allocated (was zp[1]:6) zp[1]:2 [ plus::a#0 ] +Uplifting [main] best 761 combination reg byte a [ main::w#0 ] reg byte a [ main::$2 ] zp[1]:2 [ main::a#2 main::a#1 ] reg byte x [ main::v#0 ] +Uplifting [plus] best 749 combination reg byte a [ plus::return#0 ] reg byte a [ plus::b#0 ] zp[1]:7 [ plus::a#0 ] +Uplifting [] best 749 combination zp[1]:3 [ i ] +Attempting to uplift remaining variables inzp[1]:2 [ main::a#2 main::a#1 ] +Uplifting [main] best 749 combination zp[1]:2 [ main::a#2 main::a#1 ] +Attempting to uplift remaining variables inzp[1]:7 [ plus::a#0 ] +Uplifting [plus] best 749 combination zp[1]:7 [ plus::a#0 ] +Attempting to uplift remaining variables inzp[1]:3 [ i ] +Uplifting [] best 749 combination zp[1]:3 [ i ] +Allocated (was zp[1]:7) zp[1]:4 [ plus::a#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -436,8 +424,12 @@ ASSEMBLER BEFORE OPTIMIZATION // Global Constants & labels .label SCREEN = $400 .const STACK_BASE = $103 + .label i = 3 // @begin __bbegin: + // [0] (byte) i ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z i // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 @@ -454,10 +446,12 @@ __bend_from___b1: __bend: // main main: { + .label a = 2 // [5] phi from main to main::@1 [phi:main->main::@1] __b1_from_main: - // [5] phi (byte) main::a#2 = (byte) 0 [phi:main->main::@1#0] -- vbuyy=vbuc1 - ldy #0 + // [5] phi (byte) main::a#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z a jmp __b1 // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] __b1_from___b1: @@ -465,9 +459,8 @@ main: { jmp __b1 // main::@1 __b1: - // [6] (byte) main::v#0 ← (byte) main::a#2 + (byte) 1 -- vbuxx=vbuyy_plus_1 - tya - tax + // [6] (byte) main::v#0 ← (byte) main::a#2 + (byte) 1 -- vbuxx=vbuz1_plus_1 + ldx.z a inx // [7] stackpush(byte) ← (byte) '0' -- _stackpushbyte_=vbuc1 lda #'0' @@ -481,16 +474,17 @@ main: { pla // [11] (byte) main::w#0 ← stackpull(byte) -- vbuaa=_stackpullbyte_ pla - // [12] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuaa=vbuaa_plus_vbuyy - sty.z $ff + // [12] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuaa=vbuaa_plus_vbuz1 clc - adc.z $ff - // [13] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa - sta SCREEN - // [14] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuyy=_inc_vbuyy - iny - // [15] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuyy_neq_vbuc1_then_la1 - cpy #2 + adc.z a + // [13] *((const byte*) SCREEN + (byte) i) ← (byte~) main::$2 -- pbuc1_derefidx_vbuz1=vbuaa + ldy.z i + sta SCREEN,y + // [14] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuz1=_inc_vbuz1 + inc.z a + // [15] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #2 + cmp.z a bne __b1_from___b1 jmp __breturn // main::@return @@ -499,12 +493,12 @@ main: { rts } // plus -// plus(byte zp(2) a, byte register(A) b) +// plus(byte zp(4) a, byte register(A) b) plus: { .const OFFSET_STACK_A = 1 .const OFFSET_STACK_B = 0 .const OFFSET_STACK_RETURN = 1 - .label a = 2 + .label a = 4 // [17] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x @@ -512,16 +506,18 @@ plus: { // [18] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x - // [19] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + // [19] (byte) i ← ++ (byte) i -- vbuz1=_inc_vbuz1 + inc.z i + // [20] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa clc adc.z a jmp __breturn // plus::@return __breturn: - // [20] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + // [21] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa tsx sta STACK_BASE+OFFSET_STACK_RETURN,x - // [21] return + // [22] return rts } // File Data @@ -535,23 +531,20 @@ Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Replacing label __b1_from___b1 with __b1 Removing instruction __b1_from___bbegin: -Removing instruction __b1: Removing instruction main_from___b1: Removing instruction __bend_from___b1: Removing instruction __b1_from___b1: Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __b1: Removing instruction __bend: Removing instruction __b1_from_main: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination -Updating BasicUpstart to call main directly -Removing instruction jsr main -Succesful ASM optimization Pass5SkipBegin +Adding RTS to root block +Succesful ASM optimization Pass5AddMainRts Removing instruction jmp __b1 Succesful ASM optimization Pass5NextJumpElimination -Removing instruction __bbegin: -Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE (label) @1 @@ -559,14 +552,14 @@ FINAL SYMBOL TABLE (label) @end (const byte*) SCREEN = (byte*) 1024 (const word) STACK_BASE = (word) $103 -(byte) i +(byte) i loadstore zp[1]:3 0.85 (void()) main() (byte~) main::$2 reg byte a 22.0 (label) main::@1 (label) main::@return (byte) main::a -(byte) main::a#1 reg byte y 16.5 -(byte) main::a#2 reg byte y 4.888888888888889 +(byte) main::a#1 a zp[1]:2 16.5 +(byte) main::a#2 a zp[1]:2 4.888888888888889 (byte) main::v (byte) main::v#0 reg byte x 11.0 (byte) main::w @@ -577,54 +570,64 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (const byte) plus::OFFSET_STACK_B = (byte) 0 (const byte) plus::OFFSET_STACK_RETURN = (byte) 1 (byte) plus::a -(byte) plus::a#0 a zp[1]:2 2.0 +(byte) plus::a#0 a zp[1]:4 1.3333333333333333 (byte) plus::b -(byte) plus::b#0 reg byte a 4.0 +(byte) plus::b#0 reg byte a 2.0 (byte) plus::return (byte) plus::return#0 reg byte a 4.0 -reg byte y [ main::a#2 main::a#1 ] +zp[1]:2 [ main::a#2 main::a#1 ] +zp[1]:3 [ i ] reg byte x [ main::v#0 ] reg byte a [ main::w#0 ] reg byte a [ main::$2 ] -zp[1]:2 [ plus::a#0 ] +zp[1]:4 [ plus::a#0 ] reg byte a [ plus::b#0 ] reg byte a [ plus::return#0 ] FINAL ASSEMBLER -Score: 544 +Score: 656 // File Comments // Test a procedure with calling convention stack // A slightly more complex call // Upstart .pc = $801 "Basic" -:BasicUpstart(main) +:BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 .const STACK_BASE = $103 + .label i = 3 // @begin +__bbegin: + // i = 0 + // [0] (byte) i ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z i // [1] phi from @begin to @1 [phi:@begin->@1] // @1 // [2] call main // [4] phi from @1 to main [phi:@1->main] + jsr main + rts // [3] phi from @1 to @end [phi:@1->@end] // @end // main main: { + .label a = 2 // [5] phi from main to main::@1 [phi:main->main::@1] - // [5] phi (byte) main::a#2 = (byte) 0 [phi:main->main::@1#0] -- vbuyy=vbuc1 - ldy #0 + // [5] phi (byte) main::a#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z a // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] // [5] phi (byte) main::a#2 = (byte) main::a#1 [phi:main::@1->main::@1#0] -- register_copy // main::@1 __b1: // v = a+1 - // [6] (byte) main::v#0 ← (byte) main::a#2 + (byte) 1 -- vbuxx=vbuyy_plus_1 - tya - tax + // [6] (byte) main::v#0 ← (byte) main::a#2 + (byte) 1 -- vbuxx=vbuz1_plus_1 + ldx.z a inx // plus('0', v) // [7] stackpush(byte) ← (byte) '0' -- _stackpushbyte_=vbuc1 @@ -641,18 +644,19 @@ main: { // [11] (byte) main::w#0 ← stackpull(byte) -- vbuaa=_stackpullbyte_ pla // w+a - // [12] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuaa=vbuaa_plus_vbuyy - sty.z $ff + // [12] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuaa=vbuaa_plus_vbuz1 clc - adc.z $ff + adc.z a // SCREEN[i] = w+a - // [13] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa - sta SCREEN + // [13] *((const byte*) SCREEN + (byte) i) ← (byte~) main::$2 -- pbuc1_derefidx_vbuz1=vbuaa + ldy.z i + sta SCREEN,y // for(char a:0..1) - // [14] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuyy=_inc_vbuyy - iny - // [15] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuyy_neq_vbuc1_then_la1 - cpy #2 + // [14] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuz1=_inc_vbuz1 + inc.z a + // [15] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #2 + cmp.z a bne __b1 // main::@return // } @@ -660,12 +664,12 @@ main: { rts } // plus -// plus(byte zp(2) a, byte register(A) b) +// plus(byte zp(4) a, byte register(A) b) plus: { .const OFFSET_STACK_A = 1 .const OFFSET_STACK_B = 0 .const OFFSET_STACK_RETURN = 1 - .label a = 2 + .label a = 4 // [17] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x @@ -673,16 +677,19 @@ plus: { // [18] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x + // i++; + // [19] (byte) i ← ++ (byte) i -- vbuz1=_inc_vbuz1 + inc.z i // return a+b; - // [19] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + // [20] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa clc adc.z a // plus::@return // } - // [20] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + // [21] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa tsx sta STACK_BASE+OFFSET_STACK_RETURN,x - // [21] return + // [22] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-4.sym b/src/test/ref/procedure-callingconvention-stack-4.sym index 157f2011b..4f31a7ce7 100644 --- a/src/test/ref/procedure-callingconvention-stack-4.sym +++ b/src/test/ref/procedure-callingconvention-stack-4.sym @@ -3,14 +3,14 @@ (label) @end (const byte*) SCREEN = (byte*) 1024 (const word) STACK_BASE = (word) $103 -(byte) i +(byte) i loadstore zp[1]:3 0.85 (void()) main() (byte~) main::$2 reg byte a 22.0 (label) main::@1 (label) main::@return (byte) main::a -(byte) main::a#1 reg byte y 16.5 -(byte) main::a#2 reg byte y 4.888888888888889 +(byte) main::a#1 a zp[1]:2 16.5 +(byte) main::a#2 a zp[1]:2 4.888888888888889 (byte) main::v (byte) main::v#0 reg byte x 11.0 (byte) main::w @@ -21,16 +21,17 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (const byte) plus::OFFSET_STACK_B = (byte) 0 (const byte) plus::OFFSET_STACK_RETURN = (byte) 1 (byte) plus::a -(byte) plus::a#0 a zp[1]:2 2.0 +(byte) plus::a#0 a zp[1]:4 1.3333333333333333 (byte) plus::b -(byte) plus::b#0 reg byte a 4.0 +(byte) plus::b#0 reg byte a 2.0 (byte) plus::return (byte) plus::return#0 reg byte a 4.0 -reg byte y [ main::a#2 main::a#1 ] +zp[1]:2 [ main::a#2 main::a#1 ] +zp[1]:3 [ i ] reg byte x [ main::v#0 ] reg byte a [ main::w#0 ] reg byte a [ main::$2 ] -zp[1]:2 [ plus::a#0 ] +zp[1]:4 [ plus::a#0 ] reg byte a [ plus::b#0 ] reg byte a [ plus::return#0 ] diff --git a/src/test/ref/procedure-callingconvention-stack-5.asm b/src/test/ref/procedure-callingconvention-stack-5.asm index 36670d832..105e36b4c 100644 --- a/src/test/ref/procedure-callingconvention-stack-5.asm +++ b/src/test/ref/procedure-callingconvention-stack-5.asm @@ -1,15 +1,23 @@ // Test a procedure with calling convention stack // Return value larger than parameter .pc = $801 "Basic" -:BasicUpstart(main) +:BasicUpstart(__bbegin) .pc = $80d "Program" .label SCREEN = $400 .const SIZEOF_SIGNED_WORD = 2 .const STACK_BASE = $103 .label current = 2 +__bbegin: + // current = 48 + lda #<$30 + sta.z current + lda #>$30 + sta.z current+1 + jsr main + rts main: { - .label __0 = 2 - .label __1 = 4 + .label __0 = 4 + .label __1 = 2 // next() pha pha @@ -41,8 +49,16 @@ main: { } next: { .const OFFSET_STACK_RETURN = 0 - .label return = 2 + .label return = 4 // return current++; + lda.z current + sta.z return + lda.z current+1 + sta.z return+1 + inc.z current + bne !+ + inc.z current+1 + !: // } tsx lda.z return diff --git a/src/test/ref/procedure-callingconvention-stack-5.cfg b/src/test/ref/procedure-callingconvention-stack-5.cfg index e7127030e..05d25d7f0 100644 --- a/src/test/ref/procedure-callingconvention-stack-5.cfg +++ b/src/test/ref/procedure-callingconvention-stack-5.cfg @@ -2,33 +2,36 @@ [0] phi() to:@1 @1: scope:[] from @begin - [1] phi() - [2] call main + [1] (signed word) current ← (signed word) $30 + to:@2 +@2: scope:[] from @1 + [2] phi() + [3] call main to:@end -@end: scope:[] from @1 - [3] phi() +@end: scope:[] from @2 + [4] phi() (void()) main() -main: scope:[main] from @1 +main: scope:[main] from @2 sideeffect stackpushbytes((number) 2) - [5] callexecute next - [6] (signed word~) main::$0 ← stackpull(signed word) - [7] *((const signed word*) SCREEN) ← (signed word~) main::$0 + [6] callexecute next + [7] (signed word~) main::$0 ← stackpull(signed word) + [8] *((const signed word*) SCREEN) ← (signed word~) main::$0 sideeffect stackpushbytes((number) 2) - [9] callexecute next - [10] (signed word~) main::$1 ← stackpull(signed word) - [11] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 + [10] callexecute next + [11] (signed word~) main::$1 ← stackpull(signed word) + [12] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 to:main::@return main::@return: scope:[main] from main - [12] return + [13] return to:@return __stackcall (signed word()) next() next: scope:[next] from - [13] (signed word) current#5 ← phi( ) - [14] (signed word) next::return#0 ← (signed word) current#5 + [14] (signed word) next::return#0 ← (signed word) current + [15] (signed word) current ← ++ (signed word) current to:next::@return next::@return: scope:[next] from next - [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 - [16] return + [16] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 + [17] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-5.log b/src/test/ref/procedure-callingconvention-stack-5.log index d4abab2a3..d3d7be583 100644 --- a/src/test/ref/procedure-callingconvention-stack-5.log +++ b/src/test/ref/procedure-callingconvention-stack-5.log @@ -1,6 +1,7 @@ Fixing pointer array-indexing *((const signed word*) SCREEN + (number) 0) Fixing pointer array-indexing *((const signed word*) SCREEN + (number) 1) Culled Empty Block (label) next::@1 +Converting PHI-variable modified inside __stackcall procedure next() to load/store (signed word) current Calling convention STACK_CALL adding prepare/execute/finalize for (signed word~) main::$0 ← call next Calling convention STACK_CALL adding prepare/execute/finalize for (signed word~) main::$1 ← call next Calling convention STACK_CALL adding stack return stackidx(signed word,next::OFFSET_STACK_RETURN) ← next::return @@ -13,7 +14,6 @@ CONTROL FLOW GRAPH SSA (void()) main() main: scope:[main] from @2 - (signed word) current#7 ← phi( @2/(signed word) current#8 ) sideeffect stackpushbytes((number) 2) callexecute next (signed word~) main::$0 ← stackpull(signed word) @@ -26,19 +26,16 @@ main: scope:[main] from @2 *((const signed word*) SCREEN + (number~) main::$3) ← (signed word~) main::$1 to:main::@return main::@return: scope:[main] from main - (signed word) current#4 ← phi( main/(signed word) current#7 ) - (signed word) current#0 ← (signed word) current#4 return to:@return @1: scope:[] from @begin - (signed word) current#1 ← (signed word) $30 + (signed word) current ← (signed word) $30 to:@2 __stackcall (signed word()) next() next: scope:[next] from - (signed word) current#5 ← phi( ) - (signed word) next::return#0 ← (signed word) current#5 - (signed word) current#2 ← ++ (signed word) current#5 + (signed word) next::return#0 ← (signed word) current + (signed word) current ← ++ (signed word) current to:next::@return next::@return: scope:[next] from next (signed word) next::return#1 ← phi( next/(signed word) next::return#0 ) @@ -46,12 +43,9 @@ next::@return: scope:[next] from next return to:@return @2: scope:[] from @1 - (signed word) current#8 ← phi( @1/(signed word) current#1 ) call main to:@3 @3: scope:[] from @2 - (signed word) current#6 ← phi( @2/(signed word) current#0 ) - (signed word) current#3 ← (signed word) current#6 to:@end @end: scope:[] from @3 @@ -64,16 +58,7 @@ SYMBOL TABLE SSA (const signed word*) SCREEN = (signed word*)(number) $400 (const byte) SIZEOF_SIGNED_WORD = (byte) 2 (const word) STACK_BASE = (word) $103 -(signed word) current -(signed word) current#0 -(signed word) current#1 -(signed word) current#2 -(signed word) current#3 -(signed word) current#4 -(signed word) current#5 -(signed word) current#6 -(signed word) current#7 -(signed word) current#8 +(signed word) current loadstore (void()) main() (signed word~) main::$0 (signed word~) main::$1 @@ -101,35 +86,25 @@ Finalized unsigned number type (byte) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions Inferred type updated to byte in (unumber~) main::$2 ← (byte) 0 * (const byte) SIZEOF_SIGNED_WORD Inferred type updated to byte in (unumber~) main::$3 ← (byte) 1 * (const byte) SIZEOF_SIGNED_WORD -Alias (signed word) current#0 = (signed word) current#4 (signed word) current#7 Alias (signed word) next::return#0 = (signed word) next::return#1 -Alias (signed word) current#1 = (signed word) current#8 -Alias (signed word) current#3 = (signed word) current#6 Successful SSA optimization Pass2AliasElimination -Identical Phi Values (signed word) current#0 (signed word) current#1 -Identical Phi Values (signed word) current#3 (signed word) current#0 -Successful SSA optimization Pass2IdenticalPhiElimination -Constant right-side identified [4] (byte~) main::$2 ← (byte) 0 * (const byte) SIZEOF_SIGNED_WORD -Constant right-side identified [9] (byte~) main::$3 ← (byte) 1 * (const byte) SIZEOF_SIGNED_WORD +Constant right-side identified [3] (byte~) main::$2 ← (byte) 0 * (const byte) SIZEOF_SIGNED_WORD +Constant right-side identified [8] (byte~) main::$3 ← (byte) 1 * (const byte) SIZEOF_SIGNED_WORD Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::$2 = 0*SIZEOF_SIGNED_WORD Constant (const byte) main::$3 = 1*SIZEOF_SIGNED_WORD -Constant (const signed word) current#1 = $30 Successful SSA optimization Pass2ConstantIdentification Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_SIGNED_WORD in Successful SSA optimization PassNSimplifyConstantZero -Simplifying expression containing zero SCREEN in [5] *((const signed word*) SCREEN + (const byte) main::$2) ← (signed word~) main::$0 +Simplifying expression containing zero SCREEN in [4] *((const signed word*) SCREEN + (const byte) main::$2) ← (signed word~) main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused variable (signed word) current#2 and assignment [11] (signed word) current#2 ← ++ (signed word) current#5 Eliminating unused constant (const byte) main::$2 -Eliminating unused constant (const signed word) current#1 Successful SSA optimization PassNEliminateUnusedVars Constant inlined main::$3 = (byte) 1*(const byte) SIZEOF_SIGNED_WORD Successful SSA optimization Pass2ConstantInlining Consolidated array index constant in *(SCREEN+1*SIZEOF_SIGNED_WORD) Successful SSA optimization Pass2ConstantAdditionElimination 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 @3 Adding NOP phi() at start of @end @@ -137,13 +112,11 @@ CALL GRAPH Calls in [] to main:3 Calls in [main] to next:7 next:11 -Created 1 initial phi equivalence classes -Coalesced down to 1 phi equivalence classes -Culled Empty Block (label) @1 +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes Culled Empty Block (label) @3 -Renumbering block @2 to @1 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 FINAL CONTROL FLOW GRAPH @@ -151,59 +124,61 @@ FINAL CONTROL FLOW GRAPH [0] phi() to:@1 @1: scope:[] from @begin - [1] phi() - [2] call main + [1] (signed word) current ← (signed word) $30 + to:@2 +@2: scope:[] from @1 + [2] phi() + [3] call main to:@end -@end: scope:[] from @1 - [3] phi() +@end: scope:[] from @2 + [4] phi() (void()) main() -main: scope:[main] from @1 +main: scope:[main] from @2 sideeffect stackpushbytes((number) 2) - [5] callexecute next - [6] (signed word~) main::$0 ← stackpull(signed word) - [7] *((const signed word*) SCREEN) ← (signed word~) main::$0 + [6] callexecute next + [7] (signed word~) main::$0 ← stackpull(signed word) + [8] *((const signed word*) SCREEN) ← (signed word~) main::$0 sideeffect stackpushbytes((number) 2) - [9] callexecute next - [10] (signed word~) main::$1 ← stackpull(signed word) - [11] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 + [10] callexecute next + [11] (signed word~) main::$1 ← stackpull(signed word) + [12] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 to:main::@return main::@return: scope:[main] from main - [12] return + [13] return to:@return __stackcall (signed word()) next() next: scope:[next] from - [13] (signed word) current#5 ← phi( ) - [14] (signed word) next::return#0 ← (signed word) current#5 + [14] (signed word) next::return#0 ← (signed word) current + [15] (signed word) current ← ++ (signed word) current to:next::@return next::@return: scope:[next] from next - [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 - [16] return + [16] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 + [17] return to:@return VARIABLE REGISTER WEIGHTS -(signed word) current -(signed word) current#5 2.0 +(signed word) current loadstore 0.7272727272727273 (void()) main() (signed word~) main::$0 4.0 (signed word~) main::$1 4.0 __stackcall (signed word()) next() (signed word) next::return -(signed word) next::return#0 4.0 +(signed word) next::return#0 2.0 Initial phi equivalence classes -[ current#5 ] +Added variable current to live range equivalence class [ current ] Added variable main::$0 to live range equivalence class [ main::$0 ] Added variable main::$1 to live range equivalence class [ main::$1 ] Added variable next::return#0 to live range equivalence class [ next::return#0 ] Complete equivalence classes -[ current#5 ] +[ current ] [ main::$0 ] [ main::$1 ] [ next::return#0 ] -Allocated zp[2]:2 [ current#5 ] +Allocated zp[2]:2 [ current ] Allocated zp[2]:4 [ main::$0 ] Allocated zp[2]:6 [ main::$1 ] Allocated zp[2]:8 [ next::return#0 ] @@ -224,15 +199,23 @@ Target platform is c64basic / MOS6502X .label current = 2 // @begin __bbegin: - // [1] phi from @begin to @1 [phi:@begin->@1] -__b1_from___bbegin: jmp __b1 // @1 __b1: - // [2] call main + // [1] (signed word) current ← (signed word) $30 -- vwsz1=vwsc1 + lda #<$30 + sta.z current + lda #>$30 + sta.z current+1 + // [2] phi from @1 to @2 [phi:@1->@2] +__b2_from___b1: + jmp __b2 + // @2 +__b2: + // [3] call main jsr main - // [3] phi from @1 to @end [phi:@1->@end] -__bend_from___b1: + // [4] phi from @2 to @end [phi:@2->@end] +__bend_from___b2: jmp __bend // @end __bend: @@ -243,14 +226,14 @@ main: { // sideeffect stackpushbytes((number) 2) -- _stackpushbyte_2 pha pha - // [5] callexecute next -- jsr + // [6] callexecute next -- jsr jsr next - // [6] (signed word~) main::$0 ← stackpull(signed word) -- vwsz1=_stackpullsword_ + // [7] (signed word~) main::$0 ← stackpull(signed word) -- vwsz1=_stackpullsword_ pla sta.z __0 pla sta.z __0+1 - // [7] *((const signed word*) SCREEN) ← (signed word~) main::$0 -- _deref_pwsc1=vwsz1 + // [8] *((const signed word*) SCREEN) ← (signed word~) main::$0 -- _deref_pwsc1=vwsz1 lda.z __0 sta SCREEN lda.z __0+1 @@ -258,14 +241,14 @@ main: { // sideeffect stackpushbytes((number) 2) -- _stackpushbyte_2 pha pha - // [9] callexecute next -- jsr + // [10] callexecute next -- jsr jsr next - // [10] (signed word~) main::$1 ← stackpull(signed word) -- vwsz1=_stackpullsword_ + // [11] (signed word~) main::$1 ← stackpull(signed word) -- vwsz1=_stackpullsword_ pla sta.z __1 pla sta.z __1+1 - // [11] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 -- _deref_pwsc1=vwsz1 + // [12] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 -- _deref_pwsc1=vwsz1 lda.z __1 sta SCREEN+1*SIZEOF_SIGNED_WORD lda.z __1+1 @@ -273,56 +256,62 @@ main: { jmp __breturn // main::@return __breturn: - // [12] return + // [13] return rts } // next next: { .const OFFSET_STACK_RETURN = 0 .label return = 8 - // [14] (signed word) next::return#0 ← (signed word) current#5 -- vwsz1=vwsz2 + // [14] (signed word) next::return#0 ← (signed word) current -- vwsz1=vwsz2 lda.z current sta.z return lda.z current+1 sta.z return+1 + // [15] (signed word) current ← ++ (signed word) current -- vwsz1=_inc_vwsz1 + inc.z current + bne !+ + inc.z current+1 + !: jmp __breturn // next::@return __breturn: - // [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1 + // [16] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1 tsx lda.z return sta STACK_BASE+OFFSET_STACK_RETURN,x lda.z return+1 sta STACK_BASE+OFFSET_STACK_RETURN+1,x - // [16] return + // [17] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS -Statement [6] (signed word~) main::$0 ← stackpull(signed word) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a -Statement [7] *((const signed word*) SCREEN) ← (signed word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [10] (signed word~) main::$1 ← stackpull(signed word) [ main::$1 ] ( main:2 [ main::$1 ] ) always clobbers reg byte a -Statement [11] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [14] (signed word) next::return#0 ← (signed word) current#5 [ next::return#0 ] ( main:2::next:5 [ next::return#0 ] main:2::next:9 [ next::return#0 ] ) always clobbers reg byte a -Statement [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 [ ] ( main:2::next:5 [ ] main:2::next:9 [ ] ) always clobbers reg byte a reg byte x -Potential registers zp[2]:2 [ current#5 ] : zp[2]:2 , +Statement [1] (signed word) current ← (signed word) $30 [ current ] ( [ current ] ) always clobbers reg byte a +Statement [7] (signed word~) main::$0 ← stackpull(signed word) [ current main::$0 ] ( main:3 [ current main::$0 ] ) always clobbers reg byte a +Statement [8] *((const signed word*) SCREEN) ← (signed word~) main::$0 [ current ] ( main:3 [ current ] ) always clobbers reg byte a +Statement [11] (signed word~) main::$1 ← stackpull(signed word) [ main::$1 ] ( main:3 [ main::$1 ] ) always clobbers reg byte a +Statement [12] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 [ ] ( main:3 [ ] ) always clobbers reg byte a +Statement [14] (signed word) next::return#0 ← (signed word) current [ current next::return#0 ] ( main:3::next:6 [ current next::return#0 ] main:3::next:10 [ current next::return#0 ] ) always clobbers reg byte a +Statement [16] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 [ current ] ( main:3::next:6 [ current ] main:3::next:10 [ current ] ) always clobbers reg byte a reg byte x +Potential registers zp[2]:2 [ current ] : zp[2]:2 , Potential registers zp[2]:4 [ main::$0 ] : zp[2]:4 , Potential registers zp[2]:6 [ main::$1 ] : zp[2]:6 , Potential registers zp[2]:8 [ next::return#0 ] : zp[2]:8 , REGISTER UPLIFT SCOPES Uplift Scope [main] 4: zp[2]:4 [ main::$0 ] 4: zp[2]:6 [ main::$1 ] -Uplift Scope [next] 4: zp[2]:8 [ next::return#0 ] -Uplift Scope [] 2: zp[2]:2 [ current#5 ] +Uplift Scope [next] 2: zp[2]:8 [ next::return#0 ] +Uplift Scope [] 0.73: zp[2]:2 [ current ] -Uplifting [main] best 140 combination zp[2]:4 [ main::$0 ] zp[2]:6 [ main::$1 ] -Uplifting [next] best 140 combination zp[2]:8 [ next::return#0 ] -Uplifting [] best 140 combination zp[2]:2 [ current#5 ] -Coalescing zero page register [ zp[2]:2 [ current#5 ] ] with [ zp[2]:8 [ next::return#0 ] ] - score: 1 -Coalescing zero page register [ zp[2]:4 [ main::$0 ] ] with [ zp[2]:2 [ current#5 next::return#0 ] ] -Allocated (was zp[2]:4) zp[2]:2 [ main::$0 current#5 next::return#0 ] -Allocated (was zp[2]:6) zp[2]:4 [ main::$1 ] +Uplifting [main] best 192 combination zp[2]:4 [ main::$0 ] zp[2]:6 [ main::$1 ] +Uplifting [next] best 192 combination zp[2]:8 [ next::return#0 ] +Uplifting [] best 192 combination zp[2]:2 [ current ] +Coalescing zero page register [ zp[2]:6 [ main::$1 ] ] with [ zp[2]:2 [ current ] ] +Coalescing zero page register [ zp[2]:8 [ next::return#0 ] ] with [ zp[2]:4 [ main::$0 ] ] +Allocated (was zp[2]:6) zp[2]:2 [ main::$1 current ] +Allocated (was zp[2]:8) zp[2]:4 [ next::return#0 main::$0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -339,33 +328,41 @@ ASSEMBLER BEFORE OPTIMIZATION .label current = 2 // @begin __bbegin: - // [1] phi from @begin to @1 [phi:@begin->@1] -__b1_from___bbegin: jmp __b1 // @1 __b1: - // [2] call main + // [1] (signed word) current ← (signed word) $30 -- vwsz1=vwsc1 + lda #<$30 + sta.z current + lda #>$30 + sta.z current+1 + // [2] phi from @1 to @2 [phi:@1->@2] +__b2_from___b1: + jmp __b2 + // @2 +__b2: + // [3] call main jsr main - // [3] phi from @1 to @end [phi:@1->@end] -__bend_from___b1: + // [4] phi from @2 to @end [phi:@2->@end] +__bend_from___b2: jmp __bend // @end __bend: // main main: { - .label __0 = 2 - .label __1 = 4 + .label __0 = 4 + .label __1 = 2 // sideeffect stackpushbytes((number) 2) -- _stackpushbyte_2 pha pha - // [5] callexecute next -- jsr + // [6] callexecute next -- jsr jsr next - // [6] (signed word~) main::$0 ← stackpull(signed word) -- vwsz1=_stackpullsword_ + // [7] (signed word~) main::$0 ← stackpull(signed word) -- vwsz1=_stackpullsword_ pla sta.z __0 pla sta.z __0+1 - // [7] *((const signed word*) SCREEN) ← (signed word~) main::$0 -- _deref_pwsc1=vwsz1 + // [8] *((const signed word*) SCREEN) ← (signed word~) main::$0 -- _deref_pwsc1=vwsz1 lda.z __0 sta SCREEN lda.z __0+1 @@ -373,14 +370,14 @@ main: { // sideeffect stackpushbytes((number) 2) -- _stackpushbyte_2 pha pha - // [9] callexecute next -- jsr + // [10] callexecute next -- jsr jsr next - // [10] (signed word~) main::$1 ← stackpull(signed word) -- vwsz1=_stackpullsword_ + // [11] (signed word~) main::$1 ← stackpull(signed word) -- vwsz1=_stackpullsword_ pla sta.z __1 pla sta.z __1+1 - // [11] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 -- _deref_pwsc1=vwsz1 + // [12] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 -- _deref_pwsc1=vwsz1 lda.z __1 sta SCREEN+1*SIZEOF_SIGNED_WORD lda.z __1+1 @@ -388,80 +385,88 @@ main: { jmp __breturn // main::@return __breturn: - // [12] return + // [13] return rts } // next next: { .const OFFSET_STACK_RETURN = 0 - .label return = 2 - // [14] (signed word) next::return#0 ← (signed word) current#5 + .label return = 4 + // [14] (signed word) next::return#0 ← (signed word) current -- vwsz1=vwsz2 + lda.z current + sta.z return + lda.z current+1 + sta.z return+1 + // [15] (signed word) current ← ++ (signed word) current -- vwsz1=_inc_vwsz1 + inc.z current + bne !+ + inc.z current+1 + !: jmp __breturn // next::@return __breturn: - // [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1 + // [16] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1 tsx lda.z return sta STACK_BASE+OFFSET_STACK_RETURN,x lda.z return+1 sta STACK_BASE+OFFSET_STACK_RETURN+1,x - // [16] return + // [17] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __bend Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination -Removing instruction __b1_from___bbegin: Removing instruction __b1: -Removing instruction __bend_from___b1: +Removing instruction __b2_from___b1: +Removing instruction __bend_from___b2: Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __b2: Removing instruction __bend: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination -Updating BasicUpstart to call main directly -Removing instruction jsr main -Succesful ASM optimization Pass5SkipBegin -Removing instruction __bbegin: -Succesful ASM optimization Pass5UnusedLabelElimination +Adding RTS to root block +Succesful ASM optimization Pass5AddMainRts FINAL SYMBOL TABLE (label) @1 +(label) @2 (label) @begin (label) @end (const signed word*) SCREEN = (signed word*) 1024 (const byte) SIZEOF_SIGNED_WORD = (byte) 2 (const word) STACK_BASE = (word) $103 -(signed word) current -(signed word) current#5 current zp[2]:2 2.0 +(signed word) current loadstore zp[2]:2 0.7272727272727273 (void()) main() -(signed word~) main::$0 zp[2]:2 4.0 -(signed word~) main::$1 zp[2]:4 4.0 +(signed word~) main::$0 zp[2]:4 4.0 +(signed word~) main::$1 zp[2]:2 4.0 (label) main::@return __stackcall (signed word()) next() (label) next::@return (const byte) next::OFFSET_STACK_RETURN = (byte) 0 (signed word) next::return -(signed word) next::return#0 return zp[2]:2 4.0 +(signed word) next::return#0 return zp[2]:4 2.0 -zp[2]:2 [ main::$0 current#5 next::return#0 ] -zp[2]:4 [ main::$1 ] +zp[2]:2 [ main::$1 current ] +zp[2]:4 [ next::return#0 main::$0 ] FINAL ASSEMBLER -Score: 110 +Score: 156 // File Comments // Test a procedure with calling convention stack // Return value larger than parameter // Upstart .pc = $801 "Basic" -:BasicUpstart(main) +:BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 @@ -469,28 +474,38 @@ Score: 110 .const STACK_BASE = $103 .label current = 2 // @begin - // [1] phi from @begin to @1 [phi:@begin->@1] +__bbegin: // @1 - // [2] call main - // [3] phi from @1 to @end [phi:@1->@end] + // current = 48 + // [1] (signed word) current ← (signed word) $30 -- vwsz1=vwsc1 + lda #<$30 + sta.z current + lda #>$30 + sta.z current+1 + // [2] phi from @1 to @2 [phi:@1->@2] + // @2 + // [3] call main + jsr main + rts + // [4] phi from @2 to @end [phi:@2->@end] // @end // main main: { - .label __0 = 2 - .label __1 = 4 + .label __0 = 4 + .label __1 = 2 // next() // sideeffect stackpushbytes((number) 2) -- _stackpushbyte_2 pha pha - // [5] callexecute next -- jsr + // [6] callexecute next -- jsr jsr next - // [6] (signed word~) main::$0 ← stackpull(signed word) -- vwsz1=_stackpullsword_ + // [7] (signed word~) main::$0 ← stackpull(signed word) -- vwsz1=_stackpullsword_ pla sta.z __0 pla sta.z __0+1 // SCREEN[0] = next() - // [7] *((const signed word*) SCREEN) ← (signed word~) main::$0 -- _deref_pwsc1=vwsz1 + // [8] *((const signed word*) SCREEN) ← (signed word~) main::$0 -- _deref_pwsc1=vwsz1 lda.z __0 sta SCREEN lda.z __0+1 @@ -499,39 +514,48 @@ main: { // sideeffect stackpushbytes((number) 2) -- _stackpushbyte_2 pha pha - // [9] callexecute next -- jsr + // [10] callexecute next -- jsr jsr next - // [10] (signed word~) main::$1 ← stackpull(signed word) -- vwsz1=_stackpullsword_ + // [11] (signed word~) main::$1 ← stackpull(signed word) -- vwsz1=_stackpullsword_ pla sta.z __1 pla sta.z __1+1 // SCREEN[1] = next() - // [11] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 -- _deref_pwsc1=vwsz1 + // [12] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 -- _deref_pwsc1=vwsz1 lda.z __1 sta SCREEN+1*SIZEOF_SIGNED_WORD lda.z __1+1 sta SCREEN+1*SIZEOF_SIGNED_WORD+1 // main::@return // } - // [12] return + // [13] return rts } // next next: { .const OFFSET_STACK_RETURN = 0 - .label return = 2 + .label return = 4 // return current++; - // [14] (signed word) next::return#0 ← (signed word) current#5 + // [14] (signed word) next::return#0 ← (signed word) current -- vwsz1=vwsz2 + lda.z current + sta.z return + lda.z current+1 + sta.z return+1 + // [15] (signed word) current ← ++ (signed word) current -- vwsz1=_inc_vwsz1 + inc.z current + bne !+ + inc.z current+1 + !: // next::@return // } - // [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1 + // [16] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1 tsx lda.z return sta STACK_BASE+OFFSET_STACK_RETURN,x lda.z return+1 sta STACK_BASE+OFFSET_STACK_RETURN+1,x - // [16] return + // [17] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-5.sym b/src/test/ref/procedure-callingconvention-stack-5.sym index 64067d892..2519d1b9d 100644 --- a/src/test/ref/procedure-callingconvention-stack-5.sym +++ b/src/test/ref/procedure-callingconvention-stack-5.sym @@ -1,20 +1,20 @@ (label) @1 +(label) @2 (label) @begin (label) @end (const signed word*) SCREEN = (signed word*) 1024 (const byte) SIZEOF_SIGNED_WORD = (byte) 2 (const word) STACK_BASE = (word) $103 -(signed word) current -(signed word) current#5 current zp[2]:2 2.0 +(signed word) current loadstore zp[2]:2 0.7272727272727273 (void()) main() -(signed word~) main::$0 zp[2]:2 4.0 -(signed word~) main::$1 zp[2]:4 4.0 +(signed word~) main::$0 zp[2]:4 4.0 +(signed word~) main::$1 zp[2]:2 4.0 (label) main::@return __stackcall (signed word()) next() (label) next::@return (const byte) next::OFFSET_STACK_RETURN = (byte) 0 (signed word) next::return -(signed word) next::return#0 return zp[2]:2 4.0 +(signed word) next::return#0 return zp[2]:4 2.0 -zp[2]:2 [ main::$0 current#5 next::return#0 ] -zp[2]:4 [ main::$1 ] +zp[2]:2 [ main::$1 current ] +zp[2]:4 [ next::return#0 main::$0 ] diff --git a/src/test/ref/procedure-callingconvention-stack-7.asm b/src/test/ref/procedure-callingconvention-stack-7.asm index 6ced63854..d5fbb50ef 100644 --- a/src/test/ref/procedure-callingconvention-stack-7.asm +++ b/src/test/ref/procedure-callingconvention-stack-7.asm @@ -5,39 +5,28 @@ .pc = $80d "Program" .label SCREEN = $400 printline: { - .label i = 2 - // i=0 - lda #0 - sta.z i + ldx #0 __b1: // for(char i=0; i<40; i++) - lda.z i - cmp #$28 + cpx #$28 bcc __b2 // } rts __b2: // SCREEN[i] = '*' lda #'*' - ldy.z i - sta SCREEN,y + sta SCREEN,x // for(char i=0; i<40; i++) - inc.z i + inx jmp __b1 } main: { - .label val = 3 - // val - lda #0 - sta.z val // val = *SCREEN - lda SCREEN - sta.z val + ldy SCREEN // printline() jsr printline // SCREEN[80] = val - lda.z val - sta SCREEN+$50 + sty SCREEN+$50 // } rts } diff --git a/src/test/ref/procedure-callingconvention-stack-7.cfg b/src/test/ref/procedure-callingconvention-stack-7.cfg index 71ee443b2..b6c7c6b84 100644 --- a/src/test/ref/procedure-callingconvention-stack-7.cfg +++ b/src/test/ref/procedure-callingconvention-stack-7.cfg @@ -10,25 +10,25 @@ __stackcall (void()) printline() printline: scope:[printline] from - [4] (byte) printline::i ← (byte) 0 + [4] phi() to:printline::@1 printline::@1: scope:[printline] from printline printline::@2 - [5] if((byte) printline::i<(byte) $28) goto printline::@2 + [5] (byte) printline::i#2 ← phi( printline/(byte) 0 printline::@2/(byte) printline::i#1 ) + [6] if((byte) printline::i#2<(byte) $28) goto printline::@2 to:printline::@return printline::@return: scope:[printline] from printline::@1 - [6] return + [7] return to:@return printline::@2: scope:[printline] from printline::@1 - [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' - [8] (byte) printline::i ← ++ (byte) printline::i + [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' + [9] (byte) printline::i#1 ← ++ (byte) printline::i#2 to:printline::@1 __stackcall (void()) main() main: scope:[main] from - [9] (byte) main::val ← (byte) 0 - [10] (byte) main::val ← *((const byte*) SCREEN) + [10] (byte) main::val#1 ← *((const byte*) SCREEN) [11] callexecute printline - [12] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val + [12] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val#1 to:main::@return main::@return: scope:[main] from main [13] return diff --git a/src/test/ref/procedure-callingconvention-stack-7.log b/src/test/ref/procedure-callingconvention-stack-7.log index 85fde0357..2f656ecff 100644 --- a/src/test/ref/procedure-callingconvention-stack-7.log +++ b/src/test/ref/procedure-callingconvention-stack-7.log @@ -12,10 +12,10 @@ CONTROL FLOW GRAPH SSA __stackcall (void()) main() main: scope:[main] from - (byte) main::val ← (byte) 0 - (byte) main::val ← *((const byte*) SCREEN) + (byte) main::val#0 ← (byte) 0 + (byte) main::val#1 ← *((const byte*) SCREEN) callexecute printline - *((const byte*) SCREEN + (number) $50) ← (byte) main::val + *((const byte*) SCREEN + (number) $50) ← (byte) main::val#1 to:main::@return main::@return: scope:[main] from main return @@ -23,15 +23,17 @@ main::@return: scope:[main] from main __stackcall (void()) printline() printline: scope:[printline] from - (byte) printline::i ← (byte) 0 + (byte) printline::i#0 ← (byte) 0 to:printline::@1 printline::@1: scope:[printline] from printline printline::@2 - (bool~) printline::$0 ← (byte) printline::i < (number) $28 + (byte) printline::i#2 ← phi( printline/(byte) printline::i#0 printline::@2/(byte) printline::i#1 ) + (bool~) printline::$0 ← (byte) printline::i#2 < (number) $28 if((bool~) printline::$0) goto printline::@2 to:printline::@return printline::@2: scope:[printline] from printline::@1 - *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' - (byte) printline::i ← ++ (byte) printline::i + (byte) printline::i#3 ← phi( printline::@1/(byte) printline::i#2 ) + *((const byte*) SCREEN + (byte) printline::i#3) ← (byte) '*' + (byte) printline::i#1 ← ++ (byte) printline::i#3 to:printline::@1 printline::@return: scope:[printline] from printline::@1 return @@ -48,16 +50,22 @@ SYMBOL TABLE SSA (const byte*) SCREEN = (byte*)(number) $400 __stackcall (void()) main() (label) main::@return -(byte) main::val loadstore +(byte) main::val +(byte) main::val#0 +(byte) main::val#1 __stackcall (void()) printline() (bool~) printline::$0 (label) printline::@1 (label) printline::@2 (label) printline::@return -(byte) printline::i loadstore +(byte) printline::i +(byte) printline::i#0 +(byte) printline::i#1 +(byte) printline::i#2 +(byte) printline::i#3 -Adding number conversion cast (unumber) $50 in *((const byte*) SCREEN + (number) $50) ← (byte) main::val -Adding number conversion cast (unumber) $28 in (bool~) printline::$0 ← (byte) printline::i < (number) $28 +Adding number conversion cast (unumber) $50 in *((const byte*) SCREEN + (number) $50) ← (byte) main::val#1 +Adding number conversion cast (unumber) $28 in (bool~) printline::$0 ← (byte) printline::i#2 < (number) $28 Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant pointer cast (byte*) 1024 Simplifying constant integer cast $50 @@ -66,23 +74,36 @@ Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) $50 Finalized unsigned number type (byte) $28 Successful SSA optimization PassNFinalizeNumberTypeConversions -Simple Condition (bool~) printline::$0 [7] if((byte) printline::i<(byte) $28) goto printline::@2 +Alias (byte) printline::i#2 = (byte) printline::i#3 +Successful SSA optimization Pass2AliasElimination +Simple Condition (bool~) printline::$0 [8] if((byte) printline::i#2<(byte) $28) goto printline::@2 Successful SSA optimization Pass2ConditionalJumpSimplification +Constant (const byte) main::val#0 = 0 +Constant (const byte) printline::i#0 = 0 +Successful SSA optimization Pass2ConstantIdentification +Eliminating unused constant (const byte) main::val#0 +Successful SSA optimization PassNEliminateUnusedVars +Inlining constant with var siblings (const byte) printline::i#0 +Constant inlined printline::i#0 = (byte) 0 +Successful SSA optimization Pass2ConstantInlining Consolidated array index constant in *(SCREEN+$50) Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of @begin Adding NOP phi() at start of @2 Adding NOP phi() at start of @end +Adding NOP phi() at start of printline CALL GRAPH Calls in [] to main:2 -Calls in [main] to printline:11 +Calls in [main] to printline:12 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes +Created 1 initial phi equivalence classes +Coalesced [10] printline::i#4 ← printline::i#1 +Coalesced down to 1 phi equivalence classes Renumbering block @2 to @1 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 printline FINAL CONTROL FLOW GRAPH @begin: scope:[] from @@ -97,25 +118,25 @@ FINAL CONTROL FLOW GRAPH __stackcall (void()) printline() printline: scope:[printline] from - [4] (byte) printline::i ← (byte) 0 + [4] phi() to:printline::@1 printline::@1: scope:[printline] from printline printline::@2 - [5] if((byte) printline::i<(byte) $28) goto printline::@2 + [5] (byte) printline::i#2 ← phi( printline/(byte) 0 printline::@2/(byte) printline::i#1 ) + [6] if((byte) printline::i#2<(byte) $28) goto printline::@2 to:printline::@return printline::@return: scope:[printline] from printline::@1 - [6] return + [7] return to:@return printline::@2: scope:[printline] from printline::@1 - [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' - [8] (byte) printline::i ← ++ (byte) printline::i + [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' + [9] (byte) printline::i#1 ← ++ (byte) printline::i#2 to:printline::@1 __stackcall (void()) main() main: scope:[main] from - [9] (byte) main::val ← (byte) 0 - [10] (byte) main::val ← *((const byte*) SCREEN) + [10] (byte) main::val#1 ← *((const byte*) SCREEN) [11] callexecute printline - [12] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val + [12] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val#1 to:main::@return main::@return: scope:[main] from main [13] return @@ -124,18 +145,21 @@ main::@return: scope:[main] from main VARIABLE REGISTER WEIGHTS __stackcall (void()) main() -(byte) main::val loadstore 3.0 +(byte) main::val +(byte) main::val#1 2.0 __stackcall (void()) printline() -(byte) printline::i loadstore 11.5 +(byte) printline::i +(byte) printline::i#1 22.0 +(byte) printline::i#2 14.666666666666666 Initial phi equivalence classes -Added variable printline::i to live range equivalence class [ printline::i ] -Added variable main::val to live range equivalence class [ main::val ] +[ printline::i#2 printline::i#1 ] +Added variable main::val#1 to live range equivalence class [ main::val#1 ] Complete equivalence classes -[ printline::i ] -[ main::val ] -Allocated zp[1]:2 [ printline::i ] -Allocated zp[1]:3 [ main::val ] +[ printline::i#2 printline::i#1 ] +[ main::val#1 ] +Allocated zp[1]:2 [ printline::i#2 printline::i#1 ] +Allocated zp[1]:3 [ main::val#1 ] INITIAL ASM Target platform is c64basic / MOS6502X @@ -165,43 +189,45 @@ __bend: // printline printline: { .label i = 2 - // [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 + // [5] phi from printline to printline::@1 [phi:printline->printline::@1] + __b1_from_printline: + // [5] phi (byte) printline::i#2 = (byte) 0 [phi:printline->printline::@1#0] -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // printline::@1 __b1: - // [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 + // [6] if((byte) printline::i#2<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #$28 bcc __b2 jmp __breturn // printline::@return __breturn: - // [6] return + // [7] return rts // printline::@2 __b2: - // [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 + // [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 lda #'*' ldy.z i sta SCREEN,y - // [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 + // [9] (byte) printline::i#1 ← ++ (byte) printline::i#2 -- vbuz1=_inc_vbuz1 inc.z i + // [5] phi from printline::@2 to printline::@1 [phi:printline::@2->printline::@1] + __b1_from___b2: + // [5] phi (byte) printline::i#2 = (byte) printline::i#1 [phi:printline::@2->printline::@1#0] -- register_copy jmp __b1 } // main main: { .label val = 3 - // [9] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z val - // [10] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1 + // [10] (byte) main::val#1 ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1 lda SCREEN sta.z val // [11] callexecute printline -- jsr jsr printline - // [12] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1 + // [12] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val#1 -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN+$50 jmp __breturn @@ -213,27 +239,21 @@ main: { // File Data REGISTER UPLIFT POTENTIAL REGISTERS -Statement [4] (byte) printline::i ← (byte) 0 [ printline::i ] ( main:2::printline:11 [ main::val printline::i ] ) always clobbers reg byte a -Statement [5] if((byte) printline::i<(byte) $28) goto printline::@2 [ printline::i ] ( main:2::printline:11 [ main::val printline::i ] ) always clobbers reg byte a -Statement [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' [ printline::i ] ( main:2::printline:11 [ main::val printline::i ] ) always clobbers reg byte a reg byte y -Statement [9] (byte) main::val ← (byte) 0 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [10] (byte) main::val ← *((const byte*) SCREEN) [ main::val ] ( main:2 [ main::val ] ) always clobbers reg byte a -Statement [12] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val [ ] ( main:2 [ ] ) always clobbers reg byte a -Potential registers zp[1]:2 [ printline::i ] : zp[1]:2 , -Potential registers zp[1]:3 [ main::val ] : zp[1]:3 , +Statement [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' [ printline::i#2 ] ( main:2::printline:11 [ main::val#1 printline::i#2 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::val#1 ] +Removing always clobbered register reg byte a as potential for zp[1]:2 [ printline::i#2 printline::i#1 ] +Statement [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' [ printline::i#2 ] ( main:2::printline:11 [ main::val#1 printline::i#2 ] ) always clobbers reg byte a +Potential registers zp[1]:2 [ printline::i#2 printline::i#1 ] : zp[1]:2 , reg byte x , reg byte y , +Potential registers zp[1]:3 [ main::val#1 ] : zp[1]:3 , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [printline] 11.5: zp[1]:2 [ printline::i ] -Uplift Scope [main] 3: zp[1]:3 [ main::val ] +Uplift Scope [printline] 36.67: zp[1]:2 [ printline::i#2 printline::i#1 ] +Uplift Scope [main] 2: zp[1]:3 [ main::val#1 ] Uplift Scope [] -Uplifting [printline] best 345 combination zp[1]:2 [ printline::i ] -Uplifting [main] best 345 combination zp[1]:3 [ main::val ] -Uplifting [] best 345 combination -Attempting to uplift remaining variables inzp[1]:2 [ printline::i ] -Uplifting [printline] best 345 combination zp[1]:2 [ printline::i ] -Attempting to uplift remaining variables inzp[1]:3 [ main::val ] -Uplifting [main] best 345 combination zp[1]:3 [ main::val ] +Uplifting [printline] best 292 combination reg byte x [ printline::i#2 printline::i#1 ] +Uplifting [main] best 286 combination reg byte y [ main::val#1 ] +Uplifting [] best 286 combination ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -261,46 +281,41 @@ __bend_from___b1: __bend: // printline printline: { - .label i = 2 - // [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z i + // [5] phi from printline to printline::@1 [phi:printline->printline::@1] + __b1_from_printline: + // [5] phi (byte) printline::i#2 = (byte) 0 [phi:printline->printline::@1#0] -- vbuxx=vbuc1 + ldx #0 jmp __b1 // printline::@1 __b1: - // [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 - lda.z i - cmp #$28 + // [6] if((byte) printline::i#2<(byte) $28) goto printline::@2 -- vbuxx_lt_vbuc1_then_la1 + cpx #$28 bcc __b2 jmp __breturn // printline::@return __breturn: - // [6] return + // [7] return rts // printline::@2 __b2: - // [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 + // [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' -- pbuc1_derefidx_vbuxx=vbuc2 lda #'*' - ldy.z i - sta SCREEN,y - // [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 - inc.z i + sta SCREEN,x + // [9] (byte) printline::i#1 ← ++ (byte) printline::i#2 -- vbuxx=_inc_vbuxx + inx + // [5] phi from printline::@2 to printline::@1 [phi:printline::@2->printline::@1] + __b1_from___b2: + // [5] phi (byte) printline::i#2 = (byte) printline::i#1 [phi:printline::@2->printline::@1#0] -- register_copy jmp __b1 } // main main: { - .label val = 3 - // [9] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z val - // [10] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1 - lda SCREEN - sta.z val + // [10] (byte) main::val#1 ← *((const byte*) SCREEN) -- vbuyy=_deref_pbuc1 + ldy SCREEN // [11] callexecute printline -- jsr jsr printline - // [12] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1 - lda.z val - sta SCREEN+$50 + // [12] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val#1 -- _deref_pbuc1=vbuyy + sty SCREEN+$50 jmp __breturn // main::@return __breturn: @@ -321,7 +336,9 @@ Removing instruction __b1: Removing instruction __bend_from___b1: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction __bend: +Removing instruction __b1_from_printline: Removing instruction __breturn: +Removing instruction __b1_from___b2: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination Updating BasicUpstart to call main directly @@ -337,19 +354,22 @@ FINAL SYMBOL TABLE (const byte*) SCREEN = (byte*) 1024 __stackcall (void()) main() (label) main::@return -(byte) main::val loadstore zp[1]:3 3.0 +(byte) main::val +(byte) main::val#1 reg byte y 2.0 __stackcall (void()) printline() (label) printline::@1 (label) printline::@2 (label) printline::@return -(byte) printline::i loadstore zp[1]:2 11.5 +(byte) printline::i +(byte) printline::i#1 reg byte x 22.0 +(byte) printline::i#2 reg byte x 14.666666666666666 -zp[1]:2 [ printline::i ] -zp[1]:3 [ main::val ] +reg byte x [ printline::i#2 printline::i#1 ] +reg byte y [ main::val#1 ] FINAL ASSEMBLER -Score: 297 +Score: 211 // File Comments // Test a procedure with calling convention stack @@ -368,52 +388,43 @@ Score: 297 // @end // printline printline: { - .label i = 2 - // i=0 - // [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z i + // [5] phi from printline to printline::@1 [phi:printline->printline::@1] + // [5] phi (byte) printline::i#2 = (byte) 0 [phi:printline->printline::@1#0] -- vbuxx=vbuc1 + ldx #0 // printline::@1 __b1: // for(char i=0; i<40; i++) - // [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 - lda.z i - cmp #$28 + // [6] if((byte) printline::i#2<(byte) $28) goto printline::@2 -- vbuxx_lt_vbuc1_then_la1 + cpx #$28 bcc __b2 // printline::@return // } - // [6] return + // [7] return rts // printline::@2 __b2: // SCREEN[i] = '*' - // [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 + // [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' -- pbuc1_derefidx_vbuxx=vbuc2 lda #'*' - ldy.z i - sta SCREEN,y + sta SCREEN,x // for(char i=0; i<40; i++) - // [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 - inc.z i + // [9] (byte) printline::i#1 ← ++ (byte) printline::i#2 -- vbuxx=_inc_vbuxx + inx + // [5] phi from printline::@2 to printline::@1 [phi:printline::@2->printline::@1] + // [5] phi (byte) printline::i#2 = (byte) printline::i#1 [phi:printline::@2->printline::@1#0] -- register_copy jmp __b1 } // main main: { - .label val = 3 - // val - // [9] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z val // val = *SCREEN - // [10] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1 - lda SCREEN - sta.z val + // [10] (byte) main::val#1 ← *((const byte*) SCREEN) -- vbuyy=_deref_pbuc1 + ldy SCREEN // printline() // [11] callexecute printline -- jsr jsr printline // SCREEN[80] = val - // [12] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1 - lda.z val - sta SCREEN+$50 + // [12] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val#1 -- _deref_pbuc1=vbuyy + sty SCREEN+$50 // main::@return // } // [13] return diff --git a/src/test/ref/procedure-callingconvention-stack-7.sym b/src/test/ref/procedure-callingconvention-stack-7.sym index 498bea49a..2f8ecbb6c 100644 --- a/src/test/ref/procedure-callingconvention-stack-7.sym +++ b/src/test/ref/procedure-callingconvention-stack-7.sym @@ -4,12 +4,15 @@ (const byte*) SCREEN = (byte*) 1024 __stackcall (void()) main() (label) main::@return -(byte) main::val loadstore zp[1]:3 3.0 +(byte) main::val +(byte) main::val#1 reg byte y 2.0 __stackcall (void()) printline() (label) printline::@1 (label) printline::@2 (label) printline::@return -(byte) printline::i loadstore zp[1]:2 11.5 +(byte) printline::i +(byte) printline::i#1 reg byte x 22.0 +(byte) printline::i#2 reg byte x 14.666666666666666 -zp[1]:2 [ printline::i ] -zp[1]:3 [ main::val ] +reg byte x [ printline::i#2 printline::i#1 ] +reg byte y [ main::val#1 ] diff --git a/src/test/ref/procedure-callingconvention-stack-8.asm b/src/test/ref/procedure-callingconvention-stack-8.asm index f56e19964..4479aae68 100644 --- a/src/test/ref/procedure-callingconvention-stack-8.asm +++ b/src/test/ref/procedure-callingconvention-stack-8.asm @@ -12,24 +12,19 @@ __bbegin: jsr main rts printline: { - .label i = 3 - // i=0 - lda #0 - sta.z i + ldx #0 __b1: // for(char i=0; i<40; i++) - lda.z i - cmp #$28 + cpx #$28 bcc __b2 // } rts __b2: // SCREEN[i] = '*' lda #'*' - ldy.z i - sta SCREEN,y + sta SCREEN,x // for(char i=0; i<40; i++) - inc.z i + inx jmp __b1 } main: { diff --git a/src/test/ref/procedure-callingconvention-stack-8.cfg b/src/test/ref/procedure-callingconvention-stack-8.cfg index f192268d5..f30d7dfd2 100644 --- a/src/test/ref/procedure-callingconvention-stack-8.cfg +++ b/src/test/ref/procedure-callingconvention-stack-8.cfg @@ -10,25 +10,26 @@ __stackcall (void()) printline() printline: scope:[printline] from - [4] (byte) printline::i ← (byte) 0 + [4] phi() to:printline::@1 printline::@1: scope:[printline] from printline printline::@2 - [5] if((byte) printline::i<(byte) $28) goto printline::@2 + [5] (byte) printline::i#2 ← phi( printline/(byte) 0 printline::@2/(byte) printline::i#1 ) + [6] if((byte) printline::i#2<(byte) $28) goto printline::@2 to:printline::@return printline::@return: scope:[printline] from printline::@1 - [6] return + [7] return to:@return printline::@2: scope:[printline] from printline::@1 - [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' - [8] (byte) printline::i ← ++ (byte) printline::i + [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' + [9] (byte) printline::i#1 ← ++ (byte) printline::i#2 to:printline::@1 __stackcall (void()) main() main: scope:[main] from - [9] (byte) val ← (byte) '-' - [10] callexecute printline - [11] *((const byte*) SCREEN+(byte) $50) ← (byte) val + [10] (byte) val ← (byte) '-' + [11] callexecute printline + [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val to:main::@return main::@return: scope:[main] from main - [12] return + [13] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-8.log b/src/test/ref/procedure-callingconvention-stack-8.log index a3ca7bfed..84599fcca 100644 --- a/src/test/ref/procedure-callingconvention-stack-8.log +++ b/src/test/ref/procedure-callingconvention-stack-8.log @@ -3,6 +3,7 @@ Culled Empty Block (label) printline::@4 Culled Empty Block (label) printline::@3 Culled Empty Block (label) printline::@5 Culled Empty Block (label) printline::@6 +Converting PHI-variable modified inside __stackcall procedure main() to load/store (byte) val Calling convention STACK_CALL adding prepare/execute/finalize for call printline Calling convention STACK_CALL adding prepare/execute/finalize for call main @@ -23,15 +24,17 @@ main::@return: scope:[main] from main __stackcall (void()) printline() printline: scope:[printline] from - (byte) printline::i ← (byte) 0 + (byte) printline::i#0 ← (byte) 0 to:printline::@1 printline::@1: scope:[printline] from printline printline::@2 - (bool~) printline::$0 ← (byte) printline::i < (number) $28 + (byte) printline::i#2 ← phi( printline/(byte) printline::i#0 printline::@2/(byte) printline::i#1 ) + (bool~) printline::$0 ← (byte) printline::i#2 < (number) $28 if((bool~) printline::$0) goto printline::@2 to:printline::@return printline::@2: scope:[printline] from printline::@1 - *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' - (byte) printline::i ← ++ (byte) printline::i + (byte) printline::i#3 ← phi( printline::@1/(byte) printline::i#2 ) + *((const byte*) SCREEN + (byte) printline::i#3) ← (byte) '*' + (byte) printline::i#1 ← ++ (byte) printline::i#3 to:printline::@1 printline::@return: scope:[printline] from printline::@1 return @@ -53,11 +56,15 @@ __stackcall (void()) printline() (label) printline::@1 (label) printline::@2 (label) printline::@return -(byte) printline::i loadstore +(byte) printline::i +(byte) printline::i#0 +(byte) printline::i#1 +(byte) printline::i#2 +(byte) printline::i#3 (byte) val loadstore Adding number conversion cast (unumber) $50 in *((const byte*) SCREEN + (number) $50) ← (byte) val -Adding number conversion cast (unumber) $28 in (bool~) printline::$0 ← (byte) printline::i < (number) $28 +Adding number conversion cast (unumber) $28 in (bool~) printline::$0 ← (byte) printline::i#2 < (number) $28 Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant pointer cast (byte*) 1024 Simplifying constant integer cast $50 @@ -66,21 +73,31 @@ Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) $50 Finalized unsigned number type (byte) $28 Successful SSA optimization PassNFinalizeNumberTypeConversions -Simple Condition (bool~) printline::$0 [7] if((byte) printline::i<(byte) $28) goto printline::@2 +Alias (byte) printline::i#2 = (byte) printline::i#3 +Successful SSA optimization Pass2AliasElimination +Simple Condition (bool~) printline::$0 [8] if((byte) printline::i#2<(byte) $28) goto printline::@2 Successful SSA optimization Pass2ConditionalJumpSimplification +Constant (const byte) printline::i#0 = 0 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with var siblings (const byte) printline::i#0 +Constant inlined printline::i#0 = (byte) 0 +Successful SSA optimization Pass2ConstantInlining Consolidated array index constant in *(SCREEN+$50) Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of @2 Adding NOP phi() at start of @end +Adding NOP phi() at start of printline CALL GRAPH Calls in [] to main:2 -Calls in [main] to printline:10 +Calls in [main] to printline:12 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes +Created 1 initial phi equivalence classes +Coalesced [10] printline::i#4 ← printline::i#1 +Coalesced down to 1 phi equivalence classes Renumbering block @2 to @1 Adding NOP phi() at start of @1 Adding NOP phi() at start of @end +Adding NOP phi() at start of printline FINAL CONTROL FLOW GRAPH @begin: scope:[] from @@ -95,44 +112,47 @@ FINAL CONTROL FLOW GRAPH __stackcall (void()) printline() printline: scope:[printline] from - [4] (byte) printline::i ← (byte) 0 + [4] phi() to:printline::@1 printline::@1: scope:[printline] from printline printline::@2 - [5] if((byte) printline::i<(byte) $28) goto printline::@2 + [5] (byte) printline::i#2 ← phi( printline/(byte) 0 printline::@2/(byte) printline::i#1 ) + [6] if((byte) printline::i#2<(byte) $28) goto printline::@2 to:printline::@return printline::@return: scope:[printline] from printline::@1 - [6] return + [7] return to:@return printline::@2: scope:[printline] from printline::@1 - [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' - [8] (byte) printline::i ← ++ (byte) printline::i + [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' + [9] (byte) printline::i#1 ← ++ (byte) printline::i#2 to:printline::@1 __stackcall (void()) main() main: scope:[main] from - [9] (byte) val ← (byte) '-' - [10] callexecute printline - [11] *((const byte*) SCREEN+(byte) $50) ← (byte) val + [10] (byte) val ← (byte) '-' + [11] callexecute printline + [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val to:main::@return main::@return: scope:[main] from main - [12] return + [13] return to:@return VARIABLE REGISTER WEIGHTS __stackcall (void()) main() __stackcall (void()) printline() -(byte) printline::i loadstore 11.5 +(byte) printline::i +(byte) printline::i#1 22.0 +(byte) printline::i#2 14.666666666666666 (byte) val loadstore 3.0 Initial phi equivalence classes +[ printline::i#2 printline::i#1 ] Added variable val to live range equivalence class [ val ] -Added variable printline::i to live range equivalence class [ printline::i ] Complete equivalence classes +[ printline::i#2 printline::i#1 ] [ val ] -[ printline::i ] -Allocated zp[1]:2 [ val ] -Allocated zp[1]:3 [ printline::i ] +Allocated zp[1]:2 [ printline::i#2 printline::i#1 ] +Allocated zp[1]:3 [ val ] INITIAL ASM Target platform is c64basic / MOS6502X @@ -145,7 +165,7 @@ Target platform is c64basic / MOS6502X .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 - .label val = 2 + .label val = 3 // @begin __bbegin: // [0] (byte) val ← (byte) 0 -- vbuz1=vbuc1 @@ -165,72 +185,79 @@ __bend_from___b1: __bend: // printline printline: { - .label i = 3 - // [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 + .label i = 2 + // [5] phi from printline to printline::@1 [phi:printline->printline::@1] + __b1_from_printline: + // [5] phi (byte) printline::i#2 = (byte) 0 [phi:printline->printline::@1#0] -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // printline::@1 __b1: - // [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 + // [6] if((byte) printline::i#2<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #$28 bcc __b2 jmp __breturn // printline::@return __breturn: - // [6] return + // [7] return rts // printline::@2 __b2: - // [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 + // [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 lda #'*' ldy.z i sta SCREEN,y - // [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 + // [9] (byte) printline::i#1 ← ++ (byte) printline::i#2 -- vbuz1=_inc_vbuz1 inc.z i + // [5] phi from printline::@2 to printline::@1 [phi:printline::@2->printline::@1] + __b1_from___b2: + // [5] phi (byte) printline::i#2 = (byte) printline::i#1 [phi:printline::@2->printline::@1#0] -- register_copy jmp __b1 } // main main: { - // [9] (byte) val ← (byte) '-' -- vbuz1=vbuc1 + // [10] (byte) val ← (byte) '-' -- vbuz1=vbuc1 lda #'-' sta.z val - // [10] callexecute printline -- jsr + // [11] callexecute printline -- jsr jsr printline - // [11] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1 + // [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN+$50 jmp __breturn // main::@return __breturn: - // [12] return + // [13] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [0] (byte) val ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a -Statement [4] (byte) printline::i ← (byte) 0 [ printline::i ] ( main:2::printline:10 [ val printline::i ] ) always clobbers reg byte a -Statement [5] if((byte) printline::i<(byte) $28) goto printline::@2 [ printline::i ] ( main:2::printline:10 [ val printline::i ] ) always clobbers reg byte a -Statement [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' [ printline::i ] ( main:2::printline:10 [ val printline::i ] ) always clobbers reg byte a reg byte y -Statement [9] (byte) val ← (byte) '-' [ val ] ( main:2 [ val ] ) always clobbers reg byte a -Statement [11] *((const byte*) SCREEN+(byte) $50) ← (byte) val [ ] ( main:2 [ ] ) always clobbers reg byte a -Potential registers zp[1]:2 [ val ] : zp[1]:2 , -Potential registers zp[1]:3 [ printline::i ] : zp[1]:3 , +Statement [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' [ printline::i#2 ] ( main:2::printline:11 [ val printline::i#2 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:2 [ printline::i#2 printline::i#1 ] +Statement [10] (byte) val ← (byte) '-' [ val ] ( main:2 [ val ] ) always clobbers reg byte a +Statement [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [0] (byte) val ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a +Statement [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' [ printline::i#2 ] ( main:2::printline:11 [ val printline::i#2 ] ) always clobbers reg byte a +Statement [10] (byte) val ← (byte) '-' [ val ] ( main:2 [ val ] ) always clobbers reg byte a +Statement [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val [ ] ( main:2 [ ] ) always clobbers reg byte a +Potential registers zp[1]:2 [ printline::i#2 printline::i#1 ] : zp[1]:2 , reg byte x , reg byte y , +Potential registers zp[1]:3 [ val ] : zp[1]:3 , REGISTER UPLIFT SCOPES -Uplift Scope [printline] 11.5: zp[1]:3 [ printline::i ] -Uplift Scope [] 3: zp[1]:2 [ val ] +Uplift Scope [printline] 36.67: zp[1]:2 [ printline::i#2 printline::i#1 ] +Uplift Scope [] 3: zp[1]:3 [ val ] Uplift Scope [main] -Uplifting [printline] best 343 combination zp[1]:3 [ printline::i ] -Uplifting [] best 343 combination zp[1]:2 [ val ] -Uplifting [main] best 343 combination -Attempting to uplift remaining variables inzp[1]:3 [ printline::i ] -Uplifting [printline] best 343 combination zp[1]:3 [ printline::i ] -Attempting to uplift remaining variables inzp[1]:2 [ val ] -Uplifting [] best 343 combination zp[1]:2 [ val ] +Uplifting [printline] best 295 combination reg byte x [ printline::i#2 printline::i#1 ] +Uplifting [] best 295 combination zp[1]:3 [ val ] +Uplifting [main] best 295 combination +Attempting to uplift remaining variables inzp[1]:3 [ val ] +Uplifting [] best 295 combination zp[1]:3 [ val ] +Allocated (was zp[1]:3) zp[1]:2 [ val ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -262,46 +289,47 @@ __bend_from___b1: __bend: // printline printline: { - .label i = 3 - // [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z i + // [5] phi from printline to printline::@1 [phi:printline->printline::@1] + __b1_from_printline: + // [5] phi (byte) printline::i#2 = (byte) 0 [phi:printline->printline::@1#0] -- vbuxx=vbuc1 + ldx #0 jmp __b1 // printline::@1 __b1: - // [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 - lda.z i - cmp #$28 + // [6] if((byte) printline::i#2<(byte) $28) goto printline::@2 -- vbuxx_lt_vbuc1_then_la1 + cpx #$28 bcc __b2 jmp __breturn // printline::@return __breturn: - // [6] return + // [7] return rts // printline::@2 __b2: - // [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 + // [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' -- pbuc1_derefidx_vbuxx=vbuc2 lda #'*' - ldy.z i - sta SCREEN,y - // [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 - inc.z i + sta SCREEN,x + // [9] (byte) printline::i#1 ← ++ (byte) printline::i#2 -- vbuxx=_inc_vbuxx + inx + // [5] phi from printline::@2 to printline::@1 [phi:printline::@2->printline::@1] + __b1_from___b2: + // [5] phi (byte) printline::i#2 = (byte) printline::i#1 [phi:printline::@2->printline::@1#0] -- register_copy jmp __b1 } // main main: { - // [9] (byte) val ← (byte) '-' -- vbuz1=vbuc1 + // [10] (byte) val ← (byte) '-' -- vbuz1=vbuc1 lda #'-' sta.z val - // [10] callexecute printline -- jsr + // [11] callexecute printline -- jsr jsr printline - // [11] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1 + // [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN+$50 jmp __breturn // main::@return __breturn: - // [12] return + // [13] return rts } // File Data @@ -318,7 +346,9 @@ Removing instruction __bend_from___b1: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction __b1: Removing instruction __bend: +Removing instruction __b1_from_printline: Removing instruction __breturn: +Removing instruction __b1_from___b2: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination Adding RTS to root block @@ -335,15 +365,17 @@ __stackcall (void()) printline() (label) printline::@1 (label) printline::@2 (label) printline::@return -(byte) printline::i loadstore zp[1]:3 11.5 +(byte) printline::i +(byte) printline::i#1 reg byte x 22.0 +(byte) printline::i#2 reg byte x 14.666666666666666 (byte) val loadstore zp[1]:2 3.0 +reg byte x [ printline::i#2 printline::i#1 ] zp[1]:2 [ val ] -zp[1]:3 [ printline::i ] FINAL ASSEMBLER -Score: 307 +Score: 232 // File Comments // Test a procedure with calling convention stack @@ -370,50 +402,48 @@ __bbegin: // @end // printline printline: { - .label i = 3 - // i=0 - // [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z i + // [5] phi from printline to printline::@1 [phi:printline->printline::@1] + // [5] phi (byte) printline::i#2 = (byte) 0 [phi:printline->printline::@1#0] -- vbuxx=vbuc1 + ldx #0 // printline::@1 __b1: // for(char i=0; i<40; i++) - // [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 - lda.z i - cmp #$28 + // [6] if((byte) printline::i#2<(byte) $28) goto printline::@2 -- vbuxx_lt_vbuc1_then_la1 + cpx #$28 bcc __b2 // printline::@return // } - // [6] return + // [7] return rts // printline::@2 __b2: // SCREEN[i] = '*' - // [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 + // [8] *((const byte*) SCREEN + (byte) printline::i#2) ← (byte) '*' -- pbuc1_derefidx_vbuxx=vbuc2 lda #'*' - ldy.z i - sta SCREEN,y + sta SCREEN,x // for(char i=0; i<40; i++) - // [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 - inc.z i + // [9] (byte) printline::i#1 ← ++ (byte) printline::i#2 -- vbuxx=_inc_vbuxx + inx + // [5] phi from printline::@2 to printline::@1 [phi:printline::@2->printline::@1] + // [5] phi (byte) printline::i#2 = (byte) printline::i#1 [phi:printline::@2->printline::@1#0] -- register_copy jmp __b1 } // main main: { // val = '-' - // [9] (byte) val ← (byte) '-' -- vbuz1=vbuc1 + // [10] (byte) val ← (byte) '-' -- vbuz1=vbuc1 lda #'-' sta.z val // printline() - // [10] callexecute printline -- jsr + // [11] callexecute printline -- jsr jsr printline // SCREEN[80] = val - // [11] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1 + // [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN+$50 // main::@return // } - // [12] return + // [13] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-8.sym b/src/test/ref/procedure-callingconvention-stack-8.sym index 967207a07..54c9c762a 100644 --- a/src/test/ref/procedure-callingconvention-stack-8.sym +++ b/src/test/ref/procedure-callingconvention-stack-8.sym @@ -8,8 +8,10 @@ __stackcall (void()) printline() (label) printline::@1 (label) printline::@2 (label) printline::@return -(byte) printline::i loadstore zp[1]:3 11.5 +(byte) printline::i +(byte) printline::i#1 reg byte x 22.0 +(byte) printline::i#2 reg byte x 14.666666666666666 (byte) val loadstore zp[1]:2 3.0 +reg byte x [ printline::i#2 printline::i#1 ] zp[1]:2 [ val ] -zp[1]:3 [ printline::i ] diff --git a/src/test/ref/procedure-callingconvention-stack-9.asm b/src/test/ref/procedure-callingconvention-stack-9.asm index ea15d46ad..cc308fd3d 100644 --- a/src/test/ref/procedure-callingconvention-stack-9.asm +++ b/src/test/ref/procedure-callingconvention-stack-9.asm @@ -12,18 +12,13 @@ __bbegin: jsr main rts printother: { - .label i = 3 - // for(char i:0..5) - lda #0 - sta.z i + ldx #0 __b1: // (SCREEN+40)[i]++; - ldx.z i inc SCREEN+$28,x // for(char i:0..5) - inc.z i - lda #6 - cmp.z i + inx + cpx #6 bne __b1 // } rts @@ -54,10 +49,7 @@ pval: { rts } main: { - .label i = 4 - // for(char i:0..5) - lda #0 - sta.z i + ldy #0 __b1: // pval() jsr pval @@ -66,9 +58,8 @@ main: { // ival() jsr ival // for(char i:0..5) - inc.z i - lda #6 - cmp.z i + iny + cpy #6 bne __b1 // } rts diff --git a/src/test/ref/procedure-callingconvention-stack-9.cfg b/src/test/ref/procedure-callingconvention-stack-9.cfg index ea6c94b20..32a46933f 100644 --- a/src/test/ref/procedure-callingconvention-stack-9.cfg +++ b/src/test/ref/procedure-callingconvention-stack-9.cfg @@ -10,63 +10,64 @@ __stackcall (void()) printother() printother: scope:[printother] from - [4] (byte) printother::i ← (byte) 0 + [4] phi() to:printother::@1 printother::@1: scope:[printother] from printother printother::@1 - [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) - [6] (byte) printother::i ← ++ (byte) printother::i - [7] if((byte) printother::i!=(byte) 6) goto printother::@1 + [5] (byte) printother::i#2 ← phi( printother/(byte) 0 printother::@1/(byte) printother::i#1 ) + [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i#2) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i#2) + [7] (byte) printother::i#1 ← ++ (byte) printother::i#2 + [8] if((byte) printother::i#1!=(byte) 6) goto printother::@1 to:printother::@return printother::@return: scope:[printother] from printother::@1 - [8] return + [9] return to:@return __stackcall (void()) incval() incval: scope:[incval] from - [9] (byte) val ← ++ (byte) val + [10] (byte) val ← ++ (byte) val to:incval::@return incval::@return: scope:[incval] from incval - [10] return + [11] return to:@return __stackcall (void()) printval() printval: scope:[printval] from - [11] *((const byte*) SCREEN) ← (byte) val + [12] *((const byte*) SCREEN) ← (byte) val to:printval::@return printval::@return: scope:[printval] from printval - [12] return + [13] return to:@return __stackcall (void()) ival() ival: scope:[ival] from - [13] phi() - [14] callexecute incval + [14] phi() + [15] callexecute incval to:ival::@return ival::@return: scope:[ival] from ival - [15] return + [16] return to:@return __stackcall (void()) pval() pval: scope:[pval] from - [16] phi() - [17] callexecute printval + [17] phi() + [18] callexecute printval to:pval::@return pval::@return: scope:[pval] from pval - [18] return + [19] return to:@return __stackcall (void()) main() main: scope:[main] from - [19] (byte) main::i ← (byte) 0 + [20] phi() to:main::@1 main::@1: scope:[main] from main main::@1 - [20] phi() - [21] callexecute pval - [22] callexecute printother - [23] callexecute ival - [24] (byte) main::i ← ++ (byte) main::i - [25] if((byte) main::i!=(byte) 6) goto main::@1 + [21] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 ) + [22] callexecute pval + [23] callexecute printother + [24] callexecute ival + [25] (byte) main::i#1 ← ++ (byte) main::i#2 + [26] if((byte) main::i#1!=(byte) 6) goto main::@1 to:main::@return main::@return: scope:[main] from main::@1 - [26] return + [27] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-9.log b/src/test/ref/procedure-callingconvention-stack-9.log index 29222644f..ae8b97b56 100644 --- a/src/test/ref/procedure-callingconvention-stack-9.log +++ b/src/test/ref/procedure-callingconvention-stack-9.log @@ -5,6 +5,7 @@ Culled Empty Block (label) @3 Culled Empty Block (label) @4 Culled Empty Block (label) @5 Culled Empty Block (label) printother::@2 +Converting PHI-variable modified inside __stackcall procedure main() to load/store (byte) val Calling convention STACK_CALL adding prepare/execute/finalize for call pval Calling convention STACK_CALL adding prepare/execute/finalize for call printother Calling convention STACK_CALL adding prepare/execute/finalize for call ival @@ -19,14 +20,15 @@ CONTROL FLOW GRAPH SSA __stackcall (void()) main() main: scope:[main] from - (byte) main::i ← (byte) 0 + (byte) main::i#0 ← (byte) 0 to:main::@1 main::@1: scope:[main] from main main::@1 + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) callexecute pval callexecute printother callexecute ival - (byte) main::i ← (byte) main::i + rangenext(0,5) - (bool~) main::$3 ← (byte) main::i != rangelast(0,5) + (byte) main::i#1 ← (byte) main::i#2 + rangenext(0,5) + (bool~) main::$3 ← (byte) main::i#1 != rangelast(0,5) if((bool~) main::$3) goto main::@1 to:main::@return main::@return: scope:[main] from main::@1 @@ -67,12 +69,13 @@ incval::@return: scope:[incval] from incval __stackcall (void()) printother() printother: scope:[printother] from - (byte) printother::i ← (byte) 0 + (byte) printother::i#0 ← (byte) 0 to:printother::@1 printother::@1: scope:[printother] from printother printother::@1 - *((const byte*) SCREEN+(number) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(number) $28 + (byte) printother::i) - (byte) printother::i ← (byte) printother::i + rangenext(0,5) - (bool~) printother::$1 ← (byte) printother::i != rangelast(0,5) + (byte) printother::i#2 ← phi( printother/(byte) printother::i#0 printother::@1/(byte) printother::i#1 ) + *((const byte*) SCREEN+(number) $28 + (byte) printother::i#2) ← ++ *((const byte*) SCREEN+(number) $28 + (byte) printother::i#2) + (byte) printother::i#1 ← (byte) printother::i#2 + rangenext(0,5) + (bool~) printother::$1 ← (byte) printother::i#1 != rangelast(0,5) if((bool~) printother::$1) goto printother::@1 to:printother::@return printother::@return: scope:[printother] from printother::@1 @@ -96,12 +99,18 @@ __stackcall (void()) main() (bool~) main::$3 (label) main::@1 (label) main::@return -(byte) main::i loadstore +(byte) main::i +(byte) main::i#0 +(byte) main::i#1 +(byte) main::i#2 __stackcall (void()) printother() (bool~) printother::$1 (label) printother::@1 (label) printother::@return -(byte) printother::i loadstore +(byte) printother::i +(byte) printother::i#0 +(byte) printother::i#1 +(byte) printother::i#2 __stackcall (void()) printval() (label) printval::@return __stackcall (void()) pval() @@ -109,7 +118,7 @@ __stackcall (void()) pval() (byte) val loadstore Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← (byte) val -Adding number conversion cast (unumber) $28 in *((const byte*) SCREEN+(number) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(number) $28 + (byte) printother::i) +Adding number conversion cast (unumber) $28 in *((const byte*) SCREEN+(number) $28 + (byte) printother::i#2) ← ++ *((const byte*) SCREEN+(number) $28 + (byte) printother::i#2) Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant pointer cast (byte*) 1024 Simplifying constant integer cast 0 @@ -118,17 +127,20 @@ Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) $28 Successful SSA optimization PassNFinalizeNumberTypeConversions -Simple Condition (bool~) main::$3 [7] if((byte) main::i!=rangelast(0,5)) goto main::@1 -Simple Condition (bool~) printother::$1 [21] if((byte) printother::i!=rangelast(0,5)) goto printother::@1 +Simple Condition (bool~) main::$3 [8] if((byte) main::i#1!=rangelast(0,5)) goto main::@1 +Simple Condition (bool~) printother::$1 [23] if((byte) printother::i#1!=rangelast(0,5)) goto printother::@1 Successful SSA optimization Pass2ConditionalJumpSimplification -Resolved ranged next value [5] main::i ← ++ main::i to ++ -Resolved ranged comparison value [7] if(main::i!=rangelast(0,5)) goto main::@1 to (number) 6 -Resolved ranged next value [19] printother::i ← ++ printother::i to ++ -Resolved ranged comparison value [21] if(printother::i!=rangelast(0,5)) goto printother::@1 to (number) 6 -Simplifying expression containing zero SCREEN in [13] *((const byte*) SCREEN + (byte) 0) ← (byte) val +Constant (const byte) main::i#0 = 0 +Constant (const byte) printother::i#0 = 0 +Successful SSA optimization Pass2ConstantIdentification +Resolved ranged next value [6] main::i#1 ← ++ main::i#2 to ++ +Resolved ranged comparison value [8] if(main::i#1!=rangelast(0,5)) goto main::@1 to (number) 6 +Resolved ranged next value [21] printother::i#1 ← ++ printother::i#2 to ++ +Resolved ranged comparison value [23] if(printother::i#1!=rangelast(0,5)) goto printother::@1 to (number) 6 +Simplifying expression containing zero SCREEN in [14] *((const byte*) SCREEN + (byte) 0) ← (byte) val Successful SSA optimization PassNSimplifyExpressionWithZero -Adding number conversion cast (unumber) 6 in if((byte) main::i!=(number) 6) goto main::@1 -Adding number conversion cast (unumber) 6 in if((byte) printother::i!=(number) 6) goto printother::@1 +Adding number conversion cast (unumber) 6 in if((byte) main::i#1!=(number) 6) goto main::@1 +Adding number conversion cast (unumber) 6 in if((byte) printother::i#1!=(number) 6) goto printother::@1 Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant integer cast 6 Simplifying constant integer cast 6 @@ -136,25 +148,38 @@ Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 6 Finalized unsigned number type (byte) 6 Successful SSA optimization PassNFinalizeNumberTypeConversions +Inlining constant with var siblings (const byte) main::i#0 +Inlining constant with var siblings (const byte) printother::i#0 +Constant inlined main::i#0 = (byte) 0 +Constant inlined printother::i#0 = (byte) 0 +Successful SSA optimization Pass2ConstantInlining +Added new block during phi lifting main::@3(between main::@1 and main::@1) +Added new block during phi lifting printother::@3(between printother::@1 and printother::@1) Adding NOP phi() at start of @6 Adding NOP phi() at start of @end +Adding NOP phi() at start of printother Adding NOP phi() at start of ival Adding NOP phi() at start of pval -Adding NOP phi() at start of main::@1 +Adding NOP phi() at start of main CALL GRAPH Calls in [] to main:2 -Calls in [ival] to incval:14 -Calls in [pval] to printval:17 -Calls in [main] to pval:21 printother:22 ival:23 +Calls in [ival] to incval:16 +Calls in [pval] to printval:19 +Calls in [main] to pval:23 printother:24 ival:25 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes +Created 2 initial phi equivalence classes +Coalesced [10] printother::i#3 ← printother::i#1 +Coalesced [29] main::i#3 ← main::i#1 +Coalesced down to 2 phi equivalence classes +Culled Empty Block (label) printother::@3 +Culled Empty Block (label) main::@3 Renumbering block @6 to @1 Adding NOP phi() at start of @1 Adding NOP phi() at start of @end +Adding NOP phi() at start of printother Adding NOP phi() at start of ival Adding NOP phi() at start of pval -Adding NOP phi() at start of main::@1 +Adding NOP phi() at start of main FINAL CONTROL FLOW GRAPH @begin: scope:[] from @@ -169,65 +194,66 @@ FINAL CONTROL FLOW GRAPH __stackcall (void()) printother() printother: scope:[printother] from - [4] (byte) printother::i ← (byte) 0 + [4] phi() to:printother::@1 printother::@1: scope:[printother] from printother printother::@1 - [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) - [6] (byte) printother::i ← ++ (byte) printother::i - [7] if((byte) printother::i!=(byte) 6) goto printother::@1 + [5] (byte) printother::i#2 ← phi( printother/(byte) 0 printother::@1/(byte) printother::i#1 ) + [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i#2) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i#2) + [7] (byte) printother::i#1 ← ++ (byte) printother::i#2 + [8] if((byte) printother::i#1!=(byte) 6) goto printother::@1 to:printother::@return printother::@return: scope:[printother] from printother::@1 - [8] return + [9] return to:@return __stackcall (void()) incval() incval: scope:[incval] from - [9] (byte) val ← ++ (byte) val + [10] (byte) val ← ++ (byte) val to:incval::@return incval::@return: scope:[incval] from incval - [10] return + [11] return to:@return __stackcall (void()) printval() printval: scope:[printval] from - [11] *((const byte*) SCREEN) ← (byte) val + [12] *((const byte*) SCREEN) ← (byte) val to:printval::@return printval::@return: scope:[printval] from printval - [12] return + [13] return to:@return __stackcall (void()) ival() ival: scope:[ival] from - [13] phi() - [14] callexecute incval + [14] phi() + [15] callexecute incval to:ival::@return ival::@return: scope:[ival] from ival - [15] return + [16] return to:@return __stackcall (void()) pval() pval: scope:[pval] from - [16] phi() - [17] callexecute printval + [17] phi() + [18] callexecute printval to:pval::@return pval::@return: scope:[pval] from pval - [18] return + [19] return to:@return __stackcall (void()) main() main: scope:[main] from - [19] (byte) main::i ← (byte) 0 + [20] phi() to:main::@1 main::@1: scope:[main] from main main::@1 - [20] phi() - [21] callexecute pval - [22] callexecute printother - [23] callexecute ival - [24] (byte) main::i ← ++ (byte) main::i - [25] if((byte) main::i!=(byte) 6) goto main::@1 + [21] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 ) + [22] callexecute pval + [23] callexecute printother + [24] callexecute ival + [25] (byte) main::i#1 ← ++ (byte) main::i#2 + [26] if((byte) main::i#1!=(byte) 6) goto main::@1 to:main::@return main::@return: scope:[main] from main::@1 - [26] return + [27] return to:@return null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope printother @@ -240,24 +266,28 @@ VARIABLE REGISTER WEIGHTS __stackcall (void()) incval() __stackcall (void()) ival() __stackcall (void()) main() -(byte) main::i loadstore 5.0 +(byte) main::i +(byte) main::i#1 16.5 +(byte) main::i#2 5.5 __stackcall (void()) printother() -(byte) printother::i loadstore 14.25 +(byte) printother::i +(byte) printother::i#1 16.5 +(byte) printother::i#2 22.0 __stackcall (void()) printval() __stackcall (void()) pval() (byte) val loadstore 0.42105263157894735 Initial phi equivalence classes +[ printother::i#2 printother::i#1 ] +[ main::i#2 main::i#1 ] Added variable val to live range equivalence class [ val ] -Added variable printother::i to live range equivalence class [ printother::i ] -Added variable main::i to live range equivalence class [ main::i ] Complete equivalence classes +[ printother::i#2 printother::i#1 ] +[ main::i#2 main::i#1 ] [ val ] -[ printother::i ] -[ main::i ] -Allocated zp[1]:2 [ val ] -Allocated zp[1]:3 [ printother::i ] -Allocated zp[1]:4 [ main::i ] +Allocated zp[1]:2 [ printother::i#2 printother::i#1 ] +Allocated zp[1]:3 [ main::i#2 main::i#1 ] +Allocated zp[1]:4 [ val ] INITIAL ASM Target platform is c64basic / MOS6502X @@ -270,7 +300,7 @@ Target platform is c64basic / MOS6502X .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 - .label val = 2 + .label val = 4 // @begin __bbegin: // [0] (byte) val ← (byte) 0 -- vbuz1=vbuc1 @@ -290,135 +320,139 @@ __bend_from___b1: __bend: // printother printother: { - .label i = 3 - // [4] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1 + .label i = 2 + // [5] phi from printother to printother::@1 [phi:printother->printother::@1] + __b1_from_printother: + // [5] phi (byte) printother::i#2 = (byte) 0 [phi:printother->printother::@1#0] -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 + // [5] phi from printother::@1 to printother::@1 [phi:printother::@1->printother::@1] + __b1_from___b1: + // [5] phi (byte) printother::i#2 = (byte) printother::i#1 [phi:printother::@1->printother::@1#0] -- register_copy + jmp __b1 // printother::@1 __b1: - // [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1 + // [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i#2) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i#2) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1 ldx.z i inc SCREEN+$28,x - // [6] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1 + // [7] (byte) printother::i#1 ← ++ (byte) printother::i#2 -- vbuz1=_inc_vbuz1 inc.z i - // [7] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1 + // [8] if((byte) printother::i#1!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1 lda #6 cmp.z i - bne __b1 + bne __b1_from___b1 jmp __breturn // printother::@return __breturn: - // [8] return + // [9] return rts } // incval incval: { - // [9] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1 + // [10] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1 inc.z val jmp __breturn // incval::@return __breturn: - // [10] return + // [11] return rts } // printval printval: { - // [11] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1 + // [12] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN jmp __breturn // printval::@return __breturn: - // [12] return + // [13] return rts } // ival ival: { - // [14] callexecute incval -- jsr + // [15] callexecute incval -- jsr jsr incval jmp __breturn // ival::@return __breturn: - // [15] return + // [16] return rts } // pval pval: { - // [17] callexecute printval -- jsr + // [18] callexecute printval -- jsr jsr printval jmp __breturn // pval::@return __breturn: - // [18] return + // [19] return rts } // main main: { - .label i = 4 - // [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + .label i = 3 + // [21] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [21] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 lda #0 sta.z i - // [20] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1] - __b1_from_main: + jmp __b1 + // [21] phi from main::@1 to main::@1 [phi:main::@1->main::@1] __b1_from___b1: + // [21] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy jmp __b1 // main::@1 __b1: - // [21] callexecute pval -- jsr + // [22] callexecute pval -- jsr jsr pval - // [22] callexecute printother -- jsr + // [23] callexecute printother -- jsr jsr printother - // [23] callexecute ival -- jsr + // [24] callexecute ival -- jsr jsr ival - // [24] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [25] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 inc.z i - // [25] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + // [26] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 lda #6 cmp.z i bne __b1_from___b1 jmp __breturn // main::@return __breturn: - // [26] return + // [27] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [0] (byte) val ← (byte) 0 [ val ] ( [ val ] ) always clobbers reg byte a -Statement [4] (byte) printother::i ← (byte) 0 [ printother::i ] ( main:2::printother:22 [ val main::i printother::i ] ) always clobbers reg byte a -Statement [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) [ printother::i ] ( main:2::printother:22 [ val main::i printother::i ] ) always clobbers reg byte x -Statement [7] if((byte) printother::i!=(byte) 6) goto printother::@1 [ printother::i ] ( main:2::printother:22 [ val main::i printother::i ] ) always clobbers reg byte a -Statement [11] *((const byte*) SCREEN) ← (byte) val [ val ] ( main:2::pval:21::printval:17 [ main::i val ] ) always clobbers reg byte a -Statement [19] (byte) main::i ← (byte) 0 [ val main::i ] ( main:2 [ val main::i ] ) always clobbers reg byte a -Statement [25] if((byte) main::i!=(byte) 6) goto main::@1 [ val main::i ] ( main:2 [ val main::i ] ) always clobbers reg byte a -Potential registers zp[1]:2 [ val ] : zp[1]:2 , -Potential registers zp[1]:3 [ printother::i ] : zp[1]:3 , -Potential registers zp[1]:4 [ main::i ] : zp[1]:4 , +Statement [12] *((const byte*) SCREEN) ← (byte) val [ val ] ( main:2::pval:22::printval:18 [ main::i#2 val ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::i#2 main::i#1 ] +Statement [0] (byte) val ← (byte) 0 [ val ] ( [ val ] ) always clobbers reg byte a +Statement [12] *((const byte*) SCREEN) ← (byte) val [ val ] ( main:2::pval:22::printval:18 [ main::i#2 val ] ) always clobbers reg byte a +Potential registers zp[1]:2 [ printother::i#2 printother::i#1 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ main::i#2 main::i#1 ] : zp[1]:3 , reg byte x , reg byte y , +Potential registers zp[1]:4 [ val ] : zp[1]:4 , REGISTER UPLIFT SCOPES -Uplift Scope [printother] 14.25: zp[1]:3 [ printother::i ] -Uplift Scope [main] 5: zp[1]:4 [ main::i ] -Uplift Scope [] 0.42: zp[1]:2 [ val ] +Uplift Scope [printother] 38.5: zp[1]:2 [ printother::i#2 printother::i#1 ] +Uplift Scope [main] 22: zp[1]:3 [ main::i#2 main::i#1 ] +Uplift Scope [] 0.42: zp[1]:4 [ val ] Uplift Scope [pval] Uplift Scope [ival] Uplift Scope [printval] Uplift Scope [incval] -Uplifting [printother] best 722 combination zp[1]:3 [ printother::i ] -Uplifting [main] best 722 combination zp[1]:4 [ main::i ] -Uplifting [] best 722 combination zp[1]:2 [ val ] -Uplifting [pval] best 722 combination -Uplifting [ival] best 722 combination -Uplifting [printval] best 722 combination -Uplifting [incval] best 722 combination -Attempting to uplift remaining variables inzp[1]:3 [ printother::i ] -Uplifting [printother] best 722 combination zp[1]:3 [ printother::i ] -Attempting to uplift remaining variables inzp[1]:4 [ main::i ] -Uplifting [main] best 722 combination zp[1]:4 [ main::i ] -Attempting to uplift remaining variables inzp[1]:2 [ val ] -Uplifting [] best 722 combination zp[1]:2 [ val ] +Uplifting [printother] best 779 combination reg byte x [ printother::i#2 printother::i#1 ] +Uplifting [main] best 689 combination reg byte y [ main::i#2 main::i#1 ] +Uplifting [] best 689 combination zp[1]:4 [ val ] +Uplifting [pval] best 689 combination +Uplifting [ival] best 689 combination +Uplifting [printval] best 689 combination +Uplifting [incval] best 689 combination +Attempting to uplift remaining variables inzp[1]:4 [ val ] +Uplifting [] best 689 combination zp[1]:4 [ val ] +Allocated (was zp[1]:4) zp[1]:2 [ val ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -450,97 +484,99 @@ __bend_from___b1: __bend: // printother printother: { - .label i = 3 - // [4] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z i + // [5] phi from printother to printother::@1 [phi:printother->printother::@1] + __b1_from_printother: + // [5] phi (byte) printother::i#2 = (byte) 0 [phi:printother->printother::@1#0] -- vbuxx=vbuc1 + ldx #0 + jmp __b1 + // [5] phi from printother::@1 to printother::@1 [phi:printother::@1->printother::@1] + __b1_from___b1: + // [5] phi (byte) printother::i#2 = (byte) printother::i#1 [phi:printother::@1->printother::@1#0] -- register_copy jmp __b1 // printother::@1 __b1: - // [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1 - ldx.z i + // [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i#2) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i#2) -- pbuc1_derefidx_vbuxx=_inc_pbuc1_derefidx_vbuxx inc SCREEN+$28,x - // [6] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1 - inc.z i - // [7] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1 - lda #6 - cmp.z i - bne __b1 + // [7] (byte) printother::i#1 ← ++ (byte) printother::i#2 -- vbuxx=_inc_vbuxx + inx + // [8] if((byte) printother::i#1!=(byte) 6) goto printother::@1 -- vbuxx_neq_vbuc1_then_la1 + cpx #6 + bne __b1_from___b1 jmp __breturn // printother::@return __breturn: - // [8] return + // [9] return rts } // incval incval: { - // [9] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1 + // [10] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1 inc.z val jmp __breturn // incval::@return __breturn: - // [10] return + // [11] return rts } // printval printval: { - // [11] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1 + // [12] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN jmp __breturn // printval::@return __breturn: - // [12] return + // [13] return rts } // ival ival: { - // [14] callexecute incval -- jsr + // [15] callexecute incval -- jsr jsr incval jmp __breturn // ival::@return __breturn: - // [15] return + // [16] return rts } // pval pval: { - // [17] callexecute printval -- jsr + // [18] callexecute printval -- jsr jsr printval jmp __breturn // pval::@return __breturn: - // [18] return + // [19] return rts } // main main: { - .label i = 4 - // [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z i - // [20] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1] + // [21] phi from main to main::@1 [phi:main->main::@1] __b1_from_main: + // [21] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuyy=vbuc1 + ldy #0 + jmp __b1 + // [21] phi from main::@1 to main::@1 [phi:main::@1->main::@1] __b1_from___b1: + // [21] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy jmp __b1 // main::@1 __b1: - // [21] callexecute pval -- jsr + // [22] callexecute pval -- jsr jsr pval - // [22] callexecute printother -- jsr + // [23] callexecute printother -- jsr jsr printother - // [23] callexecute ival -- jsr + // [24] callexecute ival -- jsr jsr ival - // [24] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 - inc.z i - // [25] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 - lda #6 - cmp.z i + // [25] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuyy=_inc_vbuyy + iny + // [26] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuyy_neq_vbuc1_then_la1 + cpy #6 bne __b1_from___b1 jmp __breturn // main::@return __breturn: - // [26] return + // [27] return rts } // File Data @@ -558,22 +594,28 @@ Removing instruction jmp __b1 Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Replacing label __b1_from___b1 with __b1 +Replacing label __b1_from___b1 with __b1 Removing instruction __b1_from___bbegin: Removing instruction __bend_from___b1: -Removing instruction __b1_from_main: +Removing instruction __b1_from___b1: Removing instruction __b1_from___b1: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction __b1: Removing instruction __bend: +Removing instruction __b1_from_printother: Removing instruction __breturn: Removing instruction __breturn: Removing instruction __breturn: Removing instruction __breturn: Removing instruction __breturn: +Removing instruction __b1_from_main: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination Adding RTS to root block Succesful ASM optimization Pass5AddMainRts +Removing instruction jmp __b1 +Removing instruction jmp __b1 +Succesful ASM optimization Pass5NextJumpElimination FINAL SYMBOL TABLE (label) @1 @@ -587,24 +629,28 @@ __stackcall (void()) ival() __stackcall (void()) main() (label) main::@1 (label) main::@return -(byte) main::i loadstore zp[1]:4 5.0 +(byte) main::i +(byte) main::i#1 reg byte y 16.5 +(byte) main::i#2 reg byte y 5.5 __stackcall (void()) printother() (label) printother::@1 (label) printother::@return -(byte) printother::i loadstore zp[1]:3 14.25 +(byte) printother::i +(byte) printother::i#1 reg byte x 16.5 +(byte) printother::i#2 reg byte x 22.0 __stackcall (void()) printval() (label) printval::@return __stackcall (void()) pval() (label) pval::@return (byte) val loadstore zp[1]:2 0.42105263157894735 +reg byte x [ printother::i#2 printother::i#1 ] +reg byte y [ main::i#2 main::i#1 ] zp[1]:2 [ val ] -zp[1]:3 [ printother::i ] -zp[1]:4 [ main::i ] FINAL ASSEMBLER -Score: 617 +Score: 497 // File Comments // Test a procedure with calling convention stack @@ -631,99 +677,95 @@ __bbegin: // @end // printother printother: { - .label i = 3 - // for(char i:0..5) - // [4] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z i + // [5] phi from printother to printother::@1 [phi:printother->printother::@1] + // [5] phi (byte) printother::i#2 = (byte) 0 [phi:printother->printother::@1#0] -- vbuxx=vbuc1 + ldx #0 + // [5] phi from printother::@1 to printother::@1 [phi:printother::@1->printother::@1] + // [5] phi (byte) printother::i#2 = (byte) printother::i#1 [phi:printother::@1->printother::@1#0] -- register_copy // printother::@1 __b1: // (SCREEN+40)[i]++; - // [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1 - ldx.z i + // [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i#2) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i#2) -- pbuc1_derefidx_vbuxx=_inc_pbuc1_derefidx_vbuxx inc SCREEN+$28,x // for(char i:0..5) - // [6] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1 - inc.z i - // [7] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1 - lda #6 - cmp.z i + // [7] (byte) printother::i#1 ← ++ (byte) printother::i#2 -- vbuxx=_inc_vbuxx + inx + // [8] if((byte) printother::i#1!=(byte) 6) goto printother::@1 -- vbuxx_neq_vbuc1_then_la1 + cpx #6 bne __b1 // printother::@return // } - // [8] return + // [9] return rts } // incval incval: { // val++; - // [9] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1 + // [10] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1 inc.z val // incval::@return // } - // [10] return + // [11] return rts } // printval printval: { // SCREEN[0] = val - // [11] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1 + // [12] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN // printval::@return // } - // [12] return + // [13] return rts } // ival ival: { // incval() - // [14] callexecute incval -- jsr + // [15] callexecute incval -- jsr jsr incval // ival::@return // } - // [15] return + // [16] return rts } // pval pval: { // printval() - // [17] callexecute printval -- jsr + // [18] callexecute printval -- jsr jsr printval // pval::@return // } - // [18] return + // [19] return rts } // main main: { - .label i = 4 - // for(char i:0..5) - // [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 - lda #0 - sta.z i - // [20] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1] + // [21] phi from main to main::@1 [phi:main->main::@1] + // [21] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuyy=vbuc1 + ldy #0 + // [21] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + // [21] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy // main::@1 __b1: // pval() - // [21] callexecute pval -- jsr + // [22] callexecute pval -- jsr jsr pval // printother() - // [22] callexecute printother -- jsr + // [23] callexecute printother -- jsr jsr printother // ival() - // [23] callexecute ival -- jsr + // [24] callexecute ival -- jsr jsr ival // for(char i:0..5) - // [24] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 - inc.z i - // [25] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 - lda #6 - cmp.z i + // [25] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuyy=_inc_vbuyy + iny + // [26] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuyy_neq_vbuc1_then_la1 + cpy #6 bne __b1 // main::@return // } - // [26] return + // [27] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-9.sym b/src/test/ref/procedure-callingconvention-stack-9.sym index a0d32093f..5a1dee45f 100644 --- a/src/test/ref/procedure-callingconvention-stack-9.sym +++ b/src/test/ref/procedure-callingconvention-stack-9.sym @@ -9,17 +9,21 @@ __stackcall (void()) ival() __stackcall (void()) main() (label) main::@1 (label) main::@return -(byte) main::i loadstore zp[1]:4 5.0 +(byte) main::i +(byte) main::i#1 reg byte y 16.5 +(byte) main::i#2 reg byte y 5.5 __stackcall (void()) printother() (label) printother::@1 (label) printother::@return -(byte) printother::i loadstore zp[1]:3 14.25 +(byte) printother::i +(byte) printother::i#1 reg byte x 16.5 +(byte) printother::i#2 reg byte x 22.0 __stackcall (void()) printval() (label) printval::@return __stackcall (void()) pval() (label) pval::@return (byte) val loadstore zp[1]:2 0.42105263157894735 +reg byte x [ printother::i#2 printother::i#1 ] +reg byte y [ main::i#2 main::i#1 ] zp[1]:2 [ val ] -zp[1]:3 [ printother::i ] -zp[1]:4 [ main::i ]