1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-08-02 09:29:35 +00:00

Fixed word constructor detection to detect all inline word constructors.

This commit is contained in:
jespergravgaard 2017-12-27 21:47:07 +01:00
parent 212e8572de
commit 4a7dd31d40
13 changed files with 1435 additions and 100 deletions

View File

@ -3,6 +3,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import java.util.ArrayList;
import java.util.ListIterator;
import java.util.Map;
/** A {@link ValueReplacer} that replaces symbols with their alias. */
@ -83,7 +84,7 @@ public class AliasReplacer implements ValueReplacer.Replacer {
* @param replaceable The replaceable value
*/
@Override
public void execute(ValueReplacer.ReplaceableValue replaceable, Statement currentStmt, ControlFlowBlock currentBlock) {
public void execute(ValueReplacer.ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
if (replaceable.get() != null) {
RValue replacement = getReplacement(replaceable.get(), aliases);
if (replacement != null) {

View File

@ -15,62 +15,28 @@ public class Pass1ExtractInlineStrings extends Pass1Base {
@Override
public boolean step() {
ValueReplacer.executeAll(getGraph(), (replaceable, currentStmt, currentBlock) -> {
ValueReplacer.executeAll(getGraph(), (replaceable, currentStmt, stmtIt, currentBlock) -> {
String nameHint = null;
if(currentStmt instanceof StatementCall) {
StatementCall call = (StatementCall) currentStmt;
List<RValue> parameters = call.getParameters();
for (int i = 0; i < parameters.size(); i++) {
for(int i = 0; i < parameters.size(); i++) {
RValue parameter = parameters.get(i);
if(parameter.equals(replaceable.get())) {
// The replaceable value is the parameter - use the parameter name as name hint
Procedure procedure = getProgram().getScope().getProcedure(call.getProcedure());
Procedure procedure = Pass1ExtractInlineStrings.this.getProgram().getScope().getProcedure(call.getProcedure());
nameHint = procedure.getParameterNames().get(i);
break;
}
}
}
Scope blockScope = getProgram().getScope().getScope(currentBlock.getScope());
Scope blockScope = Pass1ExtractInlineStrings.this.getProgram().getScope().getScope(currentBlock.getScope());
RValue value = replaceable.get();
if(value instanceof ConstantString) {
ConstantVar strConst = createStringConstantVar(blockScope, (ConstantString) replaceable.get(), nameHint);
ConstantVar strConst = Pass1ExtractInlineStrings.this.createStringConstantVar(blockScope, (ConstantString) replaceable.get(), nameHint);
replaceable.set(strConst.getRef());
}
});
/*
for (ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
Scope blockScope = getProgram().getScope().getScope(block.getScope());
while (stmtIt.hasNext()) {
Statement statement = stmtIt.next();
if (statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;
Procedure procedure = getProgram().getScope().getProcedure(call.getProcedure());
List<RValue> parameters = call.getParameters();
int size = parameters.size();
for (int i = 0; i < size; i++) {
String parameterName = procedure.getParameterNames().get(i);
execute(new ValueReplacer.ReplaceableCallParameter(call, i), blockScope, parameterName);
}
} else if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(assignment.getrValue1()==null && assignment.getOperator()==null && assignment.getrValue2() instanceof ConstantString) {
// This will be picked up later as a constant - the temporary constant variable is not needed
continue;
}
if(assignment.getrValue1() instanceof ConstantString && assignment.getrValue2() instanceof ConstantString) {
// This will be picked up later as a constant - the temporary constant variable is not needed
continue;
}
execute(new ValueReplacer.ReplaceableRValue1(assignment), blockScope, null);
execute(new ValueReplacer.ReplaceableRValue2(assignment), blockScope, null);
} else if (statement instanceof StatementReturn) {
execute(new ValueReplacer.ReplaceableReturn((StatementReturn) statement), blockScope, null);
}
}
}
*/
return false;
}

View File

@ -2,6 +2,8 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import java.util.ListIterator;
/**
* Identifies word constructors <code>{ b1, b2 }</code> and replaces
* them with a binary operator <code>word w = b1 w= b2 ;</code>
@ -14,35 +16,54 @@ public class Pass2FixWordConstructors extends Pass2SsaOptimization{
@Override
public boolean step() {
boolean optimized = false;
ProgramScope programScope = getProgram().getScope();
for (ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
for (Statement statement : block.getStatements()) {
if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(assignment.getrValue1()==null && assignment.getOperator()==null) {
if(assignment.getrValue2() instanceof ValueList) {
ValueList list = (ValueList) assignment.getrValue2();
if(list.getList().size()==2) {
// We have a simple assignment of a length 2 value list to a variable
SymbolType lType = SymbolTypeInference.inferType(programScope, assignment.getlValue());
SymbolType elmType1 = SymbolTypeInference.inferType(programScope, list.getList().get(0));
SymbolType elmType2 = SymbolTypeInference.inferType(programScope, list.getList().get(1));
if(SymbolType.isWord(lType) && SymbolType.isByte(elmType1) && SymbolType.isByte(elmType2)) {
// Types are word = { byte, byte } - perform the modification
assignment.setrValue1(list.getList().get(0));
assignment.setOperator(Operator.WORD);
assignment.setrValue2(list.getList().get(1));
getLog().append("Fixing word constructor with " + assignment.toString());
optimized = true;
final boolean[] optimized = {false};
ValueReplacer.executeAll(getGraph(), new ValueReplacer.Replacer() {
@Override
public void execute(ValueReplacer.ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
RValue rValue = replaceable.get();
if(rValue instanceof ValueList) {
ValueList list = (ValueList) rValue;
if(list.getList().size() == 2) {
// We have a simple assignment of a length 2 value list to a variable
SymbolType elmType1 = SymbolTypeInference.inferType(Pass2FixWordConstructors.this.getScope(), list.getList().get(0));
SymbolType elmType2 = SymbolTypeInference.inferType(Pass2FixWordConstructors.this.getScope(), list.getList().get(1));
if(SymbolType.isByte(elmType1) && SymbolType.isByte(elmType2)) {
// We have a 2-element list { byte, byte }
// Check if we are assigning into a declared byte array
if(currentStmt instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) currentStmt;
if(assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2().equals(rValue)) {
SymbolType lType = SymbolTypeInference.inferType(Pass2FixWordConstructors.this.getScope(), assignment.getlValue());
if(lType instanceof SymbolTypeArray && SymbolType.isByte(((SymbolTypeArray) lType).getElementType())) {
// We are assigning into a declared byte array - do not convert!
return;
}
}
}
// Convert list to a word constructor in a new tmp variable
Scope currentScope = getScope().getScope(currentBlock.getScope());
VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
tmpVar.setTypeInferred(SymbolType.WORD);
// Move backward - to insert before the current statement
stmtIt.previous();
// Add assignment of the new tmpVar
StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), list.getList().get(0), Operator.WORD, list.getList().get(1));
stmtIt.add(assignment);
// Move back before the current statement
stmtIt.next();
// Replace current value with the reference
replaceable.set(tmpVar.getRef());
Pass2FixWordConstructors.this.getLog().append("Fixing word constructor with " + assignment.toString());
optimized[0] = true;
}
}
}
}
}
return optimized;
});
return optimized[0];
}
}

View File

@ -1,9 +1,10 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import org.stringtemplate.v4.ST;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ListIterator;
/**
* A replacer capable to alias all usages of a variable (or constant var) with a suitable replacement
@ -15,10 +16,11 @@ public class ValueReplacer {
/**
* Execute replacement of a replaceable value.
* @param replaceable The replaceable value
* @param currentStmt The current statement that the value is a part of
* @param currentStmt The statement iterator - just past the current statement that the value is a part of. Current statment can be retrieved by calling
* @param stmtIt The statement iterator - just past the current statement. Can be used for modifying the control flow block.
* @param currentBlock The current block that the value is a part of
*/
void execute(ReplaceableValue replaceable, Statement currentStmt, ControlFlowBlock currentBlock);
void execute(ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock);
}
/**
@ -29,31 +31,33 @@ public class ValueReplacer {
*/
public static void executeAll(ControlFlowGraph graph, Replacer replacer) {
for (ControlFlowBlock block : graph.getAllBlocks()) {
for (Statement statement : block.getStatements()) {
ListIterator<Statement> statementsIt = block.getStatements().listIterator();
while(statementsIt.hasNext()) {
Statement statement = statementsIt.next();
if (statement instanceof StatementAssignment) {
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, block);
executeAll(new ReplaceableRValue1((StatementAssignment) statement), replacer, statement, block);
executeAll(new ReplaceableRValue2((StatementAssignment) statement), replacer, statement, block);
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableRValue1((StatementAssignment) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableRValue2((StatementAssignment) statement), replacer, statement,statementsIt, block);
} else if (statement instanceof StatementCall) {
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, block);
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, statementsIt, block);
StatementCall call = (StatementCall) statement;
if (call.getParameters() != null) {
int size = call.getParameters().size();
for (int i = 0; i < size; i++) {
executeAll(new ReplaceableCallParameter(call, i), replacer, statement, block);
executeAll(new ReplaceableCallParameter(call, i), replacer, statement, statementsIt, block);
}
}
} else if (statement instanceof StatementConditionalJump) {
executeAll(new ReplaceableCondRValue1((StatementConditionalJump) statement), replacer, statement, block);
executeAll(new ReplaceableCondRValue2((StatementConditionalJump) statement), replacer, statement, block);
executeAll(new ReplaceableCondRValue1((StatementConditionalJump) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableCondRValue2((StatementConditionalJump) statement), replacer, statement, statementsIt, block);
} else if (statement instanceof StatementReturn) {
executeAll(new ReplaceableReturn((StatementReturn) statement), replacer, statement, block);
executeAll(new ReplaceableReturn((StatementReturn) statement), replacer, statement, statementsIt, block);
} else if (statement instanceof StatementPhiBlock) {
for (StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
executeAll(new ReplaceablePhiVariable(phiVariable), replacer, statement, block);
executeAll(new ReplaceablePhiVariable(phiVariable), replacer, statement, statementsIt, block);
int size = phiVariable.getValues().size();
for (int i = 0; i < size; i++) {
executeAll(new ReplaceablePhiValue(phiVariable, i), replacer, statement, block);
executeAll(new ReplaceablePhiValue(phiVariable, i), replacer, statement, statementsIt, block);
}
}
}
@ -66,10 +70,10 @@ public class ValueReplacer {
* @param replaceable The replaceable value
* @param replacer The value replacer
*/
public static void executeAll(ReplaceableValue replaceable, Replacer replacer, Statement currentStmt, ControlFlowBlock currentBlock ) {
replacer.execute(replaceable, currentStmt, currentBlock);
public static void executeAll(ReplaceableValue replaceable, Replacer replacer, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock ) {
replacer.execute(replaceable, currentStmt, stmtIt, currentBlock);
for (ReplaceableValue subValue : replaceable.getSubValues()) {
executeAll(subValue, replacer, currentStmt, currentBlock);
executeAll(subValue, replacer, currentStmt, stmtIt, currentBlock);
}
}

View File

@ -10067,8 +10067,8 @@ Multiple usages for variable. Not optimizing sub-constant (byte) init_plot_table
Multiple usages for variable. Not optimizing sub-constant (byte) init_plot_tables::y#2
Multiple usages for variable. Not optimizing sub-constant (byte) init_plot_tables::y#2
Multiple usages for variable. Not optimizing sub-constant (byte*) init_plot_tables::yoffs#2
Fixing word constructor with plot::plotter_x#0 ← *(plot_xhi#0 + plot::x#4) w= *(plot_xlo#0 + plot::x#4)
Fixing word constructor with plot::plotter_y#0 ← *(plot_yhi#0 + plot::y#4) w= *(plot_ylo#0 + plot::y#4)
Fixing word constructor with plot::$2 ← *(plot_xhi#0 + plot::x#4) w= *(plot_xlo#0 + plot::x#4)
Fixing word constructor with plot::$3 ← *(plot_yhi#0 + plot::y#4) w= *(plot_ylo#0 + plot::y#4)
Succesful SSA optimization Pass2FixWordConstructors
CONTROL FLOW GRAPH
@begin: scope:[] from
@ -10346,8 +10346,10 @@ line_ydxd::@return: scope:[line_ydxd] from line_ydxd::@2
plot: scope:[plot] from line_xdyd::@1 line_xdyi::@1 line_ydxd::@1 line_ydxi::@1
(byte) plot::y#4 ← phi( line_xdyd::@1/(byte) plot::y#1 line_xdyi::@1/(byte) plot::y#0 line_ydxd::@1/(byte) plot::y#3 line_ydxi::@1/(byte) plot::y#2 )
(byte) plot::x#4 ← phi( line_xdyd::@1/(byte) plot::x#1 line_xdyi::@1/(byte) plot::x#0 line_ydxd::@1/(byte) plot::x#3 line_ydxi::@1/(byte) plot::x#2 )
(word) plot::plotter_x#0 ← *((const byte*) plot_xhi#0 + (byte) plot::x#4) w= *((const byte*) plot_xlo#0 + (byte) plot::x#4)
(word) plot::plotter_y#0 ← *((const byte*) plot_yhi#0 + (byte) plot::y#4) w= *((const byte*) plot_ylo#0 + (byte) plot::y#4)
(word~) plot::$2 ← *((const byte*) plot_xhi#0 + (byte) plot::x#4) w= *((const byte*) plot_xlo#0 + (byte) plot::x#4)
(word) plot::plotter_x#0 ← (word~) plot::$2
(word~) plot::$3 ← *((const byte*) plot_yhi#0 + (byte) plot::y#4) w= *((const byte*) plot_ylo#0 + (byte) plot::y#4)
(word) plot::plotter_y#0 ← (word~) plot::$3
(word~) plot::$0 ← (word) plot::plotter_x#0 + (word) plot::plotter_y#0
(byte*) plot::plotter#0 ← ((byte*)) (word~) plot::$0
(byte~) plot::$1 ← *((byte*) plot::plotter#0) | *((const byte*) plot_bit#0 + (byte) plot::x#4)
@ -10703,8 +10705,10 @@ line_ydxd::@return: scope:[line_ydxd] from line_ydxd::@2
plot: scope:[plot] from line_xdyd::@1 line_xdyi::@1 line_ydxd::@1 line_ydxi::@1
(byte) plot::y#4 ← phi( line_xdyd::@1/(byte) plot::y#1 line_xdyi::@1/(byte) plot::y#0 line_ydxd::@1/(byte) plot::y#3 line_ydxi::@1/(byte) plot::y#2 )
(byte) plot::x#4 ← phi( line_xdyd::@1/(byte) plot::x#1 line_xdyi::@1/(byte) plot::x#0 line_ydxd::@1/(byte) plot::x#3 line_ydxi::@1/(byte) plot::x#2 )
(word) plot::plotter_x#0 ← *((const byte*) plot_xhi#0 + (byte) plot::x#4) w= *((const byte*) plot_xlo#0 + (byte) plot::x#4)
(word) plot::plotter_y#0 ← *((const byte*) plot_yhi#0 + (byte) plot::y#4) w= *((const byte*) plot_ylo#0 + (byte) plot::y#4)
(word~) plot::$2 ← *((const byte*) plot_xhi#0 + (byte) plot::x#4) w= *((const byte*) plot_xlo#0 + (byte) plot::x#4)
(word) plot::plotter_x#0 ← (word~) plot::$2
(word~) plot::$3 ← *((const byte*) plot_yhi#0 + (byte) plot::y#4) w= *((const byte*) plot_ylo#0 + (byte) plot::y#4)
(word) plot::plotter_y#0 ← (word~) plot::$3
(word~) plot::$0 ← (word) plot::plotter_x#0 + (word) plot::plotter_y#0
(byte*) plot::plotter#0 ← ((byte*)) (word~) plot::$0
(byte~) plot::$1 ← *((byte*) plot::plotter#0) | *((const byte*) plot_bit#0 + (byte) plot::x#4)
@ -10849,6 +10853,8 @@ Not aliassing across scopes: plot::y#3 line_ydxd::y#3
Not aliassing across scopes: plot::x#4 plot::x#1
Not aliassing across scopes: plot::y#4 plot::y#1
Alias (byte) lines::l#2 = (byte/word~) lines::$0 (byte/word~) lines::$1
Alias (word) plot::plotter_x#0 = (word~) plot::$2
Alias (word) plot::plotter_y#0 = (word~) plot::$3
Succesful SSA optimization Pass2AliasElimination
CONTROL FLOW GRAPH
@begin: scope:[] from

View File

@ -678,9 +678,41 @@ main::@return: scope:[main] from main::@3
to:@end
@end: scope:[] from @1
Fixing word constructor with main::w#0 ← *(main::his#2 + main::h#4) w= main::l#2
Fixing word constructor with main::$8 ← *(main::his#2 + main::h#4) w= main::l#2
Succesful SSA optimization Pass2FixWordConstructors
CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from @1
to:main::@1
main::@1: scope:[main] from main main::@3
(byte) main::h#4 ← phi( main/(const byte) main::h#0 main::@3/(byte) main::h#1 )
(byte[]) main::his#2 ← phi( main/(const byte[]) main::his#0 main::@3/(byte[]) main::his#2 )
to:main::@2
main::@2: scope:[main] from main::@1 main::@2
(byte) main::l#2 ← phi( main::@1/(const byte) main::l#0 main::@2/(byte) main::l#1 )
(word~) main::$8 ← *((byte[]) main::his#2 + (byte) main::h#4) w= (byte) main::l#2
(word) main::w#0 ← (word~) main::$8
(byte*) main::sc#0 ← ((byte*)) (word) main::w#0
*((byte*) main::sc#0) ← (byte) '*'
(byte) main::l#1 ← ++ (byte) main::l#2
if((byte) main::l#1!=(byte/signed byte/word/signed word) 8) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@2
(byte) main::h#1 ← ++ (byte) main::h#4
if((byte) main::h#1!=(byte/signed byte/word/signed word) 3) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@1: scope:[] from @begin
call main param-assignment
to:@end
@end: scope:[] from @1
Alias (word) main::w#0 = (word~) main::$8
Succesful SSA optimization Pass2AliasElimination
CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from @1

View File

@ -4225,7 +4225,7 @@ main::@return: scope:[main] from main::@16
to:@end
@end: scope:[] from @35
Fixing word constructor with getFAC::return#0 ← *(memHi#0) w= *(memLo#0)
Fixing word constructor with getFAC::$0 ← *(memHi#0) w= *(memLo#0)
Succesful SSA optimization Pass2FixWordConstructors
CONTROL FLOW GRAPH
@begin: scope:[] from
@ -4306,7 +4306,8 @@ setFAC::@return: scope:[setFAC] from setFAC::@1
to:@return
getFAC: scope:[getFAC] from main::@13
asm { jsr$b1aasty$festa$ff }
(word) getFAC::return#0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
(word~) getFAC::$0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
(word) getFAC::return#0 ← (word~) getFAC::$0
to:getFAC::@return
getFAC::@return: scope:[getFAC] from getFAC
return
@ -4435,6 +4436,208 @@ Culled Empty Block (label) main::@5
Culled Empty Block (label) @35
Succesful SSA optimization Pass2CullEmptyBlocks
CONTROL FLOW GRAPH
@begin: scope:[] from
to:@34
print_ln: scope:[print_ln] from main::@15
to:print_ln::@1
print_ln::@1: scope:[print_ln] from print_ln print_ln::@1
(byte*) line_cursor#6 ← phi( print_ln/(byte*) line_cursor#13 print_ln::@1/(byte*) line_cursor#1 )
(byte*) line_cursor#1 ← (byte*) line_cursor#6 + (byte/signed byte/word/signed word) 40
if((byte*) line_cursor#1<(byte*) char_cursor#10) goto print_ln::@1
to:print_ln::@return
print_ln::@return: scope:[print_ln] from print_ln::@1
return
to:@return
print_word: scope:[print_word] from main::@14
(byte) print_byte::b#0 ← > (word) print_word::w#0
call print_byte param-assignment
to:print_word::@1
print_word::@1: scope:[print_word] from print_word
(byte) print_byte::b#1 ← < (word) print_word::w#0
call print_byte param-assignment
to:print_word::@return
print_word::@return: scope:[print_word] from print_word::@1
return
to:@return
print_byte: scope:[print_byte] from print_word print_word::@1
(byte*) char_cursor#31 ← phi( print_word/(byte*) char_cursor#32 print_word::@1/(byte*) char_cursor#10 )
(byte) print_byte::b#2 ← phi( print_word/(byte) print_byte::b#0 print_word::@1/(byte) print_byte::b#1 )
(byte~) print_byte::$0 ← (byte) print_byte::b#2 >> (byte/signed byte/word/signed word) 4
(byte) print_char::ch#0 ← *((const byte[]) print_byte::hextab#0 + (byte~) print_byte::$0)
call print_char param-assignment
to:print_byte::@1
print_byte::@1: scope:[print_byte] from print_byte
(byte~) print_byte::$2 ← (byte) print_byte::b#2 & (byte/signed byte/word/signed word) 15
(byte) print_char::ch#1 ← *((const byte[]) print_byte::hextab#0 + (byte~) print_byte::$2)
call print_char param-assignment
to:print_byte::@return
print_byte::@return: scope:[print_byte] from print_byte::@1
return
to:@return
print_char: scope:[print_char] from print_byte print_byte::@1
(byte*) char_cursor#23 ← phi( print_byte/(byte*) char_cursor#31 print_byte::@1/(byte*) char_cursor#10 )
(byte) print_char::ch#2 ← phi( print_byte/(byte) print_char::ch#0 print_byte::@1/(byte) print_char::ch#1 )
*((byte*) char_cursor#23) ← (byte) print_char::ch#2
(byte*) char_cursor#10 ← ++ (byte*) char_cursor#23
to:print_char::@return
print_char::@return: scope:[print_char] from print_char
return
to:@return
prepareMEM: scope:[prepareMEM] from addMEMtoFAC divMEMbyFAC mulFACbyMEM setFAC setMEMtoFAC
(byte*) prepareMEM::mem#5 ← phi( addMEMtoFAC/(const byte[]) prepareMEM::mem#2 divMEMbyFAC/(const byte[]) prepareMEM::mem#3 mulFACbyMEM/(byte*) prepareMEM::mem#4 setFAC/(byte*) prepareMEM::mem#0 setMEMtoFAC/(byte*) prepareMEM::mem#1 )
(byte~) prepareMEM::$0 ← < (byte*) prepareMEM::mem#5
*((const byte*) memLo#0) ← (byte~) prepareMEM::$0
(byte~) prepareMEM::$1 ← > (byte*) prepareMEM::mem#5
*((const byte*) memHi#0) ← (byte~) prepareMEM::$1
to:prepareMEM::@return
prepareMEM::@return: scope:[prepareMEM] from prepareMEM
return
to:@return
setFAC: scope:[setFAC] from main main::@1 main::@8
(word) setFAC::w#3 ← phi( main/(const word) setFAC::w#0 main::@1/(word) setFAC::w#1 main::@8/(const word) setFAC::w#2 )
(byte*) prepareMEM::mem#0 ← ((byte*)) (word) setFAC::w#3
call prepareMEM param-assignment
to:setFAC::@1
setFAC::@1: scope:[setFAC] from setFAC
asm { ldy$felda$ffjsr$b391 }
to:setFAC::@return
setFAC::@return: scope:[setFAC] from setFAC::@1
return
to:@return
getFAC: scope:[getFAC] from main::@13
asm { jsr$b1aasty$festa$ff }
(word~) getFAC::$0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
(word) getFAC::return#0 ← (word~) getFAC::$0
to:getFAC::@return
getFAC::@return: scope:[getFAC] from getFAC
return
to:@return
setMEMtoFAC: scope:[setMEMtoFAC] from main::@4 main::@7
(byte*) setMEMtoFAC::mem#2 ← phi( main::@4/(const byte[]) setMEMtoFAC::mem#0 main::@7/(const byte[]) setMEMtoFAC::mem#1 )
(byte*) prepareMEM::mem#1 ← (byte*) setMEMtoFAC::mem#2
call prepareMEM param-assignment
to:setMEMtoFAC::@1
setMEMtoFAC::@1: scope:[setMEMtoFAC] from setMEMtoFAC
asm { ldx$feldy$ffjsr$bbd4 }
to:setMEMtoFAC::@return
setMEMtoFAC::@return: scope:[setMEMtoFAC] from setMEMtoFAC::@1
return
to:@return
addMEMtoFAC: scope:[addMEMtoFAC] from main::@12
call prepareMEM param-assignment
to:addMEMtoFAC::@1
addMEMtoFAC::@1: scope:[addMEMtoFAC] from addMEMtoFAC
asm { lda$feldy$ffjsr$b867 }
to:addMEMtoFAC::@return
addMEMtoFAC::@return: scope:[addMEMtoFAC] from addMEMtoFAC::@1
return
to:@return
divMEMbyFAC: scope:[divMEMbyFAC] from main::@9
call prepareMEM param-assignment
to:divMEMbyFAC::@1
divMEMbyFAC::@1: scope:[divMEMbyFAC] from divMEMbyFAC
asm { lda$feldy$ffjsr$bb0f }
to:divMEMbyFAC::@return
divMEMbyFAC::@return: scope:[divMEMbyFAC] from divMEMbyFAC::@1
return
to:@return
mulFACbyMEM: scope:[mulFACbyMEM] from main::@11 main::@6
(byte*) mulFACbyMEM::mem#2 ← phi( main::@11/(const byte[]) mulFACbyMEM::mem#1 main::@6/(const byte*) mulFACbyMEM::mem#0 )
(byte*) prepareMEM::mem#4 ← (byte*) mulFACbyMEM::mem#2
call prepareMEM param-assignment
to:mulFACbyMEM::@1
mulFACbyMEM::@1: scope:[mulFACbyMEM] from mulFACbyMEM
asm { lda$feldy$ffjsr$ba28 }
to:mulFACbyMEM::@return
mulFACbyMEM::@return: scope:[mulFACbyMEM] from mulFACbyMEM::@1
return
to:@return
sinFAC: scope:[sinFAC] from main::@10
asm { jsr$e26b }
to:sinFAC::@return
sinFAC::@return: scope:[sinFAC] from sinFAC
return
to:@return
divFACby10: scope:[divFACby10] from main::@3
asm { jsr$bafe }
to:divFACby10::@return
divFACby10::@return: scope:[divFACby10] from divFACby10
return
to:@return
main: scope:[main] from @34
call setFAC param-assignment
to:main::@3
main::@3: scope:[main] from main
call divFACby10 param-assignment
to:main::@4
main::@4: scope:[main] from main::@3
call setMEMtoFAC param-assignment
to:main::@1
main::@1: scope:[main] from main::@16 main::@4
(byte*) line_cursor#13 ← phi( main::@16/(byte*) line_cursor#1 main::@4/(const byte*) char_cursor#0 )
(byte*) char_cursor#32 ← phi( main::@16/(byte*) line_cursor#1 main::@4/(const byte*) char_cursor#0 )
(byte) main::i#10 ← phi( main::@16/(byte) main::i#1 main::@4/(const byte) main::i#0 )
(word) setFAC::w#1 ← ((word)) (byte) main::i#10
call setFAC param-assignment
to:main::@6
main::@6: scope:[main] from main::@1
call mulFACbyMEM param-assignment
to:main::@7
main::@7: scope:[main] from main::@6
call setMEMtoFAC param-assignment
to:main::@8
main::@8: scope:[main] from main::@7
call setFAC param-assignment
to:main::@9
main::@9: scope:[main] from main::@8
call divMEMbyFAC param-assignment
to:main::@10
main::@10: scope:[main] from main::@9
call sinFAC param-assignment
to:main::@11
main::@11: scope:[main] from main::@10
call mulFACbyMEM param-assignment
to:main::@12
main::@12: scope:[main] from main::@11
call addMEMtoFAC param-assignment
to:main::@13
main::@13: scope:[main] from main::@12
call getFAC param-assignment
(word) getFAC::return#2 ← (word) getFAC::return#0
to:main::@14
main::@14: scope:[main] from main::@13
(word) print_word::w#0 ← (word) getFAC::return#2
call print_word param-assignment
to:main::@15
main::@15: scope:[main] from main::@14
call print_ln param-assignment
to:main::@16
main::@16: scope:[main] from main::@15
(byte) main::i#1 ← ++ (byte) main::i#10
if((byte) main::i#1!=(byte/signed byte/word/signed word) 26) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@16
return
to:@return
@34: scope:[] from @begin
call main param-assignment
to:@end
@end: scope:[] from @34
Not aliassing across scopes: line_cursor#6 line_cursor#13
Not aliassing across scopes: print_byte::b#2 print_byte::b#0
Not aliassing across scopes: char_cursor#31 char_cursor#32
Not aliassing across scopes: print_char::ch#2 print_char::ch#0
Not aliassing across scopes: char_cursor#23 char_cursor#31
Not aliassing across scopes: prepareMEM::mem#1 setMEMtoFAC::mem#2
Not aliassing across scopes: prepareMEM::mem#4 mulFACbyMEM::mem#2
Not aliassing across scopes: char_cursor#32 line_cursor#1
Not aliassing across scopes: line_cursor#13 line_cursor#1
Not aliassing across scopes: getFAC::return#2 getFAC::return#0
Not aliassing across scopes: print_word::w#0 getFAC::return#2
Alias (word) getFAC::return#0 = (word~) getFAC::$0
Succesful SSA optimization Pass2AliasElimination
CONTROL FLOW GRAPH
@begin: scope:[] from
to:@34
print_ln: scope:[print_ln] from main::@15

View File

@ -12954,7 +12954,7 @@ Multiple usages for variable. Not optimizing sub-constant (byte) init::i#2
Multiple usages for variable. Not optimizing sub-constant (byte) place_sprites::spr_x#2
Multiple usages for variable. Not optimizing sub-constant (byte*) gen_sprites::spr#2
Multiple usages for variable. Not optimizing sub-constant (byte*) gen_chargen_sprite::sprite#4
Fixing word constructor with getFAC::return#0 ← *(memHi#0) w= *(memLo#0)
Fixing word constructor with getFAC::$0 ← *(memHi#0) w= *(memLo#0)
Succesful SSA optimization Pass2FixWordConstructors
CONTROL FLOW GRAPH
@begin: scope:[] from
@ -12982,7 +12982,8 @@ setFAC::@return: scope:[setFAC] from setFAC::@1
to:@return
getFAC: scope:[getFAC] from gen_sintab::@21
asm { jsr$b1aasty$festa$ff }
(word) getFAC::return#0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
(word~) getFAC::$0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
(word) getFAC::return#0 ← (word~) getFAC::$0
to:getFAC::@return
getFAC::@return: scope:[getFAC] from getFAC
return
@ -13444,7 +13445,8 @@ setFAC::@return: scope:[setFAC] from setFAC::@1
to:@return
getFAC: scope:[getFAC] from gen_sintab::@21
asm { jsr$b1aasty$festa$ff }
(word) getFAC::return#0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
(word~) getFAC::$0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
(word) getFAC::return#0 ← (word~) getFAC::$0
to:getFAC::@return
getFAC::@return: scope:[getFAC] from getFAC
return
@ -13917,7 +13919,8 @@ setFAC::@return: scope:[setFAC] from setFAC::@1
to:@return
getFAC: scope:[getFAC] from gen_sintab::@21
asm { jsr$b1aasty$festa$ff }
(word) getFAC::return#0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
(word~) getFAC::$0 ← *((const byte*) memHi#0) w= *((const byte*) memLo#0)
(word) getFAC::return#0 ← (word~) getFAC::$0
to:getFAC::@return
getFAC::@return: scope:[getFAC] from getFAC
return
@ -14353,6 +14356,7 @@ Not aliassing across scopes: gen_chargen_sprite::sprite#11 gen_chargen_sprite::s
Not aliassing across scopes: progress_cursor#34 progress_cursor#22
Not aliassing across scopes: getFAC::return#2 getFAC::return#0
Not aliassing across scopes: gen_sintab::$23 getFAC::return#2
Alias (word) getFAC::return#0 = (word~) getFAC::$0
Alias (byte) init::i#2 = (byte/word~) init::$1
Succesful SSA optimization Pass2AliasElimination
CONTROL FLOW GRAPH

View File

@ -0,0 +1,26 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
jsr main
main: {
.const b = 4
.const pos = $501
.const bgcol = $d021
.const w = b*$100+0
.const w2 = 1*$100+1+w+0*$100+0
.const sc = w2
lda bs+1
sta sc
lda pos
cmp #'m'
bne b1
lda #5
sta bgcol
breturn:
rts
b1:
lda #2
sta bgcol
jmp breturn
bs: .byte 'c', 'm'
}

View File

@ -0,0 +1,22 @@
@begin: scope:[] from
[0] phi() [ ] ( )
to:@1
@1: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main param-assignment [ ] ( )
to:@end
@end: scope:[] from @1
[3] phi() [ ] ( )
main: scope:[main] from @1
[4] *((const byte*) main::sc#0) ← *((const byte[]) main::bs#0+(byte/signed byte/word/signed word) 1) [ ] ( main:2 [ ] )
[5] if(*((const byte*) main::pos#0)!=(byte) 'm') goto main::@1 [ ] ( main:2 [ ] )
to:main::@3
main::@3: scope:[main] from main
[6] *((const byte*) main::bgcol#0) ← (byte/signed byte/word/signed word) 5 [ ] ( main:2 [ ] )
to:main::@return
main::@return: scope:[main] from main::@1 main::@3
[7] return [ ] ( main:2 [ ] )
to:@return
main::@1: scope:[main] from main
[8] *((const byte*) main::bgcol#0) ← (byte/signed byte/word/signed word) 2 [ ] ( main:2 [ ] )
to:main::@return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@3
(label) main::@return
(byte) main::b
(const byte) main::b#0 b = (byte/signed byte/word/signed word) 4
(byte*) main::bgcol
(const byte*) main::bgcol#0 bgcol = ((byte*))(word) 53281
(byte[]) main::bs
(const byte[]) main::bs#0 bs = { (byte) 'c', (byte) 'm' }
(byte*) main::pos
(const byte*) main::pos#0 pos = ((byte*))(word/signed word) 1281
(byte*) main::sc
(const byte*) main::sc#0 sc = ((byte*))(const word) main::w2#0
(word) main::w
(const word) main::w#0 w = (const byte) main::b#0*(word/signed word) 256+(byte/signed byte/word/signed word) 0
(word) main::w2
(const word) main::w2#0 w2 = (byte/signed byte/word/signed word) 1*(word/signed word) 256+(byte/signed byte/word/signed word) 1+(const word) main::w#0+(byte/signed byte/word/signed word) 0*(word/signed word) 256+(byte/signed byte/word/signed word) 0

View File

@ -1,10 +1,19 @@
void main() {
byte[] bs = { 'c', 'm' }; // constant byte array
byte b = 4; // constant byte
word w = { b, 0 }; // constant inline word
word w2 = { 1, 1 } + w; // constant inline word inside expression
byte* sc = w2; // implicit cast to (byte*)
*sc = bs[0];
byte[] bs = { 'c', 'm' }; // constant byte array
byte b = 4; // constant byte
word w = { b, 0 }; // constant inline word
word w2 = { 1, 1 } + w + { 0, 0 }; // constant inline words inside expression
byte* sc = w2; // implicit cast to (byte*)
*sc = bs[1]; // In the end $501 is set to 'c'
// Test the result
byte* pos = $501;
byte* bgcol = $d021;
if(*pos=='m') {
*bgcol = 5;
} else {
*bgcol = 2;
}
}