1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-03 12:07:26 +00:00

Added test illustrating variable alive range propagation problem when using call stack.

This commit is contained in:
jespergravgaard 2020-03-01 23:02:07 +01:00
parent 7720eb8c13
commit 5d7533de5d
19 changed files with 2116 additions and 24 deletions

View File

@ -513,12 +513,8 @@ public class Compiler {
program.clearStatementInfos(); program.clearStatementInfos();
program.clearVariableReferenceInfos(); program.clearVariableReferenceInfos();
//getLog().append("CONTROL FLOW GRAPH - LIVE RANGES FOUND");
//getLog().append(program.getGraph().toString(program));
pass2AssertSSA(); pass2AssertSSA();
//getLog().setVerboseLiveRanges(false);
// Phi mem coalesce removes as many variables introduced by phi lifting as possible - as long as their live ranges do not overlap // Phi mem coalesce removes as many variables introduced by phi lifting as possible - as long as their live ranges do not overlap
new Pass3PhiMemCoalesce(program).step(); new Pass3PhiMemCoalesce(program).step();
new PassNCullEmptyBlocks(program).step(); new PassNCullEmptyBlocks(program).step();
@ -539,6 +535,12 @@ public class Compiler {
new PassNStatementIndices(program).execute(); new PassNStatementIndices(program).execute();
pass2AssertSSA(); pass2AssertSSA();
// program.getLiveRangeVariablesEffective();
// getLog().append("CONTROL FLOW GRAPH - LIVE RANGES FOUND");
// getLog().append(program.getGraph().toString(program));
program.getLiveRangeVariablesEffective();
getLog().append("\nFINAL CONTROL FLOW GRAPH"); getLog().append("\nFINAL CONTROL FLOW GRAPH");
getLog().append(program.getGraph().toString(program)); getLog().append(program.getGraph().toString(program));

View File

@ -381,9 +381,14 @@ public class Program {
return symbolInfos; return symbolInfos;
} }
public boolean hasLiveRangeVariablesEffective() {
return liveRangeVariablesEffective!=null;
}
public LiveRangeVariablesEffective getLiveRangeVariablesEffective() { public LiveRangeVariablesEffective getLiveRangeVariablesEffective() {
if(liveRangeVariablesEffective==null) if(liveRangeVariablesEffective==null) {
this.liveRangeVariablesEffective = new PassNCalcLiveRangesEffective(this).calculate(); this.liveRangeVariablesEffective = new PassNCalcLiveRangesEffective(this).calculate();
}
return liveRangeVariablesEffective; return liveRangeVariablesEffective;
} }

View File

@ -81,16 +81,18 @@ public abstract class StatementBase implements Statement {
LiveRangeVariables liveRanges = program.getLiveRangeVariables(); LiveRangeVariables liveRanges = program.getLiveRangeVariables();
StringBuilder alive = new StringBuilder(); StringBuilder alive = new StringBuilder();
alive.append(getAliveString(liveRanges.getAlive(index))); alive.append(getAliveString(liveRanges.getAlive(index)));
LiveRangeVariablesEffective liveRangeVariablesEffective = program.getLiveRangeVariablesEffective(); if(program.hasLiveRangeVariablesEffective()) {
if(liveRangeVariablesEffective != null) { LiveRangeVariablesEffective liveRangeVariablesEffective = program.getLiveRangeVariablesEffective();
LiveRangeVariablesEffective.AliveCombinations aliveCombinations = liveRangeVariablesEffective.getAliveCombinations(this); if(liveRangeVariablesEffective != null) {
alive.append(" ( "); LiveRangeVariablesEffective.AliveCombinations aliveCombinations = liveRangeVariablesEffective.getAliveCombinations(this);
for(LiveRangeVariablesEffective.CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) { alive.append(" ( ");
alive.append(getCallPathString(callPath.getPath())); for(LiveRangeVariablesEffective.CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) {
alive.append(getAliveString(aliveCombinations.getEffectiveAliveAtStmt(callPath))); alive.append(getCallPathString(callPath.getPath()));
alive.append(" "); alive.append(getAliveString(aliveCombinations.getEffectiveAliveAtStmt(callPath)));
alive.append(" ");
}
alive.append(")");
} }
alive.append(")");
} }
return alive.toString(); return alive.toString();
} }

View File

