mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-26 12:49:21 +00:00
Added test illustrating variable alive range propagation problem when using call stack.
This commit is contained in:
parent
7720eb8c13
commit
5d7533de5d
@ -513,12 +513,8 @@ public class Compiler {
|
||||
|
||||
program.clearStatementInfos();
|
||||
program.clearVariableReferenceInfos();
|
||||
//getLog().append("CONTROL FLOW GRAPH - LIVE RANGES FOUND");
|
||||
//getLog().append(program.getGraph().toString(program));
|
||||
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
|
||||
new Pass3PhiMemCoalesce(program).step();
|
||||
new PassNCullEmptyBlocks(program).step();
|
||||
@ -539,6 +535,12 @@ public class Compiler {
|
||||
new PassNStatementIndices(program).execute();
|
||||
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(program.getGraph().toString(program));
|
||||
|
||||
|
@ -381,9 +381,14 @@ public class Program {
|
||||
return symbolInfos;
|
||||
}
|
||||
|
||||
public boolean hasLiveRangeVariablesEffective() {
|
||||
return liveRangeVariablesEffective!=null;
|
||||
}
|
||||
|
||||
public LiveRangeVariablesEffective getLiveRangeVariablesEffective() {
|
||||
if(liveRangeVariablesEffective==null)
|
||||
if(liveRangeVariablesEffective==null) {
|
||||
this.liveRangeVariablesEffective = new PassNCalcLiveRangesEffective(this).calculate();
|
||||
}
|
||||
return liveRangeVariablesEffective;
|
||||
}
|
||||
|
||||
|
@ -81,16 +81,18 @@ public abstract class StatementBase implements Statement {
|
||||
LiveRangeVariables liveRanges = program.getLiveRangeVariables();
|
||||
StringBuilder alive = new StringBuilder();
|
||||
alive.append(getAliveString(liveRanges.getAlive(index)));
|
||||
LiveRangeVariablesEffective liveRangeVariablesEffective = program.getLiveRangeVariablesEffective();
|
||||
if(liveRangeVariablesEffective != null) {
|
||||
LiveRangeVariablesEffective.AliveCombinations aliveCombinations = liveRangeVariablesEffective.getAliveCombinations(this);
|
||||
alive.append(" ( ");
|
||||
for(LiveRangeVariablesEffective.CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) {
|
||||
alive.append(getCallPathString(callPath.getPath()));
|
||||
alive.append(getAliveString(aliveCombinations.getEffectiveAliveAtStmt(callPath)));
|
||||
alive.append(" ");
|
||||
if(program.hasLiveRangeVariablesEffective()) {
|
||||
LiveRangeVariablesEffective liveRangeVariablesEffective = program.getLiveRangeVariablesEffective();
|
||||
if(liveRangeVariablesEffective != null) {
|
||||
LiveRangeVariablesEffective.AliveCombinations aliveCombinations = liveRangeVariablesEffective.getAliveCombinations(this);
|
||||
alive.append(" ( ");
|
||||
for(LiveRangeVariablesEffective.CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) {
|
||||
alive.append(getCallPathString(callPath.getPath()));
|
||||
alive.append(getAliveString(aliveCombinations.getEffectiveAliveAtStmt(callPath)));
|
||||
alive.append(" ");
|
||||
}
|
||||
alive.append(")");
|
||||
}
|
||||
alive.append(")");
|
||||
}
|
||||
return alive.toString();
|
||||
}
|
||||
|
@ -279,19 +279,20 @@ public class TestPrograms {
|
||||
compileAndCompare("declared-memory-var-0");
|
||||
}
|
||||
|
||||
/*
|
||||
@Test
|
||||
public void testProcedureCallingConventionStack9() throws IOException, URISyntaxException {
|
||||
compileAndCompare("procedure-callingconvention-stack-9");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcedureCallingConventionStack8() throws IOException, URISyntaxException {
|
||||
compileAndCompare("procedure-callingconvention-stack-8", log().verboseLiveRanges()); //, log().verboseCreateSsa().verboseParse().verboseStatementSequence());
|
||||
compileAndCompare("procedure-callingconvention-stack-8");
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
@Test
|
||||
public void testProcedureCallingConventionStack7() throws IOException, URISyntaxException {
|
||||
compileAndCompare("procedure-callingconvention-stack-7", log().verboseLiveRanges()); //, log().verboseCreateSsa().verboseParse().verboseStatementSequence());
|
||||
compileAndCompare("procedure-callingconvention-stack-7");
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
@Test
|
||||
|
@ -1,5 +1,5 @@
|
||||
// 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 var_model(ma_zp)
|
||||
@ -7,8 +7,8 @@
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main(void) {
|
||||
char val = 0;
|
||||
val = '-';
|
||||
char val;
|
||||
val = *SCREEN;
|
||||
printline();
|
||||
SCREEN[80] = val;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// 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 var_model(ma_zp)
|
||||
|
44
src/test/kc/procedure-callingconvention-stack-9.kc
Normal file
44
src/test/kc/procedure-callingconvention-stack-9.kc
Normal 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]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
46
src/test/ref/procedure-callingconvention-stack-7.asm
Normal file
46
src/test/ref/procedure-callingconvention-stack-7.asm
Normal 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
|
||||
}
|
39
src/test/ref/procedure-callingconvention-stack-7.cfg
Normal file
39
src/test/ref/procedure-callingconvention-stack-7.cfg
Normal 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
|
440
src/test/ref/procedure-callingconvention-stack-7.log
Normal file
440
src/test/ref/procedure-callingconvention-stack-7.log
Normal 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
|
||||
|
15
src/test/ref/procedure-callingconvention-stack-7.sym
Normal file
15
src/test/ref/procedure-callingconvention-stack-7.sym
Normal 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 ]
|
46
src/test/ref/procedure-callingconvention-stack-8.asm
Normal file
46
src/test/ref/procedure-callingconvention-stack-8.asm
Normal 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
|
||||
}
|
38
src/test/ref/procedure-callingconvention-stack-8.cfg
Normal file
38
src/test/ref/procedure-callingconvention-stack-8.cfg
Normal 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
|
436
src/test/ref/procedure-callingconvention-stack-8.log
Normal file
436
src/test/ref/procedure-callingconvention-stack-8.log
Normal 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
|
||||
|
15
src/test/ref/procedure-callingconvention-stack-8.sym
Normal file
15
src/test/ref/procedure-callingconvention-stack-8.sym
Normal 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 ]
|
75
src/test/ref/procedure-callingconvention-stack-9.asm
Normal file
75
src/test/ref/procedure-callingconvention-stack-9.asm
Normal 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
|
||||
}
|
84
src/test/ref/procedure-callingconvention-stack-9.cfg
Normal file
84
src/test/ref/procedure-callingconvention-stack-9.cfg
Normal 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
|
780
src/test/ref/procedure-callingconvention-stack-9.log
Normal file
780
src/test/ref/procedure-callingconvention-stack-9.log
Normal 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
|
||||
|
24
src/test/ref/procedure-callingconvention-stack-9.sym
Normal file
24
src/test/ref/procedure-callingconvention-stack-9.sym
Normal 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 ]
|
Loading…
Reference in New Issue
Block a user