1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Moving __Stackcall stack operations back to pass 1/2 from pass 4 ASM code generation.

This commit is contained in:
jespergravgaard 2020-03-07 00:33:07 +01:00
parent 689aeb0ca6
commit 9e2e38e671
66 changed files with 1345 additions and 1291 deletions

View File

@ -1,7 +1,6 @@
package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementInfos;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.Label;
import dk.camelot64.kickc.model.symbols.Procedure;

View File

@ -53,6 +53,8 @@ public class ControlFlowGraphBaseVisitor<T> {
return visitAsm((StatementAsm) statement);
} else if(statement instanceof StatementKickAsm) {
return visitKickAsm((StatementKickAsm) statement);
} else if(statement instanceof StatementStackPull) {
return visitStackPull((StatementStackPull) statement);
} else {
throw new RuntimeException("Unhandled statement type " + statement);
}
@ -117,4 +119,8 @@ public class ControlFlowGraphBaseVisitor<T> {
public T visitKickAsm(StatementKickAsm asm) {
return null;
}
public T visitStackPull(StatementStackPull stackPull) {
return null;
}
}

View File

@ -221,4 +221,8 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
return new StatementKickAsm(orig.getKickAsmCode(), orig.getLocation(), orig.getBytes(), orig.getCycles(), orig.getUses(), orig.getDeclaredClobber(), orig.getSource(), orig.getComments());
}
@Override
public Object visitStackPull(StatementStackPull orig) {
return new StatementStackPull(orig.getPullBytes(), orig.getSource(), orig.getComments());
}
}

View File

@ -4,7 +4,6 @@ import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.asm.AsmProgram;
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementInfos;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.passes.calcs.*;

View File

@ -1,9 +1,7 @@
package dk.camelot64.kickc.model.statements;
package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.ControlFlowGraph;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.Program;
import java.util.Map;

View File

