1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-02 00:41:42 +00:00

Added static register value analysis - eliminating uncecasary loads.

This commit is contained in:
jespergravgaard 2017-05-30 11:09:39 +02:00
parent b7fd96c4ee
commit 2a2d873e62
5 changed files with 284 additions and 6 deletions

View File

@ -2,6 +2,6 @@ lda {zpptrby1}
clc
adc #{coby1}
sta {zpptrby1}
bcs !+
bcc !+
inc {zpptrby1}+1
!:

View File

@ -0,0 +1,182 @@
package dk.camelot64.kickc.asm.parser;
import dk.camelot64.kickc.asm.*;
import java.util.HashMap;
import java.util.Map;
/**
* Perform static analysis of an ASM program infering information about the values of registers entering each instruction
*/
public class AsmProgramStaticRegisterValues {
private AsmProgram program;
private Map<AsmInstruction, AsmRegisterValues> values;
public AsmProgramStaticRegisterValues(AsmProgram program) {
this.program = program;
this.values = new HashMap<>();
initValues();
}
public AsmRegisterValues getValues(AsmInstruction instruction) {
return values.get(instruction);
}
private void initValues() {
AsmRegisterValues current = new AsmRegisterValues();
for (AsmLine line : program.getLines()) {
if (line instanceof AsmLabel) {
current = new AsmRegisterValues();
} else if (line instanceof AsmInstruction) {
AsmInstruction instruction = (AsmInstruction) line;
values.put(instruction, current);
current = new AsmRegisterValues(current);
AsmInstructionType instructionType = instruction.getType();
AsmClobber clobber = instructionType.getClobber();
if (clobber.isClobberA()) {
current.setA(null);
}
if (clobber.isClobberX()) {
current.setX(null);
}
if (clobber.isClobberY()) {
current.setY(null);
}
if (clobber.isClobberC()) {
current.setC(null);
}
if (clobber.isClobberN()) {
current.setN(null);
}
if (clobber.isClobberV()) {
current.setV(null);
}
if (clobber.isClobberZ()) {
current.setZ(null);
}
if (instructionType.getMnemnonic().equals("lda") && instructionType.getAddressingMode().equals(AsmAddressingMode.IMM)) {
try {
int immValue = Integer.parseInt(instruction.getParameter());
current.setZ(immValue == 0);
current.setN(immValue > 127);
current.setA(immValue);
} catch (NumberFormatException e) {
// ignore
}
}
if (instructionType.getMnemnonic().equals("ldx") && instructionType.getAddressingMode().equals(AsmAddressingMode.IMM)) {
try {
int immValue = Integer.parseInt(instruction.getParameter());
current.setZ(immValue == 0);
current.setN(immValue > 127);
current.setX(immValue);
} catch (NumberFormatException e) {
// ignore
}
}
if (instructionType.getMnemnonic().equals("ldy") && instructionType.getAddressingMode().equals(AsmAddressingMode.IMM)) {
try {
int immValue = Integer.parseInt(instruction.getParameter());
current.setZ(immValue == 0);
current.setN(immValue > 127);
current.setY(immValue);
} catch (NumberFormatException e) {
// ignore
}
}
if (instructionType.getMnemnonic().equals("sec")) {
current.setC(Boolean.TRUE);
}
if (instructionType.getMnemnonic().equals("clc")) {
current.setC(Boolean.FALSE);
}
}
}
}
/**
* Known values of registers/flags at an instruction. null where value is unknown.
*/
public static class AsmRegisterValues {
private Integer a;
private Integer x;
private Integer y;
private Boolean c;
private Boolean v;
private Boolean n;
private Boolean z;
public AsmRegisterValues() {
}
public AsmRegisterValues(AsmRegisterValues original) {
this.a = original.getA();
this.x = original.getX();
this.y = original.getY();
this.c = original.getC();
this.v = original.getV();
this.n = original.getN();
this.z = original.getZ();
}
public Integer getA() {
return a;
}
public Integer getX() {
return x;
}
public Integer getY() {
return y;
}
public Boolean getC() {
return c;
}
public Boolean getV() {
return v;
}
public Boolean getN() {
return n;
}
public Boolean getZ() {
return z;
}
public void setA(Integer a) {
this.a = a;
}
public void setX(Integer x) {
this.x = x;
}
public void setY(Integer y) {
this.y = y;
}
public void setC(Boolean c) {
this.c = c;
}
public void setV(Boolean v) {
this.v = v;
}
public void setN(Boolean n) {
this.n = n;
}
public void setZ(Boolean z) {
this.z = z;
}
}
}

View File

