1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-04-22 03:38:31 +00:00

Propagating live ranges backwards through calls to avoid coalescing variables in procedures with variables alive outside during the call.

This commit is contained in:
jespergravgaard 2017-07-29 11:08:24 +02:00
parent 9634741d76
commit 438bdc38b4
20 changed files with 3100 additions and 2007 deletions

View File

@ -44,11 +44,11 @@ public class ControlFlowGraphBaseVisitor<T> {
}
}
public T visitProcedureBegin(StatementProcedureBegin statement) {
public T visitProcedureBegin(StatementProcedureBegin procedureBegin) {
return null;
}
public T visitProcedureEnd(StatementProcedureEnd statement) {
public T visitProcedureEnd(StatementProcedureEnd procedureEnd) {
return null;
}
@ -76,7 +76,7 @@ public class ControlFlowGraphBaseVisitor<T> {
return null;
}
public T visitCall(StatementCall callLValue) {
public T visitCall(StatementCall call) {
return null;
}

View File

@ -157,10 +157,10 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
}
@Override
public StatementCall visitCall(StatementCall callLValue) {
LValue lValue = callLValue.getlValue();
String procedureName = callLValue.getProcedureName();
List<RValue> parameters = callLValue.getParameters();
public StatementCall visitCall(StatementCall origCall) {
LValue lValue = origCall.getlValue();
String procedureName = origCall.getProcedureName();
List<RValue> parameters = origCall.getParameters();
return new StatementCall(lValue, procedureName, parameters);
}

View File

@ -12,8 +12,21 @@ public class ProcedureRef extends SymbolRef {
super(fullName);
}
/**
* Get the label of the block where the procedure code starts
* @return The label of the code block
*/
@JsonIgnore
public LabelRef getLabelRef() {
return new LabelRef(getFullName());
}
/**
* Get the label of the block containing the final procedure return
* @return The label of the code block
*/
@JsonIgnore
public LabelRef getReturnBlock() {
return new LabelRef(getFullName()+"::@return");
}
}

View File

@ -71,11 +71,11 @@ public class Pass2AssertBlocks extends Pass2SsaAssertion {
}
@Override
public Void visitCall(StatementCall callLValue) {
ProcedureRef procedure = callLValue.getProcedure();
public Void visitCall(StatementCall call) {
ProcedureRef procedure = call.getProcedure();
LabelRef procLabelRef = procedure.getLabelRef();
assertBlock(procLabelRef);
return super.visitCall(callLValue);
return super.visitCall(call);
}
@Override

View File

@ -20,9 +20,9 @@ public class Pass2AssertNoCallLvalues extends Pass2SsaAssertion {
ControlFlowGraphBaseVisitor<Void> checkCalls = new ControlFlowGraphBaseVisitor<Void>() {
@Override
public Void visitCall(StatementCall callLValue) {
if(callLValue.getlValue()!=null) {
throw new AssertionFailed("No call lValue allowed! "+callLValue);
public Void visitCall(StatementCall call) {
if(call.getlValue()!=null) {
throw new AssertionFailed("No call lValue allowed! "+ call);
}
return null;
}

View File

@ -18,10 +18,10 @@ public class Pass2AssertNoCallParameters extends Pass2SsaAssertion {
ControlFlowGraphBaseVisitor<Void> checkCalls = new ControlFlowGraphBaseVisitor<Void>() {
@Override
public Void visitCall(StatementCall callLValue) {
List<RValue> parameters = callLValue.getParameters();
public Void visitCall(StatementCall call) {
List<RValue> parameters = call.getParameters();
if(parameters!=null && parameters.size()>0) {
throw new AssertionFailed("No call parameters allowed! "+callLValue);
throw new AssertionFailed("No call parameters allowed! "+ call);
}
return null;
}

View File

@ -15,13 +15,13 @@ public class Pass2AssertNoProcs extends Pass2SsaAssertion {
ControlFlowGraphBaseVisitor<Void> checkCalls = new ControlFlowGraphBaseVisitor<Void>() {
@Override
public Void visitProcedureBegin(StatementProcedureBegin statement) {
throw new AssertionFailed("No proc statements allowed! "+statement);
public Void visitProcedureBegin(StatementProcedureBegin procedureBegin) {
throw new AssertionFailed("No proc statements allowed! "+ procedureBegin);
}
@Override
public Void visitProcedureEnd(StatementProcedureEnd statement) {
throw new AssertionFailed("No proc statements allowed! "+statement);
public Void visitProcedureEnd(StatementProcedureEnd procedureEnd) {
throw new AssertionFailed("No proc statements allowed! "+ procedureEnd);
}
};
checkCalls.visitGraph(getGraph());

View File

@ -91,19 +91,19 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
}
@Override
public Void visitProcedureBegin(StatementProcedureBegin statement) {
ProcedureRef procedureRef = statement.getProcedure();
public Void visitProcedureBegin(StatementProcedureBegin procedureBegin) {
ProcedureRef procedureRef = procedureBegin.getProcedure();
Procedure procedure = programScope.getProcedure(procedureRef);
symbols.add(procedure);
return super.visitProcedureBegin(statement);
return super.visitProcedureBegin(procedureBegin);
}
@Override
public Void visitProcedureEnd(StatementProcedureEnd statement) {
ProcedureRef procedureRef = statement.getProcedure();
public Void visitProcedureEnd(StatementProcedureEnd procedureEnd) {
ProcedureRef procedureRef = procedureEnd.getProcedure();
Procedure procedure = programScope.getProcedure(procedureRef);
symbols.add(procedure);
return super.visitProcedureEnd(statement);
return super.visitProcedureEnd(procedureEnd);
}
@Override
@ -141,15 +141,15 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
}
@Override
public Void visitCall(StatementCall callLValue) {
addSymbol(callLValue.getlValue());
addSymbol(callLValue.getProcedure());
if(callLValue.getParameters()!=null) {
for (RValue param : callLValue.getParameters()) {
public Void visitCall(StatementCall call) {
addSymbol(call.getlValue());
addSymbol(call.getProcedure());
if(call.getParameters()!=null) {
for (RValue param : call.getParameters()) {
addSymbol(param);
}
}
return super.visitCall(callLValue);
return super.visitCall(call);
}
@Override

View File

@ -147,15 +147,15 @@ public class Pass3LiveRangesAnalysis {
}
@Override
public Void visitCall(StatementCall callLValue) {
if (callLValue.getlValue() instanceof PointerDereferenceIndexed) {
addInitialLiveRange(((PointerDereferenceIndexed) callLValue.getlValue()).getPointer());
addInitialLiveRange(((PointerDereferenceIndexed) callLValue.getlValue()).getIndex());
} else if (callLValue.getlValue() instanceof PointerDereferenceSimple) {
addInitialLiveRange(((PointerDereferenceSimple) callLValue.getlValue()).getPointer());
public Void visitCall(StatementCall call) {
if (call.getlValue() instanceof PointerDereferenceIndexed) {
addInitialLiveRange(((PointerDereferenceIndexed) call.getlValue()).getPointer());
addInitialLiveRange(((PointerDereferenceIndexed) call.getlValue()).getIndex());
} else if (call.getlValue() instanceof PointerDereferenceSimple) {
addInitialLiveRange(((PointerDereferenceSimple) call.getlValue()).getPointer());
}
if (callLValue.getParameters() != null) {
for (RValue parameter : callLValue.getParameters()) {
if (call.getParameters() != null) {
for (RValue parameter : call.getParameters()) {
addInitialLiveRange(parameter);
}
}
@ -287,19 +287,41 @@ public class Pass3LiveRangesAnalysis {
}
}
/**
* Get the statement executed just before entering a specific block
*
* @param block The block to find the previous statement for
* @return The statement executed just before entering the block.
* If there are several predecessor blocks multiple statements are returned.
*/
private ArrayList<Statement> getPreviousStatements(ControlFlowBlock block) {
ArrayList<Statement> statements = new ArrayList<>();
List<ControlFlowBlock> predecessors = program.getGraph().getPredecessors(block);
for (ControlFlowBlock predecessor : predecessors) {
List<Statement> predecessorStatements = predecessor.getStatements();
if (predecessorStatements.size() == 0) {
// Predecessor has no statements - go further back!
statements.addAll(getPreviousStatements(predecessor));
} else {
// Add last statement from predecessor
Statement predecessorLastStatement = predecessorStatements.get(predecessorStatements.size() - 1);
statements.add(predecessorLastStatement);
}
ArrayList<Statement> lastStatements = getLastStatements(predecessor);
statements.addAll(lastStatements);
}
return statements;
}
/**
* Get the last statement executed in a specific block.
* If the block is empty the last statement of the previous block is returned.
* @param block The block to examine
* @return The last statement of the block (or the last statement of previous blocks if the block is empty)
*/
private ArrayList<Statement> getLastStatements(ControlFlowBlock block) {
ArrayList<Statement> statements = new ArrayList<>();
List<Statement> blockStatements = block.getStatements();
if (blockStatements.size() == 0) {
// Block has no statements - go further back!
statements.addAll(getPreviousStatements(block));
} else {
// Add last statement from block
Statement predecessorLastStatement = blockStatements.get(blockStatements.size() - 1);
statements.add(predecessorLastStatement);
}
return statements;
}
@ -315,47 +337,48 @@ public class Pass3LiveRangesAnalysis {
}
@Override
public Void visitCall(StatementCall callLValue) {
if (callLValue.getlValue() != null) {
propagate(callLValue, getPreviousStatements(), Arrays.asList(callLValue.getlValue()));
}
public Void visitCall(StatementCall call) {
propagate(call, getPreviousStatements(), null);
// Also propagate back through all statements of the procedure
ProcedureRef procedure = call.getProcedure();
LabelRef procedureReturnBlock = procedure.getReturnBlock();
ControlFlowBlock returnBlock = program.getGraph().getBlock(procedureReturnBlock);
propagate(call, getLastStatements(returnBlock), null);
return null;
}
@Override
public Void visitAssignment(StatementAssignment assignment) {
if (assignment.getlValue() != null) {
propagate(assignment, getPreviousStatements(), Arrays.asList(assignment.getlValue()));
}
propagate(assignment, getPreviousStatements(), Arrays.asList(assignment.getlValue()));
return null;
}
@Override
public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
propagate(conditionalJump, getPreviousStatements(), new ArrayList<LValue>());
propagate(conditionalJump, getPreviousStatements(), null);
return null;
}
@Override
public Void visitJump(StatementJump jump) {
propagate(jump, getPreviousStatements(), new ArrayList<LValue>());
propagate(jump, getPreviousStatements(), null);
return null;
}
@Override
public Void visitReturn(StatementReturn aReturn) {
propagate(aReturn, getPreviousStatements(), new ArrayList<LValue>());
propagate(aReturn, getPreviousStatements(), null);
return null;
}
@Override
public Void visitProcedureBegin(StatementProcedureBegin statement) {
throw new RuntimeException("Statement not supported during live range propagation. Should be eliminated in earlier phase. " + statement);
public Void visitProcedureBegin(StatementProcedureBegin procedureBegin) {
throw new RuntimeException("Statement not supported during live range propagation. Should be eliminated in earlier phase. " + procedureBegin);
}
@Override
public Void visitProcedureEnd(StatementProcedureEnd statement) {
throw new RuntimeException("Statement not supported during live range propagation. Should be eliminated in earlier phase. " + statement);
public Void visitProcedureEnd(StatementProcedureEnd procedureEnd) {
throw new RuntimeException("Statement not supported during live range propagation. Should be eliminated in earlier phase. " + procedureEnd);
}
@Override

View File

@ -58,6 +58,11 @@ public class TestCompilationOutput extends TestCase {
tester.testFile("loopnest");
}
public void testLoopNest2() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("loopnest2");
}
private void testFile(String fileName) throws IOException, URISyntaxException {
String inputPath = testPath + fileName + ".kc";

View File

@ -3,31 +3,15 @@ byte* SCREEN = $0400;
main();
void main() {
byte i=100;
do {
byte j=100;
do {
nest1();
} while (--j>0)
} while (--i>0)
byte i=100;
do {
nest();
} while (--i>0)
}
void nest1() {
byte i=100;
do {
byte j=100;
do {
nest2();
} while (--j>0)
} while (--i>0)
}
void nest2() {
byte i=100;
do {
byte j=100;
do {
*SCREEN = j;
} while (--j>0)
} while (--i>0)
void nest() {
byte j=100;
do {
*SCREEN = j;
} while (--j>0)
}

View File

@ -0,0 +1,33 @@
byte* SCREEN = $0400;
main();
void main() {
byte i=100;
do {
byte j=100;
do {
nest1();
} while (--j>0)
} while (--i>0)
}
void nest1() {
byte i=100;
do {
byte j=100;
do {
nest2();
} while (--j>0)
} while (--i>0)
}
void nest2() {
byte i=100;
do {
byte j=100;
do {
*SCREEN = j;
} while (--j>0)
} while (--i>0)
}

View File

@ -7,63 +7,23 @@ main__B1_from_main:
sta 2
main__B1_from_B3:
main__B1:
main__B2_from_B1:
lda #100
sta 3
main__B2_from_B5:
main__B2:
jsr nest1
main__B5:
dec 3
lda 3
bne main__B2_from_B5
jsr nest
main__B3:
dec 2
lda 2
bne main__B1_from_B3
main__Breturn:
rts
nest1:
nest1__B1_from_nest1:
lda #100
sta 2
nest1__B1_from_B3:
nest1__B1:
nest1__B2_from_B1:
nest:
nest__B1_from_nest:
lda #100
sta 3
nest1__B2_from_B5:
nest1__B2:
jsr nest2
nest1__B5:
dec 3
lda 3
bne nest1__B2_from_B5
nest1__B3:
dec 2
lda 2
bne nest1__B1_from_B3
nest1__Breturn:
rts
nest2:
nest2__B1_from_nest2:
lda #100
sta 2
nest2__B1_from_B3:
nest2__B1:
nest2__B2_from_B1:
lda #100
sta 3
nest2__B2_from_B2:
nest2__B2:
nest__B1_from_B1:
nest__B1:
lda 3
sta 1024
dec 3
lda 3
bne nest2__B2_from_B2
nest2__B3:
dec 2
lda 2
bne nest2__B1_from_B3
nest2__Breturn:
bne nest__B1_from_B1
nest__Breturn:
rts

View File

@ -5,58 +5,24 @@
main: from @BEGIN
to:main::@1
main::@1: from main main::@3
[1] (byte) main::i#2 ← phi( main/(byte) 100 main::@3/(byte) main::i#1 ) [ ]
to:main::@2
main::@2: from main::@1 main::@5
[2] (byte) main::j#2 ← phi( main::@1/(byte) 100 main::@5/(byte) main::j#1 ) [ ]
[3] call nest1 param-assignment [ main::j#2 main::i#2 ]
to:main::@5
main::@5: from main::@2
[4] (byte) main::j#1 ← -- (byte) main::j#2 [ main::j#1 main::i#2 ]
[5] if((byte) main::j#1>(byte) 0) goto main::@2 [ main::j#1 main::i#2 ]
[1] (byte) main::i#2 ← phi( main/(byte) 100 main::@3/(byte) main::i#1 ) [ main::i#2 ]
[2] call nest param-assignment [ main::i#2 ]
to:main::@3
main::@3: from main::@5
[6] (byte) main::i#1 ← -- (byte) main::i#2 [ main::i#1 ]
[7] if((byte) main::i#1>(byte) 0) goto main::@1 [ main::i#1 ]
main::@3: from main::@1
[3] (byte) main::i#1 ← -- (byte) main::i#2 [ main::i#1 ]
[4] if((byte) main::i#1>(byte) 0) goto main::@1 [ main::i#1 ]
to:main::@return
main::@return: from main::@3
[8] return [ ]
[5] return [ ]
to:@RETURN
nest1: from main::@2
to:nest1::@1
nest1::@1: from nest1 nest1::@3
[9] (byte) nest1::i#2 ← phi( nest1/(byte) 100 nest1::@3/(byte) nest1::i#1 ) [ ]
to:nest1::@2
nest1::@2: from nest1::@1 nest1::@5
[10] (byte) nest1::j#2 ← phi( nest1::@1/(byte) 100 nest1::@5/(byte) nest1::j#1 ) [ ]
[11] call nest2 param-assignment [ nest1::j#2 nest1::i#2 ]
to:nest1::@5
nest1::@5: from nest1::@2
[12] (byte) nest1::j#1 ← -- (byte) nest1::j#2 [ nest1::j#1 nest1::i#2 ]
[13] if((byte) nest1::j#1>(byte) 0) goto nest1::@2 [ nest1::j#1 nest1::i#2 ]
to:nest1::@3
nest1::@3: from nest1::@5
[14] (byte) nest1::i#1 ← -- (byte) nest1::i#2 [ nest1::i#1 ]
[15] if((byte) nest1::i#1>(byte) 0) goto nest1::@1 [ nest1::i#1 ]
to:nest1::@return
nest1::@return: from nest1::@3
[16] return [ ]
to:@RETURN
nest2: from nest1::@2
to:nest2::@1
nest2::@1: from nest2 nest2::@3
[17] (byte) nest2::i#2 ← phi( nest2/(byte) 100 nest2::@3/(byte) nest2::i#1 ) [ nest2::i#2 ]
to:nest2::@2
nest2::@2: from nest2::@1 nest2::@2
[18] (byte) nest2::j#2 ← phi( nest2::@1/(byte) 100 nest2::@2/(byte) nest2::j#1 ) [ nest2::j#2 nest2::i#2 ]
[19] *((word) 1024) ← (byte) nest2::j#2 [ nest2::j#2 nest2::i#2 ]
[20] (byte) nest2::j#1 ← -- (byte) nest2::j#2 [ nest2::j#1 nest2::i#2 ]
[21] if((byte) nest2::j#1>(byte) 0) goto nest2::@2 [ nest2::j#1 nest2::i#2 ]
to:nest2::@3
nest2::@3: from nest2::@2
[22] (byte) nest2::i#1 ← -- (byte) nest2::i#2 [ nest2::i#1 ]
[23] if((byte) nest2::i#1>(byte) 0) goto nest2::@1 [ nest2::i#1 ]
to:nest2::@return
nest2::@return: from nest2::@3
[24] return [ ]
nest: from main::@1
to:nest::@1
nest::@1: from nest nest::@1
[6] (byte) nest::j#2 ← phi( nest/(byte) 100 nest::@1/(byte) nest::j#1 ) [ main::i#2 nest::j#2 ]
[7] *((word) 1024) ← (byte) nest::j#2 [ main::i#2 nest::j#2 ]
[8] (byte) nest::j#1 ← -- (byte) nest::j#2 [ main::i#2 nest::j#1 ]
[9] if((byte) nest::j#1>(byte) 0) goto nest::@1 [ main::i#2 nest::j#1 ]
to:nest::@return
nest::@return: from nest::@1
[10] return [ main::i#2 ]
to:@RETURN

File diff suppressed because it is too large Load Diff

View File

@ -3,42 +3,19 @@
(byte*) SCREEN
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@5
(label) main::@return
(byte) main::i
(byte) main::i#1 zp byte:2
(byte) main::i#2 zp byte:2
(byte) main::j
(byte) main::j#1 zp byte:3
(byte) main::j#2 zp byte:3
(void()) nest1()
(label) nest1::@1
(label) nest1::@2
(label) nest1::@3
(label) nest1::@5
(label) nest1::@return
(byte) nest1::i
(byte) nest1::i#1 zp byte:2
(byte) nest1::i#2 zp byte:2
(byte) nest1::j
(byte) nest1::j#1 zp byte:3
(byte) nest1::j#2 zp byte:3
(void()) nest2()
(label) nest2::@1
(label) nest2::@2
(label) nest2::@3
(label) nest2::@return
(byte) nest2::i
(byte) nest2::i#1 zp byte:2
(byte) nest2::i#2 zp byte:2
(byte) nest2::j
(byte) nest2::j#1 zp byte:3
(byte) nest2::j#2 zp byte:3
(void()) nest()
(label) nest::@1
(label) nest::@return
(byte) nest::j
(byte) nest::j#1 zp byte:3
(byte) nest::j#2 zp byte:3
zp byte:2 [ main::i#2 main::i#1 nest1::i#2 nest1::i#1 nest2::i#2 nest2::i#1 ]
zp byte:3 [ main::j#2 main::j#1 nest1::j#2 nest1::j#1 nest2::j#2 nest2::j#1 ]
zp byte:2 [ main::i#2 main::i#1 ]
zp byte:3 [ nest::j#2 nest::j#1 ]

View File

@ -0,0 +1,69 @@
BBEGIN:
jsr main
BEND:
main:
main__B1_from_main:
lda #100
sta 2
main__B1_from_B3:
main__B1:
main__B2_from_B1:
lda #100
sta 3
main__B2_from_B5:
main__B2:
jsr nest1
main__B5:
dec 3
lda 3
bne main__B2_from_B5
main__B3:
dec 2
lda 2
bne main__B1_from_B3
main__Breturn:
rts
nest1:
nest1__B1_from_nest1:
lda #100
sta 4
nest1__B1_from_B3:
nest1__B1:
nest1__B2_from_B1:
lda #100
sta 5
nest1__B2_from_B5:
nest1__B2:
jsr nest2
nest1__B5:
dec 5
lda 5
bne nest1__B2_from_B5
nest1__B3:
dec 4
lda 4
bne nest1__B1_from_B3
nest1__Breturn:
rts
nest2:
nest2__B1_from_nest2:
lda #100
sta 6
nest2__B1_from_B3:
nest2__B1:
nest2__B2_from_B1:
lda #100
sta 7
nest2__B2_from_B2:
nest2__B2:
lda 7
sta 1024
dec 7
lda 7
bne nest2__B2_from_B2
nest2__B3:
dec 6
lda 6
bne nest2__B1_from_B3
nest2__Breturn:
rts

View File

@ -0,0 +1,62 @@
@BEGIN: from
[0] call main param-assignment [ ]
to:@END
@END: from @BEGIN
main: from @BEGIN
to:main::@1
main::@1: from main main::@3
[1] (byte) main::i#2 ← phi( main/(byte) 100 main::@3/(byte) main::i#1 ) [ main::i#2 ]
to:main::@2
main::@2: from main::@1 main::@5
[2] (byte) main::j#2 ← phi( main::@1/(byte) 100 main::@5/(byte) main::j#1 ) [ main::j#2 main::i#2 ]
[3] call nest1 param-assignment [ main::j#2 main::i#2 ]
to:main::@5
main::@5: from main::@2
[4] (byte) main::j#1 ← -- (byte) main::j#2 [ main::j#1 main::i#2 ]
[5] if((byte) main::j#1>(byte) 0) goto main::@2 [ main::j#1 main::i#2 ]
to:main::@3
main::@3: from main::@5
[6] (byte) main::i#1 ← -- (byte) main::i#2 [ main::i#1 ]
[7] if((byte) main::i#1>(byte) 0) goto main::@1 [ main::i#1 ]
to:main::@return
main::@return: from main::@3
[8] return [ ]
to:@RETURN
nest1: from main::@2
to:nest1::@1
nest1::@1: from nest1 nest1::@3
[9] (byte) nest1::i#2 ← phi( nest1/(byte) 100 nest1::@3/(byte) nest1::i#1 ) [ main::j#2 main::i#2 nest1::i#2 ]
to:nest1::@2
nest1::@2: from nest1::@1 nest1::@5
[10] (byte) nest1::j#2 ← phi( nest1::@1/(byte) 100 nest1::@5/(byte) nest1::j#1 ) [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 ]
[11] call nest2 param-assignment [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 ]
to:nest1::@5
nest1::@5: from nest1::@2
[12] (byte) nest1::j#1 ← -- (byte) nest1::j#2 [ main::j#2 main::i#2 nest1::j#1 nest1::i#2 ]
[13] if((byte) nest1::j#1>(byte) 0) goto nest1::@2 [ main::j#2 main::i#2 nest1::j#1 nest1::i#2 ]
to:nest1::@3
nest1::@3: from nest1::@5
[14] (byte) nest1::i#1 ← -- (byte) nest1::i#2 [ main::j#2 main::i#2 nest1::i#1 ]
[15] if((byte) nest1::i#1>(byte) 0) goto nest1::@1 [ main::j#2 main::i#2 nest1::i#1 ]
to:nest1::@return
nest1::@return: from nest1::@3
[16] return [ main::j#2 main::i#2 ]
to:@RETURN
nest2: from nest1::@2
to:nest2::@1
nest2::@1: from nest2 nest2::@3
[17] (byte) nest2::i#2 ← phi( nest2/(byte) 100 nest2::@3/(byte) nest2::i#1 ) [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::i#2 ]
to:nest2::@2
nest2::@2: from nest2::@1 nest2::@2
[18] (byte) nest2::j#2 ← phi( nest2::@1/(byte) 100 nest2::@2/(byte) nest2::j#1 ) [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::j#2 nest2::i#2 ]
[19] *((word) 1024) ← (byte) nest2::j#2 [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::j#2 nest2::i#2 ]
[20] (byte) nest2::j#1 ← -- (byte) nest2::j#2 [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::j#1 nest2::i#2 ]
[21] if((byte) nest2::j#1>(byte) 0) goto nest2::@2 [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::j#1 nest2::i#2 ]
to:nest2::@3
nest2::@3: from nest2::@2
[22] (byte) nest2::i#1 ← -- (byte) nest2::i#2 [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::i#1 ]
[23] if((byte) nest2::i#1>(byte) 0) goto nest2::@1 [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::i#1 ]
to:nest2::@return
nest2::@return: from nest2::@3
[24] return [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 ]
to:@RETURN

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
(label) @BEGIN
(label) @END
(byte*) SCREEN
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@5
(label) main::@return
(byte) main::i
(byte) main::i#1 zp byte:2
(byte) main::i#2 zp byte:2
(byte) main::j
(byte) main::j#1 zp byte:3
(byte) main::j#2 zp byte:3
(void()) nest1()
(label) nest1::@1
(label) nest1::@2
(label) nest1::@3
(label) nest1::@5
(label) nest1::@return
(byte) nest1::i
(byte) nest1::i#1 zp byte:4
(byte) nest1::i#2 zp byte:4
(byte) nest1::j
(byte) nest1::j#1 zp byte:5
(byte) nest1::j#2 zp byte:5
(void()) nest2()
(label) nest2::@1
(label) nest2::@2
(label) nest2::@3
(label) nest2::@return
(byte) nest2::i
(byte) nest2::i#1 zp byte:6
(byte) nest2::i#2 zp byte:6
(byte) nest2::j
(byte) nest2::j#1 zp byte:7
(byte) nest2::j#2 zp byte:7
zp byte:2 [ main::i#2 main::i#1 ]
zp byte:3 [ main::j#2 main::j#1 ]
zp byte:4 [ nest1::i#2 nest1::i#1 ]
zp byte:5 [ nest1::j#2 nest1::j#1 ]
zp byte:6 [ nest2::i#2 nest2::i#1 ]
zp byte:7 [ nest2::j#2 nest2::j#1 ]