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:
parent
7720eb8c13
commit
5d7533de5d
@ -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));
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
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