@ -9,7 +9,7 @@ import java.util.List;
/** Optimization performed on Assembler Code (Asm Code).
* Optimizations are performed repeatedly until none of them yield any result
**/
public class Pass4AsmOptimization {
public abstract class Pass4AsmOptimization {
private AsmProgram program;
@ -17,6 +17,13 @@ public class Pass4AsmOptimization {
this.program = program;
}
/**
* Attempt to perform optimization.
*
* @return true if an optimization was performed. false if no optimization was possible.
*/
public abstract boolean optimize();
public AsmProgram getProgram() {
return program;
}

View File

@ -0,0 +1,75 @@
package dk.camelot64.kickc.icl;
import dk.camelot64.kickc.asm.*;
import dk.camelot64.kickc.asm.parser.AsmProgramStaticRegisterValues;
import java.util.ArrayList;
import java.util.List;
/** Maps out register values entering all instructions. Removes unnecessary loads / clears / sets */
public class Pass4UnnecesaryLoadElimination extends Pass4AsmOptimization {
public Pass4UnnecesaryLoadElimination(AsmProgram program) {
super(program);
}
@Override
public boolean optimize() {
AsmProgramStaticRegisterValues staticValues = new AsmProgramStaticRegisterValues(getProgram());
List<AsmLine> removes = new ArrayList<>();
for (AsmLine line : getProgram().getLines()) {
if(line instanceof AsmInstruction) {
AsmInstruction instruction = (AsmInstruction) line;
AsmInstructionType instructionType = instruction.getType();
if(instructionType.getMnemnonic().equals("lda") && instructionType.getAddressingMode().equals(AsmAddressingMode.IMM)) {
try {
int immValue = Integer.parseInt(instruction.getParameter());
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if (instructionValues.getA() != null && instructionValues.getA().equals(immValue)) {
removes.add(instruction);
}
} catch (NumberFormatException e) {
// ignore
}
}
if(instructionType.getMnemnonic().equals("ldx") && instructionType.getAddressingMode().equals(AsmAddressingMode.IMM)) {
try {
int immValue = Integer.parseInt(instruction.getParameter());
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if(instructionValues.getX()!=null && instructionValues.getX().equals(immValue)) {
removes.add(instruction);
}
} catch (NumberFormatException e) {
// ignore
}
}
if(instructionType.getMnemnonic().equals("ldy") && instructionType.getAddressingMode().equals(AsmAddressingMode.IMM)) {
try {
int immValue = Integer.parseInt(instruction.getParameter());
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if(instructionValues.getY()!=null && instructionValues.getY().equals(immValue)) {
removes.add(instruction);
}
} catch (NumberFormatException e) {
// ignore
}
}
if(instructionType.getMnemnonic().equals("clc")) {
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if(Boolean.FALSE.equals(instructionValues.getC())) {
removes.add(instruction);
}
}
if(instructionType.getMnemnonic().equals("sec")) {
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if(Boolean.TRUE.equals(instructionValues.getC())) {
removes.add(instruction);
}
}
}
}
remove(removes);
return removes.size()>0;
}
}

View File

@ -13,7 +13,7 @@ import java.util.List;
/** Test my KickC Grammar */
public class Main {
public static void main(String[] args) throws IOException {
final String fileName = "src/dk/camelot64/kickc/test/bresenhamarr.kc";
final String fileName = "src/dk/camelot64/kickc/test/bresenham.kc";
final CharStream input = CharStreams.fromFileName(fileName);
System.out.println(input.toString());
KickCLexer lexer = new KickCLexer(input);
@ -59,7 +59,7 @@ public class Main {
for (Pass2SsaOptimization optimization : optimizations) {
boolean stepOptimized = optimization.optimize();
if (stepOptimized) {
System.out.println("Succesful optimization "+optimization);
System.out.println("Succesful SSA optimization "+optimization);
ssaOptimized = true;
System.out.println("CONTROL FLOW GRAPH");
System.out.println(controlFlowGraph.toString());
@ -72,10 +72,24 @@ public class Main {
Pass3CodeGeneration pass3CodeGeneration = new Pass3CodeGeneration(controlFlowGraph, symbolTable);
AsmProgram asmProgram = pass3CodeGeneration.generate();
Pass4NextJumpElimination pass5NextJumpElimination = new Pass4NextJumpElimination(asmProgram);
System.out.println("INITIAL ASM");
System.out.println(asmProgram.toString());
List<Pass4AsmOptimization> pass4Optimizations = new ArrayList<>();
pass4Optimizations.add(new Pass4NextJumpElimination(asmProgram));
pass4Optimizations.add(new Pass4UnnecesaryLoadElimination(asmProgram));
boolean asmOptimized = true;
while(asmOptimized) {
asmOptimized = pass5NextJumpElimination.optimize();
asmOptimized = false;
for (Pass4AsmOptimization optimization : pass4Optimizations) {
boolean stepOtimized = optimization.optimize();
if(stepOtimized) {
System.out.println("Succesful ASM optimization "+optimization);
asmOptimized = true;
System.out.println("ASSEMBLER");
System.out.println(asmProgram.toString());
}
}
}
System.out.println("SYMBOLS");