@ -312,6 +312,28 @@ public interface ProgramValue {
}
/** Number of bytes constant used by stack pull . */
class StackPullBytes implements ProgramValue {
private StatementStackPull statementStackPull;
StackPullBytes(StatementStackPull statementStackPull) {
this.statementStackPull = statementStackPull;
}
@Override
public Value get() {
return statementStackPull.getPullBytes();
}
@Override
public void set(Value value) {
statementStackPull.setPullBytes((ConstantValue) value);
}
}
class BlockLabel implements ProgramValue {
private final ControlFlowBlock block;
@ -790,7 +812,7 @@ public interface ProgramValue {
@Override
public void set(Value val) {
stackIdxValue.setStackOffset((ConstantRef) val);
stackIdxValue.setStackOffset((ConstantValue) val);
}
}

View File

@ -48,7 +48,7 @@ public class ProgramValueIterator {
* @param programValueHandler The programValueHandler to execute
*/
public static void execute(Variable variable, ProgramValueHandler programValueHandler) {
if(variable.getInitValue()!=null) {
if(variable.getInitValue() != null) {
execute(new ProgramValue.ProgramValueInitValue(variable), programValueHandler, null, null, null);
}
if(variable.isArray()) {
@ -145,15 +145,15 @@ public class ProgramValueIterator {
} else if(statement instanceof StatementKickAsm) {
StatementKickAsm statementKickAsm = (StatementKickAsm) statement;
RValue location = statementKickAsm.getLocation();
if(location!=null) {
if(location != null) {
execute(new ProgramValue.ProgramValueKickAsmLocation(statementKickAsm), handler, statement, statementsIt, block);
}
RValue bytes = statementKickAsm.getLocation();
if(bytes!=null) {
if(bytes != null) {
execute(new ProgramValue.ProgramValueKickAsmBytes(statementKickAsm), handler, statement, statementsIt, block);
}
RValue cycles = statementKickAsm.getLocation();
if(cycles!=null) {
if(cycles != null) {
execute(new ProgramValue.ProgramValueKickAsmCycles(statementKickAsm), handler, statement, statementsIt, block);
}
List<SymbolRef> uses = statementKickAsm.getUses();
@ -166,6 +166,9 @@ public class ProgramValueIterator {
for(String label : referenced.keySet()) {
execute(new ProgramValue.ProgramValueAsmReferenced(statementAsm, label), handler, statement, statementsIt, block);
}
} else if(statement instanceof StatementStackPull) {
StatementStackPull statementStackPull = (StatementStackPull) statement;
execute(new ProgramValue.StackPullBytes(statementStackPull), handler, statement, statementsIt, block);
}
}
@ -245,13 +248,13 @@ public class ProgramValueIterator {
subValues.add(new ProgramValue.ProgramValueLValueIntermediateVariable((LvalueIntermediate) value));
} else if(value instanceof ParamValue) {
subValues.add(new ProgramValue.ProgramValueParamValue((ParamValue) value));
} else if(value instanceof StackIdxValue) {
subValues.add(new ProgramValue.ProgramValueStackIdxValue((StackIdxValue) value));
} else if(value instanceof MemsetValue) {
subValues.add(new ProgramValue.ProgramValueMemsetValue((MemsetValue) value));
} else if(value instanceof MemcpyValue) {
subValues.add(new ProgramValue.ProgramValueMempySize((MemcpyValue) value));
subValues.add(new ProgramValue.ProgramValueMempySource((MemcpyValue) value));
} else if(value instanceof StackIdxValue) {
subValues.add(new ProgramValue.ProgramValueStackIdxValue((StackIdxValue) value));
} else if(value == null ||
value instanceof SymbolVariableRef ||
value instanceof Variable ||
@ -259,8 +262,9 @@ public class ProgramValueIterator {
value instanceof ConstantLiteral ||
value instanceof StructZero ||
value instanceof Label ||
value instanceof LabelRef
) {
value instanceof LabelRef ||
value instanceof StackPullValue
) {
// No sub values
} else {
throw new RuntimeException("Unhandled value type " + value.getClass());

View File

@ -26,7 +26,7 @@ public class StatementAsm extends StatementBase {
private AsmClobber declaredClobber;
public StatementAsm(String asmBody, Map<String, SymbolRef> referenced, AsmClobber declaredClobber, StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.asmBody = asmBody;
this.referenced = referenced;
this.declaredClobber = declaredClobber;

View File

@ -7,6 +7,7 @@ import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.values.RValue;
import java.util.List;
import java.util.Objects;
/**
* Single Static Assignment Form Statement.
@ -28,27 +29,15 @@ public class StatementAssignment extends StatementBase implements StatementLValu
private boolean initialAssignment;
public StatementAssignment(LValue lValue, RValue rValue2, boolean initialAssignment, StatementSource source, List<Comment> comments) {
this(lValue, null, null, rValue2, initialAssignment, null, source, comments);
this(lValue, null, null, rValue2, initialAssignment, source, comments);
}
public StatementAssignment(LValue lValue, Operator operator, RValue rValue2, boolean initialAssignment, StatementSource source, List<Comment> comments) {
this(lValue, null, operator, rValue2, initialAssignment, null, source, comments);
this(lValue, null, operator, rValue2, initialAssignment, source, comments);
}
public StatementAssignment(LValue lValue, RValue rValue1, Operator operator, RValue rValue2, boolean initialAssignment, StatementSource source, List<Comment> comments) {
this(lValue, rValue1, operator, rValue2, initialAssignment, null, source, comments);
}
public StatementAssignment(
LValue lValue,
RValue rValue1,
Operator operator,
RValue rValue2,
boolean initialAssignment,
Integer index,
StatementSource source,
List<Comment> comments) {
super(index, source, comments);
super(source, comments);
this.lValue = lValue;
this.rValue1 = rValue1;
this.operator = operator;
@ -56,7 +45,6 @@ public class StatementAssignment extends StatementBase implements StatementLValu
this.initialAssignment = initialAssignment;
}
public LValue getlValue() {
return lValue;
}
@ -114,22 +102,16 @@ public class StatementAssignment extends StatementBase implements StatementLValu
if(this == o) return true;
if(o == null || getClass() != o.getClass()) return false;
if(!super.equals(o)) return false;
StatementAssignment that = (StatementAssignment) o;
if(!lValue.equals(that.lValue)) return false;
if(rValue1 != null ? !rValue1.equals(that.rValue1) : that.rValue1 != null) return false;
if(operator != null ? !operator.equals(that.operator) : that.operator != null) return false;
return rValue2 != null ? rValue2.equals(that.rValue2) : that.rValue2 == null;
return initialAssignment == that.initialAssignment &&
Objects.equals(lValue, that.lValue) &&
Objects.equals(rValue1, that.rValue1) &&
Objects.equals(operator, that.operator) &&
Objects.equals(rValue2, that.rValue2);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + lValue.hashCode();
result = 31 * result + (rValue1 != null ? rValue1.hashCode() : 0);
result = 31 * result + (operator != null ? operator.hashCode() : 0);
result = 31 * result + (rValue2 != null ? rValue2.hashCode() : 0);
return result;
return Objects.hash(super.hashCode(), lValue, rValue1, operator, rValue2, initialAssignment);
}
}

View File

@ -16,8 +16,8 @@ public abstract class StatementBase implements Statement {
/** Comments preceding the statement in the source code. */
private List<Comment> comments;
public StatementBase(Integer index, StatementSource source, List<Comment> comments) {
this.index = index;
public StatementBase(StatementSource source, List<Comment> comments) {
this.index = null;
this.source = source;
this.comments = comments;
}

View File

@ -28,7 +28,7 @@ public class StatementCall extends StatementBase implements StatementLValue, Sta
private boolean initialAssignment;
public StatementCall(LValue lValue, String procedureName, List<RValue> parameters, StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.lValue = lValue;
this.procedureName = procedureName;
this.parameters = parameters;

View File

@ -20,7 +20,7 @@ public class StatementCallExecute extends StatementBase implements StatementCall
private ProcedureRef procedure;
public StatementCallExecute(ProcedureRef procedure, StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.procedure = procedure;
}

View File

@ -25,7 +25,7 @@ public class StatementCallFinalize extends StatementBase implements StatementLVa
private boolean initialAssignment;
public StatementCallFinalize(LValue lValue, ProcedureRef procedure, StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.lValue = lValue;
this.procedure = procedure;
}

View File

@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.statements;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.values.ProcedureRef;
import dk.camelot64.kickc.model.values.RValue;
import java.util.List;
@ -24,7 +23,7 @@ public class StatementCallPointer extends StatementBase implements StatementLVal
private boolean initialAssignment;
public StatementCallPointer(LValue lValue, RValue procedure, List<RValue> parameters, StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.lValue = lValue;
this.procedure = procedure;
this.parameters = parameters;

View File

@ -23,7 +23,7 @@ public class StatementCallPrepare extends StatementBase {
private List<RValue> parameters;
public StatementCallPrepare(ProcedureRef procedure, List<RValue> parameters, StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.procedure = procedure;
this.parameters = parameters;
}

View File

@ -27,7 +27,7 @@ public class StatementConditionalJump extends StatementBase {
private boolean wasUnrolled;
public StatementConditionalJump(RValue condition, LabelRef destination,StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.rValue1 = null;
this.operator = null;
this.rValue2 = condition;
@ -41,7 +41,7 @@ public class StatementConditionalJump extends StatementBase {
LabelRef destination,
StatementSource source,
List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.rValue1 = rValue1;
this.operator = operator;
this.rValue2 = rValue2;

View File

@ -17,7 +17,7 @@ public class StatementJump extends StatementBase {
private LabelRef destination;
public StatementJump(LabelRef destination, StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.destination = destination;
}

View File

@ -5,7 +5,6 @@ import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.SymbolRef;
import dk.camelot64.kickc.model.values.SymbolVariableRef;
import java.util.ArrayList;
import java.util.List;
@ -32,13 +31,13 @@ public class StatementKickAsm extends StatementBase {
private AsmClobber declaredClobber;
public StatementKickAsm(String kickAsmCode, StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.kickAsmCode = kickAsmCode;
this.uses = new ArrayList<>();
}
public StatementKickAsm(String kickAsmCode, RValue location, RValue bytes, RValue cycles, List<SymbolRef> uses, AsmClobber declaredClobber, StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.kickAsmCode = kickAsmCode;
this.location = location;
this.bytes = bytes;

View File

@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.Program;
import java.util.ArrayList;
import java.util.List;
/**
@ -15,7 +14,7 @@ public class StatementLabel extends StatementBase {
private LabelRef label;
public StatementLabel(LabelRef label, StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.label = label;
}

View File

@ -24,7 +24,7 @@ public class StatementPhiBlock extends StatementBase {
private List<PhiVariable> phiVariables;
public StatementPhiBlock(List<Comment> comments) {
super(null, new StatementSource(RuleContext.EMPTY), comments);
super(new StatementSource(RuleContext.EMPTY), comments);
this.phiVariables = new ArrayList<>();
}

View File

@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.values.ProcedureRef;
import dk.camelot64.kickc.model.Program;
import java.util.ArrayList;
import java.util.List;
/** Procedure declaration in SSA */
@ -15,7 +14,7 @@ public class StatementProcedureBegin extends StatementBase {
private Strategy strategy;
public StatementProcedureBegin(ProcedureRef procedure,StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.procedure = procedure;
}

View File

@ -14,7 +14,7 @@ public class StatementProcedureEnd extends StatementBase {
private ProcedureRef procedure;
public StatementProcedureEnd(ProcedureRef procedure, StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.procedure = procedure;
}

View File

@ -17,7 +17,7 @@ public class StatementReturn extends StatementBase {
private RValue value;
public StatementReturn(RValue value, StatementSource source, List<Comment> comments) {
super(null, source, comments);
super(source, comments);
this.value = value;
}

View File

@ -0,0 +1,31 @@
package dk.camelot64.kickc.model.statements;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.values.ConstantValue;
import java.util.List;
/** Pulls some bytes of the stack. */
public class StatementStackPull extends StatementBase {
private ConstantValue pullBytes;
public StatementStackPull(ConstantValue pullBytes, StatementSource source, List<Comment> comments) {
super(source, comments);
this.pullBytes = pullBytes;
}
public ConstantValue getPullBytes() {
return pullBytes;
}
public void setPullBytes(ConstantValue pullBytes) {
this.pullBytes = pullBytes;
}
@Override
public String toString(Program program, boolean aliveInfo) {
return "stackpull("+pullBytes.toString(program)+")";
}
}

View File

@ -10,7 +10,8 @@ import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.unwinding.*;
import dk.camelot64.kickc.passes.unwinding.ValueSource;
import dk.camelot64.kickc.passes.unwinding.ValueSourceFactory;
import java.util.ArrayList;
import java.util.List;
@ -90,16 +91,10 @@ public class Pass1UnwindStructValues extends Pass1Base {
private boolean unwindCall(StatementCall call, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
// Unwind struct value return value
boolean lvalUnwound = false;
final ValueSource lValueSource = ValueSourceFactory.getValueSource(call.getlValue(), getProgram(), getScope(), call, stmtIt, currentBlock);
if(lValueSource != null && lValueSource.isUnwindable()) {
ArrayList<RValue> unwoundMembers = new ArrayList<>();
for(String memberName : lValueSource.getMemberNames(getScope())) {
ValueSource memberUnwinding = lValueSource.getMemberUnwinding(memberName, getProgram(), getScope(), call, stmtIt, currentBlock);
unwoundMembers.add(memberUnwinding.getSimpleValue(getScope()));
}
ValueList unwoundLValue = new ValueList(unwoundMembers);
call.setlValue(unwoundLValue);
final ValueSource valueSource = ValueSourceFactory.getValueSource(call.getlValue(), getProgram(), getScope(), call, stmtIt, currentBlock);
RValue unwoundLValue = unwindValue(valueSource, call, stmtIt, currentBlock);
if(unwoundLValue != null && !call.getlValue().equals(unwoundLValue)) {
call.setlValue((LValue) unwoundLValue);
getLog().append("Converted procedure call LValue to member unwinding " + call.toString(getProgram(), false));
lvalUnwound = true;
}
@ -132,6 +127,31 @@ public class Pass1UnwindStructValues extends Pass1Base {
return (anyParameterUnwound || lvalUnwound);
}
/**
* Unwind an LVa.lue to a ValueList if it is unwindable.
* @param value The value to unwind
* @param statement The current statement
* @param stmtIt Statement iterator
* @param currentBlock current block
* @return The unwound ValueList. null if the value is not unwindable.
*/
private RValue unwindValue(ValueSource lValueSource, Statement statement, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
if(lValueSource==null) {
return null;
} else if(lValueSource.isSimple()) {
return lValueSource.getSimpleValue(getScope());
} else if(lValueSource.isUnwindable()) {
ArrayList<RValue> unwoundMembers = new ArrayList<>();
for(String memberName : lValueSource.getMemberNames(getScope())) {
ValueSource memberUnwinding = lValueSource.getMemberUnwinding(memberName, getProgram(), getScope(), statement, stmtIt, currentBlock);
unwoundMembers.add(unwindValue(memberUnwinding, statement, stmtIt, currentBlock));
}
return new ValueList(unwoundMembers);
} else {
return null;
}
}
/**
* Unwind any return value that is a struct value into the member values
*
@ -139,22 +159,15 @@ public class Pass1UnwindStructValues extends Pass1Base {
*/
private boolean unwindReturn(StatementReturn statementReturn, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
boolean modified = false;
// Unwind struct value return value
final ValueSource returnVarUnwinding = ValueSourceFactory.getValueSource(statementReturn.getValue(), getProgram(), getScope(), statementReturn, stmtIt, currentBlock);
if(returnVarUnwinding != null && returnVarUnwinding.isUnwindable()) {
ArrayList<RValue> unwoundMembers = new ArrayList<>();
for(String memberName : returnVarUnwinding.getMemberNames(getScope())) {
final ValueSource memberUnwinding = returnVarUnwinding.getMemberUnwinding(memberName, getProgram(), getScope(), statementReturn, stmtIt, currentBlock);
unwoundMembers.add(memberUnwinding.getSimpleValue(getScope()));
}
ValueList unwoundReturnValue = new ValueList(unwoundMembers);
statementReturn.setValue(unwoundReturnValue);
boolean unwound = false;
final ValueSource valueSource = ValueSourceFactory.getValueSource(statementReturn.getValue(), getProgram(), getScope(), statementReturn, stmtIt, currentBlock);
RValue unwoundValue = unwindValue(valueSource, statementReturn, stmtIt, currentBlock);
if(unwoundValue != null && !statementReturn.getValue().equals(unwoundValue)) {
statementReturn.setValue(unwoundValue);
getLog().append("Converted procedure struct return value to member unwinding " + statementReturn.toString(getProgram(), false));
modified = true;
unwound = true;
}
return modified;
return unwound;
}
/**

View File

@ -10,7 +10,7 @@ import dk.camelot64.kickc.model.operators.Operator;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
import dk.camelot64.kickc.model.statements.StatementInfos;
import dk.camelot64.kickc.model.StatementInfos;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.RValue;

View File

@ -889,94 +889,16 @@ public class Pass4CodeGeneration {
asm.getCurrentChunk().setFragment("jsr");
asm.addInstruction("jsr", AsmAddressingMode.ABS, call.getProcedure().getFullName(), false);
}
} else if(statement instanceof StatementCallFinalize) {
StatementCallFinalize call = (StatementCallFinalize) statement;
Procedure procedure = getScope().getProcedure(call.getProcedure());
if(Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) {
long stackFrameByteSize = CallingConventionStack.getStackFrameByteSize(procedure);
long returnByteSize = procedure.getReturnType() == null ? 0 : procedure.getReturnType().getSizeBytes();
long stackCleanBytes = (call.getlValue() == null) ? stackFrameByteSize : (stackFrameByteSize - returnByteSize);
if(stackCleanBytes > 0) {
// Clean up the stack
String pullSignature = "_stackpullbyte_" + stackCleanBytes;
AsmFragmentInstanceSpec pullFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, pullSignature, new LinkedHashMap<>(), block.getScope());
generateAsm(asm, pullFragmentInstanceSpec);
}
// Pull result from the stack
if(call.getlValue() != null) {
if(stackCleanBytes > 0)
asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(program, verboseAliveInfo));
boolean isValueListStruct = (call.getlValue() instanceof ValueList) && (procedure.getReturnType() instanceof SymbolTypeStruct);
if(!isValueListStruct) {
// Simple return value - fetch from stack
SymbolType returnType = procedure.getReturnType();
AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory(call.getlValue(), new StackPullValue(returnType), program, block.getScope());
ensureEncoding(asm, asmFragmentInstanceSpecFactory);
generateAsm(asm, asmFragmentInstanceSpecFactory.getAsmFragmentInstanceSpec());
} else {
// Struct value list return value - fetch each member from stack
final List<RValue> lValues = ((ValueList) call.getlValue()).getList();
final StructDefinition structDefinition = ((SymbolTypeStruct) procedure.getReturnType()).getStructDefinition(getScope());
final List<Variable> memberVars = new ArrayList<>(structDefinition.getAllVars(false));
for(int i = 0; i < memberVars.size(); i++) {
LValue lValue = (LValue) lValues.get(i);
Variable memberDef = memberVars.get(i);
final SymbolType memberType = memberDef.getType();
if(i > 0)
asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(program, verboseAliveInfo));
AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory(lValue, new StackPullValue(memberType), program, block.getScope());
ensureEncoding(asm, asmFragmentInstanceSpecFactory);
generateAsm(asm, asmFragmentInstanceSpecFactory.getAsmFragmentInstanceSpec());
asm.getCurrentChunk().setSubStatementIdx(i);
asm.getCurrentChunk().setSubStatementId(memberDef.toString(program));
}
}
}
}
} else if(statement instanceof StatementStackPull) {
String pullSignature = "_stackpullbyte_" + AsmFormat.getAsmConstant(program, ((StatementStackPull) statement).getPullBytes(), 99, block.getScope());
AsmFragmentInstanceSpec pullFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, pullSignature, new LinkedHashMap<>(), block.getScope());
generateAsm(asm, pullFragmentInstanceSpec);
} else if(statement instanceof StatementReturn) {
Procedure procedure = null;
ScopeRef scope = block.getScope();
if(!scope.equals(ScopeRef.ROOT)) {
procedure = getScope().getProcedure(scope.getFullName());
}
if(procedure != null && Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) {
StatementReturn returnStatement = (StatementReturn) statement;
if(returnStatement.getValue() != null) {
// Store return value on stack
asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(program, verboseAliveInfo));
SymbolType returnType = procedure.getReturnType();
boolean isValueListStruct = (returnStatement.getValue() instanceof ValueList) && (returnType instanceof SymbolTypeStruct);
if(!isValueListStruct) {
// A simple return type - put it on the stack
ConstantRef returnOffsetConstant = CallingConventionStack.getReturnOffsetConstant(procedure);
AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory(new StackIdxValue(returnOffsetConstant, returnType), returnStatement.getValue(), program, block.getScope());
ensureEncoding(asm, asmFragmentInstanceSpecFactory);
generateAsm(asm, asmFragmentInstanceSpecFactory.getAsmFragmentInstanceSpec());
} else {
// A struct return value in a value list - Store each value on the stack
final List<RValue> returnValues = ((ValueList) returnStatement.getValue()).getList();
final StructDefinition structDefinition = ((SymbolTypeStruct) returnType).getStructDefinition(getScope());
final List<Variable> memberVars = new ArrayList<>(structDefinition.getAllVars(false));
for(int i = 0; i < memberVars.size(); i++) {
RValue returnValue = returnValues.get(i);
Variable memberDef = memberVars.get(i);
final SymbolType memberType = memberDef.getType();
ConstantRef returnOffsetConstant = CallingConventionStack.getReturnOffsetConstant(procedure);
ConstantRef structMemberOffsetConstant = SizeOfConstants.getStructMemberOffsetConstant(getScope(), structDefinition, memberDef.getLocalName());
ConstantBinary memberReturnOffsetConstant = new ConstantBinary(returnOffsetConstant, Operators.PLUS, structMemberOffsetConstant);
if(i > 0)
asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(program, verboseAliveInfo));
AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory(new StackIdxValue(memberReturnOffsetConstant, memberType), returnValue, program, block.getScope());
ensureEncoding(asm, asmFragmentInstanceSpecFactory);
generateAsm(asm, asmFragmentInstanceSpecFactory.getAsmFragmentInstanceSpec());
asm.getCurrentChunk().setSubStatementIdx(i);
asm.getCurrentChunk().setSubStatementId(memberDef.toString(program));
}
}
}
}
if(procedure == null || procedure.getInterruptType() == null) {
asm.addInstruction("rts", AsmAddressingMode.NON, null, false);
} else {

View File

@ -1,18 +1,23 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CallingConventionStack;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.symbols.StructDefinition;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
import java.util.HashMap;
import java.util.ListIterator;
import java.util.Map;
import java.util.*;
/** Handle calling convention {@link Procedure.CallingConvention#STACK_CALL} by converting the making control flow graph and symbols calling convention specific. */
public class PassNCallingConventionStack extends Pass2SsaOptimization {
@ -68,8 +73,8 @@ public class PassNCallingConventionStack extends Pass2SsaOptimization {
}
}
// Convert param(xxx) to stackidx(PARAM_X) = xxx
if(offsetConstants.size() > 0) {
// Convert ParamValue to StackIdxValue
ProgramValueIterator.execute(getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> {
if(programValue.get() instanceof ParamValue) {
// Convert ParamValues to calling-convention specific param-value
@ -84,7 +89,122 @@ public class PassNCallingConventionStack extends Pass2SsaOptimization {
}
});
}
// Convert procedure return xxx to stackidx(RETURN) = xxx;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
if(statement instanceof StatementReturn) {
final Scope blockScope = getScope().getScope(block.getScope());
if(blockScope instanceof Procedure) {
Procedure procedure = (Procedure) blockScope;
final SymbolType returnType = procedure.getReturnType();
if(!SymbolType.VOID.equals(returnType) && Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) {
ConstantRef returnOffsetConstant = CallingConventionStack.getReturnOffsetConstant(procedure);
final RValue value = ((StatementReturn) statement).getValue();
stmtIt.previous();
generateStackReturnValues(value, returnType, returnOffsetConstant, statement.getSource(), statement.getComments(), stmtIt);
stmtIt.next();
((StatementReturn) statement).setValue(null);
}
}
}
}
}
// Convert xxx = callfinalize to xxx = stackpull(type);
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
if(statement instanceof StatementCallFinalize) {
final StatementCallFinalize call = (StatementCallFinalize) statement;
Procedure procedure = getScope().getProcedure(call.getProcedure());
final SymbolType returnType = procedure.getReturnType();
if(Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) {
long stackFrameByteSize = CallingConventionStack.getStackFrameByteSize(procedure);
long returnByteSize = procedure.getReturnType() == null ? 0 : procedure.getReturnType().getSizeBytes();
long stackCleanBytes = (call.getlValue() == null) ? stackFrameByteSize : (stackFrameByteSize - returnByteSize);
stmtIt.previous();
final StatementSource source = call.getSource();
final List<Comment> comments = call.getComments();
if(stackCleanBytes > 0) {
// Clean up the stack
stmtIt.add(new StatementStackPull( new ConstantInteger(stackCleanBytes), source, comments));
//String pullSignature = "_stackpullbyte_" + stackCleanBytes;
}
final RValue value = call.getlValue();
if(value!=null)
generateStackPullValues(value, returnType, statement.getSource(), statement.getComments(), stmtIt);
stmtIt.next();
stmtIt.remove();
}
}
}
}
return false;
}
/**
* Put a return value onto the stack by generating stackidx(RETURN) = xxx assignments
*
* @param value The value to return
* @param returnType The type of the value
* @param stackReturnOffset The offset onto the stack to place the value at
* @param source The source line
* @param comments The comments
* @param stmtIt The statment iterator used to add statements to.
*/
private void generateStackReturnValues(RValue value, SymbolType returnType, ConstantValue stackReturnOffset, StatementSource source, List<Comment> comments, ListIterator<Statement> stmtIt) {
if(!(value instanceof ValueList) || !(returnType instanceof SymbolTypeStruct)) {
// A simple value to put on the stack
final StatementAssignment stackReturn = new StatementAssignment(new StackIdxValue(stackReturnOffset, returnType), value, false, source, comments);
stmtIt.add(stackReturn);
getLog().append("Calling convention " + Procedure.CallingConvention.STACK_CALL + " adding stack return " + stackReturn);
} else {
// A struct to put on the stack
final List<RValue> memberValues = ((ValueList) value).getList();
final StructDefinition structDefinition = ((SymbolTypeStruct) returnType).getStructDefinition(getScope());
final List<Variable> memberVars = new ArrayList<>(structDefinition.getAllVars(false));
for(int i = 0; i < memberVars.size(); i++) {
final Variable memberVar = memberVars.get(i);
final RValue memberValue = memberValues.get(i);
ConstantRef structMemberOffsetConstant = SizeOfConstants.getStructMemberOffsetConstant(getScope(), structDefinition, memberVar.getLocalName());
ConstantBinary memberReturnOffsetConstant = new ConstantBinary(stackReturnOffset, Operators.PLUS, structMemberOffsetConstant);
generateStackReturnValues(memberValue, memberVar.getType(), memberReturnOffsetConstant, source, comments, stmtIt);
}
}
}
/**
* Generate stack pull xxx = stackpull(type) assignments
*
* @param value The value to return
* @param symbolType The type of the value
* @param source The source line
* @param comments The comments
* @param stmtIt The statment iterator used to add statements to.
*/
private void generateStackPullValues(RValue value, SymbolType symbolType, StatementSource source, List<Comment> comments, ListIterator<Statement> stmtIt) {
if(!(value instanceof ValueList) || !(symbolType instanceof SymbolTypeStruct)) {
// A simple value to put on the stack
final StatementAssignment stackPull = new StatementAssignment((LValue) value, new StackPullValue(symbolType), false, source, comments);
stmtIt.add(stackPull);
getLog().append("Calling convention " + Procedure.CallingConvention.STACK_CALL + " adding stack pull " + stackPull);
} else {
// A struct to put on the stack
final List<RValue> memberValues = ((ValueList) value).getList();
final StructDefinition structDefinition = ((SymbolTypeStruct) symbolType).getStructDefinition(getScope());
final List<Variable> memberVars = new ArrayList<>(structDefinition.getAllVars(false));
for(int i = 0; i < memberVars.size(); i++) {
final Variable memberVar = memberVars.get(i);
final RValue memberValue = memberValues.get(i);
generateStackPullValues(memberValue, memberVar.getType(), source, comments, stmtIt);
}
}
}
}

View File

@ -4,7 +4,7 @@ package dk.camelot64.kickc.passes.calcs;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementInfos;
import dk.camelot64.kickc.model.StatementInfos;
import java.util.LinkedHashMap;

View File

@ -61,8 +61,8 @@ public class ValueSourceFactory {
return structValueSource.getMemberUnwinding(((StructMemberRef) value).getMemberName(), program, programScope, currentStmt, stmtIt, currentBlock);
}
if(valueType instanceof SymbolTypeStruct && value instanceof ParamValue) {
final StructDefinition structDefinition = ((SymbolTypeStruct) valueType).getStructDefinition(programScope);
return new ValueSourceParamList((ParamValue) value, structDefinition);
final ValueSource subValueSource = getValueSource(((ParamValue) value).getParameter(), program, programScope, currentStmt, stmtIt, currentBlock);
return new ValueSourceParamValue(subValueSource);
}
return null;
}

View File

@ -1,65 +0,0 @@
package dk.camelot64.kickc.passes.unwinding;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.symbols.ArraySpec;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.StructDefinition;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.values.ParamValue;
import dk.camelot64.kickc.model.values.RValue;
import java.util.ListIterator;
/** A parameter value list. */
public class ValueSourceParamList extends ValueSourceBase {
private final StructDefinition structDefinition;
private final ParamValue paramValue;
public ValueSourceParamList(ParamValue paramValue, StructDefinition structDefinition) {
this.paramValue = paramValue;
this.structDefinition = structDefinition;
}
@Override
public SymbolType getSymbolType() {
return structDefinition.getType();
}
@Override
public ArraySpec getArraySpec() {
return null;
}
@Override
protected boolean isStructClassic() {
return false;
}
@Override
public RValue getSimpleValue(ProgramScope programScope) {
throw new InternalError("Not a simple value");
}
@Override
public LValue getBulkLValue(ProgramScope scope) {
throw new InternalError("Not a bulk value");
}
@Override
public RValue getBulkRValue(ProgramScope scope) {
throw new InternalError("Not a bulk value");
}
@Override
public ValueSource getMemberUnwinding(String memberName, Program program, ProgramScope programScope, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
final ValueSource paramValueSource = ValueSourceFactory.getValueSource(paramValue.getParameter(), program, programScope, currentStmt, stmtIt, currentBlock);
final ValueSource memberUnwinding = paramValueSource.getMemberUnwinding(memberName, program, programScope, currentStmt, stmtIt, currentBlock);
return new ValueSourceParamValue(memberUnwinding);
}
}

View File

@ -14,7 +14,7 @@ import dk.camelot64.kickc.model.values.VariableRef;
import java.util.ListIterator;
/** An unwound parameter value. */
/** A parameter value list. */
public class ValueSourceParamValue extends ValueSourceBase {
private final ValueSource valueSource;
@ -30,7 +30,7 @@ public class ValueSourceParamValue extends ValueSourceBase {
@Override
public ArraySpec getArraySpec() {
return valueSource.getArraySpec();
return null;
}
@Override
@ -55,7 +55,8 @@ public class ValueSourceParamValue extends ValueSourceBase {
@Override
public ValueSource getMemberUnwinding(String memberName, Program program, ProgramScope programScope, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
throw new InternalError("Not unwindable");
final ValueSource memberUnwinding = valueSource.getMemberUnwinding(memberName, program, programScope, currentStmt, stmtIt, currentBlock);
return new ValueSourceParamValue(memberUnwinding);
}
}

View File

@ -279,6 +279,11 @@ public class TestPrograms {
compileAndCompare("declared-memory-var-0");
}
@Test
public void testProcedureCallingConventionStack11() throws IOException, URISyntaxException {
compileAndCompare("procedure-callingconvention-stack-11");
}
@Test
public void testProcedureCallingConventionStack10() throws IOException, URISyntaxException {
compileAndCompare("procedure-callingconvention-stack-10");

View File

@ -0,0 +1,44 @@
// Test a procedure with calling convention stack
// Returning and passing struct of struct values
#pragma calling(__stackcall)
#pragma var_model(ma_zp)
const char* SCREEN = 0x0400;
char idx = 0;
struct Point {
char x;
char y;
};
struct Vector {
struct Point p1;
struct Point p2;
};
void main(void) {
for(char i=0;i<5;i++) {
struct Vector v = get(i);
print(v);
}
}
struct Vector get(char i) {
struct Vector v = { {i, i/2}, {i+1, i*2} };
return v;
}
void print(struct Vector v) {
SCREEN[idx++] = v.p1.x;
SCREEN[idx++] = v.p1.y;
SCREEN[idx++] = v.p2.x;
SCREEN[idx++] = v.p2.y;
SCREEN[idx++] = ' ';
}

View File

@ -12,19 +12,21 @@
main: scope:[main] from @1
[4] callprepare plus (byte) '0' (byte) 7
[5] callexecute plus
[6] (byte~) main::$0 ← callfinalize plus
[7] *((const byte*) SCREEN) ← (byte~) main::$0
stackpull((number) 1)
[7] (byte~) main::$0 ← stackpull(byte)
[8] *((const byte*) SCREEN) ← (byte~) main::$0
to:main::@return
main::@return: scope:[main] from main
[8] return
[9] return
to:@return
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
plus: scope:[plus] from
[9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A)
[10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B)
[11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
[10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A)
[11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B)
[12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
to:plus::@return
plus::@return: scope:[plus] from plus
[12] return (byte) plus::return#0
[13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0
[14] return
to:@return

View File

@ -3,6 +3,8 @@ Culled Empty Block (label) plus::@1
Calling convention STACK_CALL adding prepare/execute/finalize for (byte~) main::$0 ← call plus (byte) '0' (number) 7
Calling convention STACK_CALL replacing param((byte) plus::a) with stackidx(byte,(const byte) plus::OFFSET_STACK_A)
Calling convention STACK_CALL replacing param((byte) plus::b) with stackidx(byte,(const byte) plus::OFFSET_STACK_B)
Calling convention STACK_CALL adding stack return stackidx(byte,plus::OFFSET_STACK_RETURN) ← plus::return
Calling convention STACK_CALL adding stack pull main::$0 ← stackpull(byte)
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
@ -12,7 +14,8 @@ CONTROL FLOW GRAPH SSA
main: scope:[main] from @2
callprepare plus (byte) '0' (number) 7
callexecute plus
(byte~) main::$0 ← callfinalize plus
stackpull((number) 1)
(byte~) main::$0 ← stackpull(byte)
*((const byte*) SCREEN + (number) 0) ← (byte~) main::$0
to:main::@return
main::@return: scope:[main] from main
@ -28,7 +31,8 @@ plus: scope:[plus] from
to:plus::@return
plus::@return: scope:[plus] from plus
(byte) plus::return#1 ← phi( plus/(byte) plus::return#0 )
return (byte) plus::return#1
stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#1
return
to:@return
@2: scope:[] from @begin
call main
@ -73,10 +77,8 @@ Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte) plus::return#0 = (byte~) plus::$0 (byte) plus::return#1
Successful SSA optimization Pass2AliasElimination
Simplifying expression containing zero SCREEN in [3] *((const byte*) SCREEN + (byte) 0) ← (byte~) main::$0
Simplifying expression containing zero SCREEN in [4] *((const byte*) SCREEN + (byte) 0) ← (byte~) main::$0
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) plus::OFFSET_STACK_RETURN
Successful SSA optimization PassNEliminateUnusedVars
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @3
@ -108,34 +110,36 @@ FINAL CONTROL FLOW GRAPH
main: scope:[main] from @1
[4] callprepare plus (byte) '0' (byte) 7
[5] callexecute plus
[6] (byte~) main::$0 ← callfinalize plus
[7] *((const byte*) SCREEN) ← (byte~) main::$0
stackpull((number) 1)
[7] (byte~) main::$0 ← stackpull(byte)
[8] *((const byte*) SCREEN) ← (byte~) main::$0
to:main::@return
main::@return: scope:[main] from main
[8] return
[9] return
to:@return
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
plus: scope:[plus] from
[9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A)
[10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B)
[11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
[10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A)
[11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B)
[12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
to:plus::@return
plus::@return: scope:[plus] from plus
[12] return (byte) plus::return#0
[13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0
[14] return
to:@return
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte~) main::$0 2.0
(byte~) main::$0 4.0
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(byte) plus::a
(byte) plus::a#0 2.0
(byte) plus::b
(byte) plus::b#0 4.0
(byte) plus::return
(byte) plus::return#0 2.0
(byte) plus::return#0 4.0
Initial phi equivalence classes
Added variable main::$0 to live range equivalence class [ main::$0 ]
@ -188,18 +192,18 @@ main: {
pha
// [5] callexecute plus -- jsr
jsr plus
// [6] (byte~) main::$0 ← callfinalize plus -- _stackpullbyte_1
// stackpull((number) 1) -- _stackpullbyte_1
pla
// [6] (byte~) main::$0 ← callfinalize plus -- vbuz1=_stackpullbyte_
// [7] (byte~) main::$0 ← stackpull(byte) -- vbuz1=_stackpullbyte_
pla
sta.z __0
// [7] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuz1
// [8] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuz1
lda.z __0
sta SCREEN
jmp __breturn
// main::@return
__breturn:
// [8] return
// [9] return
rts
}
// plus
@ -207,18 +211,19 @@ main: {
plus: {
.const OFFSET_STACK_A = 1
.const OFFSET_STACK_B = 0
.const OFFSET_STACK_RETURN = 1
.label a = 3
.label b = 4
.label return = 5
// [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
// [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
// [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackidxbyte_vbuc1
// [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
sta.z b
// [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3
// [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3
lda.z a
clc
adc.z b
@ -226,41 +231,43 @@ plus: {
jmp __breturn
// plus::@return
__breturn:
// [12] return (byte) plus::return#0
// [12] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1
// [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1
lda.z return
tsx
sta STACK_BASE+OFFSET_STACK_RETURN,x
// [14] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] (byte~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement stackpull((number) 1) always clobbers reg byte a
Statement [7] (byte~) main::$0 ← stackpull(byte) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Removing always clobbered register reg byte a as potential for zp[1]:3 [ plus::a#0 ]
Removing always clobbered register reg byte x as potential for zp[1]:3 [ plus::a#0 ]
Statement [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a
Statement [12] return (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x
Statement [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a
Statement [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x
Statement [4] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] (byte~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a
Statement [12] return (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x
Statement stackpull((number) 1) always clobbers reg byte a
Statement [7] (byte~) main::$0 ← stackpull(byte) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a
Statement [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x
Potential registers zp[1]:2 [ main::$0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:3 [ plus::a#0 ] : zp[1]:3 , reg byte y ,
Potential registers zp[1]:4 [ plus::b#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:5 [ plus::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [plus] 4: zp[1]:4 [ plus::b#0 ] 2: zp[1]:3 [ plus::a#0 ] 2: zp[1]:5 [ plus::return#0 ]
Uplift Scope [main] 2: zp[1]:2 [ main::$0 ]
Uplift Scope [plus] 4: zp[1]:4 [ plus::b#0 ] 4: zp[1]:5 [ plus::return#0 ] 2: zp[1]:3 [ plus::a#0 ]
Uplift Scope [main] 4: zp[1]:2 [ main::$0 ]
Uplift Scope []
Uplifting [plus] best 91 combination reg byte a [ plus::b#0 ] zp[1]:3 [ plus::a#0 ] reg byte a [ plus::return#0 ]
Uplifting [plus] best 91 combination reg byte a [ plus::b#0 ] reg byte a [ plus::return#0 ] zp[1]:3 [ plus::a#0 ]
Uplifting [main] best 85 combination reg byte a [ main::$0 ]
Uplifting [] best 85 combination
Attempting to uplift remaining variables inzp[1]:3 [ plus::a#0 ]
@ -301,16 +308,16 @@ main: {
pha
// [5] callexecute plus -- jsr
jsr plus
// [6] (byte~) main::$0 ← callfinalize plus -- _stackpullbyte_1
// stackpull((number) 1) -- _stackpullbyte_1
pla
// [6] (byte~) main::$0 ← callfinalize plus -- vbuaa=_stackpullbyte_
// [7] (byte~) main::$0 ← stackpull(byte) -- vbuaa=_stackpullbyte_
pla
// [7] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa
// [8] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa
sta SCREEN
jmp __breturn
// main::@return
__breturn:
// [8] return
// [9] return
rts
}
// plus
@ -320,23 +327,23 @@ plus: {
.const OFFSET_STACK_B = 0
.const OFFSET_STACK_RETURN = 1
.label a = 2
// [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
// [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
// [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1
// [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
// [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
// [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
clc
adc.z a
jmp __breturn
// plus::@return
__breturn:
// [12] return (byte) plus::return#0
// [12] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa
// [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa
tsx
sta STACK_BASE+OFFSET_STACK_RETURN,x
// [14] return
rts
}
// File Data
@ -368,7 +375,7 @@ FINAL SYMBOL TABLE
(const byte*) SCREEN = (byte*) 1024
(const word) STACK_BASE = (word) $103
(void()) main()
(byte~) main::$0 reg byte a 2.0
(byte~) main::$0 reg byte a 4.0
(label) main::@return
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(label) plus::@return
@ -380,7 +387,7 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(byte) plus::b
(byte) plus::b#0 reg byte a 4.0
(byte) plus::return
(byte) plus::return#0 reg byte a 2.0
(byte) plus::return#0 reg byte a 4.0
reg byte a [ main::$0 ]
zp[1]:2 [ plus::a#0 ]
@ -417,16 +424,16 @@ main: {
pha
// [5] callexecute plus -- jsr
jsr plus
// [6] (byte~) main::$0 ← callfinalize plus -- _stackpullbyte_1
// stackpull((number) 1) -- _stackpullbyte_1
pla
// [6] (byte~) main::$0 ← callfinalize plus -- vbuaa=_stackpullbyte_
// [7] (byte~) main::$0 ← stackpull(byte) -- vbuaa=_stackpullbyte_
pla
// SCREEN[0] = plus('0', 7)
// [7] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa
// [8] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa
sta SCREEN
// main::@return
// }
// [8] return
// [9] return
rts
}
// plus
@ -436,23 +443,23 @@ plus: {
.const OFFSET_STACK_B = 0
.const OFFSET_STACK_RETURN = 1
.label a = 2
// [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
// [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
// [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1
// [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
// return a+b;
// [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
// [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
clc
adc.z a
// plus::@return
// }
// [12] return (byte) plus::return#0
// [12] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa
// [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa
tsx
sta STACK_BASE+OFFSET_STACK_RETURN,x
// [14] return
rts
}
// File Data

View File

@ -4,7 +4,7 @@
(const byte*) SCREEN = (byte*) 1024
(const word) STACK_BASE = (word) $103
(void()) main()
(byte~) main::$0 reg byte a 2.0
(byte~) main::$0 reg byte a 4.0
(label) main::@return
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(label) plus::@return
@ -16,7 +16,7 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(byte) plus::b
(byte) plus::b#0 reg byte a 4.0
(byte) plus::return
(byte) plus::return#0 reg byte a 2.0
(byte) plus::return#0 reg byte a 4.0
reg byte a [ main::$0 ]
zp[1]:2 [ plus::a#0 ]

View File

@ -12,19 +12,21 @@
main: scope:[main] from @1
[4] callprepare plus (byte) '0' (byte) 7
[5] callexecute plus
[6] (byte~) main::$0 ← callfinalize plus
[7] *((const byte*) SCREEN) ← (byte~) main::$0
stackpull((number) 1)
[7] (byte~) main::$0 ← stackpull(byte)
[8] *((const byte*) SCREEN) ← (byte~) main::$0
to:main::@return
main::@return: scope:[main] from main
[8] return
[9] return
to:@return
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
plus: scope:[plus] from
[9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A)
[10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B)
[11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
[10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A)
[11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B)
[12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
to:plus::@return
plus::@return: scope:[plus] from plus
[12] return (byte) plus::return#0
[13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0
[14] return
to:@return

View File

@ -3,6 +3,8 @@ Culled Empty Block (label) plus::@1
Calling convention STACK_CALL adding prepare/execute/finalize for (byte~) main::$0 ← call plus (byte) '0' (number) 7
Calling convention STACK_CALL replacing param((byte) plus::a) with stackidx(byte,(const byte) plus::OFFSET_STACK_A)
Calling convention STACK_CALL replacing param((byte) plus::b) with stackidx(byte,(const byte) plus::OFFSET_STACK_B)
Calling convention STACK_CALL adding stack return stackidx(byte,plus::OFFSET_STACK_RETURN) ← plus::return
Calling convention STACK_CALL adding stack pull main::$0 ← stackpull(byte)
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
@ -12,7 +14,8 @@ CONTROL FLOW GRAPH SSA
main: scope:[main] from @2
callprepare plus (byte) '0' (number) 7
callexecute plus
(byte~) main::$0 ← callfinalize plus
stackpull((number) 1)
(byte~) main::$0 ← stackpull(byte)
*((const byte*) SCREEN + (number) 0) ← (byte~) main::$0
to:main::@return
main::@return: scope:[main] from main
@ -28,7 +31,8 @@ plus: scope:[plus] from
to:plus::@return
plus::@return: scope:[plus] from plus
(byte) plus::return#1 ← phi( plus/(byte) plus::return#0 )
return (byte) plus::return#1
stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#1
return
to:@return
@2: scope:[] from @begin
call main
@ -73,10 +77,8 @@ Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte) plus::return#0 = (byte~) plus::$0 (byte) plus::return#1
Successful SSA optimization Pass2AliasElimination
Simplifying expression containing zero SCREEN in [3] *((const byte*) SCREEN + (byte) 0) ← (byte~) main::$0
Simplifying expression containing zero SCREEN in [4] *((const byte*) SCREEN + (byte) 0) ← (byte~) main::$0
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) plus::OFFSET_STACK_RETURN
Successful SSA optimization PassNEliminateUnusedVars
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @3
@ -108,34 +110,36 @@ FINAL CONTROL FLOW GRAPH
main: scope:[main] from @1
[4] callprepare plus (byte) '0' (byte) 7
[5] callexecute plus
[6] (byte~) main::$0 ← callfinalize plus
[7] *((const byte*) SCREEN) ← (byte~) main::$0
stackpull((number) 1)
[7] (byte~) main::$0 ← stackpull(byte)
[8] *((const byte*) SCREEN) ← (byte~) main::$0
to:main::@return
main::@return: scope:[main] from main
[8] return
[9] return
to:@return
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
plus: scope:[plus] from
[9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A)
[10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B)
[11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
[10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A)
[11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B)
[12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
to:plus::@return
plus::@return: scope:[plus] from plus
[12] return (byte) plus::return#0
[13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0
[14] return
to:@return
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte~) main::$0 2.0
(byte~) main::$0 4.0
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(byte) plus::a
(byte) plus::a#0 2.0
(byte) plus::b
(byte) plus::b#0 4.0
(byte) plus::return
(byte) plus::return#0 2.0
(byte) plus::return#0 4.0
Initial phi equivalence classes
Added variable main::$0 to live range equivalence class [ main::$0 ]
@ -188,18 +192,18 @@ main: {
pha
// [5] callexecute plus -- jsr
jsr plus
// [6] (byte~) main::$0 ← callfinalize plus -- _stackpullbyte_1
// stackpull((number) 1) -- _stackpullbyte_1
pla
// [6] (byte~) main::$0 ← callfinalize plus -- vbuz1=_stackpullbyte_
// [7] (byte~) main::$0 ← stackpull(byte) -- vbuz1=_stackpullbyte_
pla
sta.z __0
// [7] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuz1
// [8] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuz1
lda.z __0
sta SCREEN
jmp __breturn
// main::@return
__breturn:
// [8] return
// [9] return
rts
}
// plus
@ -207,18 +211,19 @@ main: {
plus: {
.const OFFSET_STACK_A = 1
.const OFFSET_STACK_B = 0
.const OFFSET_STACK_RETURN = 1
.label a = 3
.label b = 4
.label return = 5
// [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
// [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
// [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackidxbyte_vbuc1
// [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
sta.z b
// [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3
// [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3
lda.z a
clc
adc.z b
@ -226,41 +231,43 @@ plus: {
jmp __breturn
// plus::@return
__breturn:
// [12] return (byte) plus::return#0
// [12] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1
// [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1
lda.z return
tsx
sta STACK_BASE+OFFSET_STACK_RETURN,x
// [14] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] (byte~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement stackpull((number) 1) always clobbers reg byte a
Statement [7] (byte~) main::$0 ← stackpull(byte) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Removing always clobbered register reg byte a as potential for zp[1]:3 [ plus::a#0 ]
Removing always clobbered register reg byte x as potential for zp[1]:3 [ plus::a#0 ]
Statement [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a
Statement [12] return (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x
Statement [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a
Statement [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x
Statement [4] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] (byte~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a
Statement [12] return (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x
Statement stackpull((number) 1) always clobbers reg byte a
Statement [7] (byte~) main::$0 ← stackpull(byte) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a
Statement [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x
Potential registers zp[1]:2 [ main::$0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:3 [ plus::a#0 ] : zp[1]:3 , reg byte y ,
Potential registers zp[1]:4 [ plus::b#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:5 [ plus::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [plus] 4: zp[1]:4 [ plus::b#0 ] 2: zp[1]:3 [ plus::a#0 ] 2: zp[1]:5 [ plus::return#0 ]
Uplift Scope [main] 2: zp[1]:2 [ main::$0 ]
Uplift Scope [plus] 4: zp[1]:4 [ plus::b#0 ] 4: zp[1]:5 [ plus::return#0 ] 2: zp[1]:3 [ plus::a#0 ]
Uplift Scope [main] 4: zp[1]:2 [ main::$0 ]
Uplift Scope []
Uplifting [plus] best 91 combination reg byte a [ plus::b#0 ] zp[1]:3 [ plus::a#0 ] reg byte a [ plus::return#0 ]
Uplifting [plus] best 91 combination reg byte a [ plus::b#0 ] reg byte a [ plus::return#0 ] zp[1]:3 [ plus::a#0 ]
Uplifting [main] best 85 combination reg byte a [ main::$0 ]
Uplifting [] best 85 combination
Attempting to uplift remaining variables inzp[1]:3 [ plus::a#0 ]
@ -301,16 +308,16 @@ main: {
pha
// [5] callexecute plus -- jsr
jsr plus
// [6] (byte~) main::$0 ← callfinalize plus -- _stackpullbyte_1
// stackpull((number) 1) -- _stackpullbyte_1
pla
// [6] (byte~) main::$0 ← callfinalize plus -- vbuaa=_stackpullbyte_
// [7] (byte~) main::$0 ← stackpull(byte) -- vbuaa=_stackpullbyte_
pla
// [7] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa
// [8] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa
sta SCREEN
jmp __breturn
// main::@return
__breturn:
// [8] return
// [9] return
rts
}
// plus
@ -320,23 +327,23 @@ plus: {
.const OFFSET_STACK_B = 0
.const OFFSET_STACK_RETURN = 1
.label a = 2
// [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
// [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
// [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1
// [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
// [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
// [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
clc
adc.z a
jmp __breturn
// plus::@return
__breturn:
// [12] return (byte) plus::return#0
// [12] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa
// [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa
tsx
sta STACK_BASE+OFFSET_STACK_RETURN,x
// [14] return
rts
}
// File Data
@ -368,7 +375,7 @@ FINAL SYMBOL TABLE
(const byte*) SCREEN = (byte*) 1024
(const word) STACK_BASE = (word) $103
(void()) main()
(byte~) main::$0 reg byte a 2.0
(byte~) main::$0 reg byte a 4.0
(label) main::@return
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(label) plus::@return
@ -380,7 +387,7 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(byte) plus::b
(byte) plus::b#0 reg byte a 4.0
(byte) plus::return
(byte) plus::return#0 reg byte a 2.0
(byte) plus::return#0 reg byte a 4.0
reg byte a [ main::$0 ]
zp[1]:2 [ plus::a#0 ]
@ -417,16 +424,16 @@ main: {
pha
// [5] callexecute plus -- jsr
jsr plus
// [6] (byte~) main::$0 ← callfinalize plus -- _stackpullbyte_1
// stackpull((number) 1) -- _stackpullbyte_1
pla
// [6] (byte~) main::$0 ← callfinalize plus -- vbuaa=_stackpullbyte_
// [7] (byte~) main::$0 ← stackpull(byte) -- vbuaa=_stackpullbyte_
pla
// SCREEN[0] = plus('0', 7)
// [7] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa
// [8] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa
sta SCREEN
// main::@return
// }
// [8] return
// [9] return
rts
}
// plus
@ -436,23 +443,23 @@ plus: {
.const OFFSET_STACK_B = 0
.const OFFSET_STACK_RETURN = 1
.label a = 2
// [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
// [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
// [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1
// [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
// return a+b;
// [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
// [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
clc
adc.z a
// plus::@return
// }
// [12] return (byte) plus::return#0
// [12] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa
// [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa
tsx
sta STACK_BASE+OFFSET_STACK_RETURN,x
// [14] return
rts
}
// File Data

View File

@ -4,7 +4,7 @@
(const byte*) SCREEN = (byte*) 1024
(const word) STACK_BASE = (word) $103
(void()) main()
(byte~) main::$0 reg byte a 2.0
(byte~) main::$0 reg byte a 4.0
(label) main::@return
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(label) plus::@return
@ -16,7 +16,7 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(byte) plus::b
(byte) plus::b#0 reg byte a 4.0
(byte) plus::return
(byte) plus::return#0 reg byte a 2.0
(byte) plus::return#0 reg byte a 4.0
reg byte a [ main::$0 ]
zp[1]:2 [ plus::a#0 ]

View File

@ -6,7 +6,6 @@
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
.const STACK_BASE = $103
.const OFFSET_STRUCT_POINT_X = 0
.label idx = 2
__bbegin:
// idx = 0
@ -43,8 +42,7 @@ print: {
// get(byte register(X) i)
get: {
.const OFFSET_STACK_I = 0
.const OFFSET_STACK_RETURN = 0
.label p = 8
.label p = 6
tsx
lda STACK_BASE+OFFSET_STACK_I,x
tax
@ -55,21 +53,19 @@ get: {
stx.z p
sta p+OFFSET_STRUCT_POINT_Y
// return p;
txa
ldy p+OFFSET_STRUCT_POINT_Y
tay
// }
txa
tsx
sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_X,x
sta STACK_BASE+0,x
tya
tsx
sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_Y,x
sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x
rts
}
main: {
.label i = 3
.label p = 6
.label __1_x = 4
.label __1_y = 5
.label p = 4
// i=0
lda #0
sta.z i
@ -87,16 +83,13 @@ main: {
pha
jsr get
pla
sta.z __1_x
tax
pla
sta.z __1_y
// p = get(i)
lda.z __1_x
sta.z p
lda.z __1_y
stx.z p
sta p+OFFSET_STRUCT_POINT_Y
// print(p)
lda.z p
txa
pha
lda p+OFFSET_STRUCT_POINT_Y
pha

View File

@ -4,55 +4,57 @@
@1: scope:[] from @begin
[1] callprepare main
[2] callexecute main
[3] callfinalize main
to:@end
@end: scope:[] from @1
[4] phi()
[3] phi()
__stackcall (void()) print((byte) print::p_x , (byte) print::p_y)
print: scope:[print] from
[5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X)
[6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y)
[7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0
[8] (byte) idx ← ++ (byte) idx
[9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0
[10] (byte) idx ← ++ (byte) idx
[4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X)
[5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y)
[6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0
[7] (byte) idx ← ++ (byte) idx
[8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0
[9] (byte) idx ← ++ (byte) idx
to:print::@return
print::@return: scope:[print] from print
[11] return
[10] return
to:@return
__stackcall (struct Point()) get((byte) get::i)
get: scope:[get] from
[12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I)
[13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1
[14] *((byte*)&(struct Point) get::p) ← (byte) get::i#0
[15] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0
[16] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p)
[17] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y)
[11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I)
[12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1
[13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0
[14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0
[15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p)
[16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y)
to:get::@return
get::@return: scope:[get] from get
[18] return { (byte) get::return_x#0, (byte) get::return_y#0 }
[17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0
[18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0
[19] return
to:@return
__stackcall (void()) main()
main: scope:[main] from
[19] (byte) main::i ← (byte) 0
[20] (byte) main::i ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@2
[20] if((byte) main::i<(byte) 5) goto main::@2
[21] if((byte) main::i<(byte) 5) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[21] return
[22] return
to:@return
main::@2: scope:[main] from main::@1
[22] callprepare get (byte) main::i
[23] callexecute get
[24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get
[25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x
[26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y
[27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)
[28] callexecute print
[29] callfinalize print
[30] (byte) main::i ← ++ (byte) main::i
[23] callprepare get (byte) main::i
[24] callexecute get
[25] (byte~) main::$1_x ← stackpull(byte)
[26] (byte~) main::$1_y ← stackpull(byte)
[27] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x
[28] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y
[29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)
[30] callexecute print
stackpull((number) 2)
[32] (byte) main::i ← ++ (byte) main::i
to:main::@1

View File

@ -39,6 +39,10 @@ Calling convention STACK_CALL adding prepare/execute/finalize for call main
Calling convention STACK_CALL replacing param((byte) get::i) with stackidx(byte,(const byte) get::OFFSET_STACK_I)
Calling convention STACK_CALL replacing param((byte) print::p_x) with stackidx(byte,(const byte) print::OFFSET_STACK_P_X)
Calling convention STACK_CALL replacing param((byte) print::p_y) with stackidx(byte,(const byte) print::OFFSET_STACK_P_Y)
Calling convention STACK_CALL adding stack return stackidx(byte,get::OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_X) ← get::return_x
Calling convention STACK_CALL adding stack return stackidx(byte,get::OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_Y) ← get::return_y
Calling convention STACK_CALL adding stack pull main::$1_x ← stackpull(byte)
Calling convention STACK_CALL adding stack pull main::$1_y ← stackpull(byte)
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
@ -56,13 +60,14 @@ main::@1: scope:[main] from main main::@2
main::@2: scope:[main] from main::@1
callprepare get (byte) main::i
callexecute get
{ (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get
(byte~) main::$1_x ← stackpull(byte)
(byte~) main::$1_y ← stackpull(byte)
*((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_x
*((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y
(struct Point) main::p ← struct-unwound {*((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)}
callprepare print *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)
callexecute print
callfinalize print
stackpull((number) 2)
(byte) main::i ← ++ (byte) main::i
to:main::@1
main::@return: scope:[main] from main::@1
@ -83,7 +88,9 @@ get: scope:[get] from
get::@return: scope:[get] from get
(byte) get::return_y#1 ← phi( get/(byte) get::return_y#0 )
(byte) get::return_x#1 ← phi( get/(byte) get::return_x#0 )
return { (byte) get::return_x#1, (byte) get::return_y#1 }
stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::return_x#1
stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#1
return
to:@return
__stackcall (void()) print((byte) print::p_x , (byte) print::p_y)
@ -101,7 +108,6 @@ print::@return: scope:[print] from print
@3: scope:[] from @begin
callprepare main
callexecute main
callfinalize main
to:@end
@end: scope:[] from @3
@ -167,23 +173,26 @@ Alias (byte) get::return_y#0 = (byte) get::return_y#1
Successful SSA optimization Pass2AliasElimination
Simple Condition (bool~) main::$0 [3] if((byte) main::i<(byte) 5) goto main::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Removing C-classic struct-unwound assignment [9] (struct Point) main::p ← struct-unwound {*((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)}
Removing C-classic struct-unwound assignment [19] (struct Point) get::p ← struct-unwound {*((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y)}
Simplifying expression containing zero (byte*)&main::p in [7] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_x
Simplifying expression containing zero (byte*)&main::p in [10] callprepare print *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)
Simplifying expression containing zero (byte*)&get::p in [17] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::i#0
Simplifying expression containing zero (byte*)&get::p in [20] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X)
Removing C-classic struct-unwound assignment [10] (struct Point) main::p ← struct-unwound {*((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)}
Removing C-classic struct-unwound assignment [20] (struct Point) get::p ← struct-unwound {*((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y)}
Simplifying constant evaluating to zero (const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_X in [24] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::return_x#0
Successful SSA optimization PassNSimplifyConstantZero
Simplifying expression containing zero (byte*)&main::p in [8] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_x
Simplifying expression containing zero (byte*)&main::p in [11] callprepare print *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)
Simplifying expression containing zero (byte*)&get::p in [18] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::i#0
Simplifying expression containing zero (byte*)&get::p in [21] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero OFFSET_STRUCT_POINT_Y in [25] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (struct Point) get::return#0 and assignment [19] (struct Point) get::return#0 ← struct-unwound {(byte) get::return_x#0, (byte) get::return_y#0}
Eliminating unused variable (struct Point) get::return#0 and assignment [20] (struct Point) get::return#0 ← struct-unwound {(byte) get::return_x#0, (byte) get::return_y#0}
Eliminating unused constant (const byte) get::OFFSET_STACK_RETURN
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Rewriting division to use shift [14] (byte~) get::$0 ← (byte) get::i#0 / (byte) 2
Rewriting division to use shift [15] (byte~) get::$0 ← (byte) get::i#0 / (byte) 2
Successful SSA optimization Pass2MultiplyToShiftRewriting
Adding NOP phi() at start of @end
CALL GRAPH
Calls in [] to main:2
Calls in [main] to get:23 print:28
Calls in [main] to get:24 print:30
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
@ -197,57 +206,59 @@ FINAL CONTROL FLOW GRAPH
@1: scope:[] from @begin
[1] callprepare main
[2] callexecute main
[3] callfinalize main
to:@end
@end: scope:[] from @1
[4] phi()
[3] phi()
__stackcall (void()) print((byte) print::p_x , (byte) print::p_y)
print: scope:[print] from
[5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X)
[6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y)
[7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0
[8] (byte) idx ← ++ (byte) idx
[9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0
[10] (byte) idx ← ++ (byte) idx
[4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X)
[5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y)
[6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0
[7] (byte) idx ← ++ (byte) idx
[8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0
[9] (byte) idx ← ++ (byte) idx
to:print::@return
print::@return: scope:[print] from print
[11] return
[10] return
to:@return
__stackcall (struct Point()) get((byte) get::i)
get: scope:[get] from
[12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I)
[13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1
[14] *((byte*)&(struct Point) get::p) ← (byte) get::i#0
[15] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0
[16] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p)
[17] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y)
[11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I)
[12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1
[13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0
[14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0
[15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p)
[16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y)
to:get::@return
get::@return: scope:[get] from get
[18] return { (byte) get::return_x#0, (byte) get::return_y#0 }
[17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0
[18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0
[19] return
to:@return
__stackcall (void()) main()
main: scope:[main] from
[19] (byte) main::i ← (byte) 0
[20] (byte) main::i ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@2
[20] if((byte) main::i<(byte) 5) goto main::@2
[21] if((byte) main::i<(byte) 5) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[21] return
[22] return
to:@return
main::@2: scope:[main] from main::@1
[22] callprepare get (byte) main::i
[23] callexecute get
[24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get
[25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x
[26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y
[27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)
[28] callexecute print
[29] callfinalize print
[30] (byte) main::i ← ++ (byte) main::i
[23] callprepare get (byte) main::i
[24] callexecute get
[25] (byte~) main::$1_x ← stackpull(byte)
[26] (byte~) main::$1_y ← stackpull(byte)
[27] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x
[28] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y
[29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)
[30] callexecute print
stackpull((number) 2)
[32] (byte) main::i ← ++ (byte) main::i
to:main::@1
null depth in calling loop Loop head: main::@1 tails: main::@2 blocks: main::@2 main::@1 in scope print
@ -263,14 +274,14 @@ __stackcall (struct Point()) get((byte) get::i)
(struct Point) get::p loadstore
(struct Point) get::return
(byte) get::return_x
(byte) get::return_x#0 1.0
(byte) get::return_x#0 2.0
(byte) get::return_y
(byte) get::return_y#0 2.0
(byte) idx loadstore 0.7
(byte) idx loadstore 0.6666666666666666
__stackcall (void()) main()
(byte~) main::$1_x 0.8461538461538461
(byte~) main::$1_y 0.8461538461538461
(byte) main::i loadstore 3.1818181818181817
(byte~) main::$1_x 11.0
(byte~) main::$1_y 11.0
(byte) main::i loadstore 2.9166666666666665
(struct Point) main::p loadstore
__stackcall (void()) print((byte) print::p_x , (byte) print::p_y)
(byte) print::p_x
@ -342,8 +353,7 @@ __b1:
// [1] callprepare main
// [2] callexecute main -- jsr
jsr main
// [3] callfinalize main
// [4] phi from @1 to @end [phi:@1->@end]
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
@ -355,30 +365,30 @@ print: {
.const OFFSET_STACK_P_Y = 0
.label p_x = 3
.label p_y = 4
// [5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuz1=_stackidxbyte_vbuc1
// [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_P_X,x
sta.z p_x
// [6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) -- vbuz1=_stackidxbyte_vbuc1
// [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_P_Y,x
sta.z p_y
// [7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuz2
// [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuz2
lda.z p_x
ldy.z idx
sta SCREEN,y
// [8] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
// [7] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
inc.z idx
// [9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 -- pbuc1_derefidx_vbuz1=vbuz2
// [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 -- pbuc1_derefidx_vbuz1=vbuz2
lda.z p_y
ldy.z idx
sta SCREEN,y
// [10] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
// [9] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
inc.z idx
jmp __breturn
// print::@return
__breturn:
// [11] return
// [10] return
rts
}
// get
@ -390,38 +400,38 @@ get: {
.label i = 5
.label return_x = 7
.label return_y = 8
// [12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuz1=_stackidxbyte_vbuc1
// [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_I,x
sta.z i
// [13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuz1=vbuz2_ror_1
// [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuz1=vbuz2_ror_1
lda.z i
lsr
sta.z __0
// [14] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuz1
// [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuz1
lda.z i
sta.z p
// [15] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuz1
// [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuz1
lda.z __0
sta p+OFFSET_STRUCT_POINT_Y
// [16] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuz1=_deref_pbuc1
// [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuz1=_deref_pbuc1
lda.z p
sta.z return_x
// [17] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1
// [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1
lda p+OFFSET_STRUCT_POINT_Y
sta.z return_y
jmp __breturn
// get::@return
__breturn:
// [18] return { (byte) get::return_x#0, (byte) get::return_y#0 }
// [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [(byte) Point::x#0] -- _stackidxbyte_vbuc1=vbuz1
// [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 -- _stackidxbyte_vbuc1=vbuz1
lda.z return_x
tsx
sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_X,x
// [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [(byte) Point::y#1] -- _stackidxbyte_vbuc1=vbuz1
sta STACK_BASE+0,x
// [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 -- _stackidxbyte_vbuc1=vbuz1
lda.z return_y
tsx
sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_Y,x
sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x
// [19] return
rts
}
// main
@ -430,142 +440,134 @@ main: {
.label p = $c
.label __1_x = $a
.label __1_y = $b
// [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
// [20] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// main::@1
__b1:
// [20] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
// [21] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #5
bcc __b2
jmp __breturn
// main::@return
__breturn:
// [21] return
// [22] return
rts
// main::@2
__b2:
// [22] callprepare get (byte) main::i [(byte) get::i#0] -- _stackpushbyte_=vbuz1
// [23] callprepare get (byte) main::i [(byte) get::i#0] -- _stackpushbyte_=vbuz1
lda.z i
pha
// [22] callprepare get (byte) main::i -- _stackpushbyte_1
// [23] callprepare get (byte) main::i -- _stackpushbyte_1
pha
// [23] callexecute get -- jsr
// [24] callexecute get -- jsr
jsr get
// [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [(byte) Point::x#0] -- vbuz1=_stackpullbyte_
// [25] (byte~) main::$1_x ← stackpull(byte) -- vbuz1=_stackpullbyte_
pla
sta.z __1_x
// [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [(byte) Point::y#1] -- vbuz1=_stackpullbyte_
// [26] (byte~) main::$1_y ← stackpull(byte) -- vbuz1=_stackpullbyte_
pla
sta.z __1_y
// [25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuz1
// [27] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuz1
lda.z __1_x
sta.z p
// [26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuz1
// [28] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuz1
lda.z __1_y
sta p+OFFSET_STRUCT_POINT_Y
// [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_x#0] -- _stackpushbyte_=_deref_pbuc1
// [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_x#0] -- _stackpushbyte_=_deref_pbuc1
lda.z p
pha
// [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_y#1] -- _stackpushbyte_=_deref_pbuc1
// [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_y#1] -- _stackpushbyte_=_deref_pbuc1
lda p+OFFSET_STRUCT_POINT_Y
pha
// [28] callexecute print -- jsr
// [30] callexecute print -- jsr
jsr print
// [29] callfinalize print -- _stackpullbyte_2
// stackpull((number) 2) -- _stackpullbyte_2
pla
pla
// [30] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
// [32] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (byte) idx ← (byte) 0 [ idx get::p main::$1_x main::$1_y main::p ] ( [ idx get::p main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:10 [ main::$1_x ]
Removing always clobbered register reg byte a as potential for zp[1]:11 [ main::$1_y ]
Statement [5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) [ idx print::p_x#0 ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx print::p_x#0 ] ) always clobbers reg byte a reg byte x
Removing always clobbered register reg byte x as potential for zp[1]:10 [ main::$1_x ]
Removing always clobbered register reg byte x as potential for zp[1]:11 [ main::$1_y ]
Statement [6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) [ idx print::p_x#0 print::p_y#0 ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a reg byte x
Statement [0] (byte) idx ← (byte) 0 [ idx get::p main::p ] ( [ idx get::p main::p ] ) always clobbers reg byte a
Statement [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) [ idx print::p_x#0 ] ( main:2::print:30 [ get::p main::i main::p idx print::p_x#0 ] ) always clobbers reg byte a reg byte x
Statement [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) [ idx print::p_x#0 print::p_y#0 ] ( main:2::print:30 [ get::p main::i main::p idx print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a reg byte x
Removing always clobbered register reg byte a as potential for zp[1]:3 [ print::p_x#0 ]
Removing always clobbered register reg byte x as potential for zp[1]:3 [ print::p_x#0 ]
Statement [7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 [ idx print::p_y#0 ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx print::p_y#0 ] ) always clobbers reg byte a reg byte y
Removing always clobbered register reg byte y as potential for zp[1]:10 [ main::$1_x ]
Removing always clobbered register reg byte y as potential for zp[1]:11 [ main::$1_y ]
Statement [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 [ idx print::p_y#0 ] ( main:2::print:30 [ get::p main::i main::p idx print::p_y#0 ] ) always clobbers reg byte a reg byte y
Removing always clobbered register reg byte a as potential for zp[1]:4 [ print::p_y#0 ]
Removing always clobbered register reg byte y as potential for zp[1]:4 [ print::p_y#0 ]
Statement [9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 [ idx ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx ] ) always clobbers reg byte a reg byte y
Statement [12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::i#0 get::p ] ( main:2::get:23 [ idx main::i main::$1_x main::$1_y main::p get::i#0 get::p ] ) always clobbers reg byte a reg byte x
Statement [13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 [ get::i#0 get::$0 get::p ] ( main:2::get:23 [ idx main::i main::$1_x main::$1_y main::p get::i#0 get::$0 get::p ] ) always clobbers reg byte a
Statement [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 [ idx ] ( main:2::print:30 [ get::p main::i main::p idx ] ) always clobbers reg byte a reg byte y
Statement [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::i#0 get::p ] ( main:2::get:24 [ idx main::i main::p get::i#0 get::p ] ) always clobbers reg byte a reg byte x
Statement [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 [ get::i#0 get::$0 get::p ] ( main:2::get:24 [ idx main::i main::p get::i#0 get::$0 get::p ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:5 [ get::i#0 ]
Statement [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [ get::p ] ( main:2::get:23 [ idx main::i main::$1_x main::$1_y main::p get::p ] ) always clobbers reg byte x
Statement [19] (byte) main::i ← (byte) 0 [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [20] if((byte) main::i<(byte) 5) goto main::@2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [22] callprepare get (byte) main::i [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [29] callfinalize print [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [0] (byte) idx ← (byte) 0 [ idx get::p main::$1_x main::$1_y main::p ] ( [ idx get::p main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) [ idx print::p_x#0 ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx print::p_x#0 ] ) always clobbers reg byte a reg byte x
Statement [6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) [ idx print::p_x#0 print::p_y#0 ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a reg byte x
Statement [7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 [ idx print::p_y#0 ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx print::p_y#0 ] ) always clobbers reg byte a reg byte y
Statement [9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 [ idx ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx ] ) always clobbers reg byte a reg byte y
Statement [12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::i#0 get::p ] ( main:2::get:23 [ idx main::i main::$1_x main::$1_y main::p get::i#0 get::p ] ) always clobbers reg byte a reg byte x
Statement [13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 [ get::i#0 get::$0 get::p ] ( main:2::get:23 [ idx main::i main::$1_x main::$1_y main::p get::i#0 get::$0 get::p ] ) always clobbers reg byte a
Statement [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [ get::p ] ( main:2::get:23 [ idx main::i main::$1_x main::$1_y main::p get::p ] ) always clobbers reg byte x
Statement [19] (byte) main::i ← (byte) 0 [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [20] if((byte) main::i<(byte) 5) goto main::@2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [22] callprepare get (byte) main::i [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [29] callfinalize print [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 [ get::p get::return_y#0 ] ( main:2::get:24 [ idx main::i main::p get::p get::return_y#0 ] ) always clobbers reg byte x
Removing always clobbered register reg byte x as potential for zp[1]:8 [ get::return_y#0 ]
Statement [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 [ get::p ] ( main:2::get:24 [ idx main::i main::p get::p ] ) always clobbers reg byte x
Statement [20] (byte) main::i ← (byte) 0 [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a
Statement [21] if((byte) main::i<(byte) 5) goto main::@2 [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a
Statement [23] callprepare get (byte) main::i [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a
Statement [25] (byte~) main::$1_x ← stackpull(byte) [ idx get::p main::i main::$1_x main::p ] ( main:2 [ idx get::p main::i main::$1_x main::p ] ) always clobbers reg byte a
Statement [26] (byte~) main::$1_y ← stackpull(byte) [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:10 [ main::$1_x ]
Statement [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a
Statement stackpull((number) 2) always clobbers reg byte a
Statement [0] (byte) idx ← (byte) 0 [ idx get::p main::p ] ( [ idx get::p main::p ] ) always clobbers reg byte a
Statement [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) [ idx print::p_x#0 ] ( main:2::print:30 [ get::p main::i main::p idx print::p_x#0 ] ) always clobbers reg byte a reg byte x
Statement [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) [ idx print::p_x#0 print::p_y#0 ] ( main:2::print:30 [ get::p main::i main::p idx print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a reg byte x
Statement [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 [ idx print::p_y#0 ] ( main:2::print:30 [ get::p main::i main::p idx print::p_y#0 ] ) always clobbers reg byte a reg byte y
Statement [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 [ idx ] ( main:2::print:30 [ get::p main::i main::p idx ] ) always clobbers reg byte a reg byte y
Statement [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::i#0 get::p ] ( main:2::get:24 [ idx main::i main::p get::i#0 get::p ] ) always clobbers reg byte a reg byte x
Statement [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 [ get::i#0 get::$0 get::p ] ( main:2::get:24 [ idx main::i main::p get::i#0 get::$0 get::p ] ) always clobbers reg byte a
Statement [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 [ get::p get::return_y#0 ] ( main:2::get:24 [ idx main::i main::p get::p get::return_y#0 ] ) always clobbers reg byte x
Statement [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 [ get::p ] ( main:2::get:24 [ idx main::i main::p get::p ] ) always clobbers reg byte x
Statement [20] (byte) main::i ← (byte) 0 [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a
Statement [21] if((byte) main::i<(byte) 5) goto main::@2 [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a
Statement [23] callprepare get (byte) main::i [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a
Statement [25] (byte~) main::$1_x ← stackpull(byte) [ idx get::p main::i main::$1_x main::p ] ( main:2 [ idx get::p main::i main::$1_x main::p ] ) always clobbers reg byte a
Statement [26] (byte~) main::$1_y ← stackpull(byte) [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a
Statement [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a
Statement stackpull((number) 2) always clobbers reg byte a
Potential registers zp[1]:2 [ idx ] : zp[1]:2 ,
Potential registers zp[1]:3 [ print::p_x#0 ] : zp[1]:3 , reg byte y ,
Potential registers zp[1]:4 [ print::p_y#0 ] : zp[1]:4 , reg byte x ,
Potential registers zp[1]:5 [ get::i#0 ] : zp[1]:5 , reg byte x , reg byte y ,
Potential registers zp[1]:6 [ get::$0 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:7 [ get::return_x#0 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:8 [ get::return_y#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:8 [ get::return_y#0 ] : zp[1]:8 , reg byte a , reg byte y ,
Potential registers zp[1]:9 [ main::i ] : zp[1]:9 ,
Potential registers zp[1]:10 [ main::$1_x ] : zp[1]:10 ,
Potential registers zp[1]:11 [ main::$1_y ] : zp[1]:11 ,
Potential registers zp[1]:10 [ main::$1_x ] : zp[1]:10 , reg byte x , reg byte y ,
Potential registers zp[1]:11 [ main::$1_y ] : zp[1]:11 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[2]:12 [ main::p ] : zp[2]:12 ,
Potential registers zp[2]:14 [ get::p ] : zp[2]:14 ,
REGISTER UPLIFT SCOPES
Uplift Scope [get] 3: zp[1]:5 [ get::i#0 ] 2: zp[1]:6 [ get::$0 ] 2: zp[1]:8 [ get::return_y#0 ] 1: zp[1]:7 [ get::return_x#0 ] 0: zp[2]:14 [ get::p ]
Uplift Scope [main] 3.18: zp[1]:9 [ main::i ] 0.85: zp[1]:10 [ main::$1_x ] 0.85: zp[1]:11 [ main::$1_y ] 0: zp[2]:12 [ main::p ]
Uplift Scope [main] 11: zp[1]:10 [ main::$1_x ] 11: zp[1]:11 [ main::$1_y ] 2.92: zp[1]:9 [ main::i ] 0: zp[2]:12 [ main::p ]
Uplift Scope [get] 3: zp[1]:5 [ get::i#0 ] 2: zp[1]:6 [ get::$0 ] 2: zp[1]:7 [ get::return_x#0 ] 2: zp[1]:8 [ get::return_y#0 ] 0: zp[2]:14 [ get::p ]
Uplift Scope [print] 2: zp[1]:3 [ print::p_x#0 ] 1.33: zp[1]:4 [ print::p_y#0 ]
Uplift Scope [] 0.7: zp[1]:2 [ idx ]
Uplift Scope [] 0.67: zp[1]:2 [ idx ]
Uplift Scope [Point]
Uplifting [get] best 1016 combination reg byte x [ get::i#0 ] reg byte a [ get::$0 ] reg byte y [ get::return_y#0 ] reg byte a [ get::return_x#0 ] zp[2]:14 [ get::p ]
Limited combination testing to 100 combinations of 192 possible.
Uplifting [main] best 1016 combination zp[1]:9 [ main::i ] zp[1]:10 [ main::$1_x ] zp[1]:11 [ main::$1_y ] zp[2]:12 [ main::p ]
Uplifting [print] best 1012 combination reg byte y [ print::p_x#0 ] reg byte x [ print::p_y#0 ]
Uplifting [] best 1012 combination zp[1]:2 [ idx ]
Uplifting [Point] best 1012 combination
Uplifting [main] best 937 combination reg byte x [ main::$1_x ] reg byte a [ main::$1_y ] zp[1]:9 [ main::i ] zp[2]:12 [ main::p ]
Uplifting [get] best 922 combination reg byte x [ get::i#0 ] reg byte a [ get::$0 ] reg byte x [ get::return_x#0 ] zp[1]:8 [ get::return_y#0 ] zp[2]:14 [ get::p ]
Limited combination testing to 100 combinations of 144 possible.
Uplifting [print] best 918 combination reg byte y [ print::p_x#0 ] reg byte x [ print::p_y#0 ]
Uplifting [] best 918 combination zp[1]:2 [ idx ]
Uplifting [Point] best 918 combination
Attempting to uplift remaining variables inzp[1]:9 [ main::i ]
Uplifting [main] best 1012 combination zp[1]:9 [ main::i ]
Attempting to uplift remaining variables inzp[1]:10 [ main::$1_x ]
Uplifting [main] best 1012 combination zp[1]:10 [ main::$1_x ]
Attempting to uplift remaining variables inzp[1]:11 [ main::$1_y ]
Uplifting [main] best 1012 combination zp[1]:11 [ main::$1_y ]
Uplifting [main] best 918 combination zp[1]:9 [ main::i ]
Attempting to uplift remaining variables inzp[1]:8 [ get::return_y#0 ]
Uplifting [get] best 914 combination reg byte y [ get::return_y#0 ]
Attempting to uplift remaining variables inzp[1]:2 [ idx ]
Uplifting [] best 1012 combination zp[1]:2 [ idx ]
Uplifting [] best 914 combination zp[1]:2 [ idx ]
Allocated (was zp[1]:9) zp[1]:3 [ main::i ]
Allocated (was zp[1]:10) zp[1]:4 [ main::$1_x ]
Allocated (was zp[1]:11) zp[1]:5 [ main::$1_y ]
Allocated (was zp[2]:12) zp[2]:6 [ main::p ]
Allocated (was zp[2]:14) zp[2]:8 [ get::p ]
Allocated (was zp[2]:12) zp[2]:4 [ main::p ]
Allocated (was zp[2]:14) zp[2]:6 [ get::p ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -579,7 +581,6 @@ ASSEMBLER BEFORE OPTIMIZATION
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
.const STACK_BASE = $103
.const OFFSET_STRUCT_POINT_X = 0
.label idx = 2
// @begin
__bbegin:
@ -592,8 +593,7 @@ __b1:
// [1] callprepare main
// [2] callexecute main -- jsr
jsr main
// [3] callfinalize main
// [4] phi from @1 to @end [phi:@1->@end]
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
@ -603,120 +603,115 @@ __bend:
print: {
.const OFFSET_STACK_P_X = 1
.const OFFSET_STACK_P_Y = 0
// [5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuyy=_stackidxbyte_vbuc1
// [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuyy=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_P_X,x
tay
// [6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) -- vbuxx=_stackidxbyte_vbuc1
// [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) -- vbuxx=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_P_Y,x
tax
// [7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuyy
// [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuyy
tya
ldy.z idx
sta SCREEN,y
// [8] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
// [7] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
inc.z idx
// [9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 -- pbuc1_derefidx_vbuz1=vbuxx
// [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 -- pbuc1_derefidx_vbuz1=vbuxx
ldy.z idx
txa
sta SCREEN,y
// [10] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
// [9] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
inc.z idx
jmp __breturn
// print::@return
__breturn:
// [11] return
// [10] return
rts
}
// get
// get(byte register(X) i)
get: {
.const OFFSET_STACK_I = 0
.const OFFSET_STACK_RETURN = 0
.label p = 8
// [12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1
.label p = 6
// [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_I,x
tax
// [13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuaa=vbuxx_ror_1
// [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuaa=vbuxx_ror_1
txa
lsr
// [14] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuxx
// [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuxx
stx.z p
// [15] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuaa
// [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuaa
sta p+OFFSET_STRUCT_POINT_Y
// [16] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuaa=_deref_pbuc1
lda.z p
// [17] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=_deref_pbuc1
// [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuxx=_deref_pbuc1
ldx.z p
// [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=_deref_pbuc1
ldy p+OFFSET_STRUCT_POINT_Y
jmp __breturn
// get::@return
__breturn:
// [18] return { (byte) get::return_x#0, (byte) get::return_y#0 }
// [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [(byte) Point::x#0] -- _stackidxbyte_vbuc1=vbuaa
// [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 -- _stackidxbyte_vbuc1=vbuxx
txa
tsx
sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_X,x
// [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [(byte) Point::y#1] -- _stackidxbyte_vbuc1=vbuyy
sta STACK_BASE+0,x
// [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 -- _stackidxbyte_vbuc1=vbuyy
tya
tsx
sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_Y,x
sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x
// [19] return
rts
}
// main
main: {
.label i = 3
.label p = 6
.label __1_x = 4
.label __1_y = 5
// [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
.label p = 4
// [20] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// main::@1
__b1:
// [20] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
// [21] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #5
bcc __b2
jmp __breturn
// main::@return
__breturn:
// [21] return
// [22] return
rts
// main::@2
__b2:
// [22] callprepare get (byte) main::i [(byte) get::i#0] -- _stackpushbyte_=vbuz1
// [23] callprepare get (byte) main::i [(byte) get::i#0] -- _stackpushbyte_=vbuz1
lda.z i
pha
// [22] callprepare get (byte) main::i -- _stackpushbyte_1
// [23] callprepare get (byte) main::i -- _stackpushbyte_1
pha
// [23] callexecute get -- jsr
// [24] callexecute get -- jsr
jsr get
// [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [(byte) Point::x#0] -- vbuz1=_stackpullbyte_
// [25] (byte~) main::$1_x ← stackpull(byte) -- vbuxx=_stackpullbyte_
pla
sta.z __1_x
// [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [(byte) Point::y#1] -- vbuz1=_stackpullbyte_
tax
// [26] (byte~) main::$1_y ← stackpull(byte) -- vbuaa=_stackpullbyte_
pla
sta.z __1_y
// [25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuz1
lda.z __1_x
sta.z p
// [26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuz1
lda.z __1_y
// [27] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuxx
stx.z p
// [28] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuaa
sta p+OFFSET_STRUCT_POINT_Y
// [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_x#0] -- _stackpushbyte_=_deref_pbuc1
// [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_x#0] -- _stackpushbyte_=_deref_pbuc1
lda.z p
pha
// [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_y#1] -- _stackpushbyte_=_deref_pbuc1
// [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_y#1] -- _stackpushbyte_=_deref_pbuc1
lda p+OFFSET_STRUCT_POINT_Y
pha
// [28] callexecute print -- jsr
// [30] callexecute print -- jsr
jsr print
// [29] callfinalize print -- _stackpullbyte_2
// stackpull((number) 2) -- _stackpullbyte_2
pla
pla
// [30] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
// [32] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
@ -730,7 +725,10 @@ Removing instruction jmp __breturn
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction ldx.z p
Replacing instruction ldy p+OFFSET_STRUCT_POINT_Y with TAY
Replacing instruction lda.z p with TXA
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
@ -746,7 +744,6 @@ FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x loadstore
(byte) Point::y loadstore
@ -756,24 +753,23 @@ __stackcall (struct Point()) get((byte) get::i)
(byte~) get::$0 reg byte a 2.0
(label) get::@return
(const byte) get::OFFSET_STACK_I = (byte) 0
(const byte) get::OFFSET_STACK_RETURN = (byte) 0
(byte) get::i
(byte) get::i#0 reg byte x 3.0
(struct Point) get::p loadstore zp[2]:8
(struct Point) get::p loadstore zp[2]:6
(struct Point) get::return
(byte) get::return_x
(byte) get::return_x#0 reg byte a 1.0
(byte) get::return_x#0 reg byte x 2.0
(byte) get::return_y
(byte) get::return_y#0 reg byte y 2.0
(byte) idx loadstore zp[1]:2 0.7
(byte) idx loadstore zp[1]:2 0.6666666666666666
__stackcall (void()) main()
(byte~) main::$1_x zp[1]:4 0.8461538461538461
(byte~) main::$1_y zp[1]:5 0.8461538461538461
(byte~) main::$1_x reg byte x 11.0
(byte~) main::$1_y reg byte a 11.0
(label) main::@1
(label) main::@2
(label) main::@return
(byte) main::i loadstore zp[1]:3 3.1818181818181817
(struct Point) main::p loadstore zp[2]:6
(byte) main::i loadstore zp[1]:3 2.9166666666666665
(struct Point) main::p loadstore zp[2]:4
__stackcall (void()) print((byte) print::p_x , (byte) print::p_y)
(label) print::@return
(const byte) print::OFFSET_STACK_P_X = (byte) 1
@ -788,17 +784,17 @@ reg byte y [ print::p_x#0 ]
reg byte x [ print::p_y#0 ]
reg byte x [ get::i#0 ]
reg byte a [ get::$0 ]
reg byte a [ get::return_x#0 ]
reg byte x [ get::return_x#0 ]
reg byte y [ get::return_y#0 ]
zp[1]:3 [ main::i ]
zp[1]:4 [ main::$1_x ]
zp[1]:5 [ main::$1_y ]
zp[2]:6 [ main::p ]
zp[2]:8 [ get::p ]
reg byte x [ main::$1_x ]
reg byte a [ main::$1_y ]
zp[2]:4 [ main::p ]
zp[2]:6 [ get::p ]
FINAL ASSEMBLER
Score: 972
Score: 860
// File Comments
// Test a procedure with calling convention stack
@ -811,7 +807,6 @@ Score: 972
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
.const STACK_BASE = $103
.const OFFSET_STRUCT_POINT_X = 0
.label idx = 2
// @begin
__bbegin:
@ -824,8 +819,7 @@ __bbegin:
// [2] callexecute main -- jsr
jsr main
rts
// [3] callfinalize main
// [4] phi from @1 to @end [phi:@1->@end]
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// print
// print(byte register(Y) p_x, byte register(X) p_y)
@ -833,129 +827,123 @@ print: {
.const OFFSET_STACK_P_X = 1
.const OFFSET_STACK_P_Y = 0
// }
// [5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuyy=_stackidxbyte_vbuc1
// [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuyy=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_P_X,x
tay
// [6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) -- vbuxx=_stackidxbyte_vbuc1
// [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) -- vbuxx=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_P_Y,x
tax
// SCREEN[idx++] = p.x
// [7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuyy
// [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuyy
tya
ldy.z idx
sta SCREEN,y
// SCREEN[idx++] = p.x;
// [8] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
// [7] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
inc.z idx
// SCREEN[idx++] = p.y
// [9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 -- pbuc1_derefidx_vbuz1=vbuxx
// [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 -- pbuc1_derefidx_vbuz1=vbuxx
ldy.z idx
txa
sta SCREEN,y
// SCREEN[idx++] = p.y;
// [10] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
// [9] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
inc.z idx
// print::@return
// }
// [11] return
// [10] return
rts
}
// get
// get(byte register(X) i)
get: {
.const OFFSET_STACK_I = 0
.const OFFSET_STACK_RETURN = 0
.label p = 8
// [12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1
.label p = 6
// [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_I,x
tax
// i/2
// [13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuaa=vbuxx_ror_1
// [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuaa=vbuxx_ror_1
txa
lsr
// p = { i, i/2 }
// [14] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuxx
// [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuxx
stx.z p
// [15] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuaa
// [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuaa
sta p+OFFSET_STRUCT_POINT_Y
// return p;
// [16] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuaa=_deref_pbuc1
txa
// [17] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=_deref_pbuc1
ldy p+OFFSET_STRUCT_POINT_Y
// [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuxx=_deref_pbuc1
// [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=_deref_pbuc1
tay
// get::@return
// }
// [18] return { (byte) get::return_x#0, (byte) get::return_y#0 }
// [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [(byte) Point::x#0] -- _stackidxbyte_vbuc1=vbuaa
// [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 -- _stackidxbyte_vbuc1=vbuxx
txa
tsx
sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_X,x
// [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [(byte) Point::y#1] -- _stackidxbyte_vbuc1=vbuyy
sta STACK_BASE+0,x
// [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 -- _stackidxbyte_vbuc1=vbuyy
tya
tsx
sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_Y,x
sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x
// [19] return
rts
}
// main
main: {
.label i = 3
.label p = 6
.label __1_x = 4
.label __1_y = 5
.label p = 4
// i=0
// [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
// [20] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
// main::@1
__b1:
// for(char i=0;i<5;i++)
// [20] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
// [21] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #5
bcc __b2
// main::@return
// }
// [21] return
// [22] return
rts
// main::@2
__b2:
// get(i)
// [22] callprepare get (byte) main::i [(byte) get::i#0] -- _stackpushbyte_=vbuz1
// [23] callprepare get (byte) main::i [(byte) get::i#0] -- _stackpushbyte_=vbuz1
lda.z i
pha
// [22] callprepare get (byte) main::i -- _stackpushbyte_1
// [23] callprepare get (byte) main::i -- _stackpushbyte_1
pha
// [23] callexecute get -- jsr
// [24] callexecute get -- jsr
jsr get
// [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [(byte) Point::x#0] -- vbuz1=_stackpullbyte_
// [25] (byte~) main::$1_x ← stackpull(byte) -- vbuxx=_stackpullbyte_
pla
sta.z __1_x
// [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [(byte) Point::y#1] -- vbuz1=_stackpullbyte_
tax
// [26] (byte~) main::$1_y ← stackpull(byte) -- vbuaa=_stackpullbyte_
pla
sta.z __1_y
// p = get(i)
// [25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuz1
lda.z __1_x
sta.z p
// [26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuz1
lda.z __1_y
// [27] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuxx
stx.z p
// [28] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuaa
sta p+OFFSET_STRUCT_POINT_Y
// print(p)
// [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_x#0] -- _stackpushbyte_=_deref_pbuc1
lda.z p
// [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_x#0] -- _stackpushbyte_=_deref_pbuc1
txa
pha
// [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_y#1] -- _stackpushbyte_=_deref_pbuc1
// [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_y#1] -- _stackpushbyte_=_deref_pbuc1
lda p+OFFSET_STRUCT_POINT_Y
pha
// [28] callexecute print -- jsr
// [30] callexecute print -- jsr
jsr print
// [29] callfinalize print -- _stackpullbyte_2
// stackpull((number) 2) -- _stackpullbyte_2
pla
pla
// for(char i=0;i<5;i++)
// [30] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
// [32] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}

View File

@ -1,7 +1,6 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x loadstore
(byte) Point::y loadstore
@ -11,24 +10,23 @@ __stackcall (struct Point()) get((byte) get::i)
(byte~) get::$0 reg byte a 2.0
(label) get::@return
(const byte) get::OFFSET_STACK_I = (byte) 0
(const byte) get::OFFSET_STACK_RETURN = (byte) 0
(byte) get::i
(byte) get::i#0 reg byte x 3.0
(struct Point) get::p loadstore zp[2]:8
(struct Point) get::p loadstore zp[2]:6
(struct Point) get::return
(byte) get::return_x
(byte) get::return_x#0 reg byte a 1.0
(byte) get::return_x#0 reg byte x 2.0
(byte) get::return_y
(byte) get::return_y#0 reg byte y 2.0
(byte) idx loadstore zp[1]:2 0.7
(byte) idx loadstore zp[1]:2 0.6666666666666666
__stackcall (void()) main()
(byte~) main::$1_x zp[1]:4 0.8461538461538461
(byte~) main::$1_y zp[1]:5 0.8461538461538461
(byte~) main::$1_x reg byte x 11.0
(byte~) main::$1_y reg byte a 11.0
(label) main::@1
(label) main::@2
(label) main::@return
(byte) main::i loadstore zp[1]:3 3.1818181818181817
(struct Point) main::p loadstore zp[2]:6
(byte) main::i loadstore zp[1]:3 2.9166666666666665
(struct Point) main::p loadstore zp[2]:4
__stackcall (void()) print((byte) print::p_x , (byte) print::p_y)
(label) print::@return
(const byte) print::OFFSET_STACK_P_X = (byte) 1
@ -43,10 +41,10 @@ reg byte y [ print::p_x#0 ]
reg byte x [ print::p_y#0 ]
reg byte x [ get::i#0 ]
reg byte a [ get::$0 ]
reg byte a [ get::return_x#0 ]
reg byte x [ get::return_x#0 ]
reg byte y [ get::return_y#0 ]
zp[1]:3 [ main::i ]
zp[1]:4 [ main::$1_x ]
zp[1]:5 [ main::$1_y ]
zp[2]:6 [ main::p ]
zp[2]:8 [ get::p ]
reg byte x [ main::$1_x ]
reg byte a [ main::$1_y ]
zp[2]:4 [ main::p ]
zp[2]:6 [ get::p ]

View File

@ -12,19 +12,21 @@
main: scope:[main] from @1
[4] callprepare plus (word) $1234 (word) $2345
[5] callexecute plus
[6] (word~) main::$0 ← callfinalize plus
[7] *((const word*) SCREEN) ← (word~) main::$0
stackpull((number) 2)
[7] (word~) main::$0 ← stackpull(word)
[8] *((const word*) SCREEN) ← (word~) main::$0
to:main::@return
main::@return: scope:[main] from main
[8] return
[9] return
to:@return
__stackcall (word()) plus((word) plus::a , (word) plus::b)
plus: scope:[plus] from
[9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A)
[10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B)
[11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0
[10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A)
[11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B)
[12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0
to:plus::@return
plus::@return: scope:[plus] from plus
[12] return (word) plus::return#0
[13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0
[14] return
to:@return

View File

@ -4,6 +4,8 @@ Culled Empty Block (label) plus::@1
Calling convention STACK_CALL adding prepare/execute/finalize for (word~) main::$0 ← call plus (number) $1234 (number) $2345
Calling convention STACK_CALL replacing param((word) plus::a) with stackidx(word,(const byte) plus::OFFSET_STACK_A)
Calling convention STACK_CALL replacing param((word) plus::b) with stackidx(word,(const byte) plus::OFFSET_STACK_B)
Calling convention STACK_CALL adding stack return stackidx(word,plus::OFFSET_STACK_RETURN) ← plus::return
Calling convention STACK_CALL adding stack pull main::$0 ← stackpull(word)
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
@ -13,7 +15,8 @@ CONTROL FLOW GRAPH SSA
main: scope:[main] from @2
callprepare plus (number) $1234 (number) $2345
callexecute plus
(word~) main::$0 ← callfinalize plus
stackpull((number) 2)
(word~) main::$0 ← stackpull(word)
(number~) main::$1 ← (number) 0 * (const byte) SIZEOF_WORD
*((const word*) SCREEN + (number~) main::$1) ← (word~) main::$0
to:main::@return
@ -30,7 +33,8 @@ plus: scope:[plus] from
to:plus::@return
plus::@return: scope:[plus] from plus
(word) plus::return#1 ← phi( plus/(word) plus::return#0 )
return (word) plus::return#1
stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#1
return
to:@return
@2: scope:[] from @begin
call main
@ -82,16 +86,15 @@ Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to byte in (unumber~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD
Alias (word) plus::return#0 = (word~) plus::$0 (word) plus::return#1
Successful SSA optimization Pass2AliasElimination
Constant right-side identified [3] (byte~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD
Constant right-side identified [4] (byte~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::$1 = 0*SIZEOF_WORD
Successful SSA optimization Pass2ConstantIdentification
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_WORD in
Successful SSA optimization PassNSimplifyConstantZero
Simplifying expression containing zero SCREEN in [4] *((const word*) SCREEN + (const byte) main::$1) ← (word~) main::$0
Simplifying expression containing zero SCREEN in [5] *((const word*) SCREEN + (const byte) main::$1) ← (word~) main::$0
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) main::$1
Eliminating unused constant (const byte) plus::OFFSET_STACK_RETURN
Eliminating unused constant (const byte) SIZEOF_WORD
Successful SSA optimization PassNEliminateUnusedVars
Adding NOP phi() at start of @begin
@ -125,34 +128,36 @@ FINAL CONTROL FLOW GRAPH
main: scope:[main] from @1
[4] callprepare plus (word) $1234 (word) $2345
[5] callexecute plus
[6] (word~) main::$0 ← callfinalize plus
[7] *((const word*) SCREEN) ← (word~) main::$0
stackpull((number) 2)
[7] (word~) main::$0 ← stackpull(word)
[8] *((const word*) SCREEN) ← (word~) main::$0
to:main::@return
main::@return: scope:[main] from main
[8] return
[9] return
to:@return
__stackcall (word()) plus((word) plus::a , (word) plus::b)
plus: scope:[plus] from
[9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A)
[10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B)
[11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0
[10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A)
[11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B)
[12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0
to:plus::@return
plus::@return: scope:[plus] from plus
[12] return (word) plus::return#0
[13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0
[14] return
to:@return
VARIABLE REGISTER WEIGHTS
(void()) main()
(word~) main::$0 2.0
(word~) main::$0 4.0
__stackcall (word()) plus((word) plus::a , (word) plus::b)
(word) plus::a
(word) plus::a#0 2.0
(word) plus::b
(word) plus::b#0 4.0
(word) plus::return
(word) plus::return#0 2.0
(word) plus::return#0 4.0
Initial phi equivalence classes
Added variable main::$0 to live range equivalence class [ main::$0 ]
@ -209,15 +214,15 @@ main: {
pha
// [5] callexecute plus -- jsr
jsr plus
// [6] (word~) main::$0 ← callfinalize plus -- _stackpullbyte_2
// stackpull((number) 2) -- _stackpullbyte_2
pla
pla
// [6] (word~) main::$0 ← callfinalize plus -- vwuz1=_stackpullword_
// [7] (word~) main::$0 ← stackpull(word) -- vwuz1=_stackpullword_
pla
sta.z __0
pla
sta.z __0+1
// [7] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1
// [8] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1
lda.z __0
sta SCREEN
lda.z __0+1
@ -225,7 +230,7 @@ main: {
jmp __breturn
// main::@return
__breturn:
// [8] return
// [9] return
rts
}
// plus
@ -233,22 +238,23 @@ main: {
plus: {
.const OFFSET_STACK_A = 2
.const OFFSET_STACK_B = 0
.const OFFSET_STACK_RETURN = 2
.label a = 4
.label b = 6
.label return = 8
// [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1
// [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
lda STACK_BASE+OFFSET_STACK_A+1,x
sta.z a+1
// [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1
// [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
sta.z b
lda STACK_BASE+OFFSET_STACK_B+1,x
sta.z b+1
// [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz2_plus_vwuz3
// [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz2_plus_vwuz3
lda.z a
clc
adc.z b
@ -259,36 +265,37 @@ plus: {
jmp __breturn
// plus::@return
__breturn:
// [12] return (word) plus::return#0
// [12] return (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1
// [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1
tsx
lda.z return
sta STACK_BASE+OFFSET_STACK_RETURN,x
lda.z return+1
sta STACK_BASE+OFFSET_STACK_RETURN+1,x
// [14] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] callprepare plus (word) $1234 (word) $2345 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] (word~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [7] *((const word*) SCREEN) ← (word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a
Statement [12] return (word) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte a reg byte x
Statement stackpull((number) 2) always clobbers reg byte a
Statement [7] (word~) main::$0 ← stackpull(word) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [8] *((const word*) SCREEN) ← (word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a
Statement [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte a reg byte x
Potential registers zp[2]:2 [ main::$0 ] : zp[2]:2 ,
Potential registers zp[2]:4 [ plus::a#0 ] : zp[2]:4 ,
Potential registers zp[2]:6 [ plus::b#0 ] : zp[2]:6 ,
Potential registers zp[2]:8 [ plus::return#0 ] : zp[2]:8 ,
REGISTER UPLIFT SCOPES
Uplift Scope [plus] 4: zp[2]:6 [ plus::b#0 ] 2: zp[2]:4 [ plus::a#0 ] 2: zp[2]:8 [ plus::return#0 ]
Uplift Scope [main] 2: zp[2]:2 [ main::$0 ]
Uplift Scope [plus] 4: zp[2]:6 [ plus::b#0 ] 4: zp[2]:8 [ plus::return#0 ] 2: zp[2]:4 [ plus::a#0 ]
Uplift Scope [main] 4: zp[2]:2 [ main::$0 ]
Uplift Scope []
Uplifting [plus] best 164 combination zp[2]:6 [ plus::b#0 ] zp[2]:4 [ plus::a#0 ] zp[2]:8 [ plus::return#0 ]
Uplifting [plus] best 164 combination zp[2]:6 [ plus::b#0 ] zp[2]:8 [ plus::return#0 ] zp[2]:4 [ plus::a#0 ]
Uplifting [main] best 164 combination zp[2]:2 [ main::$0 ]
Uplifting [] best 164 combination
Coalescing zero page register [ zp[2]:4 [ plus::a#0 ] ] with [ zp[2]:8 [ plus::return#0 ] ] - score: 1
@ -335,15 +342,15 @@ main: {
pha
// [5] callexecute plus -- jsr
jsr plus
// [6] (word~) main::$0 ← callfinalize plus -- _stackpullbyte_2
// stackpull((number) 2) -- _stackpullbyte_2
pla
pla
// [6] (word~) main::$0 ← callfinalize plus -- vwuz1=_stackpullword_
// [7] (word~) main::$0 ← stackpull(word) -- vwuz1=_stackpullword_
pla
sta.z __0
pla
sta.z __0+1
// [7] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1
// [8] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1
lda.z __0
sta SCREEN
lda.z __0+1
@ -351,7 +358,7 @@ main: {
jmp __breturn
// main::@return
__breturn:
// [8] return
// [9] return
rts
}
// plus
@ -363,19 +370,19 @@ plus: {
.label a = 2
.label b = 4
.label return = 2
// [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1
// [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
lda STACK_BASE+OFFSET_STACK_A+1,x
sta.z a+1
// [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1
// [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
sta.z b
lda STACK_BASE+OFFSET_STACK_B+1,x
sta.z b+1
// [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2
// [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2
lda.z return
clc
adc.z b
@ -386,13 +393,13 @@ plus: {
jmp __breturn
// plus::@return
__breturn:
// [12] return (word) plus::return#0
// [12] return (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1
// [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1
tsx
lda.z return
sta STACK_BASE+OFFSET_STACK_RETURN,x
lda.z return+1
sta STACK_BASE+OFFSET_STACK_RETURN+1,x
// [14] return
rts
}
// File Data
@ -424,7 +431,7 @@ FINAL SYMBOL TABLE
(const word*) SCREEN = (word*) 1024
(const word) STACK_BASE = (word) $103
(void()) main()
(word~) main::$0 zp[2]:2 2.0
(word~) main::$0 zp[2]:2 4.0
(label) main::@return
__stackcall (word()) plus((word) plus::a , (word) plus::b)
(label) plus::@return
@ -436,7 +443,7 @@ __stackcall (word()) plus((word) plus::a , (word) plus::b)
(word) plus::b
(word) plus::b#0 b zp[2]:4 4.0
(word) plus::return
(word) plus::return#0 return zp[2]:2 2.0
(word) plus::return#0 return zp[2]:2 4.0
zp[2]:2 [ plus::a#0 plus::return#0 main::$0 ]
zp[2]:4 [ plus::b#0 ]
@ -476,23 +483,23 @@ main: {
pha
// [5] callexecute plus -- jsr
jsr plus
// [6] (word~) main::$0 ← callfinalize plus -- _stackpullbyte_2
// stackpull((number) 2) -- _stackpullbyte_2
pla
pla
// [6] (word~) main::$0 ← callfinalize plus -- vwuz1=_stackpullword_
// [7] (word~) main::$0 ← stackpull(word) -- vwuz1=_stackpullword_
pla
sta.z __0
pla
sta.z __0+1
// SCREEN[0] = plus(0x1234, 0x2345)
// [7] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1
// [8] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1
lda.z __0
sta SCREEN
lda.z __0+1
sta SCREEN+1
// main::@return
// }
// [8] return
// [9] return
rts
}
// plus
@ -504,20 +511,20 @@ plus: {
.label a = 2
.label b = 4
.label return = 2
// [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1
// [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
lda STACK_BASE+OFFSET_STACK_A+1,x
sta.z a+1
// [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1
// [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
sta.z b
lda STACK_BASE+OFFSET_STACK_B+1,x
sta.z b+1
// return a+b;
// [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2
// [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2
lda.z return
clc
adc.z b
@ -527,13 +534,13 @@ plus: {
sta.z return+1
// plus::@return
// }
// [12] return (word) plus::return#0
// [12] return (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1
// [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1
tsx
lda.z return
sta STACK_BASE+OFFSET_STACK_RETURN,x
lda.z return+1
sta STACK_BASE+OFFSET_STACK_RETURN+1,x
// [14] return
rts
}
// File Data

View File

@ -4,7 +4,7 @@
(const word*) SCREEN = (word*) 1024
(const word) STACK_BASE = (word) $103
(void()) main()
(word~) main::$0 zp[2]:2 2.0
(word~) main::$0 zp[2]:2 4.0
(label) main::@return
__stackcall (word()) plus((word) plus::a , (word) plus::b)
(label) plus::@return
@ -16,7 +16,7 @@ __stackcall (word()) plus((word) plus::a , (word) plus::b)
(word) plus::b
(word) plus::b#0 b zp[2]:4 4.0
(word) plus::return
(word) plus::return#0 return zp[2]:2 2.0
(word) plus::return#0 return zp[2]:2 4.0
zp[2]:2 [ plus::a#0 plus::return#0 main::$0 ]
zp[2]:4 [ plus::b#0 ]

View File

@ -12,19 +12,21 @@
main: scope:[main] from @1
[4] callprepare plus (byte) '0' (byte) 7
[5] callexecute plus
[6] (word~) main::$0 ← callfinalize plus
[7] *((const word*) SCREEN) ← (word~) main::$0
stackpull((number) 2)
[7] (word~) main::$0 ← stackpull(word)
[8] *((const word*) SCREEN) ← (word~) main::$0
to:main::@return
main::@return: scope:[main] from main
[8] return
[9] return
to:@return
__stackcall (word()) plus((word) plus::a , (word) plus::b)
plus: scope:[plus] from
[9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A)
[10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B)
[11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0
[10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A)
[11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B)
[12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0
to:plus::@return
plus::@return: scope:[plus] from plus
[12] return (word) plus::return#0
[13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0
[14] return
to:@return

View File

@ -4,6 +4,8 @@ Culled Empty Block (label) plus::@1
Calling convention STACK_CALL adding prepare/execute/finalize for (word~) main::$0 ← call plus (byte) '0' (number) 7
Calling convention STACK_CALL replacing param((word) plus::a) with stackidx(word,(const byte) plus::OFFSET_STACK_A)
Calling convention STACK_CALL replacing param((word) plus::b) with stackidx(word,(const byte) plus::OFFSET_STACK_B)
Calling convention STACK_CALL adding stack return stackidx(word,plus::OFFSET_STACK_RETURN) ← plus::return
Calling convention STACK_CALL adding stack pull main::$0 ← stackpull(word)
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
@ -13,7 +15,8 @@ CONTROL FLOW GRAPH SSA
main: scope:[main] from @2
callprepare plus (byte) '0' (number) 7
callexecute plus
(word~) main::$0 ← callfinalize plus
stackpull((number) 2)
(word~) main::$0 ← stackpull(word)
(number~) main::$1 ← (number) 0 * (const byte) SIZEOF_WORD
*((const word*) SCREEN + (number~) main::$1) ← (word~) main::$0
to:main::@return
@ -30,7 +33,8 @@ plus: scope:[plus] from
to:plus::@return
plus::@return: scope:[plus] from plus
(word) plus::return#1 ← phi( plus/(word) plus::return#0 )
return (word) plus::return#1
stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#1
return
to:@return
@2: scope:[] from @begin
call main
@ -79,16 +83,15 @@ Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to byte in (unumber~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD
Alias (word) plus::return#0 = (word~) plus::$0 (word) plus::return#1
Successful SSA optimization Pass2AliasElimination
Constant right-side identified [3] (byte~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD
Constant right-side identified [4] (byte~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::$1 = 0*SIZEOF_WORD
Successful SSA optimization Pass2ConstantIdentification
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_WORD in
Successful SSA optimization PassNSimplifyConstantZero
Simplifying expression containing zero SCREEN in [4] *((const word*) SCREEN + (const byte) main::$1) ← (word~) main::$0
Simplifying expression containing zero SCREEN in [5] *((const word*) SCREEN + (const byte) main::$1) ← (word~) main::$0
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) main::$1
Eliminating unused constant (const byte) plus::OFFSET_STACK_RETURN
Eliminating unused constant (const byte) SIZEOF_WORD
Successful SSA optimization PassNEliminateUnusedVars
Adding NOP phi() at start of @begin
@ -122,34 +125,36 @@ FINAL CONTROL FLOW GRAPH
main: scope:[main] from @1
[4] callprepare plus (byte) '0' (byte) 7
[5] callexecute plus
[6] (word~) main::$0 ← callfinalize plus
[7] *((const word*) SCREEN) ← (word~) main::$0
stackpull((number) 2)
[7] (word~) main::$0 ← stackpull(word)
[8] *((const word*) SCREEN) ← (word~) main::$0
to:main::@return
main::@return: scope:[main] from main
[8] return
[9] return
to:@return
__stackcall (word()) plus((word) plus::a , (word) plus::b)
plus: scope:[plus] from
[9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A)
[10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B)
[11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0
[10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A)
[11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B)
[12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0
to:plus::@return
plus::@return: scope:[plus] from plus
[12] return (word) plus::return#0
[13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0
[14] return
to:@return
VARIABLE REGISTER WEIGHTS
(void()) main()
(word~) main::$0 2.0
(word~) main::$0 4.0
__stackcall (word()) plus((word) plus::a , (word) plus::b)
(word) plus::a
(word) plus::a#0 2.0
(word) plus::b
(word) plus::b#0 4.0
(word) plus::return
(word) plus::return#0 2.0
(word) plus::return#0 4.0
Initial phi equivalence classes
Added variable main::$0 to live range equivalence class [ main::$0 ]
@ -209,15 +214,15 @@ main: {
pha
// [5] callexecute plus -- jsr
jsr plus
// [6] (word~) main::$0 ← callfinalize plus -- _stackpullbyte_2
// stackpull((number) 2) -- _stackpullbyte_2
pla
pla
// [6] (word~) main::$0 ← callfinalize plus -- vwuz1=_stackpullword_
// [7] (word~) main::$0 ← stackpull(word) -- vwuz1=_stackpullword_
pla
sta.z __0
pla
sta.z __0+1
// [7] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1
// [8] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1
lda.z __0
sta SCREEN
lda.z __0+1
@ -225,7 +230,7 @@ main: {
jmp __breturn
// main::@return
__breturn:
// [8] return
// [9] return
rts
}
// plus
@ -233,22 +238,23 @@ main: {
plus: {
.const OFFSET_STACK_A = 2
.const OFFSET_STACK_B = 0
.const OFFSET_STACK_RETURN = 2
.label a = 4
.label b = 6
.label return = 8
// [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1
// [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
lda STACK_BASE+OFFSET_STACK_A+1,x
sta.z a+1
// [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1
// [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
sta.z b
lda STACK_BASE+OFFSET_STACK_B+1,x
sta.z b+1
// [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz2_plus_vwuz3
// [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz2_plus_vwuz3
lda.z a
clc
adc.z b
@ -259,36 +265,37 @@ plus: {
jmp __breturn
// plus::@return
__breturn:
// [12] return (word) plus::return#0
// [12] return (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1
// [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1
tsx
lda.z return
sta STACK_BASE+OFFSET_STACK_RETURN,x
lda.z return+1
sta STACK_BASE+OFFSET_STACK_RETURN+1,x
// [14] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] (word~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [7] *((const word*) SCREEN) ← (word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a
Statement [12] return (word) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte a reg byte x
Statement stackpull((number) 2) always clobbers reg byte a
Statement [7] (word~) main::$0 ← stackpull(word) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [8] *((const word*) SCREEN) ← (word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a
Statement [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte a reg byte x
Potential registers zp[2]:2 [ main::$0 ] : zp[2]:2 ,
Potential registers zp[2]:4 [ plus::a#0 ] : zp[2]:4 ,
Potential registers zp[2]:6 [ plus::b#0 ] : zp[2]:6 ,
Potential registers zp[2]:8 [ plus::return#0 ] : zp[2]:8 ,
REGISTER UPLIFT SCOPES
Uplift Scope [plus] 4: zp[2]:6 [ plus::b#0 ] 2: zp[2]:4 [ plus::a#0 ] 2: zp[2]:8 [ plus::return#0 ]
Uplift Scope [main] 2: zp[2]:2 [ main::$0 ]
Uplift Scope [plus] 4: zp[2]:6 [ plus::b#0 ] 4: zp[2]:8 [ plus::return#0 ] 2: zp[2]:4 [ plus::a#0 ]
Uplift Scope [main] 4: zp[2]:2 [ main::$0 ]
Uplift Scope []
Uplifting [plus] best 164 combination zp[2]:6 [ plus::b#0 ] zp[2]:4 [ plus::a#0 ] zp[2]:8 [ plus::return#0 ]
Uplifting [plus] best 164 combination zp[2]:6 [ plus::b#0 ] zp[2]:8 [ plus::return#0 ] zp[2]:4 [ plus::a#0 ]
Uplifting [main] best 164 combination zp[2]:2 [ main::$0 ]
Uplifting [] best 164 combination
Coalescing zero page register [ zp[2]:4 [ plus::a#0 ] ] with [ zp[2]:8 [ plus::return#0 ] ] - score: 1
@ -338,15 +345,15 @@ main: {
pha
// [5] callexecute plus -- jsr
jsr plus
// [6] (word~) main::$0 ← callfinalize plus -- _stackpullbyte_2
// stackpull((number) 2) -- _stackpullbyte_2
pla
pla
// [6] (word~) main::$0 ← callfinalize plus -- vwuz1=_stackpullword_
// [7] (word~) main::$0 ← stackpull(word) -- vwuz1=_stackpullword_
pla
sta.z __0
pla
sta.z __0+1
// [7] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1
// [8] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1
lda.z __0
sta SCREEN
lda.z __0+1
@ -354,7 +361,7 @@ main: {
jmp __breturn
// main::@return
__breturn:
// [8] return
// [9] return
rts
}
// plus
@ -366,19 +373,19 @@ plus: {
.label a = 2
.label b = 4
.label return = 2
// [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1
// [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
lda STACK_BASE+OFFSET_STACK_A+1,x
sta.z a+1
// [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1
// [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
sta.z b
lda STACK_BASE+OFFSET_STACK_B+1,x
sta.z b+1
// [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2
// [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2
lda.z return
clc
adc.z b
@ -389,13 +396,13 @@ plus: {
jmp __breturn
// plus::@return
__breturn:
// [12] return (word) plus::return#0
// [12] return (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1
// [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1
tsx
lda.z return
sta STACK_BASE+OFFSET_STACK_RETURN,x
lda.z return+1
sta STACK_BASE+OFFSET_STACK_RETURN+1,x
// [14] return
rts
}
// File Data
@ -427,7 +434,7 @@ FINAL SYMBOL TABLE
(const word*) SCREEN = (word*) 1024
(const word) STACK_BASE = (word) $103
(void()) main()
(word~) main::$0 zp[2]:2 2.0
(word~) main::$0 zp[2]:2 4.0
(label) main::@return
__stackcall (word()) plus((word) plus::a , (word) plus::b)
(label) plus::@return
@ -439,7 +446,7 @@ __stackcall (word()) plus((word) plus::a , (word) plus::b)
(word) plus::b
(word) plus::b#0 b zp[2]:4 4.0
(word) plus::return
(word) plus::return#0 return zp[2]:2 2.0
(word) plus::return#0 return zp[2]:2 4.0
zp[2]:2 [ plus::a#0 plus::return#0 main::$0 ]
zp[2]:4 [ plus::b#0 ]
@ -482,23 +489,23 @@ main: {
pha
// [5] callexecute plus -- jsr
jsr plus
// [6] (word~) main::$0 ← callfinalize plus -- _stackpullbyte_2
// stackpull((number) 2) -- _stackpullbyte_2
pla
pla
// [6] (word~) main::$0 ← callfinalize plus -- vwuz1=_stackpullword_
// [7] (word~) main::$0 ← stackpull(word) -- vwuz1=_stackpullword_
pla
sta.z __0
pla
sta.z __0+1
// SCREEN[0] = plus('0', 7)
// [7] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1
// [8] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1
lda.z __0
sta SCREEN
lda.z __0+1
sta SCREEN+1
// main::@return
// }
// [8] return
// [9] return
rts
}
// plus
@ -510,20 +517,20 @@ plus: {
.label a = 2
.label b = 4
.label return = 2
// [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1
// [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
lda STACK_BASE+OFFSET_STACK_A+1,x
sta.z a+1
// [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1
// [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
sta.z b
lda STACK_BASE+OFFSET_STACK_B+1,x
sta.z b+1
// return a+b;
// [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2
// [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2
lda.z return
clc
adc.z b
@ -533,13 +540,13 @@ plus: {
sta.z return+1
// plus::@return
// }
// [12] return (word) plus::return#0
// [12] return (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1
// [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1
tsx
lda.z return
sta STACK_BASE+OFFSET_STACK_RETURN,x
lda.z return+1
sta STACK_BASE+OFFSET_STACK_RETURN+1,x
// [14] return
rts
}
// File Data

View File

@ -4,7 +4,7 @@
(const word*) SCREEN = (word*) 1024
(const word) STACK_BASE = (word) $103
(void()) main()
(word~) main::$0 zp[2]:2 2.0
(word~) main::$0 zp[2]:2 4.0
(label) main::@return
__stackcall (word()) plus((word) plus::a , (word) plus::b)
(label) plus::@return
@ -16,7 +16,7 @@ __stackcall (word()) plus((word) plus::a , (word) plus::b)
(word) plus::b
(word) plus::b#0 b zp[2]:4 4.0
(word) plus::return
(word) plus::return#0 return zp[2]:2 2.0
(word) plus::return#0 return zp[2]:2 4.0
zp[2]:2 [ plus::a#0 plus::return#0 main::$0 ]
zp[2]:4 [ plus::b#0 ]

View File

@ -18,8 +18,8 @@ main: {
txa
pha
jsr plus
// w = plus('0', v)
pla
// w = plus('0', v)
pla
// w+a
sty.z $ff

View File

@ -17,22 +17,24 @@ main::@1: scope:[main] from main main::@1
[6] (byte) main::v#0 ← (byte) main::a#2 + (byte) 1
[7] callprepare plus (byte) '0' (byte) main::v#0
[8] callexecute plus
[9] (byte) main::w#0 ← callfinalize plus
[10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2
[11] *((const byte*) SCREEN) ← (byte~) main::$2
[12] (byte) main::a#1 ← ++ (byte) main::a#2
[13] if((byte) main::a#1!=(byte) 2) goto main::@1
stackpull((number) 1)
[10] (byte) main::w#0 ← stackpull(byte)
[11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2
[12] *((const byte*) SCREEN) ← (byte~) main::$2
[13] (byte) main::a#1 ← ++ (byte) main::a#2
[14] if((byte) main::a#1!=(byte) 2) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[14] return
[15] return
to:@return
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
plus: scope:[plus] from
[15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A)
[16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B)
[17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
[16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A)
[17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B)
[18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
to:plus::@return
plus::@return: scope:[plus] from plus
[18] return (byte) plus::return#0
[19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0
[20] return
to:@return

View File

@ -4,6 +4,8 @@ Culled Empty Block (label) plus::@1
Calling convention STACK_CALL adding prepare/execute/finalize for (byte~) main::$1 ← call plus (byte) '0' (byte) main::v
Calling convention STACK_CALL replacing param((byte) plus::a) with stackidx(byte,(const byte) plus::OFFSET_STACK_A)
Calling convention STACK_CALL replacing param((byte) plus::b) with stackidx(byte,(const byte) plus::OFFSET_STACK_B)
Calling convention STACK_CALL adding stack return stackidx(byte,plus::OFFSET_STACK_RETURN) ← plus::return
Calling convention STACK_CALL adding stack pull main::$1 ← stackpull(byte)
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
@ -22,7 +24,8 @@ main::@1: scope:[main] from main main::@1
(byte) main::v#0 ← (number~) main::$0
callprepare plus (byte) '0' (byte) main::v#0
callexecute plus
(byte~) main::$1 ← callfinalize plus
stackpull((number) 1)
(byte~) main::$1 ← stackpull(byte)
(byte) main::w#0 ← (byte~) main::$1
(byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2
*((const byte*) SCREEN + (byte) i#4) ← (byte~) main::$2
@ -47,7 +50,8 @@ plus: scope:[plus] from
to:plus::@return
plus::@return: scope:[plus] from plus
(byte) plus::return#1 ← phi( plus/(byte) plus::return#0 )
return (byte) plus::return#1
stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#1
return
to:@return
@2: scope:[] from @begin
(byte) i#9 ← phi( @begin/(byte) i#0 )
@ -126,17 +130,16 @@ Identical Phi Values (byte) i#8 (byte) i#0
Identical Phi Values (byte) i#1 (byte) i#8
Identical Phi Values (byte) i#3 (byte) i#1
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) main::$3 [12] if((byte) main::a#1!=rangelast(0,1)) goto main::@1
Simple Condition (bool~) main::$3 [13] if((byte) main::a#1!=rangelast(0,1)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte) i#0 = 0
Constant (const byte) main::a#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [10] main::a#1 ← ++ main::a#2 to ++
Resolved ranged comparison value [12] if(main::a#1!=rangelast(0,1)) goto main::@1 to (number) 2
Simplifying expression containing zero SCREEN in [9] *((const byte*) SCREEN + (const byte) i#0) ← (byte~) main::$2
Resolved ranged next value [11] main::a#1 ← ++ main::a#2 to ++
Resolved ranged comparison value [13] if(main::a#1!=rangelast(0,1)) goto main::@1 to (number) 2
Simplifying expression containing zero SCREEN in [10] *((const byte*) SCREEN + (const byte) i#0) ← (byte~) main::$2
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (byte) i#2 and assignment [13] (byte) i#2 ← ++ (byte) i#6
Eliminating unused constant (const byte) plus::OFFSET_STACK_RETURN
Eliminating unused variable (byte) i#2 and assignment [14] (byte) i#2 ← ++ (byte) i#6
Eliminating unused constant (const byte) i#0
Successful SSA optimization PassNEliminateUnusedVars
Eliminating unused variable - keeping the phi block (byte) i#6
@ -161,7 +164,7 @@ Calls in [] to main:2
Calls in [main] to plus:9
Created 1 initial phi equivalence classes
Coalesced [16] main::a#3 ← main::a#1
Coalesced [17] main::a#3 ← main::a#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @3
Culled Empty Block (label) main::@3
@ -191,24 +194,26 @@ main::@1: scope:[main] from main main::@1
[6] (byte) main::v#0 ← (byte) main::a#2 + (byte) 1
[7] callprepare plus (byte) '0' (byte) main::v#0
[8] callexecute plus
[9] (byte) main::w#0 ← callfinalize plus
[10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2
[11] *((const byte*) SCREEN) ← (byte~) main::$2
[12] (byte) main::a#1 ← ++ (byte) main::a#2
[13] if((byte) main::a#1!=(byte) 2) goto main::@1
stackpull((number) 1)
[10] (byte) main::w#0 ← stackpull(byte)
[11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2
[12] *((const byte*) SCREEN) ← (byte~) main::$2
[13] (byte) main::a#1 ← ++ (byte) main::a#2
[14] if((byte) main::a#1!=(byte) 2) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[14] return
[15] return
to:@return
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
plus: scope:[plus] from
[15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A)
[16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B)
[17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
[16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A)
[17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B)
[18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
to:plus::@return
plus::@return: scope:[plus] from plus
[18] return (byte) plus::return#0
[19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0
[20] return
to:@return
@ -218,18 +223,18 @@ VARIABLE REGISTER WEIGHTS
(byte~) main::$2 22.0
(byte) main::a
(byte) main::a#1 16.5
(byte) main::a#2 6.285714285714286
(byte) main::a#2 5.5
(byte) main::v
(byte) main::v#0 11.0
(byte) main::w
(byte) main::w#0 11.0
(byte) main::w#0 22.0
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(byte) plus::a
(byte) plus::a#0 2.0
(byte) plus::b
(byte) plus::b#0 4.0
(byte) plus::return
(byte) plus::return#0 2.0
(byte) plus::return#0 4.0
Initial phi equivalence classes
[ main::a#2 main::a#1 ]
@ -313,29 +318,29 @@ main: {
pha
// [8] callexecute plus -- jsr
jsr plus
// [9] (byte) main::w#0 ← callfinalize plus -- _stackpullbyte_1
// stackpull((number) 1) -- _stackpullbyte_1
pla
// [9] (byte) main::w#0 ← callfinalize plus -- vbuz1=_stackpullbyte_
// [10] (byte) main::w#0 ← stackpull(byte) -- vbuz1=_stackpullbyte_
pla
sta.z w
// [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuz1=vbuz2_plus_vbuz3
// [11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuz1=vbuz2_plus_vbuz3
lda.z w
clc
adc.z a
sta.z __2
// [11] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuz1
// [12] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuz1
lda.z __2
sta SCREEN
// [12] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuz1=_inc_vbuz1
// [13] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuz1=_inc_vbuz1
inc.z a
// [13] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
// [14] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #2
cmp.z a
bne __b1_from___b1
jmp __breturn
// main::@return
__breturn:
// [14] return
// [15] return
rts
}
// plus
@ -343,18 +348,19 @@ main: {
plus: {
.const OFFSET_STACK_A = 1
.const OFFSET_STACK_B = 0
.const OFFSET_STACK_RETURN = 1
.label a = 6
.label b = 7
.label return = 8
// [15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
// [16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
// [16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackidxbyte_vbuc1
// [17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
sta.z b
// [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3
// [18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3
lda.z a
clc
adc.z b
@ -362,11 +368,11 @@ plus: {
jmp __breturn
// plus::@return
__breturn:
// [18] return (byte) plus::return#0
// [18] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1
// [19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1
lda.z return
tsx
sta STACK_BASE+OFFSET_STACK_RETURN,x
// [20] return
rts
}
// File Data
@ -374,22 +380,24 @@ plus: {
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [7] callprepare plus (byte) '0' (byte) main::v#0 [ main::a#2 ] ( main:2 [ main::a#2 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::a#2 main::a#1 ]
Statement [9] (byte) main::w#0 ← callfinalize plus [ main::a#2 main::w#0 ] ( main:2 [ main::a#2 main::w#0 ] ) always clobbers reg byte a
Statement [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ main::a#2 main::$2 ] ( main:2 [ main::a#2 main::$2 ] ) always clobbers reg byte a
Statement [15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement stackpull((number) 1) always clobbers reg byte a
Statement [10] (byte) main::w#0 ← stackpull(byte) [ main::a#2 main::w#0 ] ( main:2 [ main::a#2 main::w#0 ] ) always clobbers reg byte a
Statement [11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ main::a#2 main::$2 ] ( main:2 [ main::a#2 main::$2 ] ) always clobbers reg byte a
Statement [16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x
Removing always clobbered register reg byte x as potential for zp[1]:2 [ main::a#2 main::a#1 ]
Statement [16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement [17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Removing always clobbered register reg byte a as potential for zp[1]:6 [ plus::a#0 ]
Removing always clobbered register reg byte x as potential for zp[1]:6 [ plus::a#0 ]
Statement [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:8 [ main::a#2 plus::return#0 ] ) always clobbers reg byte a
Statement [18] return (byte) plus::return#0 [ ] ( main:2::plus:8 [ main::a#2 ] ) always clobbers reg byte x
Statement [18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:8 [ main::a#2 plus::return#0 ] ) always clobbers reg byte a
Statement [19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:8 [ main::a#2 ] ) always clobbers reg byte x
Statement [7] callprepare plus (byte) '0' (byte) main::v#0 [ main::a#2 ] ( main:2 [ main::a#2 ] ) always clobbers reg byte a
Statement [9] (byte) main::w#0 ← callfinalize plus [ main::a#2 main::w#0 ] ( main:2 [ main::a#2 main::w#0 ] ) always clobbers reg byte a
Statement [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ main::a#2 main::$2 ] ( main:2 [ main::a#2 main::$2 ] ) always clobbers reg byte a
Statement [15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:8 [ main::a#2 plus::return#0 ] ) always clobbers reg byte a
Statement [18] return (byte) plus::return#0 [ ] ( main:2::plus:8 [ main::a#2 ] ) always clobbers reg byte x
Statement stackpull((number) 1) always clobbers reg byte a
Statement [10] (byte) main::w#0 ← stackpull(byte) [ main::a#2 main::w#0 ] ( main:2 [ main::a#2 main::w#0 ] ) always clobbers reg byte a
Statement [11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ main::a#2 main::$2 ] ( main:2 [ main::a#2 main::$2 ] ) always clobbers reg byte a
Statement [16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x
Statement [17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
Statement [18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:8 [ main::a#2 plus::return#0 ] ) always clobbers reg byte a
Statement [19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:8 [ main::a#2 ] ) always clobbers reg byte x
Potential registers zp[1]:2 [ main::a#2 main::a#1 ] : zp[1]:2 , reg byte y ,
Potential registers zp[1]:3 [ main::v#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:4 [ main::w#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y ,
@ -399,13 +407,13 @@ Potential registers zp[1]:7 [ plus::b#0 ] : zp[1]:7 , reg byte a , reg byte x ,
Potential registers zp[1]:8 [ plus::return#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 22.79: zp[1]:2 [ main::a#2 main::a#1 ] 22: zp[1]:5 [ main::$2 ] 11: zp[1]:3 [ main::v#0 ] 11: zp[1]:4 [ main::w#0 ]
Uplift Scope [plus] 4: zp[1]:7 [ plus::b#0 ] 2: zp[1]:6 [ plus::a#0 ] 2: zp[1]:8 [ plus::return#0 ]
Uplift Scope [main] 22: zp[1]:2 [ main::a#2 main::a#1 ] 22: zp[1]:4 [ main::w#0 ] 22: zp[1]:5 [ main::$2 ] 11: zp[1]:3 [ main::v#0 ]
Uplift Scope [plus] 4: zp[1]:7 [ plus::b#0 ] 4: zp[1]:8 [ plus::return#0 ] 2: zp[1]:6 [ plus::a#0 ]
Uplift Scope []
Uplifting [main] best 661 combination reg byte y [ main::a#2 main::a#1 ] reg byte a [ main::$2 ] reg byte x [ main::v#0 ] reg byte a [ main::w#0 ]
Uplifting [main] best 661 combination reg byte y [ main::a#2 main::a#1 ] reg byte a [ main::w#0 ] reg byte a [ main::$2 ] reg byte x [ main::v#0 ]
Limited combination testing to 100 combinations of 128 possible.
Uplifting [plus] best 649 combination reg byte a [ plus::b#0 ] zp[1]:6 [ plus::a#0 ] reg byte a [ plus::return#0 ]
Uplifting [plus] best 649 combination reg byte a [ plus::b#0 ] reg byte a [ plus::return#0 ] zp[1]:6 [ plus::a#0 ]
Uplifting [] best 649 combination
Attempting to uplift remaining variables inzp[1]:6 [ plus::a#0 ]
Uplifting [plus] best 649 combination zp[1]:6 [ plus::a#0 ]
@ -463,25 +471,25 @@ main: {
pha
// [8] callexecute plus -- jsr
jsr plus
// [9] (byte) main::w#0 ← callfinalize plus -- _stackpullbyte_1
// stackpull((number) 1) -- _stackpullbyte_1
pla
// [9] (byte) main::w#0 ← callfinalize plus -- vbuaa=_stackpullbyte_
// [10] (byte) main::w#0 ← stackpull(byte) -- vbuaa=_stackpullbyte_
pla
// [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuaa=vbuaa_plus_vbuyy
// [11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuaa=vbuaa_plus_vbuyy
sty.z $ff
clc
adc.z $ff
// [11] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa
// [12] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa
sta SCREEN
// [12] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuyy=_inc_vbuyy
// [13] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuyy=_inc_vbuyy
iny
// [13] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
// [14] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
cpy #2
bne __b1_from___b1
jmp __breturn
// main::@return
__breturn:
// [14] return
// [15] return
rts
}
// plus
@ -491,23 +499,23 @@ plus: {
.const OFFSET_STACK_B = 0
.const OFFSET_STACK_RETURN = 1
.label a = 2
// [15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
// [16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
// [16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1
// [17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
// [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
// [18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
clc
adc.z a
jmp __breturn
// plus::@return
__breturn:
// [18] return (byte) plus::return#0
// [18] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa
// [19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa
tsx
sta STACK_BASE+OFFSET_STACK_RETURN,x
// [20] return
rts
}
// File Data
@ -552,11 +560,11 @@ FINAL SYMBOL TABLE
(label) main::@return
(byte) main::a
(byte) main::a#1 reg byte y 16.5
(byte) main::a#2 reg byte y 6.285714285714286
(byte) main::a#2 reg byte y 5.5
(byte) main::v
(byte) main::v#0 reg byte x 11.0
(byte) main::w
(byte) main::w#0 reg byte a 11.0
(byte) main::w#0 reg byte a 22.0
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(label) plus::@return
(const byte) plus::OFFSET_STACK_A = (byte) 1
@ -567,7 +575,7 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(byte) plus::b
(byte) plus::b#0 reg byte a 4.0
(byte) plus::return
(byte) plus::return#0 reg byte a 2.0
(byte) plus::return#0 reg byte a 4.0
reg byte y [ main::a#2 main::a#1 ]
reg byte x [ main::v#0 ]
@ -621,28 +629,28 @@ main: {
pha
// [8] callexecute plus -- jsr
jsr plus
// w = plus('0', v)
// [9] (byte) main::w#0 ← callfinalize plus -- _stackpullbyte_1
// stackpull((number) 1) -- _stackpullbyte_1
pla
// [9] (byte) main::w#0 ← callfinalize plus -- vbuaa=_stackpullbyte_
// w = plus('0', v)
// [10] (byte) main::w#0 ← stackpull(byte) -- vbuaa=_stackpullbyte_
pla
// w+a
// [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuaa=vbuaa_plus_vbuyy
// [11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuaa=vbuaa_plus_vbuyy
sty.z $ff
clc
adc.z $ff
// SCREEN[i] = w+a
// [11] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa
// [12] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa
sta SCREEN
// for(char a:0..1)
// [12] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuyy=_inc_vbuyy
// [13] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuyy=_inc_vbuyy
iny
// [13] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
// [14] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
cpy #2
bne __b1
// main::@return
// }
// [14] return
// [15] return
rts
}
// plus
@ -652,23 +660,23 @@ plus: {
.const OFFSET_STACK_B = 0
.const OFFSET_STACK_RETURN = 1
.label a = 2
// [15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
// [16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_A,x
sta.z a
// [16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1
// [17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1
tsx
lda STACK_BASE+OFFSET_STACK_B,x
// return a+b;
// [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
// [18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
clc
adc.z a
// plus::@return
// }
// [18] return (byte) plus::return#0
// [18] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa
// [19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa
tsx
sta STACK_BASE+OFFSET_STACK_RETURN,x
// [20] return
rts
}
// File Data

View File

@ -10,11 +10,11 @@
(label) main::@return
(byte) main::a
(byte) main::a#1 reg byte y 16.5
(byte) main::a#2 reg byte y 6.285714285714286
(byte) main::a#2 reg byte y 5.5
(byte) main::v
(byte) main::v#0 reg byte x 11.0
(byte) main::w
(byte) main::w#0 reg byte a 11.0
(byte) main::w#0 reg byte a 22.0
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(label) plus::@return
(const byte) plus::OFFSET_STACK_A = (byte) 1
@ -25,7 +25,7 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
(byte) plus::b
(byte) plus::b#0 reg byte a 4.0
(byte) plus::return
(byte) plus::return#0 reg byte a 2.0
(byte) plus::return#0 reg byte a 4.0
reg byte y [ main::a#2 main::a#1 ]
reg byte x [ main::v#0 ]

View File

@ -12,11 +12,11 @@
main: scope:[main] from @1
[4] callprepare next
[5] callexecute next
[6] (signed word~) main::$0 ← callfinalize next
[6] (signed word~) main::$0 ← stackpull(signed word)
[7] *((const signed word*) SCREEN) ← (signed word~) main::$0
[8] callprepare next
[9] callexecute next
[10] (signed word~) main::$1 ← callfinalize next
[10] (signed word~) main::$1 ← stackpull(signed word)
[11] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1
to:main::@return
main::@return: scope:[main] from main
@ -29,5 +29,6 @@ next: scope:[next] from
[14] (signed word) next::return#0 ← (signed word) current#5
to:next::@return
next::@return: scope:[next] from next
[15] return (signed word) next::return#0
[15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0
[16] return
to:@return

View File

@ -3,6 +3,9 @@ Fixing pointer array-indexing *((const signed word*) SCREEN + (number) 1)
Culled Empty Block (label) next::@1
Calling convention STACK_CALL adding prepare/execute/finalize for (signed word~) main::$0 ← call next
Calling convention STACK_CALL adding prepare/execute/finalize for (signed word~) main::$1 ← call next
Calling convention STACK_CALL adding stack return stackidx(signed word,next::OFFSET_STACK_RETURN) ← next::return
Calling convention STACK_CALL adding stack pull main::$0 ← stackpull(signed word)
Calling convention STACK_CALL adding stack pull main::$1 ← stackpull(signed word)
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
@ -13,12 +16,12 @@ main: scope:[main] from @2
(signed word) current#7 ← phi( @2/(signed word) current#8 )
callprepare next
callexecute next
(signed word~) main::$0 ← callfinalize next
(signed word~) main::$0 ← stackpull(signed word)
(number~) main::$2 ← (number) 0 * (const byte) SIZEOF_SIGNED_WORD
*((const signed word*) SCREEN + (number~) main::$2) ← (signed word~) main::$0
callprepare next
callexecute next
(signed word~) main::$1 ← callfinalize next
(signed word~) main::$1 ← stackpull(signed word)
(number~) main::$3 ← (number) 1 * (const byte) SIZEOF_SIGNED_WORD
*((const signed word*) SCREEN + (number~) main::$3) ← (signed word~) main::$1
to:main::@return
@ -39,7 +42,8 @@ next: scope:[next] from
to:next::@return
next::@return: scope:[next] from next
(signed word) next::return#1 ← phi( next/(signed word) next::return#0 )
return (signed word) next::return#1
stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#1
return
to:@return
@2: scope:[] from @1
(signed word) current#8 ← phi( @1/(signed word) current#1 )
@ -118,7 +122,6 @@ Simplifying expression containing zero SCREEN in [5] *((const signed word*) SCRE
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (signed word) current#2 and assignment [11] (signed word) current#2 ← ++ (signed word) current#5
Eliminating unused constant (const byte) main::$2
Eliminating unused constant (const byte) next::OFFSET_STACK_RETURN
Eliminating unused constant (const signed word) current#1
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$3 = (byte) 1*(const byte) SIZEOF_SIGNED_WORD
@ -158,11 +161,11 @@ FINAL CONTROL FLOW GRAPH
main: scope:[main] from @1
[4] callprepare next
[5] callexecute next
[6] (signed word~) main::$0 ← callfinalize next
[6] (signed word~) main::$0 ← stackpull(signed word)
[7] *((const signed word*) SCREEN) ← (signed word~) main::$0
[8] callprepare next
[9] callexecute next
[10] (signed word~) main::$1 ← callfinalize next
[10] (signed word~) main::$1 ← stackpull(signed word)
[11] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1
to:main::@return
main::@return: scope:[main] from main
@ -175,7 +178,8 @@ next: scope:[next] from
[14] (signed word) next::return#0 ← (signed word) current#5
to:next::@return
next::@return: scope:[next] from next
[15] return (signed word) next::return#0
[15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0
[16] return
to:@return
@ -183,11 +187,11 @@ VARIABLE REGISTER WEIGHTS
(signed word) current
(signed word) current#5 2.0
(void()) main()
(signed word~) main::$0 2.0
(signed word~) main::$1 2.0
(signed word~) main::$0 4.0
(signed word~) main::$1 4.0
__stackcall (signed word()) next()
(signed word) next::return
(signed word) next::return#0 2.0
(signed word) next::return#0 4.0
Initial phi equivalence classes
[ current#5 ]
@ -241,7 +245,7 @@ main: {
pha
// [5] callexecute next -- jsr
jsr next
// [6] (signed word~) main::$0 ← callfinalize next -- vwsz1=_stackpullsword_
// [6] (signed word~) main::$0 ← stackpull(signed word) -- vwsz1=_stackpullsword_
pla
sta.z __0
pla
@ -256,7 +260,7 @@ main: {
pha
// [9] callexecute next -- jsr
jsr next
// [10] (signed word~) main::$1 ← callfinalize next -- vwsz1=_stackpullsword_
// [10] (signed word~) main::$1 ← stackpull(signed word) -- vwsz1=_stackpullsword_
pla
sta.z __1
pla
@ -274,6 +278,7 @@ main: {
}
// next
next: {
.const OFFSET_STACK_RETURN = 0
.label return = 8
// [14] (signed word) next::return#0 ← (signed word) current#5 -- vwsz1=vwsz2
lda.z current
@ -283,32 +288,32 @@ next: {
jmp __breturn
// next::@return
__breturn:
// [15] return (signed word) next::return#0
// [15] return (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1
// [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1
tsx
lda.z return
sta STACK_BASE+OFFSET_STACK_RETURN,x
lda.z return+1
sta STACK_BASE+OFFSET_STACK_RETURN+1,x
// [16] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] (signed word~) main::$0 ← callfinalize next [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [6] (signed word~) main::$0 ← stackpull(signed word) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
Statement [7] *((const signed word*) SCREEN) ← (signed word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [10] (signed word~) main::$1 ← callfinalize next [ main::$1 ] ( main:2 [ main::$1 ] ) always clobbers reg byte a
Statement [10] (signed word~) main::$1 ← stackpull(signed word) [ main::$1 ] ( main:2 [ main::$1 ] ) always clobbers reg byte a
Statement [11] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [14] (signed word) next::return#0 ← (signed word) current#5 [ next::return#0 ] ( main:2::next:5 [ next::return#0 ] main:2::next:9 [ next::return#0 ] ) always clobbers reg byte a
Statement [15] return (signed word) next::return#0 [ ] ( main:2::next:5 [ ] main:2::next:9 [ ] ) always clobbers reg byte a reg byte x
Statement [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 [ ] ( main:2::next:5 [ ] main:2::next:9 [ ] ) always clobbers reg byte a reg byte x
Potential registers zp[2]:2 [ current#5 ] : zp[2]:2 ,
Potential registers zp[2]:4 [ main::$0 ] : zp[2]:4 ,
Potential registers zp[2]:6 [ main::$1 ] : zp[2]:6 ,
Potential registers zp[2]:8 [ next::return#0 ] : zp[2]:8 ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 2: zp[2]:4 [ main::$0 ] 2: zp[2]:6 [ main::$1 ]
Uplift Scope [next] 2: zp[2]:8 [ next::return#0 ]
Uplift Scope [main] 4: zp[2]:4 [ main::$0 ] 4: zp[2]:6 [ main::$1 ]
Uplift Scope [next] 4: zp[2]:8 [ next::return#0 ]
Uplift Scope [] 2: zp[2]:2 [ current#5 ]
Uplifting [main] best 140 combination zp[2]:4 [ main::$0 ] zp[2]:6 [ main::$1 ]
@ -355,7 +360,7 @@ main: {
pha
// [5] callexecute next -- jsr
jsr next
// [6] (signed word~) main::$0 ← callfinalize next -- vwsz1=_stackpullsword_
// [6] (signed word~) main::$0 ← stackpull(signed word) -- vwsz1=_stackpullsword_
pla
sta.z __0
pla
@ -370,7 +375,7 @@ main: {
pha
// [9] callexecute next -- jsr
jsr next
// [10] (signed word~) main::$1 ← callfinalize next -- vwsz1=_stackpullsword_
// [10] (signed word~) main::$1 ← stackpull(signed word) -- vwsz1=_stackpullsword_
pla
sta.z __1
pla
@ -394,13 +399,13 @@ next: {
jmp __breturn
// next::@return
__breturn:
// [15] return (signed word) next::return#0
// [15] return (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1
// [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1
tsx
lda.z return
sta STACK_BASE+OFFSET_STACK_RETURN,x
lda.z return+1
sta STACK_BASE+OFFSET_STACK_RETURN+1,x
// [16] return
rts
}
// File Data
@ -435,14 +440,14 @@ FINAL SYMBOL TABLE
(signed word) current
(signed word) current#5 current zp[2]:2 2.0
(void()) main()
(signed word~) main::$0 zp[2]:2 2.0
(signed word~) main::$1 zp[2]:4 2.0
(signed word~) main::$0 zp[2]:2 4.0
(signed word~) main::$1 zp[2]:4 4.0
(label) main::@return
__stackcall (signed word()) next()
(label) next::@return
(const byte) next::OFFSET_STACK_RETURN = (byte) 0
(signed word) next::return
(signed word) next::return#0 return zp[2]:2 2.0
(signed word) next::return#0 return zp[2]:2 4.0
zp[2]:2 [ main::$0 current#5 next::return#0 ]
zp[2]:4 [ main::$1 ]
@ -479,7 +484,7 @@ main: {
pha
// [5] callexecute next -- jsr
jsr next
// [6] (signed word~) main::$0 ← callfinalize next -- vwsz1=_stackpullsword_
// [6] (signed word~) main::$0 ← stackpull(signed word) -- vwsz1=_stackpullsword_
pla
sta.z __0
pla
@ -496,7 +501,7 @@ main: {
pha
// [9] callexecute next -- jsr
jsr next
// [10] (signed word~) main::$1 ← callfinalize next -- vwsz1=_stackpullsword_
// [10] (signed word~) main::$1 ← stackpull(signed word) -- vwsz1=_stackpullsword_
pla
sta.z __1
pla
@ -520,13 +525,13 @@ next: {
// [14] (signed word) next::return#0 ← (signed word) current#5
// next::@return
// }
// [15] return (signed word) next::return#0
// [15] return (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1
// [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1
tsx
lda.z return
sta STACK_BASE+OFFSET_STACK_RETURN,x
lda.z return+1
sta STACK_BASE+OFFSET_STACK_RETURN+1,x
// [16] return
rts
}
// File Data

View File

@ -7,14 +7,14 @@
(signed word) current
(signed word) current#5 current zp[2]:2 2.0
(void()) main()
(signed word~) main::$0 zp[2]:2 2.0
(signed word~) main::$1 zp[2]:4 2.0
(signed word~) main::$0 zp[2]:2 4.0
(signed word~) main::$1 zp[2]:4 4.0
(label) main::@return
__stackcall (signed word()) next()
(label) next::@return
(const byte) next::OFFSET_STACK_RETURN = (byte) 0
(signed word) next::return
(signed word) next::return#0 return zp[2]:2 2.0
(signed word) next::return#0 return zp[2]:2 4.0
zp[2]:2 [ main::$0 current#5 next::return#0 ]
zp[2]:4 [ main::$1 ]

View File

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

View File

@ -16,7 +16,6 @@ main: scope:[main] from
(byte) main::val ← *((const byte*) SCREEN)
callprepare printline
callexecute printline
callfinalize printline
*((const byte*) SCREEN + (number) $50) ← (byte) main::val
to:main::@return
main::@return: scope:[main] from main
@ -41,7 +40,6 @@ printline::@return: scope:[printline] from printline::@1
@2: scope:[] from @begin
callprepare main
callexecute main
callfinalize main
to:@end
@end: scope:[] from @2
@ -70,7 +68,7 @@ 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 [9] if((byte) printline::i<(byte) $28) goto printline::@2
Simple Condition (bool~) printline::$0 [8] if((byte) printline::i<(byte) $28) goto printline::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Consolidated array index constant in *(SCREEN+$50)
Successful SSA optimization Pass2ConstantAdditionElimination
@ -78,7 +76,7 @@ Adding NOP phi() at start of @begin
Adding NOP phi() at start of @end
CALL GRAPH
Calls in [] to main:2
Calls in [main] to printline:13
Calls in [main] to printline:12
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
@ -93,43 +91,41 @@ FINAL CONTROL FLOW GRAPH
@1: scope:[] from @begin
[1] callprepare main
[2] callexecute main
[3] callfinalize main
to:@end
@end: scope:[] from @1
[4] phi()
[3] phi()
__stackcall (void()) printline()
printline: scope:[printline] from
[5] (byte) printline::i ← (byte) 0
[4] (byte) printline::i ← (byte) 0
to:printline::@1
printline::@1: scope:[printline] from printline printline::@2
[6] if((byte) printline::i<(byte) $28) goto printline::@2
[5] if((byte) printline::i<(byte) $28) goto printline::@2
to:printline::@return
printline::@return: scope:[printline] from printline::@1
[7] return
[6] return
to:@return
printline::@2: scope:[printline] from printline::@1
[8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*'
[9] (byte) printline::i ← ++ (byte) printline::i
[7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*'
[8] (byte) printline::i ← ++ (byte) printline::i
to:printline::@1
__stackcall (void()) main()
main: scope:[main] from
[10] (byte) main::val ← (byte) 0
[11] (byte) main::val ← *((const byte*) SCREEN)
[12] callprepare printline
[13] callexecute printline
[14] callfinalize printline
[15] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val
[9] (byte) main::val ← (byte) 0
[10] (byte) main::val ← *((const byte*) SCREEN)
[11] callprepare printline
[12] callexecute printline
[13] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val
to:main::@return
main::@return: scope:[main] from main
[16] return
[14] return
to:@return
VARIABLE REGISTER WEIGHTS
__stackcall (void()) main()
(byte) main::val loadstore 1.5
(byte) main::val loadstore 2.0
__stackcall (void()) printline()
(byte) printline::i loadstore 11.5
@ -161,8 +157,7 @@ __b1:
// [1] callprepare main
// [2] callexecute main -- jsr
jsr main
// [3] callfinalize main
// [4] phi from @1 to @end [phi:@1->@end]
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
@ -170,68 +165,67 @@ __bend:
// printline
printline: {
.label i = 2
// [5] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
// [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// printline::@1
__b1:
// [6] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
// [5] 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:
// [7] return
// [6] return
rts
// printline::@2
__b2:
// [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
// [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
lda #'*'
ldy.z i
sta SCREEN,y
// [9] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
// [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
// main
main: {
.label val = 3
// [10] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1
// [9] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z val
// [11] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1
// [10] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1
lda SCREEN
sta.z val
// [12] callprepare printline
// [13] callexecute printline -- jsr
// [11] callprepare printline
// [12] callexecute printline -- jsr
jsr printline
// [14] callfinalize printline
// [15] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1
// [13] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN+$50
jmp __breturn
// main::@return
__breturn:
// [16] return
// [14] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [5] (byte) printline::i ← (byte) 0 [ printline::i ] ( main:2::printline:13 [ main::val printline::i ] ) always clobbers reg byte a
Statement [6] if((byte) printline::i<(byte) $28) goto printline::@2 [ printline::i ] ( main:2::printline:13 [ main::val printline::i ] ) always clobbers reg byte a
Statement [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' [ printline::i ] ( main:2::printline:13 [ main::val printline::i ] ) always clobbers reg byte a reg byte y
Statement [10] (byte) main::val ← (byte) 0 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [11] (byte) main::val ← *((const byte*) SCREEN) [ main::val ] ( main:2 [ main::val ] ) always clobbers reg byte a
Statement [15] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [4] (byte) printline::i ← (byte) 0 [ printline::i ] ( main:2::printline:12 [ main::val printline::i ] ) always clobbers reg byte a
Statement [5] if((byte) printline::i<(byte) $28) goto printline::@2 [ printline::i ] ( main:2::printline:12 [ main::val printline::i ] ) always clobbers reg byte a
Statement [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' [ printline::i ] ( main:2::printline:12 [ main::val printline::i ] ) always clobbers reg byte a reg byte y
Statement [9] (byte) main::val ← (byte) 0 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [10] (byte) main::val ← *((const byte*) SCREEN) [ main::val ] ( main:2 [ main::val ] ) always clobbers reg byte a
Statement [13] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val [ ] ( main:2 [ ] ) 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 [main] 2: zp[1]:3 [ main::val ]
Uplift Scope []
Uplifting [printline] best 372 combination zp[1]:2 [ printline::i ]
@ -260,8 +254,7 @@ __b1:
// [1] callprepare main
// [2] callexecute main -- jsr
jsr main
// [3] callfinalize main
// [4] phi from @1 to @end [phi:@1->@end]
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
@ -269,51 +262,50 @@ __bend:
// printline
printline: {
.label i = 2
// [5] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
// [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// printline::@1
__b1:
// [6] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
// [5] 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:
// [7] return
// [6] return
rts
// printline::@2
__b2:
// [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
// [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
lda #'*'
ldy.z i
sta SCREEN,y
// [9] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
// [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
// main
main: {
.label val = 3
// [10] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1
// [9] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z val
// [11] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1
// [10] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1
lda SCREEN
sta.z val
// [12] callprepare printline
// [13] callexecute printline -- jsr
// [11] callprepare printline
// [12] callexecute printline -- jsr
jsr printline
// [14] callfinalize printline
// [15] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1
// [13] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN+$50
jmp __breturn
// main::@return
__breturn:
// [16] return
// [14] return
rts
}
// File Data
@ -342,7 +334,7 @@ FINAL SYMBOL TABLE
(const byte*) SCREEN = (byte*) 1024
__stackcall (void()) main()
(label) main::@return
(byte) main::val loadstore zp[1]:3 1.5
(byte) main::val loadstore zp[1]:3 2.0
__stackcall (void()) printline()
(label) printline::@1
(label) printline::@2
@ -372,36 +364,35 @@ __bbegin:
// [2] callexecute main -- jsr
jsr main
rts
// [3] callfinalize main
// [4] phi from @1 to @end [phi:@1->@end]
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// printline
printline: {
.label i = 2
// i=0
// [5] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
// [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
// printline::@1
__b1:
// for(char i=0; i<40; i++)
// [6] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
// [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #$28
bcc __b2
// printline::@return
// }
// [7] return
// [6] return
rts
// printline::@2
__b2:
// SCREEN[i] = '*'
// [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
// [7] *((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++)
// [9] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
// [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
@ -409,25 +400,24 @@ printline: {
main: {
.label val = 3
// val
// [10] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1
// [9] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z val
// val = *SCREEN
// [11] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1
// [10] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1
lda SCREEN
sta.z val
// printline()
// [12] callprepare printline
// [13] callexecute printline -- jsr
// [11] callprepare printline
// [12] callexecute printline -- jsr
jsr printline
// [14] callfinalize printline
// SCREEN[80] = val
// [15] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1
// [13] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN+$50
// main::@return
// }
// [16] return
// [14] return
rts
}
// File Data

View File

@ -4,7 +4,7 @@
(const byte*) SCREEN = (byte*) 1024
__stackcall (void()) main()
(label) main::@return
(byte) main::val loadstore zp[1]:3 1.5
(byte) main::val loadstore zp[1]:3 2.0
__stackcall (void()) printline()
(label) printline::@1
(label) printline::@2

View File

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

View File

@ -16,7 +16,6 @@ main: scope:[main] from
(byte) val ← (byte) '-'
callprepare printline
callexecute printline
callfinalize printline
*((const byte*) SCREEN + (number) $50) ← (byte) val
to:main::@return
main::@return: scope:[main] from main
@ -41,7 +40,6 @@ printline::@return: scope:[printline] from printline::@1
@2: scope:[] from @begin
callprepare main
callexecute main
callfinalize main
to:@end
@end: scope:[] from @2
@ -70,14 +68,14 @@ 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 [9] if((byte) printline::i<(byte) $28) goto printline::@2
Simple Condition (bool~) printline::$0 [8] 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 @end
CALL GRAPH
Calls in [] to main:2
Calls in [main] to printline:12
Calls in [main] to printline:11
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
@ -91,36 +89,34 @@ FINAL CONTROL FLOW GRAPH
@1: scope:[] from @begin
[1] callprepare main
[2] callexecute main
[3] callfinalize main
to:@end
@end: scope:[] from @1
[4] phi()
[3] phi()
__stackcall (void()) printline()
printline: scope:[printline] from
[5] (byte) printline::i ← (byte) 0
[4] (byte) printline::i ← (byte) 0
to:printline::@1
printline::@1: scope:[printline] from printline printline::@2
[6] if((byte) printline::i<(byte) $28) goto printline::@2
[5] if((byte) printline::i<(byte) $28) goto printline::@2
to:printline::@return
printline::@return: scope:[printline] from printline::@1
[7] return
[6] return
to:@return
printline::@2: scope:[printline] from printline::@1
[8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*'
[9] (byte) printline::i ← ++ (byte) printline::i
[7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*'
[8] (byte) printline::i ← ++ (byte) printline::i
to:printline::@1
__stackcall (void()) main()
main: scope:[main] from
[10] (byte) val ← (byte) '-'
[11] callprepare printline
[12] callexecute printline
[13] callfinalize printline
[14] *((const byte*) SCREEN+(byte) $50) ← (byte) val
[9] (byte) val ← (byte) '-'
[10] callprepare printline
[11] callexecute printline
[12] *((const byte*) SCREEN+(byte) $50) ← (byte) val
to:main::@return
main::@return: scope:[main] from main
[15] return
[13] return
to:@return
@ -128,7 +124,7 @@ VARIABLE REGISTER WEIGHTS
__stackcall (void()) main()
__stackcall (void()) printline()
(byte) printline::i loadstore 11.5
(byte) val loadstore 1.5
(byte) val loadstore 2.0
Initial phi equivalence classes
Added variable val to live range equivalence class [ val ]
@ -162,8 +158,7 @@ __b1:
// [1] callprepare main
// [2] callexecute main -- jsr
jsr main
// [3] callfinalize main
// [4] phi from @1 to @end [phi:@1->@end]
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
@ -171,64 +166,63 @@ __bend:
// printline
printline: {
.label i = 3
// [5] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
// [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// printline::@1
__b1:
// [6] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
// [5] 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:
// [7] return
// [6] return
rts
// printline::@2
__b2:
// [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
// [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
lda #'*'
ldy.z i
sta SCREEN,y
// [9] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
// [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
// main
main: {
// [10] (byte) val ← (byte) '-' -- vbuz1=vbuc1
// [9] (byte) val ← (byte) '-' -- vbuz1=vbuc1
lda #'-'
sta.z val
// [11] callprepare printline
// [12] callexecute printline -- jsr
// [10] callprepare printline
// [11] callexecute printline -- jsr
jsr printline
// [13] callfinalize printline
// [14] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1
// [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN+$50
jmp __breturn
// main::@return
__breturn:
// [15] return
// [13] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (byte) val ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a
Statement [5] (byte) printline::i ← (byte) 0 [ printline::i ] ( main:2::printline:12 [ val printline::i ] ) always clobbers reg byte a
Statement [6] if((byte) printline::i<(byte) $28) goto printline::@2 [ printline::i ] ( main:2::printline:12 [ val printline::i ] ) always clobbers reg byte a
Statement [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' [ printline::i ] ( main:2::printline:12 [ val printline::i ] ) always clobbers reg byte a reg byte y
Statement [10] (byte) val ← (byte) '-' [ val ] ( main:2 [ val ] ) always clobbers reg byte a
Statement [14] *((const byte*) SCREEN+(byte) $50) ← (byte) val [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [4] (byte) printline::i ← (byte) 0 [ printline::i ] ( main:2::printline:11 [ val printline::i ] ) always clobbers reg byte a
Statement [5] if((byte) printline::i<(byte) $28) goto printline::@2 [ printline::i ] ( main:2::printline:11 [ val printline::i ] ) always clobbers reg byte a
Statement [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' [ printline::i ] ( main:2::printline:11 [ val printline::i ] ) always clobbers reg byte a reg byte y
Statement [9] (byte) val ← (byte) '-' [ val ] ( main:2 [ val ] ) always clobbers reg byte a
Statement [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val [ ] ( main:2 [ ] ) 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 [] 2: zp[1]:2 [ val ]
Uplift Scope [main]
Uplifting [printline] best 343 combination zp[1]:3 [ printline::i ]
@ -261,8 +255,7 @@ __b1:
// [1] callprepare main
// [2] callexecute main -- jsr
jsr main
// [3] callfinalize main
// [4] phi from @1 to @end [phi:@1->@end]
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
@ -270,47 +263,46 @@ __bend:
// printline
printline: {
.label i = 3
// [5] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
// [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// printline::@1
__b1:
// [6] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
// [5] 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:
// [7] return
// [6] return
rts
// printline::@2
__b2:
// [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
// [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
lda #'*'
ldy.z i
sta SCREEN,y
// [9] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
// [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
// main
main: {
// [10] (byte) val ← (byte) '-' -- vbuz1=vbuc1
// [9] (byte) val ← (byte) '-' -- vbuz1=vbuc1
lda #'-'
sta.z val
// [11] callprepare printline
// [12] callexecute printline -- jsr
// [10] callprepare printline
// [11] callexecute printline -- jsr
jsr printline
// [13] callfinalize printline
// [14] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1
// [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN+$50
jmp __breturn
// main::@return
__breturn:
// [15] return
// [13] return
rts
}
// File Data
@ -344,7 +336,7 @@ __stackcall (void()) printline()
(label) printline::@2
(label) printline::@return
(byte) printline::i loadstore zp[1]:3 11.5
(byte) val loadstore zp[1]:2 1.5
(byte) val loadstore zp[1]:2 2.0
zp[1]:2 [ val ]
zp[1]:3 [ printline::i ]
@ -374,57 +366,55 @@ __bbegin:
// [2] callexecute main -- jsr
jsr main
rts
// [3] callfinalize main
// [4] phi from @1 to @end [phi:@1->@end]
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// printline
printline: {
.label i = 3
// i=0
// [5] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
// [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
// printline::@1
__b1:
// for(char i=0; i<40; i++)
// [6] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
// [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #$28
bcc __b2
// printline::@return
// }
// [7] return
// [6] return
rts
// printline::@2
__b2:
// SCREEN[i] = '*'
// [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2
// [7] *((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++)
// [9] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
// [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1
inc.z i
jmp __b1
}
// main
main: {
// val = '-'
// [10] (byte) val ← (byte) '-' -- vbuz1=vbuc1
// [9] (byte) val ← (byte) '-' -- vbuz1=vbuc1
lda #'-'
sta.z val
// printline()
// [11] callprepare printline
// [12] callexecute printline -- jsr
// [10] callprepare printline
// [11] callexecute printline -- jsr
jsr printline
// [13] callfinalize printline
// SCREEN[80] = val
// [14] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1
// [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN+$50
// main::@return
// }
// [15] return
// [13] return
rts
}
// File Data

View File

@ -9,7 +9,7 @@ __stackcall (void()) printline()
(label) printline::@2
(label) printline::@return
(byte) printline::i loadstore zp[1]:3 11.5
(byte) val loadstore zp[1]:2 1.5
(byte) val loadstore zp[1]:2 2.0
zp[1]:2 [ val ]
zp[1]:3 [ printline::i ]

View File

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

View File

@ -24,13 +24,10 @@ main: scope:[main] from
main::@1: scope:[main] from main main::@1
callprepare pval
callexecute pval
callfinalize pval
callprepare printother
callexecute printother
callfinalize printother
callprepare ival
callexecute ival
callfinalize 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
@ -43,7 +40,6 @@ __stackcall (void()) pval()
pval: scope:[pval] from
callprepare printval
callexecute printval
callfinalize printval
to:pval::@return
pval::@return: scope:[pval] from pval
return
@ -53,7 +49,6 @@ __stackcall (void()) ival()
ival: scope:[ival] from
callprepare incval
callexecute incval
callfinalize incval
to:ival::@return
ival::@return: scope:[ival] from ival
return
@ -91,7 +86,6 @@ printother::@return: scope:[printother] from printother::@1
@6: scope:[] from @begin
callprepare main
callexecute main
callfinalize main
to:@end
@end: scope:[] from @6
@ -130,14 +124,14 @@ 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 [13] if((byte) main::i!=rangelast(0,5)) goto main::@1
Simple Condition (bool~) printother::$1 [31] if((byte) printother::i!=rangelast(0,5)) goto printother::@1
Simple Condition (bool~) main::$3 [10] if((byte) main::i!=rangelast(0,5)) goto main::@1
Simple Condition (bool~) printother::$1 [26] if((byte) printother::i!=rangelast(0,5)) goto printother::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Resolved ranged next value [11] main::i ← ++ main::i to ++
Resolved ranged comparison value [13] if(main::i!=rangelast(0,5)) goto main::@1 to (number) 6
Resolved ranged next value [29] printother::i ← ++ printother::i to ++
Resolved ranged comparison value [31] if(printother::i!=rangelast(0,5)) goto printother::@1 to (number) 6
Simplifying expression containing zero SCREEN in [23] *((const byte*) SCREEN + (byte) 0) ← (byte) val
Resolved ranged next value [8] main::i ← ++ main::i to ++
Resolved ranged comparison value [10] if(main::i!=rangelast(0,5)) goto main::@1 to (number) 6
Resolved ranged next value [24] printother::i ← ++ printother::i to ++
Resolved ranged comparison value [26] if(printother::i!=rangelast(0,5)) goto printother::@1 to (number) 6
Simplifying expression containing zero SCREEN in [18] *((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
@ -151,9 +145,9 @@ Successful SSA optimization PassNFinalizeNumberTypeConversions
Adding NOP phi() at start of @end
CALL GRAPH
Calls in [] to main:2
Calls in [ival] to incval:15
Calls in [pval] to printval:19
Calls in [main] to pval:24 printother:27 ival:30
Calls in [ival] to incval:14
Calls in [pval] to printval:17
Calls in [main] to pval:21 printother:23 ival:25
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
@ -167,79 +161,73 @@ FINAL CONTROL FLOW GRAPH
@1: scope:[] from @begin
[1] callprepare main
[2] callexecute main
[3] callfinalize main
to:@end
@end: scope:[] from @1
[4] phi()
[3] phi()
__stackcall (void()) printother()
printother: scope:[printother] from
[5] (byte) printother::i ← (byte) 0
[4] (byte) printother::i ← (byte) 0
to:printother::@1
printother::@1: scope:[printother] from printother printother::@1
[6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i)
[7] (byte) printother::i ← ++ (byte) printother::i
[8] if((byte) printother::i!=(byte) 6) goto printother::@1
[5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i)
[6] (byte) printother::i ← ++ (byte) printother::i
[7] if((byte) printother::i!=(byte) 6) goto printother::@1
to:printother::@return
printother::@return: scope:[printother] from printother::@1
[9] return
[8] return
to:@return
__stackcall (void()) incval()
incval: scope:[incval] from
[10] (byte) val ← ++ (byte) val
[9] (byte) val ← ++ (byte) val
to:incval::@return
incval::@return: scope:[incval] from incval
[11] return
[10] return
to:@return
__stackcall (void()) printval()
printval: scope:[printval] from
[12] *((const byte*) SCREEN) ← (byte) val
[11] *((const byte*) SCREEN) ← (byte) val
to:printval::@return
printval::@return: scope:[printval] from printval
[13] return
[12] return
to:@return
__stackcall (void()) ival()
ival: scope:[ival] from
[14] callprepare incval
[15] callexecute incval
[16] callfinalize incval
[13] callprepare incval
[14] callexecute incval
to:ival::@return
ival::@return: scope:[ival] from ival
[17] return
[15] return
to:@return
__stackcall (void()) pval()
pval: scope:[pval] from
[18] callprepare printval
[19] callexecute printval
[20] callfinalize printval
[16] callprepare printval
[17] callexecute printval
to:pval::@return
pval::@return: scope:[pval] from pval
[21] return
[18] return
to:@return
__stackcall (void()) main()
main: scope:[main] from
[22] (byte) main::i ← (byte) 0
[19] (byte) main::i ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@1
[23] callprepare pval
[24] callexecute pval
[25] callfinalize pval
[26] callprepare printother
[27] callexecute printother
[28] callfinalize printother
[29] callprepare ival
[30] callexecute ival
[31] callfinalize ival
[32] (byte) main::i ← ++ (byte) main::i
[33] if((byte) main::i!=(byte) 6) goto main::@1
[20] callprepare pval
[21] callexecute pval
[22] callprepare printother
[23] callexecute printother
[24] callprepare ival
[25] callexecute ival
[26] (byte) main::i ← ++ (byte) main::i
[27] if((byte) main::i!=(byte) 6) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[34] return
[28] return
to:@return
null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope printother
@ -252,12 +240,12 @@ VARIABLE REGISTER WEIGHTS
__stackcall (void()) incval()
__stackcall (void()) ival()
__stackcall (void()) main()
(byte) main::i loadstore 2.9166666666666665
(byte) main::i loadstore 3.8888888888888893
__stackcall (void()) printother()
(byte) printother::i loadstore 14.25
__stackcall (void()) printval()
__stackcall (void()) pval()
(byte) val loadstore 0.3076923076923077
(byte) val loadstore 0.38095238095238093
Initial phi equivalence classes
Added variable val to live range equivalence class [ val ]
@ -294,8 +282,7 @@ __b1:
// [1] callprepare main
// [2] callexecute main -- jsr
jsr main
// [3] callfinalize main
// [4] phi from @1 to @end [phi:@1->@end]
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
@ -303,123 +290,118 @@ __bend:
// printother
printother: {
.label i = 3
// [5] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1
// [4] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// printother::@1
__b1:
// [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1
// [5] *((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
// [7] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1
// [6] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1
inc.z i
// [8] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1
// [7] 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:
// [9] return
// [8] return
rts
}
// incval
incval: {
// [10] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1
// [9] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1
inc.z val
jmp __breturn
// incval::@return
__breturn:
// [11] return
// [10] return
rts
}
// printval
printval: {
// [12] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1
// [11] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN
jmp __breturn
// printval::@return
__breturn:
// [13] return
// [12] return
rts
}
// ival
ival: {
// [14] callprepare incval
// [15] callexecute incval -- jsr
// [13] callprepare incval
// [14] callexecute incval -- jsr
jsr incval
// [16] callfinalize incval
jmp __breturn
// ival::@return
__breturn:
// [17] return
// [15] return
rts
}
// pval
pval: {
// [18] callprepare printval
// [19] callexecute printval -- jsr
// [16] callprepare printval
// [17] callexecute printval -- jsr
jsr printval
// [20] callfinalize printval
jmp __breturn
// pval::@return
__breturn:
// [21] return
// [18] return
rts
}
// main
main: {
.label i = 4
// [22] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
// [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// main::@1
__b1:
// [23] callprepare pval
// [24] callexecute pval -- jsr
// [20] callprepare pval
// [21] callexecute pval -- jsr
jsr pval
// [25] callfinalize pval
// [26] callprepare printother
// [27] callexecute printother -- jsr
// [22] callprepare printother
// [23] callexecute printother -- jsr
jsr printother
// [28] callfinalize printother
// [29] callprepare ival
// [30] callexecute ival -- jsr
// [24] callprepare ival
// [25] callexecute ival -- jsr
jsr ival
// [31] callfinalize ival
// [32] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
// [26] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
inc.z i
// [33] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
// [27] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #6
cmp.z i
bne __b1
jmp __breturn
// main::@return
__breturn:
// [34] return
// [28] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (byte) val ← (byte) 0 [ val ] ( [ val ] ) always clobbers reg byte a
Statement [5] (byte) printother::i ← (byte) 0 [ printother::i ] ( main:2::printother:27 [ val main::i printother::i ] ) always clobbers reg byte a
Statement [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) [ printother::i ] ( main:2::printother:27 [ val main::i printother::i ] ) always clobbers reg byte x
Statement [8] if((byte) printother::i!=(byte) 6) goto printother::@1 [ printother::i ] ( main:2::printother:27 [ val main::i printother::i ] ) always clobbers reg byte a
Statement [12] *((const byte*) SCREEN) ← (byte) val [ val ] ( main:2::pval:24::printval:19 [ main::i val ] ) always clobbers reg byte a
Statement [22] (byte) main::i ← (byte) 0 [ val main::i ] ( main:2 [ val main::i ] ) always clobbers reg byte a
Statement [33] if((byte) main::i!=(byte) 6) goto main::@1 [ val main::i ] ( main:2 [ val main::i ] ) always clobbers reg byte a
Statement [4] (byte) printother::i ← (byte) 0 [ printother::i ] ( main:2::printother:23 [ val main::i printother::i ] ) always clobbers reg byte a
Statement [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) [ printother::i ] ( main:2::printother:23 [ val main::i printother::i ] ) always clobbers reg byte x
Statement [7] if((byte) printother::i!=(byte) 6) goto printother::@1 [ printother::i ] ( main:2::printother:23 [ val main::i printother::i ] ) always clobbers reg byte a
Statement [11] *((const byte*) SCREEN) ← (byte) val [ val ] ( main:2::pval:21::printval:17 [ main::i val ] ) always clobbers reg byte a
Statement [19] (byte) main::i ← (byte) 0 [ val main::i ] ( main:2 [ val main::i ] ) always clobbers reg byte a
Statement [27] if((byte) main::i!=(byte) 6) goto main::@1 [ val main::i ] ( main:2 [ val 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.92: zp[1]:4 [ main::i ]
Uplift Scope [] 0.31: zp[1]:2 [ val ]
Uplift Scope [main] 3.89: zp[1]:4 [ main::i ]
Uplift Scope [] 0.38: zp[1]:2 [ val ]
Uplift Scope [pval]
Uplift Scope [ival]
Uplift Scope [printval]
@ -461,8 +443,7 @@ __b1:
// [1] callprepare main
// [2] callexecute main -- jsr
jsr main
// [3] callfinalize main
// [4] phi from @1 to @end [phi:@1->@end]
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
@ -470,103 +451,98 @@ __bend:
// printother
printother: {
.label i = 3
// [5] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1
// [4] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// printother::@1
__b1:
// [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1
// [5] *((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
// [7] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1
// [6] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1
inc.z i
// [8] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1
// [7] 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:
// [9] return
// [8] return
rts
}
// incval
incval: {
// [10] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1
// [9] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1
inc.z val
jmp __breturn
// incval::@return
__breturn:
// [11] return
// [10] return
rts
}
// printval
printval: {
// [12] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1
// [11] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN
jmp __breturn
// printval::@return
__breturn:
// [13] return
// [12] return
rts
}
// ival
ival: {
// [14] callprepare incval
// [15] callexecute incval -- jsr
// [13] callprepare incval
// [14] callexecute incval -- jsr
jsr incval
// [16] callfinalize incval
jmp __breturn
// ival::@return
__breturn:
// [17] return
// [15] return
rts
}
// pval
pval: {
// [18] callprepare printval
// [19] callexecute printval -- jsr
// [16] callprepare printval
// [17] callexecute printval -- jsr
jsr printval
// [20] callfinalize printval
jmp __breturn
// pval::@return
__breturn:
// [21] return
// [18] return
rts
}
// main
main: {
.label i = 4
// [22] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
// [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// main::@1
__b1:
// [23] callprepare pval
// [24] callexecute pval -- jsr
// [20] callprepare pval
// [21] callexecute pval -- jsr
jsr pval
// [25] callfinalize pval
// [26] callprepare printother
// [27] callexecute printother -- jsr
// [22] callprepare printother
// [23] callexecute printother -- jsr
jsr printother
// [28] callfinalize printother
// [29] callprepare ival
// [30] callexecute ival -- jsr
// [24] callprepare ival
// [25] callexecute ival -- jsr
jsr ival
// [31] callfinalize ival
// [32] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
// [26] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
inc.z i
// [33] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
// [27] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #6
cmp.z i
bne __b1
jmp __breturn
// main::@return
__breturn:
// [34] return
// [28] return
rts
}
// File Data
@ -609,7 +585,7 @@ __stackcall (void()) ival()
__stackcall (void()) main()
(label) main::@1
(label) main::@return
(byte) main::i loadstore zp[1]:4 2.9166666666666665
(byte) main::i loadstore zp[1]:4 3.8888888888888893
__stackcall (void()) printother()
(label) printother::@1
(label) printother::@return
@ -618,7 +594,7 @@ __stackcall (void()) printval()
(label) printval::@return
__stackcall (void()) pval()
(label) pval::@return
(byte) val loadstore zp[1]:2 0.3076923076923077
(byte) val loadstore zp[1]:2 0.38095238095238093
zp[1]:2 [ val ]
zp[1]:3 [ printother::i ]
@ -649,113 +625,107 @@ __bbegin:
// [2] callexecute main -- jsr
jsr main
rts
// [3] callfinalize main
// [4] phi from @1 to @end [phi:@1->@end]
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// printother
printother: {
.label i = 3
// for(char i:0..5)
// [5] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1
// [4] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
// printother::@1
__b1:
// (SCREEN+40)[i]++;
// [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1
// [5] *((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)
// [7] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1
// [6] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1
inc.z i
// [8] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1
// [7] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1
lda #6
cmp.z i
bne __b1
// printother::@return
// }
// [9] return
// [8] return
rts
}
// incval
incval: {
// val++;
// [10] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1
// [9] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1
inc.z val
// incval::@return
// }
// [11] return
// [10] return
rts
}
// printval
printval: {
// SCREEN[0] = val
// [12] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1
// [11] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1
lda.z val
sta SCREEN
// printval::@return
// }
// [13] return
// [12] return
rts
}
// ival
ival: {
// incval()
// [14] callprepare incval
// [15] callexecute incval -- jsr
// [13] callprepare incval
// [14] callexecute incval -- jsr
jsr incval
// [16] callfinalize incval
// ival::@return
// }
// [17] return
// [15] return
rts
}
// pval
pval: {
// printval()
// [18] callprepare printval
// [19] callexecute printval -- jsr
// [16] callprepare printval
// [17] callexecute printval -- jsr
jsr printval
// [20] callfinalize printval
// pval::@return
// }
// [21] return
// [18] return
rts
}
// main
main: {
.label i = 4
// for(char i:0..5)
// [22] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
// [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z i
// main::@1
__b1:
// pval()
// [23] callprepare pval
// [24] callexecute pval -- jsr
// [20] callprepare pval
// [21] callexecute pval -- jsr
jsr pval
// [25] callfinalize pval
// printother()
// [26] callprepare printother
// [27] callexecute printother -- jsr
// [22] callprepare printother
// [23] callexecute printother -- jsr
jsr printother
// [28] callfinalize printother
// ival()
// [29] callprepare ival
// [30] callexecute ival -- jsr
// [24] callprepare ival
// [25] callexecute ival -- jsr
jsr ival
// [31] callfinalize ival
// for(char i:0..5)
// [32] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
// [26] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1
inc.z i
// [33] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
// [27] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #6
cmp.z i
bne __b1
// main::@return
// }
// [34] return
// [28] return
rts
}
// File Data

View File

@ -9,7 +9,7 @@ __stackcall (void()) ival()
__stackcall (void()) main()
(label) main::@1
(label) main::@return
(byte) main::i loadstore zp[1]:4 2.9166666666666665
(byte) main::i loadstore zp[1]:4 3.8888888888888893
__stackcall (void()) printother()
(label) printother::@1
(label) printother::@return
@ -18,7 +18,7 @@ __stackcall (void()) printval()
(label) printval::@return
__stackcall (void()) pval()
(label) pval::@return
(byte) val loadstore zp[1]:2 0.3076923076923077
(byte) val loadstore zp[1]:2 0.38095238095238093
zp[1]:2 [ val ]
zp[1]:3 [ printother::i ]