1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-04-05 07:40:39 +00:00

Global struct values are not per default load/store, main-memory.

This commit is contained in:
jespergravgaard 2020-01-12 22:53:57 +01:00
parent ffdc590b90
commit a32f783b74
32 changed files with 1248 additions and 1016 deletions

View File

@ -222,6 +222,10 @@ public class VariableBuilder {
* @return true if the variable is single-static-assignment
*/
public boolean isSingleStaticAssignment() {
if(hasDirective(Directive.FormSsa.class))
// the __ssa directive forces single-static-assignment
//TODO: FAIL if combined with __ma, __address() or volatile!
return true;
if(hasDirective(Directive.FormMa.class))
// the __ma directive forces multiple-assignment
return false;
@ -231,6 +235,9 @@ public class VariableBuilder {
else if(isVolatile())
// volatile variables must be load/store
return false;
else if(isTypeStruct() && isScopeGlobal())
// global struct variables must be load/store
return false;
else
// All others are single-static-assignment (by default)
return true;
@ -262,10 +269,6 @@ public class VariableBuilder {
public Variable.MemoryArea getMemoryArea() {
if(isConstant())
return Variable.MemoryArea.MAIN_MEMORY;
else if(!isConstant() && isOptimize())
return Variable.MemoryArea.ZEROPAGE_MEMORY;
else if(isArray())
return Variable.MemoryArea.MAIN_MEMORY;
else if(hasDirective(Directive.MemZp.class))
return Variable.MemoryArea.ZEROPAGE_MEMORY;
else if(hasDirective(Directive.MemMain.class))
@ -273,6 +276,12 @@ public class VariableBuilder {
Directive.Address addressDirective = findDirective(Directive.Address.class);
if(addressDirective != null)
return (addressDirective.address < 0x100) ? Variable.MemoryArea.ZEROPAGE_MEMORY : Variable.MemoryArea.MAIN_MEMORY;
else if(!isConstant() && isOptimize())
return Variable.MemoryArea.ZEROPAGE_MEMORY;
else if(isArray())
return Variable.MemoryArea.MAIN_MEMORY;
else if(isTypeStruct() && isScopeGlobal())
return Variable.MemoryArea.MAIN_MEMORY;
else
return Variable.MemoryArea.ZEROPAGE_MEMORY;
}

View File

@ -1127,9 +1127,14 @@ public class TestPrograms {
assertError("struct-err-0", "Unknown struct type");
}
@Test
public void testStruct34() throws IOException, URISyntaxException {
compileAndCompare("struct-34");
}
@Test
public void testStruct33() throws IOException, URISyntaxException {
compileAndCompare("struct-33", log());
compileAndCompare("struct-33");
}
@Test

View File

@ -1,5 +1,4 @@
// Example of a struct containing an array
// Works because the struct is only handled as a value
struct Person {
char id;

17
src/test/kc/struct-34.kc Normal file
View File

@ -0,0 +1,17 @@
// Struct - forced __ssa
struct Point {
char x;
char y;
};
__mem __ssa struct Point point;
const char* SCREEN = 0x0400;
void main() {
point.x = 2;
point.y = 3;
SCREEN[0] = point.x;
SCREEN[1] = point.y;
}

View File

@ -1,19 +1,13 @@
// Test parsing a negated struct reference - which causes problems with the ASMREL labels !a++
// https://gitlab.com/camelot/kickc/issues/266
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
.label aa_b = 2
__bbegin:
lda #1
sta.z aa_b
jsr main
rts
main: {
.label SCREEN = $400
.label a = aa_b
.label a = aa
lda #0
cmp.z a
cmp a
bne !a+
lda #'a'
sta SCREEN
@ -22,3 +16,4 @@ main: {
!a:
rts
}
aa: .byte 1

View File

@ -1,5 +1,5 @@
@begin: scope:[] from
[0] (byte) aa_b#0 ← (byte) 1
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()

View File

@ -1,15 +1,10 @@
Setting inferred volatile on symbol affected by address-of (struct A*) main::a ← &(struct A) aa
Created struct value member variable (byte) aa_b
Converted struct value to member variables (struct A) aa
Adding struct value member variable copy (byte) aa_b ← (byte) 1
Rewriting struct pointer member access *((struct A*) main::a).b
Warning! Adding boolean cast to non-boolean sub-expression *((byte*~) main::$2)
Identified constant variable (struct A*) main::a
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte) aa_b#0 ← (byte) 1
(struct A) aa#0 ← struct-unwound {(byte) aa_b#0}
to:@1
(void()) main()
@ -43,10 +38,7 @@ SYMBOL TABLE SSA
(label) @end
(byte) A::b
(const byte) OFFSET_STRUCT_A_B = (byte) 0
(struct A) aa
(struct A) aa#0
(byte) aa_b
(byte) aa_b#0
(struct A) aa loadstore = { b: (byte) 1 }
(void()) main()
(bool~) main::$0
(bool~) main::$1
@ -65,24 +57,22 @@ Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inversing boolean not [4] (bool~) main::$0 ← (byte) 0 == *((byte*~) main::$2) from [3] (bool~) main::$3 ← (byte) 0 != *((byte*~) main::$2)
Inversing boolean not [5] (bool~) main::$1 ← (byte) 0 != *((byte*~) main::$2) from [4] (bool~) main::$0 ← (byte) 0 == *((byte*~) main::$2)
Inversing boolean not [2] (bool~) main::$0 ← (byte) 0 == *((byte*~) main::$2) from [1] (bool~) main::$3 ← (byte) 0 != *((byte*~) main::$2)
Inversing boolean not [3] (bool~) main::$1 ← (byte) 0 != *((byte*~) main::$2) from [2] (bool~) main::$0 ← (byte) 0 == *((byte*~) main::$2)
Successful SSA optimization Pass2UnaryNotSimplification
Simple Condition (bool~) main::$1 [6] if((byte) 0!=*((byte*~) main::$2)) goto main::@1
Simple Condition (bool~) main::$1 [4] if((byte) 0!=*((byte*~) main::$2)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Rewriting struct address-of to first member &(struct A) aa
Successful SSA optimization PassNStructAddressOfRewriting
Constant right-side identified [2] (byte*~) main::$2 ← (byte*)(const struct A*) main::a + (const byte) OFFSET_STRUCT_A_B
Constant right-side identified [0] (byte*~) main::$2 ← (byte*)(const struct A*) main::a + (const byte) OFFSET_STRUCT_A_B
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) main::$2 = (byte*)main::a+OFFSET_STRUCT_A_B
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero (byte*)main::a in
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (struct A) aa#0 and assignment [1] (struct A) aa#0 ← struct-unwound {(byte) aa_b#0}
Eliminating unused constant (const byte) OFFSET_STRUCT_A_B
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$2 = (byte*)(const struct A*) main::a
Successful SSA optimization Pass2ConstantInlining
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
@ -92,12 +82,13 @@ Calls in [] to main:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] (byte) aa_b#0 ← (byte) 1
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
@ -123,15 +114,14 @@ main::@return: scope:[main] from main::@1
VARIABLE REGISTER WEIGHTS
(byte) A::b
(struct A) aa
(byte) aa_b
(byte) aa_b#0 20.0
(struct A) aa loadstore = { b: (byte) 1 }
(void()) main()
Initial phi equivalence classes
Added variable aa to live range equivalence class [ aa ]
Complete equivalence classes
[ aa_b#0 ]
Allocated zp[1]:2 [ aa_b#0 ]
[ aa ]
Allocated mem[1] [ aa ]
INITIAL ASM
Target platform is c64basic / MOS6502X
@ -143,12 +133,8 @@ Target platform is c64basic / MOS6502X
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label aa_b = 2
// @begin
__bbegin:
// [0] (byte) aa_b#0 ← (byte) 1 -- vbuz1=vbuc1
lda #1
sta.z aa_b
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -164,10 +150,10 @@ __bend:
// main
main: {
.label SCREEN = $400
.label a = aa_b
.label a = aa
// [4] if((byte) 0!=*((byte*)(const struct A*) main::a)) goto main::@1 -- vbuc1_neq__deref_pbuc2_then_la1
lda #0
cmp.z a
cmp a
bne __b1
jmp __b2
// main::@2
@ -189,23 +175,23 @@ main: {
rts
}
// File Data
aa: .byte 1
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (byte) aa_b#0 ← (byte) 1 [ ] ( [ ] ) always clobbers reg byte a
Statement [4] if((byte) 0!=*((byte*)(const struct A*) main::a)) goto main::@1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN) ← (byte) 'a' [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers zp[1]:2 [ aa_b#0 ] : zp[1]:2 ,
Potential registers mem[1] [ aa ] : mem[1] ,
REGISTER UPLIFT SCOPES
Uplift Scope [] 20: zp[1]:2 [ aa_b#0 ]
Uplift Scope [A]
Uplift Scope [main]
Uplift Scope [] 0: mem[1] [ aa ]
Uplifting [] best 48 combination zp[1]:2 [ aa_b#0 ]
Uplifting [A] best 48 combination
Uplifting [main] best 48 combination
Attempting to uplift remaining variables inzp[1]:2 [ aa_b#0 ]
Uplifting [] best 48 combination zp[1]:2 [ aa_b#0 ]
Uplifting [A] best 44 combination
Uplifting [main] best 44 combination
Uplifting [] best 44 combination mem[1] [ aa ]
Attempting to uplift remaining variables inmem[1] [ aa ]
Uplifting [] best 44 combination mem[1] [ aa ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -216,12 +202,8 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label aa_b = 2
// @begin
__bbegin:
// [0] (byte) aa_b#0 ← (byte) 1 -- vbuz1=vbuc1
lda #1
sta.z aa_b
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -237,10 +219,10 @@ __bend:
// main
main: {
.label SCREEN = $400
.label a = aa_b
.label a = aa
// [4] if((byte) 0!=*((byte*)(const struct A*) main::a)) goto main::@1 -- vbuc1_neq__deref_pbuc2_then_la1
lda #0
cmp.z a
cmp a
bne __b1
jmp __b2
// main::@2
@ -262,6 +244,7 @@ main: {
rts
}
// File Data
aa: .byte 1
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
@ -270,18 +253,21 @@ Removing instruction jmp __b2
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
Removing instruction __bend:
Removing instruction __b2:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Skipping double jump to !a+ in bne __b1
Succesful ASM optimization Pass5DoubleJumpElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
Removing instruction __b1:
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
@ -290,52 +276,42 @@ FINAL SYMBOL TABLE
(label) @begin
(label) @end
(byte) A::b
(struct A) aa
(byte) aa_b
(byte) aa_b#0 aa_b zp[1]:2 20.0
(struct A) aa loadstore mem[1] = { b: (byte) 1 }
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(const struct A*) main::a = (struct A*)&(byte) aa_b#0
(const struct A*) main::a = &(struct A) aa
zp[1]:2 [ aa_b#0 ]
mem[1] [ aa ]
FINAL ASSEMBLER
Score: 39
Score: 23
// File Comments
// Test parsing a negated struct reference - which causes problems with the ASMREL labels !a++
// https://gitlab.com/camelot/kickc/issues/266
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label aa_b = 2
// @begin
__bbegin:
// aa = { 1 }
// [0] (byte) aa_b#0 ← (byte) 1 -- vbuz1=vbuc1
lda #1
sta.z aa_b
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
jsr main
rts
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label SCREEN = $400
.label a = aa_b
.label a = aa
// if(!a->b)
// [4] if((byte) 0!=*((byte*)(const struct A*) main::a)) goto main::@1 -- vbuc1_neq__deref_pbuc2_then_la1
lda #0
cmp.z a
cmp a
bne !a+
// main::@2
// *SCREEN = 'a'
@ -354,4 +330,5 @@ main: {
rts
}
// File Data
aa: .byte 1

View File

@ -2,14 +2,12 @@
(label) @begin
(label) @end
(byte) A::b
(struct A) aa
(byte) aa_b
(byte) aa_b#0 aa_b zp[1]:2 20.0
(struct A) aa loadstore mem[1] = { b: (byte) 1 }
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(const struct A*) main::a = (struct A*)&(byte) aa_b#0
(const struct A*) main::a = &(struct A) aa
zp[1]:2 [ aa_b#0 ]
mem[1] [ aa ]

View File

@ -2,13 +2,18 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const point_x = 2
.const point_y = 3
.const OFFSET_STRUCT_POINT_Y = 1
.const SIZEOF_STRUCT_POINT = 2
main: {
.label SCREEN = $400
lda #point_x
lda #2
sta point
lda #3
sta point+OFFSET_STRUCT_POINT_Y
lda point
sta SCREEN
lda #point_y
lda point+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
rts
}
point: .fill SIZEOF_STRUCT_POINT, 0

View File

@ -10,9 +10,11 @@
(void()) main()
main: scope:[main] from @1
[4] *((const byte*) main::SCREEN) ← (const byte) point_x#1
[5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point_y#1
[4] *((byte*)&(struct Point) point) ← (byte) 2
[5] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point)
[7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[6] return
[8] return
to:@return

View File

@ -1,43 +1,26 @@
Created struct value member variable (byte) point_x
Created struct value member variable (byte) point_y
Converted struct value to member variables (struct Point) point
Adding struct value member variable copy (byte) point_x ← (byte) 0
Adding struct value member variable copy (byte) point_y ← (byte) 0
Replacing struct member reference (struct Point) point.x with member unwinding reference (byte) point_x
Replacing struct member reference (struct Point) point.y with member unwinding reference (byte) point_y
Replacing struct member reference (struct Point) point.x with member unwinding reference (byte) point_x
Replacing struct member reference (struct Point) point.y with member unwinding reference (byte) point_y
Replacing struct member reference (struct Point) point.x with member unwinding reference *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point.y with member unwinding reference *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y)
Replacing struct member reference (struct Point) point.x with member unwinding reference *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point.y with member unwinding reference *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y)
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte) point_x#0 ← (byte) 0
(byte) point_y#0 ← (byte) 0
to:@1
(void()) main()
main: scope:[main] from @1
(byte) point_x#1 ← (number) 2
(byte) point_y#1 ← (number) 3
*((const byte*) main::SCREEN + (number) 0) ← (byte) point_x#1
*((const byte*) main::SCREEN + (number) 1) ← (byte) point_y#1
*((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 2
*((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (number) 3
*((const byte*) main::SCREEN + (number) 0) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X)
*((const byte*) main::SCREEN + (number) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
(byte) point_y#4 ← phi( main/(byte) point_y#1 )
(byte) point_x#4 ← phi( main/(byte) point_x#1 )
(byte) point_x#2 ← (byte) point_x#4
(byte) point_y#2 ← (byte) point_y#4
return
to:@return
@1: scope:[] from @begin
(byte) point_y#6 ← phi( @begin/(byte) point_y#0 )
(byte) point_x#6 ← phi( @begin/(byte) point_x#0 )
call main
to:@2
@2: scope:[] from @1
(byte) point_y#5 ← phi( @1/(byte) point_y#2 )
(byte) point_x#5 ← phi( @1/(byte) point_x#2 )
(byte) point_x#3 ← (byte) point_x#5
(byte) point_y#3 ← (byte) point_y#5
to:@end
@end: scope:[] from @2
@ -46,35 +29,22 @@ SYMBOL TABLE SSA
(label) @2
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*)(number) $400
(byte) point_x
(byte) point_x#0
(byte) point_x#1
(byte) point_x#2
(byte) point_x#3
(byte) point_x#4
(byte) point_x#5
(byte) point_x#6
(byte) point_y
(byte) point_y#0
(byte) point_y#1
(byte) point_y#2
(byte) point_y#3
(byte) point_y#4
(byte) point_y#5
(byte) point_y#6
(struct Point) point loadstore = {}
Adding number conversion cast (unumber) 2 in (byte) point_x#1 ← (number) 2
Adding number conversion cast (unumber) 3 in (byte) point_y#1 ← (number) 3
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← (byte) point_x#1
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← (byte) point_y#1
Adding number conversion cast (unumber) 2 in *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 2
Adding number conversion cast (unumber) 3 in *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (number) 3
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X)
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte) point_x#1 ← (unumber)(number) 2
Inlining cast (byte) point_y#1 ← (unumber)(number) 3
Inlining cast *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X) ← (unumber)(number) 2
Inlining cast *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (unumber)(number) 3
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
@ -87,25 +57,11 @@ Finalized unsigned number type (byte) 3
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte) point_x#1 = (byte) point_x#4 (byte) point_x#2
Alias (byte) point_y#1 = (byte) point_y#4 (byte) point_y#2
Alias (byte) point_x#0 = (byte) point_x#6
Alias (byte) point_y#0 = (byte) point_y#6
Alias (byte) point_x#3 = (byte) point_x#5
Alias (byte) point_y#3 = (byte) point_y#5
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte) point_x#3 (byte) point_x#1
Identical Phi Values (byte) point_y#3 (byte) point_y#1
Successful SSA optimization Pass2IdenticalPhiElimination
Constant (const byte) point_x#0 = 0
Constant (const byte) point_y#0 = 0
Constant (const byte) point_x#1 = 2
Constant (const byte) point_y#1 = 3
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero main::SCREEN in [4] *((const byte*) main::SCREEN + (byte) 0) ← (const byte) point_x#1
Simplifying expression containing zero (byte*)&point in [0] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
Simplifying expression containing zero (byte*)&point in [2] *((const byte*) main::SCREEN + (byte) 0) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero main::SCREEN in [2] *((const byte*) main::SCREEN + (byte) 0) ← *((byte*)&(struct Point) point)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) point_x#0
Eliminating unused constant (const byte) point_y#0
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Consolidated array index constant in *(main::SCREEN+1)
Successful SSA optimization Pass2ConstantAdditionElimination
@ -136,11 +92,13 @@ FINAL CONTROL FLOW GRAPH
(void()) main()
main: scope:[main] from @1
[4] *((const byte*) main::SCREEN) ← (const byte) point_x#1
[5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point_y#1
[4] *((byte*)&(struct Point) point) ← (byte) 2
[5] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point)
[7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[6] return
[8] return
to:@return
@ -148,11 +106,13 @@ VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
(byte) point_x
(byte) point_y
(struct Point) point loadstore = {}
Initial phi equivalence classes
Added variable point to live range equivalence class [ point ]
Complete equivalence classes
[ point ]
Allocated mem[2] [ point ]
INITIAL ASM
Target platform is c64basic / MOS6502X
@ -163,8 +123,7 @@ Target platform is c64basic / MOS6502X
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const point_x = 2
.const point_y = 3
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
@ -182,32 +141,42 @@ __bend:
// main
main: {
.label SCREEN = $400
// [4] *((const byte*) main::SCREEN) ← (const byte) point_x#1 -- _deref_pbuc1=vbuc2
lda #point_x
// [4] *((byte*)&(struct Point) point) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta point
// [5] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point+OFFSET_STRUCT_POINT_Y
// [6] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point) -- _deref_pbuc1=_deref_pbuc2
lda point
sta SCREEN
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point_y#1 -- _deref_pbuc1=vbuc2
lda #point_y
// [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [6] return
// [8] return
rts
}
// File Data
point: .fill SIZEOF_STRUCT_POINT, 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((const byte*) main::SCREEN) ← (const byte) point_x#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point_y#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [4] *((byte*)&(struct Point) point) ← (byte) 2 [ point ] ( main:2 [ point ] ) always clobbers reg byte a
Statement [5] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ point ] ( main:2 [ point ] ) always clobbers reg byte a
Statement [6] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point) [ point ] ( main:2 [ point ] ) always clobbers reg byte a
Statement [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers mem[2] [ point ] : mem[2] ,
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [main]
Uplift Scope []
Uplift Scope [] 0: mem[2] [ point ]
Uplifting [Point] best 33 combination
Uplifting [main] best 33 combination
Uplifting [] best 33 combination
Uplifting [Point] best 49 combination
Uplifting [main] best 49 combination
Uplifting [] best 49 combination mem[2] [ point ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -217,8 +186,8 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const point_x = 2
.const point_y = 3
.const OFFSET_STRUCT_POINT_Y = 1
.const SIZEOF_STRUCT_POINT = 2
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
@ -236,19 +205,26 @@ __bend:
// main
main: {
.label SCREEN = $400
// [4] *((const byte*) main::SCREEN) ← (const byte) point_x#1 -- _deref_pbuc1=vbuc2
lda #point_x
// [4] *((byte*)&(struct Point) point) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta point
// [5] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point+OFFSET_STRUCT_POINT_Y
// [6] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point) -- _deref_pbuc1=_deref_pbuc2
lda point
sta SCREEN
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point_y#1 -- _deref_pbuc1=vbuc2
lda #point_y
// [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [6] return
// [8] return
rts
}
// File Data
point: .fill SIZEOF_STRUCT_POINT, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
@ -273,20 +249,20 @@ FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(byte) point_x
(const byte) point_x#1 point_x = (byte) 2
(byte) point_y
(const byte) point_y#1 point_y = (byte) 3
(struct Point) point loadstore mem[2] = {}
mem[2] [ point ]
FINAL ASSEMBLER
Score: 18
Score: 34
// File Comments
// Minimal struct - declaration, instantiation and usage
@ -295,8 +271,8 @@ Score: 18
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const point_x = 2
.const point_y = 3
.const OFFSET_STRUCT_POINT_Y = 1
.const SIZEOF_STRUCT_POINT = 2
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
@ -306,18 +282,27 @@ Score: 18
// main
main: {
.label SCREEN = $400
// point.x = 2
// [4] *((byte*)&(struct Point) point) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta point
// point.y = 3
// [5] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = point.x
// [4] *((const byte*) main::SCREEN) ← (const byte) point_x#1 -- _deref_pbuc1=vbuc2
lda #point_x
// [6] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point) -- _deref_pbuc1=_deref_pbuc2
lda point
sta SCREEN
// SCREEN[1] = point.y
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point_y#1 -- _deref_pbuc1=vbuc2
lda #point_y
// [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// main::@return
// }
// [6] return
// [8] return
rts
}
// File Data
point: .fill SIZEOF_STRUCT_POINT, 0

View File

@ -1,13 +1,13 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(byte) point_x
(const byte) point_x#1 point_x = (byte) 2
(byte) point_y
(const byte) point_y#1 point_y = (byte) 3
(struct Point) point loadstore mem[2] = {}
mem[2] [ point ]

View File

@ -2,13 +2,22 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const point1_x = 2
.const point1_y = 3
.const OFFSET_STRUCT_POINT_Y = 1
.const SIZEOF_STRUCT_POINT = 2
main: {
.label SCREEN = $400
lda #point1_y
lda #2
sta point1
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
sta point2
lda point1
sta point2+OFFSET_STRUCT_POINT_Y
lda point2
sta SCREEN
lda #point1_x
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
rts
}
point1: .fill SIZEOF_STRUCT_POINT, 0
point2: .fill SIZEOF_STRUCT_POINT, 0

View File

@ -10,9 +10,13 @@
(void()) main()
main: scope:[main] from @1
[4] *((const byte*) main::SCREEN) ← (const byte) point1_y#1
[5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point1_x#1
[4] *((byte*)&(struct Point) point1) ← (byte) 2
[5] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((byte*)&(struct Point) point2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
[7] *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) point1)
[8] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point2)
[9] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[6] return
[10] return
to:@return

View File

@ -1,66 +1,32 @@
Created struct value member variable (byte) point1_x
Created struct value member variable (byte) point1_y
Converted struct value to member variables (struct Point) point1
Created struct value member variable (byte) point2_x
Created struct value member variable (byte) point2_y
Converted struct value to member variables (struct Point) point2
Adding struct value member variable copy (byte) point1_x ← (byte) 0
Adding struct value member variable copy (byte) point1_y ← (byte) 0
Adding struct value member variable copy (byte) point2_x ← (byte) 0
Adding struct value member variable copy (byte) point2_y ← (byte) 0
Replacing struct member reference (struct Point) point1.x with member unwinding reference (byte) point1_x
Replacing struct member reference (struct Point) point1.y with member unwinding reference (byte) point1_y
Replacing struct member reference (struct Point) point1.y with member unwinding reference (byte) point1_y
Replacing struct member reference (struct Point) point2.x with member unwinding reference (byte) point2_x
Replacing struct member reference (struct Point) point1.x with member unwinding reference (byte) point1_x
Replacing struct member reference (struct Point) point2.y with member unwinding reference (byte) point2_y
Replacing struct member reference (struct Point) point2.x with member unwinding reference (byte) point2_x
Replacing struct member reference (struct Point) point2.y with member unwinding reference (byte) point2_y
Replacing struct member reference (struct Point) point1.x with member unwinding reference *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point1.y with member unwinding reference *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
Replacing struct member reference (struct Point) point1.y with member unwinding reference *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
Replacing struct member reference (struct Point) point2.x with member unwinding reference *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point1.x with member unwinding reference *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point2.y with member unwinding reference *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y)
Replacing struct member reference (struct Point) point2.x with member unwinding reference *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point2.y with member unwinding reference *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y)
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte) point1_x#0 ← (byte) 0
(byte) point1_y#0 ← (byte) 0
(byte) point2_x#0 ← (byte) 0
(byte) point2_y#0 ← (byte) 0
to:@1
(void()) main()
main: scope:[main] from @1
(byte) point1_x#1 ← (number) 2
(byte) point1_y#1 ← (number) 3
(byte) point2_x#1 ← (byte) point1_y#1
(byte) point2_y#1 ← (byte) point1_x#1
*((const byte*) main::SCREEN + (number) 0) ← (byte) point2_x#1
*((const byte*) main::SCREEN + (number) 1) ← (byte) point2_y#1
*((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 2
*((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (number) 3
*((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
*((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
*((const byte*) main::SCREEN + (number) 0) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
*((const byte*) main::SCREEN + (number) 1) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
(byte) point2_y#4 ← phi( main/(byte) point2_y#1 )
(byte) point2_x#4 ← phi( main/(byte) point2_x#1 )
(byte) point1_y#4 ← phi( main/(byte) point1_y#1 )
(byte) point1_x#4 ← phi( main/(byte) point1_x#1 )
(byte) point1_x#2 ← (byte) point1_x#4
(byte) point1_y#2 ← (byte) point1_y#4
(byte) point2_x#2 ← (byte) point2_x#4
(byte) point2_y#2 ← (byte) point2_y#4
return
to:@return
@1: scope:[] from @begin
(byte) point2_y#6 ← phi( @begin/(byte) point2_y#0 )
(byte) point2_x#6 ← phi( @begin/(byte) point2_x#0 )
(byte) point1_y#6 ← phi( @begin/(byte) point1_y#0 )
(byte) point1_x#6 ← phi( @begin/(byte) point1_x#0 )
call main
to:@2
@2: scope:[] from @1
(byte) point2_y#5 ← phi( @1/(byte) point2_y#2 )
(byte) point2_x#5 ← phi( @1/(byte) point2_x#2 )
(byte) point1_y#5 ← phi( @1/(byte) point1_y#2 )
(byte) point1_x#5 ← phi( @1/(byte) point1_x#2 )
(byte) point1_x#3 ← (byte) point1_x#5
(byte) point1_y#3 ← (byte) point1_y#5
(byte) point2_x#3 ← (byte) point2_x#5
(byte) point2_y#3 ← (byte) point2_y#5
to:@end
@end: scope:[] from @2
@ -69,51 +35,23 @@ SYMBOL TABLE SSA
(label) @2
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*)(number) $400
(byte) point1_x
(byte) point1_x#0
(byte) point1_x#1
(byte) point1_x#2
(byte) point1_x#3
(byte) point1_x#4
(byte) point1_x#5
(byte) point1_x#6
(byte) point1_y
(byte) point1_y#0
(byte) point1_y#1
(byte) point1_y#2
(byte) point1_y#3
(byte) point1_y#4
(byte) point1_y#5
(byte) point1_y#6
(byte) point2_x
(byte) point2_x#0
(byte) point2_x#1
(byte) point2_x#2
(byte) point2_x#3
(byte) point2_x#4
(byte) point2_x#5
(byte) point2_x#6
(byte) point2_y
(byte) point2_y#0
(byte) point2_y#1
(byte) point2_y#2
(byte) point2_y#3
(byte) point2_y#4
(byte) point2_y#5
(byte) point2_y#6
(struct Point) point1 loadstore = {}
(struct Point) point2 loadstore = {}
Adding number conversion cast (unumber) 2 in (byte) point1_x#1 ← (number) 2
Adding number conversion cast (unumber) 3 in (byte) point1_y#1 ← (number) 3
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← (byte) point2_x#1
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← (byte) point2_y#1
Adding number conversion cast (unumber) 2 in *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 2
Adding number conversion cast (unumber) 3 in *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (number) 3
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte) point1_x#1 ← (unumber)(number) 2
Inlining cast (byte) point1_y#1 ← (unumber)(number) 3
Inlining cast *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X) ← (unumber)(number) 2
Inlining cast *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (unumber)(number) 3
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
@ -126,35 +64,13 @@ Finalized unsigned number type (byte) 3
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte) point1_y#1 = (byte) point2_x#1 (byte) point1_y#4 (byte) point2_x#4 (byte) point1_y#2 (byte) point2_x#2
Alias (byte) point1_x#1 = (byte) point2_y#1 (byte) point1_x#4 (byte) point2_y#4 (byte) point1_x#2 (byte) point2_y#2
Alias (byte) point1_x#0 = (byte) point1_x#6
Alias (byte) point1_y#0 = (byte) point1_y#6
Alias (byte) point2_x#0 = (byte) point2_x#6
Alias (byte) point2_y#0 = (byte) point2_y#6
Alias (byte) point1_x#3 = (byte) point1_x#5
Alias (byte) point1_y#3 = (byte) point1_y#5
Alias (byte) point2_x#3 = (byte) point2_x#5
Alias (byte) point2_y#3 = (byte) point2_y#5
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte) point1_x#3 (byte) point1_x#1
Identical Phi Values (byte) point1_y#3 (byte) point1_y#1
Identical Phi Values (byte) point2_x#3 (byte) point1_y#1
Identical Phi Values (byte) point2_y#3 (byte) point1_x#1
Successful SSA optimization Pass2IdenticalPhiElimination
Constant (const byte) point1_x#0 = 0
Constant (const byte) point1_y#0 = 0
Constant (const byte) point2_x#0 = 0
Constant (const byte) point2_y#0 = 0
Constant (const byte) point1_x#1 = 2
Constant (const byte) point1_y#1 = 3
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero main::SCREEN in [8] *((const byte*) main::SCREEN + (byte) 0) ← (const byte) point1_y#1
Simplifying expression containing zero (byte*)&point1 in [0] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
Simplifying expression containing zero (byte*)&point2 in [2] *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
Simplifying expression containing zero (byte*)&point1 in [3] *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero (byte*)&point2 in [4] *((const byte*) main::SCREEN + (byte) 0) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero main::SCREEN in [4] *((const byte*) main::SCREEN + (byte) 0) ← *((byte*)&(struct Point) point2)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) point1_x#0
Eliminating unused constant (const byte) point1_y#0
Eliminating unused constant (const byte) point2_x#0
Eliminating unused constant (const byte) point2_y#0
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Consolidated array index constant in *(main::SCREEN+1)
Successful SSA optimization Pass2ConstantAdditionElimination
@ -185,11 +101,15 @@ FINAL CONTROL FLOW GRAPH
(void()) main()
main: scope:[main] from @1
[4] *((const byte*) main::SCREEN) ← (const byte) point1_y#1
[5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point1_x#1
[4] *((byte*)&(struct Point) point1) ← (byte) 2
[5] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((byte*)&(struct Point) point2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
[7] *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) point1)
[8] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point2)
[9] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[6] return
[10] return
to:@return
@ -197,13 +117,17 @@ VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
(byte) point1_x
(byte) point1_y
(byte) point2_x
(byte) point2_y
(struct Point) point1 loadstore = {}
(struct Point) point2 loadstore = {}
Initial phi equivalence classes
Added variable point1 to live range equivalence class [ point1 ]
Added variable point2 to live range equivalence class [ point2 ]
Complete equivalence classes
[ point1 ]
[ point2 ]
Allocated mem[2] [ point1 ]
Allocated mem[2] [ point2 ]
INITIAL ASM
Target platform is c64basic / MOS6502X
@ -214,8 +138,7 @@ Target platform is c64basic / MOS6502X
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const point1_x = 2
.const point1_y = 3
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
@ -233,32 +156,52 @@ __bend:
// main
main: {
.label SCREEN = $400
// [4] *((const byte*) main::SCREEN) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
// [4] *((byte*)&(struct Point) point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta point1
// [5] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)&(struct Point) point2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta point2
// [7] *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) point1) -- _deref_pbuc1=_deref_pbuc2
lda point1
sta point2+OFFSET_STRUCT_POINT_Y
// [8] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point2) -- _deref_pbuc1=_deref_pbuc2
lda point2
sta SCREEN
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point1_x#1 -- _deref_pbuc1=vbuc2
lda #point1_x
// [9] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [6] return
// [10] return
rts
}
// File Data
point1: .fill SIZEOF_STRUCT_POINT, 0
point2: .fill SIZEOF_STRUCT_POINT, 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((const byte*) main::SCREEN) ← (const byte) point1_y#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point1_x#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [4] *((byte*)&(struct Point) point1) ← (byte) 2 [ point1 point2 ] ( main:2 [ point1 point2 ] ) always clobbers reg byte a
Statement [5] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ point1 point2 ] ( main:2 [ point1 point2 ] ) always clobbers reg byte a
Statement [6] *((byte*)&(struct Point) point2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) [ point1 point2 ] ( main:2 [ point1 point2 ] ) always clobbers reg byte a
Statement [7] *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) point1) [ point2 ] ( main:2 [ point2 ] ) always clobbers reg byte a
Statement [8] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point2) [ point2 ] ( main:2 [ point2 ] ) always clobbers reg byte a
Statement [9] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers mem[2] [ point1 ] : mem[2] ,
Potential registers mem[2] [ point2 ] : mem[2] ,
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [main]
Uplift Scope []
Uplift Scope [] 0: mem[2] [ point1 ] 0: mem[2] [ point2 ]
Uplifting [Point] best 33 combination
Uplifting [main] best 33 combination
Uplifting [] best 33 combination
Uplifting [Point] best 65 combination
Uplifting [main] best 65 combination
Uplifting [] best 65 combination mem[2] [ point1 ] mem[2] [ point2 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -268,8 +211,8 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const point1_x = 2
.const point1_y = 3
.const OFFSET_STRUCT_POINT_Y = 1
.const SIZEOF_STRUCT_POINT = 2
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
@ -287,25 +230,41 @@ __bend:
// main
main: {
.label SCREEN = $400
// [4] *((const byte*) main::SCREEN) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
// [4] *((byte*)&(struct Point) point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta point1
// [5] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)&(struct Point) point2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta point2
// [7] *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) point1) -- _deref_pbuc1=_deref_pbuc2
lda point1
sta point2+OFFSET_STRUCT_POINT_Y
// [8] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point2) -- _deref_pbuc1=_deref_pbuc2
lda point2
sta SCREEN
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point1_x#1 -- _deref_pbuc1=vbuc2
lda #point1_x
// [9] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [6] return
// [10] return
rts
}
// File Data
point1: .fill SIZEOF_STRUCT_POINT, 0
point2: .fill SIZEOF_STRUCT_POINT, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda point1+OFFSET_STRUCT_POINT_Y
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
@ -324,22 +283,22 @@ FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(byte) point1_x
(const byte) point1_x#1 point1_x = (byte) 2
(byte) point1_y
(const byte) point1_y#1 point1_y = (byte) 3
(byte) point2_x
(byte) point2_y
(struct Point) point1 loadstore mem[2] = {}
(struct Point) point2 loadstore mem[2] = {}
mem[2] [ point1 ]
mem[2] [ point2 ]
FINAL ASSEMBLER
Score: 18
Score: 46
// File Comments
// Minimal struct - two instances being used.
@ -348,8 +307,8 @@ Score: 18
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const point1_x = 2
.const point1_y = 3
.const OFFSET_STRUCT_POINT_Y = 1
.const SIZEOF_STRUCT_POINT = 2
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
@ -359,18 +318,35 @@ Score: 18
// main
main: {
.label SCREEN = $400
// point1.x = 2
// [4] *((byte*)&(struct Point) point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta point1
// point1.y = 3
// [5] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// point2.x = point1.y
// [6] *((byte*)&(struct Point) point2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
sta point2
// point2.y = point1.x
// [7] *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) point1) -- _deref_pbuc1=_deref_pbuc2
lda point1
sta point2+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = point2.x
// [4] *((const byte*) main::SCREEN) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
// [8] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point2) -- _deref_pbuc1=_deref_pbuc2
lda point2
sta SCREEN
// SCREEN[1] = point2.y
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point1_x#1 -- _deref_pbuc1=vbuc2
lda #point1_x
// [9] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// main::@return
// }
// [6] return
// [10] return
rts
}
// File Data
point1: .fill SIZEOF_STRUCT_POINT, 0
point2: .fill SIZEOF_STRUCT_POINT, 0

View File

@ -1,15 +1,15 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(byte) point1_x
(const byte) point1_x#1 point1_x = (byte) 2
(byte) point1_y
(const byte) point1_y#1 point1_y = (byte) 3
(byte) point2_x
(byte) point2_y
(struct Point) point1 loadstore mem[2] = {}
(struct Point) point2 loadstore mem[2] = {}
mem[2] [ point1 ]
mem[2] [ point2 ]

View File

@ -1,39 +1,22 @@
// Example of a struct containing an array
// Works because the struct is only handled as a value
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const jesper_id = 4
.const henriette_id = 7
__bbegin:
ldy #$40
!:
lda __0-1,y
sta jesper_name-1,y
dey
bne !-
ldy #$40
!:
lda __1-1,y
sta henriette_name-1,y
dey
bne !-
jsr main
rts
.const OFFSET_STRUCT_PERSON_NAME = 1
main: {
lda #<jesper_name
ldx jesper
lda #<jesper+OFFSET_STRUCT_PERSON_NAME
sta.z print_person.person_name
lda #>jesper_name
lda #>jesper+OFFSET_STRUCT_PERSON_NAME
sta.z print_person.person_name+1
ldy #0
ldx #jesper_id
jsr print_person
lda #<henriette_name
ldx henriette
lda #<henriette+OFFSET_STRUCT_PERSON_NAME
sta.z print_person.person_name
lda #>henriette_name
lda #>henriette+OFFSET_STRUCT_PERSON_NAME
sta.z print_person.person_name+1
ldx #henriette_id
jsr print_person
rts
}
@ -68,11 +51,11 @@ print_person: {
}
DIGIT: .text "0123456789"
.byte 0
jesper_name: .fill $40, 0
henriette_name: .fill $40, 0
__0: .text "jesper"
jesper: .byte 4
.text "jesper"
.byte 0
.fill $39, 0
__1: .text "henriette"
henriette: .byte 7
.text "henriette"
.byte 0
.fill $36, 0

View File

@ -1,51 +1,50 @@
@begin: scope:[] from
[0] *((const byte*) jesper_name) ← memcpy(*(&(const byte*) $0), byte, (number) $40)
[1] *((const byte*) henriette_name) ← memcpy(*(&(const byte*) $1), byte, (number) $40)
[0] phi()
to:@1
@1: scope:[] from @begin
[2] phi()
[3] call main
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[4] phi()
[3] phi()
(void()) main()
main: scope:[main] from @1
[5] phi()
[6] call print_person
[4] (byte) print_person::person_id#0 ← *((byte*)&(struct Person) jesper)
[5] call print_person
to:main::@1
main::@1: scope:[main] from main
[7] phi()
[8] call print_person
[6] (byte) print_person::person_id#1 ← *((byte*)&(struct Person) henriette)
[7] call print_person
to:main::@return
main::@return: scope:[main] from main::@1
[9] return
[8] return
to:@return
(void()) print_person((byte) print_person::person_id , (byte*) print_person::person_name)
print_person: scope:[print_person] from main main::@1
[10] (byte*) print_person::person_name#4 ← phi( main/(const byte*) jesper_name main::@1/(const byte*) henriette_name )
[10] (byte) idx#13 ← phi( main/(byte) 0 main::@1/(byte) idx#16 )
[10] (byte) print_person::person_id#2 ← phi( main/(const byte) jesper_id main::@1/(const byte) henriette_id )
[11] *((const byte*) SCREEN + (byte) idx#13) ← *((const byte*) DIGIT + (byte) print_person::person_id#2)
[12] (byte) idx#4 ← ++ (byte) idx#13
[13] *((const byte*) SCREEN + (byte) idx#4) ← (byte) ' '
[14] (byte) idx#5 ← ++ (byte) idx#4
[9] (byte*) print_person::person_name#4 ← phi( main/(byte*)&(struct Person) jesper+(const byte) OFFSET_STRUCT_PERSON_NAME main::@1/(byte*)&(struct Person) henriette+(const byte) OFFSET_STRUCT_PERSON_NAME )
[9] (byte) idx#13 ← phi( main/(byte) 0 main::@1/(byte) idx#16 )
[9] (byte) print_person::person_id#2 ← phi( main/(byte) print_person::person_id#0 main::@1/(byte) print_person::person_id#1 )
[10] *((const byte*) SCREEN + (byte) idx#13) ← *((const byte*) DIGIT + (byte) print_person::person_id#2)
[11] (byte) idx#4 ← ++ (byte) idx#13
[12] *((const byte*) SCREEN + (byte) idx#4) ← (byte) ' '
[13] (byte) idx#5 ← ++ (byte) idx#4
to:print_person::@1
print_person::@1: scope:[print_person] from print_person print_person::@2
[15] (byte) idx#14 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
[15] (byte) print_person::i#2 ← phi( print_person/(byte) 0 print_person::@2/(byte) print_person::i#1 )
[16] if((byte) 0!=*((byte*) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2
[14] (byte) idx#14 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
[14] (byte) print_person::i#2 ← phi( print_person/(byte) 0 print_person::@2/(byte) print_person::i#1 )
[15] if((byte) 0!=*((byte*) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2
to:print_person::@3
print_person::@3: scope:[print_person] from print_person::@1
[17] *((const byte*) SCREEN + (byte) idx#14) ← (byte) ' '
[18] (byte) idx#16 ← ++ (byte) idx#14
[16] *((const byte*) SCREEN + (byte) idx#14) ← (byte) ' '
[17] (byte) idx#16 ← ++ (byte) idx#14
to:print_person::@return
print_person::@return: scope:[print_person] from print_person::@3
[19] return
[18] return
to:@return
print_person::@2: scope:[print_person] from print_person::@1
[20] *((const byte*) SCREEN + (byte) idx#14) ← *((byte*) print_person::person_name#4 + (byte) print_person::i#2)
[21] (byte) idx#6 ← ++ (byte) idx#14
[22] (byte) print_person::i#1 ← ++ (byte) print_person::i#2
[19] *((const byte*) SCREEN + (byte) idx#14) ← *((byte*) print_person::person_name#4 + (byte) print_person::i#2)
[20] (byte) idx#6 ← ++ (byte) idx#14
[21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2
to:print_person::@1

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,12 @@
(const byte*) $0[(number) $40] = (string) "jesper"
(const byte*) $1[(number) $40] = (string) "henriette"
(label) @1
(label) @begin
(label) @end
(const byte*) DIGIT[] = (string) "0123456789"
(const byte) OFFSET_STRUCT_PERSON_NAME = (byte) 1
(byte) Person::id
(const byte*) Person::name[(number) $40] = { fill( $40, 0) }
(const byte*) SCREEN = (byte*) 1024
(const byte) henriette_id = (byte) 7
(const byte*) henriette_name[(number) $40] = { fill( $40, 0) }
(struct Person) henriette loadstore mem[65] = { id: (byte) 7, name: (string) "henriette" }
(byte) idx
(byte) idx#13 reg byte y 3.0
(byte) idx#14 reg byte x 9.75
@ -16,8 +14,7 @@
(byte) idx#4 reg byte x 3.0
(byte) idx#5 reg byte x 4.0
(byte) idx#6 reg byte x 11.0
(const byte) jesper_id = (byte) 4
(const byte*) jesper_name[(number) $40] = { fill( $40, 0) }
(struct Person) jesper loadstore mem[65] = { id: (byte) 4, name: (string) "jesper" }
(void()) main()
(label) main::@1
(label) main::@return
@ -31,13 +28,17 @@
(byte) print_person::i#2 reg byte y 11.0
(struct Person) print_person::person
(byte) print_person::person_id
(byte) print_person::person_id#2 reg byte x 2.0
(byte) print_person::person_id#0 reg byte x 4.0
(byte) print_person::person_id#1 reg byte x 4.0
(byte) print_person::person_id#2 reg byte x 6.0
(byte*) print_person::person_name
(byte*) print_person::person_name#4 person_name zp[2]:2 2.2
reg byte x [ print_person::person_id#2 ]
reg byte x [ print_person::person_id#2 print_person::person_id#0 print_person::person_id#1 ]
reg byte y [ idx#13 idx#16 ]
zp[2]:2 [ print_person::person_name#4 ]
reg byte y [ print_person::i#2 print_person::i#1 ]
reg byte x [ idx#14 idx#5 idx#6 ]
reg byte x [ idx#4 ]
mem[65] [ jesper ]
mem[65] [ henriette ]

View File

@ -1,28 +1,19 @@
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
.label point = 2
__bbegin:
ldy #SIZEOF_STRUCT_POINT
lda #0
!:
dey
sta point,y
bne !-
jsr main
rts
.const SIZEOF_STRUCT_POINT = 2
main: {
lda #2
sta.z point
sta point
lda #3
sta point+OFFSET_STRUCT_POINT_Y
lda.z point
lda point
sta SCREEN
lda point+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
rts
}
point: .fill SIZEOF_STRUCT_POINT, 0

View File

@ -1,5 +1,5 @@
@begin: scope:[] from
[0] *(&(struct Point) point) ← memset(struct Point, (const byte) SIZEOF_STRUCT_POINT)
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()

View File

@ -1,4 +1,3 @@
Adding struct value member variable copy *(&(struct Point) point) ← memset(struct Point, (const byte) SIZEOF_STRUCT_POINT)
Replacing struct member reference (struct Point) point.x with member unwinding reference *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point.y with member unwinding reference *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y)
Replacing struct member reference (struct Point) point.x with member unwinding reference *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X)
@ -6,7 +5,6 @@ Replacing struct member reference (struct Point) point.y with member unwinding r
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
*(&(struct Point) point) ← memset(struct Point, (const byte) SIZEOF_STRUCT_POINT)
to:@1
(void()) main()
@ -36,10 +34,9 @@ SYMBOL TABLE SSA
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
(void()) main()
(label) main::@return
(struct Point) point loadstore
(struct Point) point loadstore = {}
Adding number conversion cast (unumber) 2 in *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 2
Adding number conversion cast (unumber) 3 in *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (number) 3
@ -60,14 +57,15 @@ Finalized unsigned number type (byte) 3
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simplifying expression containing zero (byte*)&point in [1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
Simplifying expression containing zero (byte*)&point in [3] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [3] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) point)
Simplifying expression containing zero (byte*)&point in [0] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
Simplifying expression containing zero (byte*)&point in [2] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [2] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) point)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Consolidated array index constant in *(SCREEN+1)
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 @end
@ -77,12 +75,13 @@ Calls in [] to main:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] *(&(struct Point) point) ← memset(struct Point, (const byte) SIZEOF_STRUCT_POINT)
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
@ -107,13 +106,13 @@ VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
(struct Point) point loadstore
(struct Point) point loadstore = {}
Initial phi equivalence classes
Added variable point to live range equivalence class [ point ]
Complete equivalence classes
[ point ]
Allocated zp[2]:2 [ point ]
Allocated mem[2] [ point ]
INITIAL ASM
Target platform is c64basic / MOS6502X
@ -125,18 +124,9 @@ Target platform is c64basic / MOS6502X
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
.label point = 2
// @begin
__bbegin:
// [0] *(&(struct Point) point) ← memset(struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_memset_vbuc2
ldy #SIZEOF_STRUCT_POINT
lda #0
!:
dey
sta point,y
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -153,12 +143,12 @@ __bend:
main: {
// [4] *((byte*)&(struct Point) point) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point
sta point
// [5] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point+OFFSET_STRUCT_POINT_Y
// [6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point) -- _deref_pbuc1=_deref_pbuc2
lda.z point
lda point
sta SCREEN
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point+OFFSET_STRUCT_POINT_Y
@ -170,23 +160,23 @@ main: {
rts
}
// File Data
point: .fill SIZEOF_STRUCT_POINT, 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *(&(struct Point) point) ← memset(struct Point, (const byte) SIZEOF_STRUCT_POINT) [ point ] ( [ point ] ) always clobbers reg byte a reg byte y
Statement [4] *((byte*)&(struct Point) point) ← (byte) 2 [ point ] ( main:2 [ point ] ) always clobbers reg byte a
Statement [5] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ point ] ( main:2 [ point ] ) always clobbers reg byte a
Statement [6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point) [ point ] ( main:2 [ point ] ) always clobbers reg byte a
Statement [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers zp[2]:2 [ point ] : zp[2]:2 ,
Potential registers mem[2] [ point ] : mem[2] ,
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [main]
Uplift Scope [] 0: zp[2]:2 [ point ]
Uplift Scope [] 0: mem[2] [ point ]
Uplifting [Point] best 60 combination
Uplifting [main] best 60 combination
Uplifting [] best 60 combination zp[2]:2 [ point ]
Uplifting [Point] best 49 combination
Uplifting [main] best 49 combination
Uplifting [] best 49 combination mem[2] [ point ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -197,18 +187,10 @@ ASSEMBLER BEFORE OPTIMIZATION
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
.label point = 2
.const SIZEOF_STRUCT_POINT = 2
// @begin
__bbegin:
// [0] *(&(struct Point) point) ← memset(struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_memset_vbuc2
ldy #SIZEOF_STRUCT_POINT
lda #0
!:
dey
sta point,y
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -225,12 +207,12 @@ __bend:
main: {
// [4] *((byte*)&(struct Point) point) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point
sta point
// [5] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point+OFFSET_STRUCT_POINT_Y
// [6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point) -- _deref_pbuc1=_deref_pbuc2
lda.z point
lda point
sta SCREEN
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point+OFFSET_STRUCT_POINT_Y
@ -242,21 +224,26 @@ main: {
rts
}
// File Data
point: .fill SIZEOF_STRUCT_POINT, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
Removing instruction __bend:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
@ -269,40 +256,28 @@ FINAL SYMBOL TABLE
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
(void()) main()
(label) main::@return
(struct Point) point loadstore zp[2]:2
(struct Point) point loadstore mem[2] = {}
zp[2]:2 [ point ]
mem[2] [ point ]
FINAL ASSEMBLER
Score: 57
Score: 34
// File Comments
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
.label point = 2
.const SIZEOF_STRUCT_POINT = 2
// @begin
__bbegin:
// point
// [0] *(&(struct Point) point) ← memset(struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_memset_vbuc2
ldy #SIZEOF_STRUCT_POINT
lda #0
!:
dey
sta point,y
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
jsr main
rts
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
@ -310,14 +285,14 @@ main: {
// point.x = 2
// [4] *((byte*)&(struct Point) point) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point
sta point
// point.y = 3
// [5] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = point.x
// [6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point) -- _deref_pbuc1=_deref_pbuc2
lda.z point
lda point
sta SCREEN
// SCREEN[1] = point.y
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
@ -329,4 +304,5 @@ main: {
rts
}
// File Data
point: .fill SIZEOF_STRUCT_POINT, 0

View File

@ -8,6 +8,6 @@
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
(void()) main()
(label) main::@return
(struct Point) point loadstore zp[2]:2
(struct Point) point loadstore mem[2] = {}
zp[2]:2 [ point ]
mem[2] [ point ]

View File

@ -2,18 +2,31 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const point1_x = 2
.const point1_y = 3
.const point2_x = 4
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
main: {
.label SCREEN = $400
lda #point1_x
lda #2
sta point1
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
ldy #SIZEOF_STRUCT_POINT
!:
lda point1-1,y
sta point2-1,y
dey
bne !-
lda #4
sta point2
lda point1
sta SCREEN
lda #point1_y
lda point1+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
lda #point2_x
lda point2
sta SCREEN+2
lda #point1_y
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
rts
}
point1: .fill SIZEOF_STRUCT_POINT, 0
point2: .fill SIZEOF_STRUCT_POINT, 0

View File

@ -10,11 +10,15 @@
(void()) main()
main: scope:[main] from @1
[4] *((const byte*) main::SCREEN) ← (const byte) point1_x#1
[5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point1_y#1
[6] *((const byte*) main::SCREEN+(byte) 2) ← (const byte) point2_x#2
[7] *((const byte*) main::SCREEN+(byte) 3) ← (const byte) point1_y#1
[4] *((byte*)&(struct Point) point1) ← (byte) 2
[5] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *(&(struct Point) point2) ← memcpy(*(&(struct Point) point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
[7] *((byte*)&(struct Point) point2) ← (byte) 4
[8] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point1)
[9] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
[10] *((const byte*) main::SCREEN+(byte) 2) ← *((byte*)&(struct Point) point2)
[11] *((const byte*) main::SCREEN+(byte) 3) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[8] return
[12] return
to:@return

View File

@ -1,70 +1,34 @@
Created struct value member variable (byte) point1_x
Created struct value member variable (byte) point1_y
Converted struct value to member variables (struct Point) point1
Created struct value member variable (byte) point2_x
Created struct value member variable (byte) point2_y
Converted struct value to member variables (struct Point) point2
Adding struct value member variable copy (byte) point1_x ← (byte) 0
Adding struct value member variable copy (byte) point1_y ← (byte) 0
Adding struct value member variable copy (byte) point2_x ← (byte) 0
Adding struct value member variable copy (byte) point2_y ← (byte) 0
Adding struct value member variable copy (byte) point2_x ← (byte) point1_x
Adding struct value member variable copy (byte) point2_y ← (byte) point1_y
Replacing struct member reference (struct Point) point1.x with member unwinding reference (byte) point1_x
Replacing struct member reference (struct Point) point1.y with member unwinding reference (byte) point1_y
Replacing struct member reference (struct Point) point2.x with member unwinding reference (byte) point2_x
Replacing struct member reference (struct Point) point1.x with member unwinding reference (byte) point1_x
Replacing struct member reference (struct Point) point1.y with member unwinding reference (byte) point1_y
Replacing struct member reference (struct Point) point2.x with member unwinding reference (byte) point2_x
Replacing struct member reference (struct Point) point2.y with member unwinding reference (byte) point2_y
Adding struct value member variable copy *(&(struct Point) point2) ← memcpy(*(&(struct Point) point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
Replacing struct member reference (struct Point) point1.x with member unwinding reference *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point1.y with member unwinding reference *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
Replacing struct member reference (struct Point) point2.x with member unwinding reference *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point1.x with member unwinding reference *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point1.y with member unwinding reference *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
Replacing struct member reference (struct Point) point2.x with member unwinding reference *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point2.y with member unwinding reference *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y)
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte) point1_x#0 ← (byte) 0
(byte) point1_y#0 ← (byte) 0
(byte) point2_x#0 ← (byte) 0
(byte) point2_y#0 ← (byte) 0
to:@1
(void()) main()
main: scope:[main] from @1
(byte) point1_x#1 ← (number) 2
(byte) point1_y#1 ← (number) 3
(byte) point2_x#1 ← (byte) point1_x#1
(byte) point2_y#1 ← (byte) point1_y#1
(byte) point2_x#2 ← (number) 4
*((const byte*) main::SCREEN + (number) 0) ← (byte) point1_x#1
*((const byte*) main::SCREEN + (number) 1) ← (byte) point1_y#1
*((const byte*) main::SCREEN + (number) 2) ← (byte) point2_x#2
*((const byte*) main::SCREEN + (number) 3) ← (byte) point2_y#1
*((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 2
*((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (number) 3
*(&(struct Point) point2) ← memcpy(*(&(struct Point) point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
*((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 4
*((const byte*) main::SCREEN + (number) 0) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
*((const byte*) main::SCREEN + (number) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
*((const byte*) main::SCREEN + (number) 2) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
*((const byte*) main::SCREEN + (number) 3) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
(byte) point2_y#4 ← phi( main/(byte) point2_y#1 )
(byte) point2_x#5 ← phi( main/(byte) point2_x#2 )
(byte) point1_y#4 ← phi( main/(byte) point1_y#1 )
(byte) point1_x#4 ← phi( main/(byte) point1_x#1 )
(byte) point1_x#2 ← (byte) point1_x#4
(byte) point1_y#2 ← (byte) point1_y#4
(byte) point2_x#3 ← (byte) point2_x#5
(byte) point2_y#2 ← (byte) point2_y#4
return
to:@return
@1: scope:[] from @begin
(byte) point2_y#6 ← phi( @begin/(byte) point2_y#0 )
(byte) point2_x#7 ← phi( @begin/(byte) point2_x#0 )
(byte) point1_y#6 ← phi( @begin/(byte) point1_y#0 )
(byte) point1_x#6 ← phi( @begin/(byte) point1_x#0 )
call main
to:@2
@2: scope:[] from @1
(byte) point2_y#5 ← phi( @1/(byte) point2_y#2 )
(byte) point2_x#6 ← phi( @1/(byte) point2_x#3 )
(byte) point1_y#5 ← phi( @1/(byte) point1_y#2 )
(byte) point1_x#5 ← phi( @1/(byte) point1_x#2 )
(byte) point1_x#3 ← (byte) point1_x#5
(byte) point1_y#3 ← (byte) point1_y#5
(byte) point2_x#4 ← (byte) point2_x#6
(byte) point2_y#3 ← (byte) point2_y#5
to:@end
@end: scope:[] from @2
@ -73,56 +37,28 @@ SYMBOL TABLE SSA
(label) @2
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*)(number) $400
(byte) point1_x
(byte) point1_x#0
(byte) point1_x#1
(byte) point1_x#2
(byte) point1_x#3
(byte) point1_x#4
(byte) point1_x#5
(byte) point1_x#6
(byte) point1_y
(byte) point1_y#0
(byte) point1_y#1
(byte) point1_y#2
(byte) point1_y#3
(byte) point1_y#4
(byte) point1_y#5
(byte) point1_y#6
(byte) point2_x
(byte) point2_x#0
(byte) point2_x#1
(byte) point2_x#2
(byte) point2_x#3
(byte) point2_x#4
(byte) point2_x#5
(byte) point2_x#6
(byte) point2_x#7
(byte) point2_y
(byte) point2_y#0
(byte) point2_y#1
(byte) point2_y#2
(byte) point2_y#3
(byte) point2_y#4
(byte) point2_y#5
(byte) point2_y#6
(struct Point) point1 loadstore = {}
(struct Point) point2 loadstore = {}
Adding number conversion cast (unumber) 2 in (byte) point1_x#1 ← (number) 2
Adding number conversion cast (unumber) 3 in (byte) point1_y#1 ← (number) 3
Adding number conversion cast (unumber) 4 in (byte) point2_x#2 ← (number) 4
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← (byte) point1_x#1
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← (byte) point1_y#1
Adding number conversion cast (unumber) 2 in *((const byte*) main::SCREEN + (number) 2) ← (byte) point2_x#2
Adding number conversion cast (unumber) 3 in *((const byte*) main::SCREEN + (number) 3) ← (byte) point2_y#1
Adding number conversion cast (unumber) 2 in *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 2
Adding number conversion cast (unumber) 3 in *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (number) 3
Adding number conversion cast (unumber) 4 in *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X) ← (number) 4
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
Adding number conversion cast (unumber) 2 in *((const byte*) main::SCREEN + (number) 2) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
Adding number conversion cast (unumber) 3 in *((const byte*) main::SCREEN + (number) 3) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte) point1_x#1 ← (unumber)(number) 2
Inlining cast (byte) point1_y#1 ← (unumber)(number) 3
Inlining cast (byte) point2_x#2 ← (unumber)(number) 4
Inlining cast *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X) ← (unumber)(number) 2
Inlining cast *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (unumber)(number) 3
Inlining cast *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X) ← (unumber)(number) 4
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
@ -141,37 +77,13 @@ Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 3
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte) point1_x#1 = (byte) point2_x#1 (byte) point1_x#4 (byte) point1_x#2
Alias (byte) point1_y#1 = (byte) point2_y#1 (byte) point1_y#4 (byte) point2_y#4 (byte) point1_y#2 (byte) point2_y#2
Alias (byte) point2_x#2 = (byte) point2_x#5 (byte) point2_x#3
Alias (byte) point1_x#0 = (byte) point1_x#6
Alias (byte) point1_y#0 = (byte) point1_y#6
Alias (byte) point2_x#0 = (byte) point2_x#7
Alias (byte) point2_y#0 = (byte) point2_y#6
Alias (byte) point1_x#3 = (byte) point1_x#5
Alias (byte) point1_y#3 = (byte) point1_y#5
Alias (byte) point2_x#4 = (byte) point2_x#6
Alias (byte) point2_y#3 = (byte) point2_y#5
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte) point1_x#3 (byte) point1_x#1
Identical Phi Values (byte) point1_y#3 (byte) point1_y#1
Identical Phi Values (byte) point2_x#4 (byte) point2_x#2
Identical Phi Values (byte) point2_y#3 (byte) point1_y#1
Successful SSA optimization Pass2IdenticalPhiElimination
Constant (const byte) point1_x#0 = 0
Constant (const byte) point1_y#0 = 0
Constant (const byte) point2_x#0 = 0
Constant (const byte) point2_y#0 = 0
Constant (const byte) point1_x#1 = 2
Constant (const byte) point1_y#1 = 3
Constant (const byte) point2_x#2 = 4
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero main::SCREEN in [9] *((const byte*) main::SCREEN + (byte) 0) ← (const byte) point1_x#1
Simplifying expression containing zero (byte*)&point1 in [0] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
Simplifying expression containing zero (byte*)&point2 in [3] *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) 4
Simplifying expression containing zero (byte*)&point1 in [4] *((const byte*) main::SCREEN + (byte) 0) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero main::SCREEN in [4] *((const byte*) main::SCREEN + (byte) 0) ← *((byte*)&(struct Point) point1)
Simplifying expression containing zero (byte*)&point2 in [6] *((const byte*) main::SCREEN + (byte) 2) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_X)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) point1_x#0
Eliminating unused constant (const byte) point1_y#0
Eliminating unused constant (const byte) point2_x#0
Eliminating unused constant (const byte) point2_y#0
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Consolidated array index constant in *(main::SCREEN+1)
Consolidated array index constant in *(main::SCREEN+2)
@ -204,13 +116,17 @@ FINAL CONTROL FLOW GRAPH
(void()) main()
main: scope:[main] from @1
[4] *((const byte*) main::SCREEN) ← (const byte) point1_x#1
[5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point1_y#1
[6] *((const byte*) main::SCREEN+(byte) 2) ← (const byte) point2_x#2
[7] *((const byte*) main::SCREEN+(byte) 3) ← (const byte) point1_y#1
[4] *((byte*)&(struct Point) point1) ← (byte) 2
[5] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *(&(struct Point) point2) ← memcpy(*(&(struct Point) point1), struct Point, (const byte) SIZEOF_STRUCT_POINT)
[7] *((byte*)&(struct Point) point2) ← (byte) 4
[8] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point1)
[9] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y)
[10] *((const byte*) main::SCREEN+(byte) 2) ← *((byte*)&(struct Point) point2)
[11] *((const byte*) main::SCREEN+(byte) 3) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[8] return
[12] return
to:@return
@ -218,13 +134,17 @@ VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
(byte) point1_x
(byte) point1_y
(byte) point2_x
(byte) point2_y
(struct Point) point1 loadstore = {}
(struct Point) point2 loadstore = {}
Initial phi equivalence classes
Added variable point1 to live range equivalence class [ point1 ]
Added variable point2 to live range equivalence class [ point2 ]
Complete equivalence classes
[ point1 ]
[ point2 ]
Allocated mem[2] [ point1 ]
Allocated mem[2] [ point2 ]
INITIAL ASM
Target platform is c64basic / MOS6502X
@ -235,9 +155,8 @@ Target platform is c64basic / MOS6502X
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const point1_x = 2
.const point1_y = 3
.const point2_x = 4
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
@ -255,40 +174,64 @@ __bend:
// main
main: {
.label SCREEN = $400
// [4] *((const byte*) main::SCREEN) ← (const byte) point1_x#1 -- _deref_pbuc1=vbuc2
lda #point1_x
// [4] *((byte*)&(struct Point) point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta point1
// [5] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// [6] *(&(struct Point) point2) ← memcpy(*(&(struct Point) point1), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda point1-1,y
sta point2-1,y
dey
bne !-
// [7] *((byte*)&(struct Point) point2) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta point2
// [8] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point1) -- _deref_pbuc1=_deref_pbuc2
lda point1
sta SCREEN
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
// [9] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// [6] *((const byte*) main::SCREEN+(byte) 2) ← (const byte) point2_x#2 -- _deref_pbuc1=vbuc2
lda #point2_x
// [10] *((const byte*) main::SCREEN+(byte) 2) ← *((byte*)&(struct Point) point2) -- _deref_pbuc1=_deref_pbuc2
lda point2
sta SCREEN+2
// [7] *((const byte*) main::SCREEN+(byte) 3) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
// [11] *((const byte*) main::SCREEN+(byte) 3) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
jmp __breturn
// main::@return
__breturn:
// [8] return
// [12] return
rts
}
// File Data
point1: .fill SIZEOF_STRUCT_POINT, 0
point2: .fill SIZEOF_STRUCT_POINT, 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((const byte*) main::SCREEN) ← (const byte) point1_x#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point1_y#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] *((const byte*) main::SCREEN+(byte) 2) ← (const byte) point2_x#2 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [7] *((const byte*) main::SCREEN+(byte) 3) ← (const byte) point1_y#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [4] *((byte*)&(struct Point) point1) ← (byte) 2 [ point1 point2 ] ( main:2 [ point1 point2 ] ) always clobbers reg byte a
Statement [5] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ point1 point2 ] ( main:2 [ point1 point2 ] ) always clobbers reg byte a
Statement [6] *(&(struct Point) point2) ← memcpy(*(&(struct Point) point1), struct Point, (const byte) SIZEOF_STRUCT_POINT) [ point1 point2 ] ( main:2 [ point1 point2 ] ) always clobbers reg byte a reg byte y
Statement [7] *((byte*)&(struct Point) point2) ← (byte) 4 [ point1 point2 ] ( main:2 [ point1 point2 ] ) always clobbers reg byte a
Statement [8] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point1) [ point1 point2 ] ( main:2 [ point1 point2 ] ) always clobbers reg byte a
Statement [9] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) [ point2 ] ( main:2 [ point2 ] ) always clobbers reg byte a
Statement [10] *((const byte*) main::SCREEN+(byte) 2) ← *((byte*)&(struct Point) point2) [ point2 ] ( main:2 [ point2 ] ) always clobbers reg byte a
Statement [11] *((const byte*) main::SCREEN+(byte) 3) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers mem[2] [ point1 ] : mem[2] ,
Potential registers mem[2] [ point2 ] : mem[2] ,
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [main]
Uplift Scope []
Uplift Scope [] 0: mem[2] [ point1 ] 0: mem[2] [ point2 ]
Uplifting [Point] best 45 combination
Uplifting [main] best 45 combination
Uplifting [] best 45 combination
Uplifting [Point] best 87 combination
Uplifting [main] best 87 combination
Uplifting [] best 87 combination mem[2] [ point1 ] mem[2] [ point2 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -298,9 +241,8 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const point1_x = 2
.const point1_y = 3
.const point2_x = 4
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
@ -318,25 +260,43 @@ __bend:
// main
main: {
.label SCREEN = $400
// [4] *((const byte*) main::SCREEN) ← (const byte) point1_x#1 -- _deref_pbuc1=vbuc2
lda #point1_x
// [4] *((byte*)&(struct Point) point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta point1
// [5] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// [6] *(&(struct Point) point2) ← memcpy(*(&(struct Point) point1), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda point1-1,y
sta point2-1,y
dey
bne !-
// [7] *((byte*)&(struct Point) point2) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta point2
// [8] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point1) -- _deref_pbuc1=_deref_pbuc2
lda point1
sta SCREEN
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
// [9] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// [6] *((const byte*) main::SCREEN+(byte) 2) ← (const byte) point2_x#2 -- _deref_pbuc1=vbuc2
lda #point2_x
// [10] *((const byte*) main::SCREEN+(byte) 2) ← *((byte*)&(struct Point) point2) -- _deref_pbuc1=_deref_pbuc2
lda point2
sta SCREEN+2
// [7] *((const byte*) main::SCREEN+(byte) 3) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
// [11] *((const byte*) main::SCREEN+(byte) 3) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
jmp __breturn
// main::@return
__breturn:
// [8] return
// [12] return
rts
}
// File Data
point1: .fill SIZEOF_STRUCT_POINT, 0
point2: .fill SIZEOF_STRUCT_POINT, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
@ -361,23 +321,22 @@ FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(byte) point1_x
(const byte) point1_x#1 point1_x = (byte) 2
(byte) point1_y
(const byte) point1_y#1 point1_y = (byte) 3
(byte) point2_x
(const byte) point2_x#2 point2_x = (byte) 4
(byte) point2_y
(struct Point) point1 loadstore mem[2] = {}
(struct Point) point2 loadstore mem[2] = {}
mem[2] [ point1 ]
mem[2] [ point2 ]
FINAL ASSEMBLER
Score: 30
Score: 72
// File Comments
// Minimal struct - two instances being copied (using assignment)
@ -386,9 +345,8 @@ Score: 30
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const point1_x = 2
.const point1_y = 3
.const point2_x = 4
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
@ -398,26 +356,48 @@ Score: 30
// main
main: {
.label SCREEN = $400
// point1.x = 2
// [4] *((byte*)&(struct Point) point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta point1
// point1.y = 3
// [5] *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// point2 = point1
// [6] *(&(struct Point) point2) ← memcpy(*(&(struct Point) point1), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda point1-1,y
sta point2-1,y
dey
bne !-
// point2.x = 4
// [7] *((byte*)&(struct Point) point2) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta point2
// SCREEN[0] = point1.x
// [4] *((const byte*) main::SCREEN) ← (const byte) point1_x#1 -- _deref_pbuc1=vbuc2
lda #point1_x
// [8] *((const byte*) main::SCREEN) ← *((byte*)&(struct Point) point1) -- _deref_pbuc1=_deref_pbuc2
lda point1
sta SCREEN
// SCREEN[1] = point1.y
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
// [9] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// SCREEN[2] = point2.x
// [6] *((const byte*) main::SCREEN+(byte) 2) ← (const byte) point2_x#2 -- _deref_pbuc1=vbuc2
lda #point2_x
// [10] *((const byte*) main::SCREEN+(byte) 2) ← *((byte*)&(struct Point) point2) -- _deref_pbuc1=_deref_pbuc2
lda point2
sta SCREEN+2
// SCREEN[3] = point2.y
// [7] *((const byte*) main::SCREEN+(byte) 3) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
// [11] *((const byte*) main::SCREEN+(byte) 3) ← *((byte*)&(struct Point) point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
// main::@return
// }
// [8] return
// [12] return
rts
}
// File Data
point1: .fill SIZEOF_STRUCT_POINT, 0
point2: .fill SIZEOF_STRUCT_POINT, 0

View File

@ -1,16 +1,15 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(byte) point1_x
(const byte) point1_x#1 point1_x = (byte) 2
(byte) point1_y
(const byte) point1_y#1 point1_y = (byte) 3
(byte) point2_x
(const byte) point2_x#2 point2_x = (byte) 4
(byte) point2_y
(struct Point) point1 loadstore mem[2] = {}
(struct Point) point2 loadstore mem[2] = {}
mem[2] [ point1 ]
mem[2] [ point2 ]

View File

@ -0,0 +1,14 @@
// Struct - forced __ssa
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const point_x = 2
.const point_y = 3
main: {
lda #point_x
sta SCREEN
lda #point_y
sta SCREEN+1
rts
}

View File

@ -0,0 +1,18 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((const byte*) SCREEN) ← (const byte) point_x#1
[5] *((const byte*) SCREEN+(byte) 1) ← (const byte) point_y#1
to:main::@return
main::@return: scope:[main] from main
[6] return
to:@return

323
src/test/ref/struct-34.log Normal file
View File

@ -0,0 +1,323 @@
Created struct value member variable (byte) point_x
Created struct value member variable (byte) point_y
Converted struct value to member variables (struct Point) point
Adding struct value member variable copy (byte) point_x ← (byte) 0
Adding struct value member variable copy (byte) point_y ← (byte) 0
Replacing struct member reference (struct Point) point.x with member unwinding reference (byte) point_x
Replacing struct member reference (struct Point) point.y with member unwinding reference (byte) point_y
Replacing struct member reference (struct Point) point.x with member unwinding reference (byte) point_x
Replacing struct member reference (struct Point) point.y with member unwinding reference (byte) point_y
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte) point_x#0 ← (byte) 0
(byte) point_y#0 ← (byte) 0
to:@1
(void()) main()
main: scope:[main] from @1
(byte) point_x#1 ← (number) 2
(byte) point_y#1 ← (number) 3
*((const byte*) SCREEN + (number) 0) ← (byte) point_x#1
*((const byte*) SCREEN + (number) 1) ← (byte) point_y#1
to:main::@return
main::@return: scope:[main] from main
(byte) point_y#4 ← phi( main/(byte) point_y#1 )
(byte) point_x#4 ← phi( main/(byte) point_x#1 )
(byte) point_x#2 ← (byte) point_x#4
(byte) point_y#2 ← (byte) point_y#4
return
to:@return
@1: scope:[] from @begin
(byte) point_y#6 ← phi( @begin/(byte) point_y#0 )
(byte) point_x#6 ← phi( @begin/(byte) point_x#0 )
call main
to:@2
@2: scope:[] from @1
(byte) point_y#5 ← phi( @1/(byte) point_y#2 )
(byte) point_x#5 ← phi( @1/(byte) point_x#2 )
(byte) point_x#3 ← (byte) point_x#5
(byte) point_y#3 ← (byte) point_y#5
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @begin
(label) @end
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(void()) main()
(label) main::@return
(byte) point_x
(byte) point_x#0
(byte) point_x#1
(byte) point_x#2
(byte) point_x#3
(byte) point_x#4
(byte) point_x#5
(byte) point_x#6
(byte) point_y
(byte) point_y#0
(byte) point_y#1
(byte) point_y#2
(byte) point_y#3
(byte) point_y#4
(byte) point_y#5
(byte) point_y#6
Adding number conversion cast (unumber) 2 in (byte) point_x#1 ← (number) 2
Adding number conversion cast (unumber) 3 in (byte) point_y#1 ← (number) 3
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← (byte) point_x#1
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← (byte) point_y#1
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte) point_x#1 ← (unumber)(number) 2
Inlining cast (byte) point_y#1 ← (unumber)(number) 3
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 3
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte) point_x#1 = (byte) point_x#4 (byte) point_x#2
Alias (byte) point_y#1 = (byte) point_y#4 (byte) point_y#2
Alias (byte) point_x#0 = (byte) point_x#6
Alias (byte) point_y#0 = (byte) point_y#6
Alias (byte) point_x#3 = (byte) point_x#5
Alias (byte) point_y#3 = (byte) point_y#5
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte) point_x#3 (byte) point_x#1
Identical Phi Values (byte) point_y#3 (byte) point_y#1
Successful SSA optimization Pass2IdenticalPhiElimination
Constant (const byte) point_x#0 = 0
Constant (const byte) point_y#0 = 0
Constant (const byte) point_x#1 = 2
Constant (const byte) point_y#1 = 3
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero SCREEN in [4] *((const byte*) SCREEN + (byte) 0) ← (const byte) point_x#1
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) point_x#0
Eliminating unused constant (const byte) point_y#0
Successful SSA optimization PassNEliminateUnusedVars
Consolidated array index constant in *(SCREEN+1)
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 @end
CALL GRAPH
Calls in [] to main:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((const byte*) SCREEN) ← (const byte) point_x#1
[5] *((const byte*) SCREEN+(byte) 1) ← (const byte) point_y#1
to:main::@return
main::@return: scope:[main] from main
[6] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
(byte) point_x
(byte) point_y
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Struct - forced __ssa
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const point_x = 2
.const point_y = 3
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
// [4] *((const byte*) SCREEN) ← (const byte) point_x#1 -- _deref_pbuc1=vbuc2
lda #point_x
sta SCREEN
// [5] *((const byte*) SCREEN+(byte) 1) ← (const byte) point_y#1 -- _deref_pbuc1=vbuc2
lda #point_y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [6] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((const byte*) SCREEN) ← (const byte) point_x#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) SCREEN+(byte) 1) ← (const byte) point_y#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [main]
Uplift Scope []
Uplifting [Point] best 33 combination
Uplifting [main] best 33 combination
Uplifting [] best 33 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Struct - forced __ssa
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const point_x = 2
.const point_y = 3
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
// [4] *((const byte*) SCREEN) ← (const byte) point_x#1 -- _deref_pbuc1=vbuc2
lda #point_x
sta SCREEN
// [5] *((const byte*) SCREEN+(byte) 1) ← (const byte) point_y#1 -- _deref_pbuc1=vbuc2
lda #point_y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [6] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@return
(byte) point_x
(const byte) point_x#1 point_x = (byte) 2
(byte) point_y
(const byte) point_y#1 point_y = (byte) 3
FINAL ASSEMBLER
Score: 18
// File Comments
// Struct - forced __ssa
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const point_x = 2
.const point_y = 3
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
// SCREEN[0] = point.x
// [4] *((const byte*) SCREEN) ← (const byte) point_x#1 -- _deref_pbuc1=vbuc2
lda #point_x
sta SCREEN
// SCREEN[1] = point.y
// [5] *((const byte*) SCREEN+(byte) 1) ← (const byte) point_y#1 -- _deref_pbuc1=vbuc2
lda #point_y
sta SCREEN+1
// main::@return
// }
// [6] return
rts
}
// File Data

View File

@ -0,0 +1,13 @@
(label) @1
(label) @begin
(label) @end
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@return
(byte) point_x
(const byte) point_x#1 point_x = (byte) 2
(byte) point_y
(const byte) point_y#1 point_y = (byte) 3