@ -279,19 +279,20 @@ public class TestPrograms {
compileAndCompare("declared-memory-var-0"); compileAndCompare("declared-memory-var-0");
} }
/* @Test
public void testProcedureCallingConventionStack9() throws IOException, URISyntaxException {
compileAndCompare("procedure-callingconvention-stack-9");
}
@Test @Test
public void testProcedureCallingConventionStack8() throws IOException, URISyntaxException { public void testProcedureCallingConventionStack8() throws IOException, URISyntaxException {
compileAndCompare("procedure-callingconvention-stack-8", log().verboseLiveRanges()); //, log().verboseCreateSsa().verboseParse().verboseStatementSequence()); compileAndCompare("procedure-callingconvention-stack-8");
} }
*/
/*
@Test @Test
public void testProcedureCallingConventionStack7() throws IOException, URISyntaxException { public void testProcedureCallingConventionStack7() throws IOException, URISyntaxException {
compileAndCompare("procedure-callingconvention-stack-7", log().verboseLiveRanges()); //, log().verboseCreateSsa().verboseParse().verboseStatementSequence()); compileAndCompare("procedure-callingconvention-stack-7");
} }
*/
/* /*
@Test @Test

View File

@ -1,5 +1,5 @@
// Test a procedure with calling convention stack // Test a procedure with calling convention stack
// Illustrates live range problem with variables in different functions main::val and printline::i // Illustrates live ranges for main::val and printline::i
#pragma calling(__stackcall) #pragma calling(__stackcall)
#pragma var_model(ma_zp) #pragma var_model(ma_zp)
@ -7,8 +7,8 @@
const char* SCREEN = 0x0400; const char* SCREEN = 0x0400;
void main(void) { void main(void) {
char val = 0; char val;
val = '-'; val = *SCREEN;
printline(); printline();
SCREEN[80] = val; SCREEN[80] = val;
} }

View File

@ -1,5 +1,5 @@
// Test a procedure with calling convention stack // Test a procedure with calling convention stack
// Illustrates live range problem with variable function printline::i and global variable val // Illustrates live ranges for printline::i and global variable val
#pragma calling(__stackcall) #pragma calling(__stackcall)
#pragma var_model(ma_zp) #pragma var_model(ma_zp)

View File

@ -0,0 +1,44 @@
// Test a procedure with calling convention stack
// Illustrates live range problem with function variable printother::i and global variable val
#pragma calling(__stackcall)
#pragma var_model(ma_zp)
const char* SCREEN = 0x0400;
char val = 0;
void main(void) {
for(char i:0..5) {
pval();
printother();
ival();
}
}
void pval() {
printval();
}
void ival() {
incval();
}
void printval() {
SCREEN[0] = val;
}
void incval() {
val++;
}
void printother() {
for(char i:0..5) {
(SCREEN+40)[i]++;
}
}

View File

@ -0,0 +1,46 @@
// Test a procedure with calling convention stack
// Illustrates live ranges for main::val and printline::i
.pc = $801 "Basic"
:BasicUpstart(__b1)
.pc = $80d "Program"
.label SCREEN = $400
__b1:
jsr main
rts
printline: {
.label i = 2
// i=0
lda #0
sta.z i
__b1:
// for(char i=0; i<40; i++)
lda.z i
cmp #$28
bcc __b2
// }
rts
__b2:
// SCREEN[i] = '*'
lda #'*'
ldy.z i
sta SCREEN,y
// for(char i=0; i<40; i++)
inc.z i
jmp __b1
}
main: {
.label val = 3
// val
lda #0
sta.z val
// val = *SCREEN
lda SCREEN
sta.z val
// printline()
jsr printline
// SCREEN[80] = val
lda.z val
sta SCREEN+$50
// }
rts
}

View File

@ -0,0 +1,39 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] callprepare main
[3] callexecute main
[4] callfinalize main
to:@end
@end: scope:[] from @1
[5] phi()
__stackcall (void()) printline()
printline: scope:[printline] from
[6] (byte) printline::i ← (byte) 0
to:printline::@1
printline::@1: scope:[printline] from printline printline::@2
[7] if((byte) printline::i<(byte) $28) goto printline::@2
to:printline::@return
printline::@return: scope:[printline] from printline::@1
[8] return
to:@return
printline::@2: scope:[printline] from printline::@1
[9] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*'
[10] (byte) printline::i ← ++ (byte) printline::i
to:printline::@1
__stackcall (void()) main()
main: scope:[main] from
[11] (byte) main::val ← (byte) 0
[12] (byte) main::val ← *((const byte*) SCREEN)
[13] callprepare printline
[14] callexecute printline
[15] callfinalize printline
[16] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val
to:main::@return
main::@return: scope:[main] from main
[17] return
to:@return

View File

@ -0,0 +1,440 @@
Culled Empty Block (label) @1
Culled Empty Block (label) printline::@4
Culled Empty Block (label) printline::@3
Culled Empty Block (label) printline::@5
Culled Empty Block (label) printline::@6
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@2
__stackcall (void()) main()
main: scope:[main] from
(byte) main::val ← (byte) 0
(byte) main::val ← *((const byte*) SCREEN)
call printline
*((const byte*) SCREEN + (number) $50) ← (byte) main::val
to:main::@return
main::@return: scope:[main] from main
return
to:@return
__stackcall (void()) printline()
printline: scope:[printline] from
(byte) printline::i ← (byte) 0
to:printline::@1
printline::@1: scope:[printline] from printline printline::@2
(bool~) printline::$0 ← (byte) printline::i < (number) $28
if((bool~) printline::$0) goto printline::@2
to:printline::@return
printline::@2: scope:[printline] from printline::@1
*((const byte*) SCREEN + (byte) printline::i) ← (byte) '*'
(byte) printline::i ← ++ (byte) printline::i
to:printline::@1
printline::@return: scope:[printline] from printline::@1
return
to:@return
@2: scope:[] from @begin
call main
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(label) @2
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*)(number) $400
__stackcall (void()) main()
(label) main::@return
(byte) main::val loadstore
__stackcall (void()) printline()
(bool~) printline::$0
(label) printline::@1
(label) printline::@2
(label) printline::@return
(byte) printline::i loadstore
Adding number conversion cast (unumber) $50 in *((const byte*) SCREEN + (number) $50) ← (byte) main::val
Adding number conversion cast (unumber) $28 in (bool~) printline::$0 ← (byte) printline::i < (number) $28
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast $50
Simplifying constant integer cast $28
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) $50
Finalized unsigned number type (byte) $28
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simple Condition (bool~) printline::$0 [7] if((byte) printline::i<(byte) $28) goto printline::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Consolidated array index constant in *(SCREEN+$50)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
CALL GRAPH
Calls in [] to main:2
Calls in [main] to printline:11
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Renumbering block @2 to @1
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Calling convention STACK_CALL adding prepare/execute/finalize for [2] call main
Calling convention STACK_CALL adding prepare/execute/finalize for [11] call printline
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] callprepare main
[3] callexecute main
[4] callfinalize main
to:@end
@end: scope:[] from @1
[5] phi()
__stackcall (void()) printline()
printline: scope:[printline] from
[6] (byte) printline::i ← (byte) 0
to:printline::@1
printline::@1: scope:[printline] from printline printline::@2
[7] if((byte) printline::i<(byte) $28) goto printline::@2
to:printline::@return
printline::@return: scope:[printline] from printline::@1
[8] return
to:@return
printline::@2: scope:[printline] from printline::@1
[9] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*'
[10] (byte) printline::i ← ++ (byte) printline::i
to:printline::@1
__stackcall (void()) main()
main: scope:[main] from
[11] (byte) main::val ← (byte) 0
[12] (byte) main::val ← *((const byte*) SCREEN)
[13] callprepare printline
[14] callexecute printline
[15] callfinalize printline
[16] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val
to:main::@return
main::@return: scope:[main] from main
[17] return
to:@return
VARIABLE REGISTER WEIGHTS
__stackcall (void()) main()
(byte) main::val loadstore 1.5
__stackcall (void()) printline()
(byte) printline::i loadstore 11.5
Initial phi equivalence classes
Added variable printline::i to live range equivalence class [ printline::i ]
Added variable main::val to live range equivalence class [ main::val ]
Complete equivalence classes
[ printline::i ]
[ main::val ]
Allocated zp[1]:2 [ printline::i ]
Allocated zp[1]:3 [ main::val ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Test a procedure with calling convention stack
// Illustrates live ranges for main::val and printline::i
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] callprepare main
// [3] callexecute main -- jsr
jsr main
// [4] callfinalize main
// [5] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// printline
printline: {
.label i = 2
// [6] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// printline::@1
__b1:
// [7] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #$28
bcc __b2
jmp __breturn
// printline::@return
__breturn:
// [8] return
rts
// printline::@2
__b2:
// [9] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
lda #'*'
ldy.z i
sta SCREEN,y
// [10] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
// main
main: {
.label val = 3
// [11] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z val
// [12] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1
lda SCREEN
sta.z val
// [13] callprepare printline
// [14] callexecute printline -- jsr
jsr printline
// [15] callfinalize printline
// [16] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN+$50
jmp __breturn
// main::@return
__breturn:
// [17] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] (byte) printline::i ← (byte) 0 [ printline::i ] ( main:3::printline:14 [ main::val printline::i ] ) always clobbers reg byte a
Statement [7] if((byte) printline::i<(byte) $28) goto printline::@2 [ printline::i ] ( main:3::printline:14 [ main::val printline::i ] ) always clobbers reg byte a
Statement [9] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' [ printline::i ] ( main:3::printline:14 [ main::val printline::i ] ) always clobbers reg byte a reg byte y
Statement [11] (byte) main::val ← (byte) 0 [ ] ( main:3 [ ] ) always clobbers reg byte a
Statement [12] (byte) main::val ← *((const byte*) SCREEN) [ main::val ] ( main:3 [ main::val ] ) always clobbers reg byte a
Statement [16] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val [ ] ( main:3 [ ] ) always clobbers reg byte a
Potential registers zp[1]:2 [ printline::i ] : zp[1]:2 ,
Potential registers zp[1]:3 [ main::val ] : zp[1]:3 ,
REGISTER UPLIFT SCOPES
Uplift Scope [printline] 11.5: zp[1]:2 [ printline::i ]
Uplift Scope [main] 1.5: zp[1]:3 [ main::val ]
Uplift Scope []
Uplifting [printline] best 345 combination zp[1]:2 [ printline::i ]
Uplifting [main] best 345 combination zp[1]:3 [ main::val ]
Uplifting [] best 345 combination
Attempting to uplift remaining variables inzp[1]:2 [ printline::i ]
Uplifting [printline] best 345 combination zp[1]:2 [ printline::i ]
Attempting to uplift remaining variables inzp[1]:3 [ main::val ]
Uplifting [main] best 345 combination zp[1]:3 [ main::val ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test a procedure with calling convention stack
// Illustrates live ranges for main::val and printline::i
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] callprepare main
// [3] callexecute main -- jsr
jsr main
// [4] callfinalize main
// [5] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// printline
printline: {
.label i = 2
// [6] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// printline::@1
__b1:
// [7] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #$28
bcc __b2
jmp __breturn
// printline::@return
__breturn:
// [8] return
rts
// printline::@2
__b2:
// [9] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
lda #'*'
ldy.z i
sta SCREEN,y
// [10] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
// main
main: {
.label val = 3
// [11] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z val
// [12] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1
lda SCREEN
sta.z val
// [13] callprepare printline
// [14] callexecute printline -- jsr
jsr printline
// [15] callfinalize printline
// [16] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN+$50
jmp __breturn
// main::@return
__breturn:
// [17] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __b1
Removing instruction jmp __breturn
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:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
__stackcall (void()) main()
(label) main::@return
(byte) main::val loadstore zp[1]:3 1.5
__stackcall (void()) printline()
(label) printline::@1
(label) printline::@2
(label) printline::@return
(byte) printline::i loadstore zp[1]:2 11.5
zp[1]:2 [ printline::i ]
zp[1]:3 [ main::val ]
FINAL ASSEMBLER
Score: 309
// File Comments
// Test a procedure with calling convention stack
// Illustrates live ranges for main::val and printline::i
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__b1)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
__b1:
// [2] callprepare main
// [3] callexecute main -- jsr
jsr main
rts
// [4] callfinalize main
// [5] phi from @1 to @end [phi:@1->@end]
// @end
// printline
printline: {
.label i = 2
// i=0
// [6] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
// printline::@1
__b1:
// for(char i=0; i<40; i++)
// [7] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #$28
bcc __b2
// printline::@return
// }
// [8] return
rts
// printline::@2
__b2:
// SCREEN[i] = '*'
// [9] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
lda #'*'
ldy.z i
sta SCREEN,y
// for(char i=0; i<40; i++)
// [10] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
// main
main: {
.label val = 3
// val
// [11] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z val
// val = *SCREEN
// [12] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1
lda SCREEN
sta.z val
// printline()
// [13] callprepare printline
// [14] callexecute printline -- jsr
jsr printline
// [15] callfinalize printline
// SCREEN[80] = val
// [16] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN+$50
// main::@return
// }
// [17] return
rts
}
// File Data

View File

@ -0,0 +1,15 @@
(label) @1
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
__stackcall (void()) main()
(label) main::@return
(byte) main::val loadstore zp[1]:3 1.5
__stackcall (void()) printline()
(label) printline::@1
(label) printline::@2
(label) printline::@return
(byte) printline::i loadstore zp[1]:2 11.5
zp[1]:2 [ printline::i ]
zp[1]:3 [ main::val ]

View File

@ -0,0 +1,46 @@
// Test a procedure with calling convention stack
// Illustrates live ranges for printline::i and global variable val
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
.label SCREEN = $400
.label val = 2
__bbegin:
// val = 0
lda #0
sta.z val
jsr main
rts
printline: {
.label i = 3
// i=0
lda #0
sta.z i
__b1:
// for(char i=0; i<40; i++)
lda.z i
cmp #$28
bcc __b2
// }
rts
__b2:
// SCREEN[i] = '*'
lda #'*'
ldy.z i
sta SCREEN,y
// for(char i=0; i<40; i++)
inc.z i
jmp __b1
}
main: {
// val = '-'
lda #'-'
sta.z val
// printline()
jsr printline
// SCREEN[80] = val
lda.z val
sta SCREEN+$50
// }
rts
}

View File

@ -0,0 +1,38 @@
@begin: scope:[] from
[0] (byte) val ← (byte) 0
to:@1
@1: scope:[] from @begin
[1] phi()
[2] callprepare main
[3] callexecute main
[4] callfinalize main
to:@end
@end: scope:[] from @1
[5] phi()
__stackcall (void()) printline()
printline: scope:[printline] from
[6] (byte) printline::i ← (byte) 0
to:printline::@1
printline::@1: scope:[printline] from printline printline::@2
[7] if((byte) printline::i<(byte) $28) goto printline::@2
to:printline::@return
printline::@return: scope:[printline] from printline::@1
[8] return
to:@return
printline::@2: scope:[printline] from printline::@1
[9] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*'
[10] (byte) printline::i ← ++ (byte) printline::i
to:printline::@1
__stackcall (void()) main()
main: scope:[main] from
[11] (byte) val ← (byte) '-'
[12] callprepare printline
[13] callexecute printline
[14] callfinalize printline
[15] *((const byte*) SCREEN+(byte) $50) ← (byte) val
to:main::@return
main::@return: scope:[main] from main
[16] return
to:@return

View File

@ -0,0 +1,436 @@
Culled Empty Block (label) @1
Culled Empty Block (label) printline::@4
Culled Empty Block (label) printline::@3
Culled Empty Block (label) printline::@5
Culled Empty Block (label) printline::@6
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte) val ← (byte) 0
to:@2
__stackcall (void()) main()
main: scope:[main] from
(byte) val ← (byte) '-'
call printline
*((const byte*) SCREEN + (number) $50) ← (byte) val
to:main::@return
main::@return: scope:[main] from main
return
to:@return
__stackcall (void()) printline()
printline: scope:[printline] from
(byte) printline::i ← (byte) 0
to:printline::@1
printline::@1: scope:[printline] from printline printline::@2
(bool~) printline::$0 ← (byte) printline::i < (number) $28
if((bool~) printline::$0) goto printline::@2
to:printline::@return
printline::@2: scope:[printline] from printline::@1
*((const byte*) SCREEN + (byte) printline::i) ← (byte) '*'
(byte) printline::i ← ++ (byte) printline::i
to:printline::@1
printline::@return: scope:[printline] from printline::@1
return
to:@return
@2: scope:[] from @begin
call main
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(label) @2
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*)(number) $400
__stackcall (void()) main()
(label) main::@return
__stackcall (void()) printline()
(bool~) printline::$0
(label) printline::@1
(label) printline::@2
(label) printline::@return
(byte) printline::i loadstore
(byte) val loadstore
Adding number conversion cast (unumber) $50 in *((const byte*) SCREEN + (number) $50) ← (byte) val
Adding number conversion cast (unumber) $28 in (bool~) printline::$0 ← (byte) printline::i < (number) $28
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast $50
Simplifying constant integer cast $28
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) $50
Finalized unsigned number type (byte) $28
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simple Condition (bool~) printline::$0 [7] if((byte) printline::i<(byte) $28) goto printline::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Consolidated array index constant in *(SCREEN+$50)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
CALL GRAPH
Calls in [] to main:2
Calls in [main] to printline:10
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Renumbering block @2 to @1
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Calling convention STACK_CALL adding prepare/execute/finalize for [2] call main
Calling convention STACK_CALL adding prepare/execute/finalize for [10] call printline
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] (byte) val ← (byte) 0
to:@1
@1: scope:[] from @begin
[1] phi()
[2] callprepare main
[3] callexecute main
[4] callfinalize main
to:@end
@end: scope:[] from @1
[5] phi()
__stackcall (void()) printline()
printline: scope:[printline] from
[6] (byte) printline::i ← (byte) 0
to:printline::@1
printline::@1: scope:[printline] from printline printline::@2
[7] if((byte) printline::i<(byte) $28) goto printline::@2
to:printline::@return
printline::@return: scope:[printline] from printline::@1
[8] return
to:@return
printline::@2: scope:[printline] from printline::@1
[9] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*'
[10] (byte) printline::i ← ++ (byte) printline::i
to:printline::@1
__stackcall (void()) main()
main: scope:[main] from
[11] (byte) val ← (byte) '-'
[12] callprepare printline
[13] callexecute printline
[14] callfinalize printline
[15] *((const byte*) SCREEN+(byte) $50) ← (byte) val
to:main::@return
main::@return: scope:[main] from main
[16] return
to:@return
VARIABLE REGISTER WEIGHTS
__stackcall (void()) main()
__stackcall (void()) printline()
(byte) printline::i loadstore 11.5
(byte) val loadstore 1.5
Initial phi equivalence classes
Added variable val to live range equivalence class [ val ]
Added variable printline::i to live range equivalence class [ printline::i ]
Complete equivalence classes
[ val ]
[ printline::i ]
Allocated zp[1]:2 [ val ]
Allocated zp[1]:3 [ printline::i ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Test a procedure with calling convention stack
// Illustrates live ranges for printline::i and global variable val
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label val = 2
// @begin
__bbegin:
// [0] (byte) val ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z val
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] callprepare main
// [3] callexecute main -- jsr
jsr main
// [4] callfinalize main
// [5] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// printline
printline: {
.label i = 3
// [6] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// printline::@1
__b1:
// [7] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #$28
bcc __b2
jmp __breturn
// printline::@return
__breturn:
// [8] return
rts
// printline::@2
__b2:
// [9] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
lda #'*'
ldy.z i
sta SCREEN,y
// [10] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
// main
main: {
// [11] (byte) val ← (byte) '-' -- vbuz1=vbuc1
lda #'-'
sta.z val
// [12] callprepare printline
// [13] callexecute printline -- jsr
jsr printline
// [14] callfinalize printline
// [15] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN+$50
jmp __breturn
// main::@return
__breturn:
// [16] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (byte) val ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a
Statement [6] (byte) printline::i ← (byte) 0 [ printline::i ] ( main:3::printline:13 [ val printline::i ] ) always clobbers reg byte a
Statement [7] if((byte) printline::i<(byte) $28) goto printline::@2 [ printline::i ] ( main:3::printline:13 [ val printline::i ] ) always clobbers reg byte a
Statement [9] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' [ printline::i ] ( main:3::printline:13 [ val printline::i ] ) always clobbers reg byte a reg byte y
Statement [11] (byte) val ← (byte) '-' [ val ] ( main:3 [ val ] ) always clobbers reg byte a
Statement [15] *((const byte*) SCREEN+(byte) $50) ← (byte) val [ ] ( main:3 [ ] ) always clobbers reg byte a
Potential registers zp[1]:2 [ val ] : zp[1]:2 ,
Potential registers zp[1]:3 [ printline::i ] : zp[1]:3 ,
REGISTER UPLIFT SCOPES
Uplift Scope [printline] 11.5: zp[1]:3 [ printline::i ]
Uplift Scope [] 1.5: zp[1]:2 [ val ]
Uplift Scope [main]
Uplifting [printline] best 343 combination zp[1]:3 [ printline::i ]
Uplifting [] best 343 combination zp[1]:2 [ val ]
Uplifting [main] best 343 combination
Attempting to uplift remaining variables inzp[1]:3 [ printline::i ]
Uplifting [printline] best 343 combination zp[1]:3 [ printline::i ]
Attempting to uplift remaining variables inzp[1]:2 [ val ]
Uplifting [] best 343 combination zp[1]:2 [ val ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test a procedure with calling convention stack
// Illustrates live ranges for printline::i and global variable val
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label val = 2
// @begin
__bbegin:
// [0] (byte) val ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z val
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] callprepare main
// [3] callexecute main -- jsr
jsr main
// [4] callfinalize main
// [5] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// printline
printline: {
.label i = 3
// [6] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// printline::@1
__b1:
// [7] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #$28
bcc __b2
jmp __breturn
// printline::@return
__breturn:
// [8] return
rts
// printline::@2
__b2:
// [9] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
lda #'*'
ldy.z i
sta SCREEN,y
// [10] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
// main
main: {
// [11] (byte) val ← (byte) '-' -- vbuz1=vbuc1
lda #'-'
sta.z val
// [12] callprepare printline
// [13] callexecute printline -- jsr
jsr printline
// [14] callfinalize printline
// [15] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN+$50
jmp __breturn
// main::@return
__breturn:
// [16] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __b1
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
Removing instruction __bend:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
__stackcall (void()) main()
(label) main::@return
__stackcall (void()) printline()
(label) printline::@1
(label) printline::@2
(label) printline::@return
(byte) printline::i loadstore zp[1]:3 11.5
(byte) val loadstore zp[1]:2 1.5
zp[1]:2 [ val ]
zp[1]:3 [ printline::i ]
FINAL ASSEMBLER
Score: 307
// File Comments
// Test a procedure with calling convention stack
// Illustrates live ranges for printline::i and global variable val
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label val = 2
// @begin
__bbegin:
// val = 0
// [0] (byte) val ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z val
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] callprepare main
// [3] callexecute main -- jsr
jsr main
rts
// [4] callfinalize main
// [5] phi from @1 to @end [phi:@1->@end]
// @end
// printline
printline: {
.label i = 3
// i=0
// [6] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
// printline::@1
__b1:
// for(char i=0; i<40; i++)
// [7] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #$28
bcc __b2
// printline::@return
// }
// [8] return
rts
// printline::@2
__b2:
// SCREEN[i] = '*'
// [9] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
lda #'*'
ldy.z i
sta SCREEN,y
// for(char i=0; i<40; i++)
// [10] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
// main
main: {
// val = '-'
// [11] (byte) val ← (byte) '-' -- vbuz1=vbuc1
lda #'-'
sta.z val
// printline()
// [12] callprepare printline
// [13] callexecute printline -- jsr
jsr printline
// [14] callfinalize printline
// SCREEN[80] = val
// [15] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN+$50
// main::@return
// }
// [16] return
rts
}
// File Data

View File

@ -0,0 +1,15 @@
(label) @1
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
__stackcall (void()) main()
(label) main::@return
__stackcall (void()) printline()
(label) printline::@1
(label) printline::@2
(label) printline::@return
(byte) printline::i loadstore zp[1]:3 11.5
(byte) val loadstore zp[1]:2 1.5
zp[1]:2 [ val ]
zp[1]:3 [ printline::i ]

View File

@ -0,0 +1,75 @@
// Test a procedure with calling convention stack
// Illustrates live range problem with function variable printother::i and global variable val
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
.label SCREEN = $400
.label val = 2
__bbegin:
// val = 0
lda #0
sta.z val
jsr main
rts
printother: {
.label i = 2
// for(char i:0..5)
lda #0
sta.z i
__b1:
// (SCREEN+40)[i]++;
ldx.z i
inc SCREEN+$28,x
// for(char i:0..5)
inc.z i
lda #6
cmp.z i
bne __b1
// }
rts
}
incval: {
// val++;
inc.z val
// }
rts
}
printval: {
// SCREEN[0] = val
lda.z val
sta SCREEN
// }
rts
}
ival: {
// incval()
jsr incval
// }
rts
}
pval: {
// printval()
jsr printval
// }
rts
}
main: {
.label i = 3
// for(char i:0..5)
lda #0
sta.z i
__b1:
// pval()
jsr pval
// printother()
jsr printother
// ival()
jsr ival
// for(char i:0..5)
inc.z i
lda #6
cmp.z i
bne __b1
// }
rts
}

View File

@ -0,0 +1,84 @@
@begin: scope:[] from
[0] (byte) val ← (byte) 0
to:@1
@1: scope:[] from @begin
[1] phi()
[2] callprepare main
[3] callexecute main
[4] callfinalize main
to:@end
@end: scope:[] from @1
[5] phi()
__stackcall (void()) printother()
printother: scope:[printother] from
[6] (byte) printother::i ← (byte) 0
to:printother::@1
printother::@1: scope:[printother] from printother printother::@1
[7] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i)
[8] (byte) printother::i ← ++ (byte) printother::i
[9] if((byte) printother::i!=(byte) 6) goto printother::@1
to:printother::@return
printother::@return: scope:[printother] from printother::@1
[10] return
to:@return
__stackcall (void()) incval()
incval: scope:[incval] from
[11] (byte) val ← ++ (byte) val
to:incval::@return
incval::@return: scope:[incval] from incval
[12] return
to:@return
__stackcall (void()) printval()
printval: scope:[printval] from
[13] *((const byte*) SCREEN) ← (byte) val
to:printval::@return
printval::@return: scope:[printval] from printval
[14] return
to:@return
__stackcall (void()) ival()
ival: scope:[ival] from
[15] phi()
[16] callprepare incval
[17] callexecute incval
[18] callfinalize incval
to:ival::@return
ival::@return: scope:[ival] from ival
[19] return
to:@return
__stackcall (void()) pval()
pval: scope:[pval] from
[20] phi()
[21] callprepare printval
[22] callexecute printval
[23] callfinalize printval
to:pval::@return
pval::@return: scope:[pval] from pval
[24] return
to:@return
__stackcall (void()) main()
main: scope:[main] from
[25] (byte) main::i ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@1
[26] phi()
[27] callprepare pval
[28] callexecute pval
[29] callfinalize pval
[30] callprepare printother
[31] callexecute printother
[32] callfinalize printother
[33] callprepare ival
[34] callexecute ival
[35] callfinalize ival
[36] (byte) main::i ← ++ (byte) main::i
[37] if((byte) main::i!=(byte) 6) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[38] return
to:@return

View File

@ -0,0 +1,780 @@
Culled Empty Block (label) main::@2
Culled Empty Block (label) @1
Culled Empty Block (label) @2
Culled Empty Block (label) @3
Culled Empty Block (label) @4
Culled Empty Block (label) @5
Culled Empty Block (label) printother::@2
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte) val ← (byte) 0
to:@6
__stackcall (void()) main()
main: scope:[main] from
(byte) main::i ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@1
call pval
call printother
call ival
(byte) main::i ← (byte) main::i + rangenext(0,5)
(bool~) main::$3 ← (byte) main::i != rangelast(0,5)
if((bool~) main::$3) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
return
to:@return
__stackcall (void()) pval()
pval: scope:[pval] from
call printval
to:pval::@return
pval::@return: scope:[pval] from pval
return
to:@return
__stackcall (void()) ival()
ival: scope:[ival] from
call incval
to:ival::@return
ival::@return: scope:[ival] from ival
return
to:@return
__stackcall (void()) printval()
printval: scope:[printval] from
*((const byte*) SCREEN + (number) 0) ← (byte) val
to:printval::@return
printval::@return: scope:[printval] from printval
return
to:@return
__stackcall (void()) incval()
incval: scope:[incval] from
(byte) val ← ++ (byte) val
to:incval::@return
incval::@return: scope:[incval] from incval
return
to:@return
__stackcall (void()) printother()
printother: scope:[printother] from
(byte) printother::i ← (byte) 0
to:printother::@1
printother::@1: scope:[printother] from printother printother::@1
*((const byte*) SCREEN+(number) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(number) $28 + (byte) printother::i)
(byte) printother::i ← (byte) printother::i + rangenext(0,5)
(bool~) printother::$1 ← (byte) printother::i != rangelast(0,5)
if((bool~) printother::$1) goto printother::@1
to:printother::@return
printother::@return: scope:[printother] from printother::@1
return
to:@return
@6: scope:[] from @begin
call main
to:@end
@end: scope:[] from @6
SYMBOL TABLE SSA
(label) @6
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*)(number) $400
__stackcall (void()) incval()
(label) incval::@return
__stackcall (void()) ival()
(label) ival::@return
__stackcall (void()) main()
(bool~) main::$3
(label) main::@1
(label) main::@return
(byte) main::i loadstore
__stackcall (void()) printother()
(bool~) printother::$1
(label) printother::@1
(label) printother::@return
(byte) printother::i loadstore
__stackcall (void()) printval()
(label) printval::@return
__stackcall (void()) pval()
(label) pval::@return
(byte) val loadstore
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← (byte) val
Adding number conversion cast (unumber) $28 in *((const byte*) SCREEN+(number) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(number) $28 + (byte) printother::i)
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast $28
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) $28
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simple Condition (bool~) main::$3 [7] if((byte) main::i!=rangelast(0,5)) goto main::@1
Simple Condition (bool~) printother::$1 [21] if((byte) printother::i!=rangelast(0,5)) goto printother::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Resolved ranged next value [5] main::i ← ++ main::i to ++
Resolved ranged comparison value [7] if(main::i!=rangelast(0,5)) goto main::@1 to (number) 6
Resolved ranged next value [19] printother::i ← ++ printother::i to ++
Resolved ranged comparison value [21] if(printother::i!=rangelast(0,5)) goto printother::@1 to (number) 6
Simplifying expression containing zero SCREEN in [13] *((const byte*) SCREEN + (byte) 0) ← (byte) val
Successful SSA optimization PassNSimplifyExpressionWithZero
Adding number conversion cast (unumber) 6 in if((byte) main::i!=(number) 6) goto main::@1
Adding number conversion cast (unumber) 6 in if((byte) printother::i!=(number) 6) goto printother::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 6
Simplifying constant integer cast 6
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 6
Finalized unsigned number type (byte) 6
Successful SSA optimization PassNFinalizeNumberTypeConversions
Adding NOP phi() at start of @6
Adding NOP phi() at start of @end
Adding NOP phi() at start of ival
Adding NOP phi() at start of pval
Adding NOP phi() at start of main::@1
CALL GRAPH
Calls in [] to main:2
Calls in [ival] to incval:14
Calls in [pval] to printval:17
Calls in [main] to pval:21 printother:22 ival:23
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Renumbering block @6 to @1
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of ival
Adding NOP phi() at start of pval
Adding NOP phi() at start of main::@1
Calling convention STACK_CALL adding prepare/execute/finalize for [2] call main
Calling convention STACK_CALL adding prepare/execute/finalize for [14] call incval
Calling convention STACK_CALL adding prepare/execute/finalize for [17] call printval
Calling convention STACK_CALL adding prepare/execute/finalize for [21] call pval
Calling convention STACK_CALL adding prepare/execute/finalize for [22] call printother
Calling convention STACK_CALL adding prepare/execute/finalize for [23] call ival
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] (byte) val ← (byte) 0
to:@1
@1: scope:[] from @begin
[1] phi()
[2] callprepare main
[3] callexecute main
[4] callfinalize main
to:@end
@end: scope:[] from @1
[5] phi()
__stackcall (void()) printother()
printother: scope:[printother] from
[6] (byte) printother::i ← (byte) 0
to:printother::@1
printother::@1: scope:[printother] from printother printother::@1
[7] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i)
[8] (byte) printother::i ← ++ (byte) printother::i
[9] if((byte) printother::i!=(byte) 6) goto printother::@1
to:printother::@return
printother::@return: scope:[printother] from printother::@1
[10] return
to:@return
__stackcall (void()) incval()
incval: scope:[incval] from
[11] (byte) val ← ++ (byte) val
to:incval::@return
incval::@return: scope:[incval] from incval
[12] return
to:@return
__stackcall (void()) printval()
printval: scope:[printval] from
[13] *((const byte*) SCREEN) ← (byte) val
to:printval::@return
printval::@return: scope:[printval] from printval
[14] return
to:@return
__stackcall (void()) ival()
ival: scope:[ival] from
[15] phi()
[16] callprepare incval
[17] callexecute incval
[18] callfinalize incval
to:ival::@return
ival::@return: scope:[ival] from ival
[19] return
to:@return
__stackcall (void()) pval()
pval: scope:[pval] from
[20] phi()
[21] callprepare printval
[22] callexecute printval
[23] callfinalize printval
to:pval::@return
pval::@return: scope:[pval] from pval
[24] return
to:@return
__stackcall (void()) main()
main: scope:[main] from
[25] (byte) main::i ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@1
[26] phi()
[27] callprepare pval
[28] callexecute pval
[29] callfinalize pval
[30] callprepare printother
[31] callexecute printother
[32] callfinalize printother
[33] callprepare ival
[34] callexecute ival
[35] callfinalize ival
[36] (byte) main::i ← ++ (byte) main::i
[37] if((byte) main::i!=(byte) 6) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[38] return
to:@return
null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope printother
null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope ival
null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope pval
null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope ival
null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope pval
VARIABLE REGISTER WEIGHTS
__stackcall (void()) incval()
__stackcall (void()) ival()
__stackcall (void()) main()
(byte) main::i loadstore 2.6923076923076925
__stackcall (void()) printother()
(byte) printother::i loadstore 14.25
__stackcall (void()) printval()
__stackcall (void()) pval()
(byte) val loadstore 2.0
Initial phi equivalence classes
Added variable val to live range equivalence class [ val ]
Added variable printother::i to live range equivalence class [ printother::i ]
Added variable main::i to live range equivalence class [ main::i ]
Complete equivalence classes
[ val ]
[ printother::i ]
[ main::i ]
Allocated zp[1]:2 [ val ]
Allocated zp[1]:3 [ printother::i ]
Allocated zp[1]:4 [ main::i ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Test a procedure with calling convention stack
// Illustrates live range problem with function variable printother::i and global variable val
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label val = 2
// @begin
__bbegin:
// [0] (byte) val ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z val
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] callprepare main
// [3] callexecute main -- jsr
jsr main
// [4] callfinalize main
// [5] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// printother
printother: {
.label i = 3
// [6] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// printother::@1
__b1:
// [7] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1
ldx.z i
inc SCREEN+$28,x
// [8] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1
inc.z i
// [9] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1
lda #6
cmp.z i
bne __b1
jmp __breturn
// printother::@return
__breturn:
// [10] return
rts
}
// incval
incval: {
// [11] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1
inc.z val
jmp __breturn
// incval::@return
__breturn:
// [12] return
rts
}
// printval
printval: {
// [13] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN
jmp __breturn
// printval::@return
__breturn:
// [14] return
rts
}
// ival
ival: {
// [16] callprepare incval
// [17] callexecute incval -- jsr
jsr incval
// [18] callfinalize incval
jmp __breturn
// ival::@return
__breturn:
// [19] return
rts
}
// pval
pval: {
// [21] callprepare printval
// [22] callexecute printval -- jsr
jsr printval
// [23] callfinalize printval
jmp __breturn
// pval::@return
__breturn:
// [24] return
rts
}
// main
main: {
.label i = 4
// [25] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
// [26] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1]
__b1_from_main:
__b1_from___b1:
jmp __b1
// main::@1
__b1:
// [27] callprepare pval
// [28] callexecute pval -- jsr
jsr pval
// [29] callfinalize pval
// [30] callprepare printother
// [31] callexecute printother -- jsr
jsr printother
// [32] callfinalize printother
// [33] callprepare ival
// [34] callexecute ival -- jsr
jsr ival
// [35] callfinalize ival
// [36] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
inc.z i
// [37] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #6
cmp.z i
bne __b1_from___b1
jmp __breturn
// main::@return
__breturn:
// [38] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (byte) val ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a
Statement [6] (byte) printother::i ← (byte) 0 [ printother::i ] ( main:3::printother:31 [ main::i printother::i ] ) always clobbers reg byte a
Statement [7] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) [ printother::i ] ( main:3::printother:31 [ main::i printother::i ] ) always clobbers reg byte x
Statement [9] if((byte) printother::i!=(byte) 6) goto printother::@1 [ printother::i ] ( main:3::printother:31 [ main::i printother::i ] ) always clobbers reg byte a
Statement [13] *((const byte*) SCREEN) ← (byte) val [ ] ( main:3::pval:28::printval:22 [ main::i ] ) always clobbers reg byte a
Statement [25] (byte) main::i ← (byte) 0 [ main::i ] ( main:3 [ main::i ] ) always clobbers reg byte a
Statement [37] if((byte) main::i!=(byte) 6) goto main::@1 [ main::i ] ( main:3 [ main::i ] ) always clobbers reg byte a
Potential registers zp[1]:2 [ val ] : zp[1]:2 ,
Potential registers zp[1]:3 [ printother::i ] : zp[1]:3 ,
Potential registers zp[1]:4 [ main::i ] : zp[1]:4 ,
REGISTER UPLIFT SCOPES
Uplift Scope [printother] 14.25: zp[1]:3 [ printother::i ]
Uplift Scope [main] 2.69: zp[1]:4 [ main::i ]
Uplift Scope [] 2: zp[1]:2 [ val ]
Uplift Scope [pval]
Uplift Scope [ival]
Uplift Scope [printval]
Uplift Scope [incval]
Uplifting [printother] best 722 combination zp[1]:3 [ printother::i ]
Uplifting [main] best 722 combination zp[1]:4 [ main::i ]
Uplifting [] best 722 combination zp[1]:2 [ val ]
Uplifting [pval] best 722 combination
Uplifting [ival] best 722 combination
Uplifting [printval] best 722 combination
Uplifting [incval] best 722 combination
Attempting to uplift remaining variables inzp[1]:3 [ printother::i ]
Uplifting [printother] best 722 combination zp[1]:3 [ printother::i ]
Attempting to uplift remaining variables inzp[1]:4 [ main::i ]
Uplifting [main] best 722 combination zp[1]:4 [ main::i ]
Attempting to uplift remaining variables inzp[1]:2 [ val ]
Uplifting [] best 722 combination zp[1]:2 [ val ]
Coalescing zero page register [ zp[1]:3 [ printother::i ] ] with [ zp[1]:2 [ val ] ]
Allocated (was zp[1]:3) zp[1]:2 [ printother::i val ]
Allocated (was zp[1]:4) zp[1]:3 [ main::i ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test a procedure with calling convention stack
// Illustrates live range problem with function variable printother::i and global variable val
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label val = 2
// @begin
__bbegin:
// [0] (byte) val ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z val
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] callprepare main
// [3] callexecute main -- jsr
jsr main
// [4] callfinalize main
// [5] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// printother
printother: {
.label i = 2
// [6] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// printother::@1
__b1:
// [7] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1
ldx.z i
inc SCREEN+$28,x
// [8] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1
inc.z i
// [9] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1
lda #6
cmp.z i
bne __b1
jmp __breturn
// printother::@return
__breturn:
// [10] return
rts
}
// incval
incval: {
// [11] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1
inc.z val
jmp __breturn
// incval::@return
__breturn:
// [12] return
rts
}
// printval
printval: {
// [13] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN
jmp __breturn
// printval::@return
__breturn:
// [14] return
rts
}
// ival
ival: {
// [16] callprepare incval
// [17] callexecute incval -- jsr
jsr incval
// [18] callfinalize incval
jmp __breturn
// ival::@return
__breturn:
// [19] return
rts
}
// pval
pval: {
// [21] callprepare printval
// [22] callexecute printval -- jsr
jsr printval
// [23] callfinalize printval
jmp __breturn
// pval::@return
__breturn:
// [24] return
rts
}
// main
main: {
.label i = 3
// [25] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
// [26] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1]
__b1_from_main:
__b1_from___b1:
jmp __b1
// main::@1
__b1:
// [27] callprepare pval
// [28] callexecute pval -- jsr
jsr pval
// [29] callfinalize pval
// [30] callprepare printother
// [31] callexecute printother -- jsr
jsr printother
// [32] callfinalize printother
// [33] callprepare ival
// [34] callexecute ival -- jsr
jsr ival
// [35] callfinalize ival
// [36] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
inc.z i
// [37] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #6
cmp.z i
bne __b1_from___b1
jmp __breturn
// main::@return
__breturn:
// [38] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __b1
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __b1_from___b1 with __b1
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Removing instruction __b1_from_main:
Removing instruction __b1_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
Removing instruction __bend:
Removing instruction __breturn:
Removing instruction __breturn:
Removing instruction __breturn:
Removing instruction __breturn:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
__stackcall (void()) incval()
(label) incval::@return
__stackcall (void()) ival()
(label) ival::@return
__stackcall (void()) main()
(label) main::@1
(label) main::@return
(byte) main::i loadstore zp[1]:3 2.6923076923076925
__stackcall (void()) printother()
(label) printother::@1
(label) printother::@return
(byte) printother::i loadstore zp[1]:2 14.25
__stackcall (void()) printval()
(label) printval::@return
__stackcall (void()) pval()
(label) pval::@return
(byte) val loadstore zp[1]:2 2.0
zp[1]:2 [ printother::i val ]
zp[1]:3 [ main::i ]
FINAL ASSEMBLER
Score: 617
// File Comments
// Test a procedure with calling convention stack
// Illustrates live range problem with function variable printother::i and global variable val
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label val = 2
// @begin
__bbegin:
// val = 0
// [0] (byte) val ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z val
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] callprepare main
// [3] callexecute main -- jsr
jsr main
rts
// [4] callfinalize main
// [5] phi from @1 to @end [phi:@1->@end]
// @end
// printother
printother: {
.label i = 2
// for(char i:0..5)
// [6] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
// printother::@1
__b1:
// (SCREEN+40)[i]++;
// [7] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1
ldx.z i
inc SCREEN+$28,x
// for(char i:0..5)
// [8] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1
inc.z i
// [9] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1
lda #6
cmp.z i
bne __b1
// printother::@return
// }
// [10] return
rts
}
// incval
incval: {
// val++;
// [11] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1
inc.z val
// incval::@return
// }
// [12] return
rts
}
// printval
printval: {
// SCREEN[0] = val
// [13] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN
// printval::@return
// }
// [14] return
rts
}
// ival
ival: {
// incval()
// [16] callprepare incval
// [17] callexecute incval -- jsr
jsr incval
// [18] callfinalize incval
// ival::@return
// }
// [19] return
rts
}
// pval
pval: {
// printval()
// [21] callprepare printval
// [22] callexecute printval -- jsr
jsr printval
// [23] callfinalize printval
// pval::@return
// }
// [24] return
rts
}
// main
main: {
.label i = 3
// for(char i:0..5)
// [25] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
// [26] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1]
// main::@1
__b1:
// pval()
// [27] callprepare pval
// [28] callexecute pval -- jsr
jsr pval
// [29] callfinalize pval
// printother()
// [30] callprepare printother
// [31] callexecute printother -- jsr
jsr printother
// [32] callfinalize printother
// ival()
// [33] callprepare ival
// [34] callexecute ival -- jsr
jsr ival
// [35] callfinalize ival
// for(char i:0..5)
// [36] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
inc.z i
// [37] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #6
cmp.z i
bne __b1
// main::@return
// }
// [38] return
rts
}
// File Data

View File

@ -0,0 +1,24 @@
(label) @1
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
__stackcall (void()) incval()
(label) incval::@return
__stackcall (void()) ival()
(label) ival::@return
__stackcall (void()) main()
(label) main::@1
(label) main::@return
(byte) main::i loadstore zp[1]:3 2.6923076923076925
__stackcall (void()) printother()
(label) printother::@1
(label) printother::@return
(byte) printother::i loadstore zp[1]:2 14.25
__stackcall (void()) printval()
(label) printval::@return
__stackcall (void()) pval()
(label) pval::@return
(byte) val loadstore zp[1]:2 2.0
zp[1]:2 [ printother::i val ]
zp[1]:3 [ main::i ]