mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Improve GVN to evaluate constants
This commit is contained in:
parent
ea9605e518
commit
7b31def2b4
|
@ -28,6 +28,9 @@ public class GlobalValueNumbering implements MethodOptimization {
|
||||||
private Map<String, KnownValue> knownValues = new HashMap<>();
|
private Map<String, KnownValue> knownValues = new HashMap<>();
|
||||||
private boolean eliminate;
|
private boolean eliminate;
|
||||||
private int[] map;
|
private int[] map;
|
||||||
|
private Number[] numericConstants;
|
||||||
|
private Number evaluatedConstant;
|
||||||
|
private int receiver;
|
||||||
private Program program;
|
private Program program;
|
||||||
private int currentBlockIndex;
|
private int currentBlockIndex;
|
||||||
private DominatorTree domTree;
|
private DominatorTree domTree;
|
||||||
|
@ -46,6 +49,7 @@ public class GlobalValueNumbering implements MethodOptimization {
|
||||||
domTree = GraphUtils.buildDominatorTree(cfg);
|
domTree = GraphUtils.buildDominatorTree(cfg);
|
||||||
Graph dom = GraphUtils.buildDominatorGraph(domTree, cfg.size());
|
Graph dom = GraphUtils.buildDominatorGraph(domTree, cfg.size());
|
||||||
map = new int[program.variableCount()];
|
map = new int[program.variableCount()];
|
||||||
|
numericConstants = new Number[program.variableCount()];
|
||||||
for (int i = 0; i < map.length; ++i) {
|
for (int i = 0; i < map.length; ++i) {
|
||||||
map[i] = i;
|
map[i] = i;
|
||||||
}
|
}
|
||||||
|
@ -86,12 +90,35 @@ public class GlobalValueNumbering implements MethodOptimization {
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
for (int i = 0; i < block.getInstructions().size(); ++i) {
|
for (int i = 0; i < block.getInstructions().size(); ++i) {
|
||||||
|
evaluatedConstant = null;
|
||||||
Instruction currentInsn = block.getInstructions().get(i);
|
Instruction currentInsn = block.getInstructions().get(i);
|
||||||
currentInsn.acceptVisitor(optimizer);
|
currentInsn.acceptVisitor(optimizer);
|
||||||
if (eliminate) {
|
if (eliminate) {
|
||||||
affected = true;
|
affected = true;
|
||||||
block.getInstructions().set(i, new EmptyInstruction());
|
block.getInstructions().set(i, new EmptyInstruction());
|
||||||
eliminate = false;
|
eliminate = false;
|
||||||
|
} else if (evaluatedConstant != null) {
|
||||||
|
if (evaluatedConstant instanceof Integer) {
|
||||||
|
IntegerConstantInstruction newInsn = new IntegerConstantInstruction();
|
||||||
|
newInsn.setConstant((Integer) evaluatedConstant);
|
||||||
|
newInsn.setReceiver(program.variableAt(receiver));
|
||||||
|
block.getInstructions().set(i, newInsn);
|
||||||
|
} else if (evaluatedConstant instanceof Long) {
|
||||||
|
LongConstantInstruction newInsn = new LongConstantInstruction();
|
||||||
|
newInsn.setConstant((Long) evaluatedConstant);
|
||||||
|
newInsn.setReceiver(program.variableAt(receiver));
|
||||||
|
block.getInstructions().set(i, newInsn);
|
||||||
|
} else if (evaluatedConstant instanceof Float) {
|
||||||
|
FloatConstantInstruction newInsn = new FloatConstantInstruction();
|
||||||
|
newInsn.setConstant((Float) evaluatedConstant);
|
||||||
|
newInsn.setReceiver(program.variableAt(receiver));
|
||||||
|
block.getInstructions().set(i, newInsn);
|
||||||
|
} else if (evaluatedConstant instanceof Double) {
|
||||||
|
DoubleConstantInstruction newInsn = new DoubleConstantInstruction();
|
||||||
|
newInsn.setConstant((Double) evaluatedConstant);
|
||||||
|
newInsn.setReceiver(program.variableAt(receiver));
|
||||||
|
block.getInstructions().set(i, newInsn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (TryCatchJoint joint : outputJoints.get(v)) {
|
for (TryCatchJoint joint : outputJoints.get(v)) {
|
||||||
|
@ -157,18 +184,22 @@ public class GlobalValueNumbering implements MethodOptimization {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IntegerConstantInstruction insn) {
|
public void visit(IntegerConstantInstruction insn) {
|
||||||
|
numericConstants[insn.getReceiver().getIndex()] = insn.getConstant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(LongConstantInstruction insn) {
|
public void visit(LongConstantInstruction insn) {
|
||||||
|
numericConstants[insn.getReceiver().getIndex()] = insn.getConstant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(FloatConstantInstruction insn) {
|
public void visit(FloatConstantInstruction insn) {
|
||||||
|
numericConstants[insn.getReceiver().getIndex()] = insn.getConstant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(DoubleConstantInstruction insn) {
|
public void visit(DoubleConstantInstruction insn) {
|
||||||
|
numericConstants[insn.getReceiver().getIndex()] = insn.getConstant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -232,6 +263,189 @@ public class GlobalValueNumbering implements MethodOptimization {
|
||||||
if (commutative) {
|
if (commutative) {
|
||||||
bind(insn.getReceiver().getIndex(), "@" + b + value + "@" + a);
|
bind(insn.getReceiver().getIndex(), "@" + b + value + "@" + a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
evaluateBinary(insn.getOperation(), insn.getOperandType(), a, b);
|
||||||
|
if (evaluatedConstant != null) {
|
||||||
|
numericConstants[insn.getReceiver().getIndex()] = evaluatedConstant;
|
||||||
|
}
|
||||||
|
receiver = insn.getReceiver().getIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void evaluateBinary(BinaryOperation operation, NumericOperandType type, int a, int b) {
|
||||||
|
Number first = numericConstants[a];
|
||||||
|
Number second = numericConstants[b];
|
||||||
|
if (first == null || second == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case INT: {
|
||||||
|
int p = first.intValue();
|
||||||
|
int q = second.intValue();
|
||||||
|
switch (operation) {
|
||||||
|
case ADD:
|
||||||
|
evaluatedConstant = p + q;
|
||||||
|
break;
|
||||||
|
case SUBTRACT:
|
||||||
|
evaluatedConstant = p - q;
|
||||||
|
break;
|
||||||
|
case MULTIPLY:
|
||||||
|
evaluatedConstant = p * q;
|
||||||
|
break;
|
||||||
|
case DIVIDE:
|
||||||
|
if (q != 0) {
|
||||||
|
evaluatedConstant = p / q;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODULO:
|
||||||
|
if (q != 0) {
|
||||||
|
evaluatedConstant = p % q;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COMPARE:
|
||||||
|
evaluatedConstant = Integer.compare(p, q);
|
||||||
|
break;
|
||||||
|
case AND:
|
||||||
|
evaluatedConstant = p & q;
|
||||||
|
break;
|
||||||
|
case OR:
|
||||||
|
evaluatedConstant = p | q;
|
||||||
|
break;
|
||||||
|
case XOR:
|
||||||
|
evaluatedConstant = p ^ q;
|
||||||
|
break;
|
||||||
|
case SHIFT_LEFT:
|
||||||
|
evaluatedConstant = p << q;
|
||||||
|
break;
|
||||||
|
case SHIFT_RIGHT:
|
||||||
|
evaluatedConstant = p >> q;
|
||||||
|
break;
|
||||||
|
case SHIFT_RIGHT_UNSIGNED:
|
||||||
|
evaluatedConstant = p >>> q;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LONG: {
|
||||||
|
long p = first.longValue();
|
||||||
|
long q = second.longValue();
|
||||||
|
switch (operation) {
|
||||||
|
case ADD:
|
||||||
|
evaluatedConstant = p + q;
|
||||||
|
break;
|
||||||
|
case SUBTRACT:
|
||||||
|
evaluatedConstant = p - q;
|
||||||
|
break;
|
||||||
|
case MULTIPLY:
|
||||||
|
evaluatedConstant = p * q;
|
||||||
|
break;
|
||||||
|
case DIVIDE:
|
||||||
|
if (q != 0) {
|
||||||
|
evaluatedConstant = p / q;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODULO:
|
||||||
|
if (q != 0) {
|
||||||
|
evaluatedConstant = p % q;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COMPARE:
|
||||||
|
evaluatedConstant = Long.compare(p, q);
|
||||||
|
break;
|
||||||
|
case AND:
|
||||||
|
evaluatedConstant = p & q;
|
||||||
|
break;
|
||||||
|
case OR:
|
||||||
|
evaluatedConstant = p | q;
|
||||||
|
break;
|
||||||
|
case XOR:
|
||||||
|
evaluatedConstant = p ^ q;
|
||||||
|
break;
|
||||||
|
case SHIFT_LEFT:
|
||||||
|
evaluatedConstant = p << q;
|
||||||
|
break;
|
||||||
|
case SHIFT_RIGHT:
|
||||||
|
evaluatedConstant = p >> q;
|
||||||
|
break;
|
||||||
|
case SHIFT_RIGHT_UNSIGNED:
|
||||||
|
evaluatedConstant = p >>> q;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FLOAT: {
|
||||||
|
float p = first.floatValue();
|
||||||
|
float q = second.floatValue();
|
||||||
|
switch (operation) {
|
||||||
|
case ADD:
|
||||||
|
evaluatedConstant = p + q;
|
||||||
|
break;
|
||||||
|
case SUBTRACT:
|
||||||
|
evaluatedConstant = p - q;
|
||||||
|
break;
|
||||||
|
case MULTIPLY:
|
||||||
|
evaluatedConstant = p * q;
|
||||||
|
break;
|
||||||
|
case DIVIDE:
|
||||||
|
if (q != 0) {
|
||||||
|
evaluatedConstant = p / q;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODULO:
|
||||||
|
if (q != 0) {
|
||||||
|
evaluatedConstant = p % q;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COMPARE:
|
||||||
|
evaluatedConstant = Float.compare(p, q);
|
||||||
|
break;
|
||||||
|
case AND:
|
||||||
|
case OR:
|
||||||
|
case XOR:
|
||||||
|
case SHIFT_LEFT:
|
||||||
|
case SHIFT_RIGHT:
|
||||||
|
case SHIFT_RIGHT_UNSIGNED:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DOUBLE: {
|
||||||
|
double p = first.doubleValue();
|
||||||
|
double q = second.doubleValue();
|
||||||
|
switch (operation) {
|
||||||
|
case ADD:
|
||||||
|
evaluatedConstant = p + q;
|
||||||
|
break;
|
||||||
|
case SUBTRACT:
|
||||||
|
evaluatedConstant = p - q;
|
||||||
|
break;
|
||||||
|
case MULTIPLY:
|
||||||
|
evaluatedConstant = p * q;
|
||||||
|
break;
|
||||||
|
case DIVIDE:
|
||||||
|
if (q != 0) {
|
||||||
|
evaluatedConstant = p / q;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODULO:
|
||||||
|
if (q != 0) {
|
||||||
|
evaluatedConstant = p % q;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COMPARE:
|
||||||
|
evaluatedConstant = Double.compare(p, q);
|
||||||
|
break;
|
||||||
|
case AND:
|
||||||
|
case OR:
|
||||||
|
case XOR:
|
||||||
|
case SHIFT_LEFT:
|
||||||
|
case SHIFT_RIGHT:
|
||||||
|
case SHIFT_RIGHT_UNSIGNED:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -239,6 +453,26 @@ public class GlobalValueNumbering implements MethodOptimization {
|
||||||
int a = map[insn.getOperand().getIndex()];
|
int a = map[insn.getOperand().getIndex()];
|
||||||
insn.setOperand(program.variableAt(a));
|
insn.setOperand(program.variableAt(a));
|
||||||
bind(insn.getReceiver().getIndex(), "-@" + a);
|
bind(insn.getReceiver().getIndex(), "-@" + a);
|
||||||
|
|
||||||
|
Number value = numericConstants[a];
|
||||||
|
if (value != null) {
|
||||||
|
switch (insn.getOperandType()) {
|
||||||
|
case INT:
|
||||||
|
evaluatedConstant = -value.intValue();
|
||||||
|
break;
|
||||||
|
case LONG:
|
||||||
|
evaluatedConstant = -value.longValue();
|
||||||
|
break;
|
||||||
|
case FLOAT:
|
||||||
|
evaluatedConstant = -value.floatValue();
|
||||||
|
break;
|
||||||
|
case DOUBLE:
|
||||||
|
evaluatedConstant = -value.doubleValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
receiver = insn.getReceiver().getIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -259,6 +493,26 @@ public class GlobalValueNumbering implements MethodOptimization {
|
||||||
int a = map[insn.getValue().getIndex()];
|
int a = map[insn.getValue().getIndex()];
|
||||||
insn.setValue(program.variableAt(a));
|
insn.setValue(program.variableAt(a));
|
||||||
bind(insn.getReceiver().getIndex(), "@" + a + "::" + insn.getTargetType());
|
bind(insn.getReceiver().getIndex(), "@" + a + "::" + insn.getTargetType());
|
||||||
|
|
||||||
|
Number value = numericConstants[a];
|
||||||
|
if (value != null) {
|
||||||
|
switch (insn.getTargetType()) {
|
||||||
|
case INT:
|
||||||
|
evaluatedConstant = value.intValue();
|
||||||
|
break;
|
||||||
|
case LONG:
|
||||||
|
evaluatedConstant = value.longValue();
|
||||||
|
break;
|
||||||
|
case FLOAT:
|
||||||
|
evaluatedConstant = value.floatValue();
|
||||||
|
break;
|
||||||
|
case DOUBLE:
|
||||||
|
evaluatedConstant = value.doubleValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
receiver = insn.getReceiver().getIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -266,6 +520,30 @@ public class GlobalValueNumbering implements MethodOptimization {
|
||||||
int a = map[insn.getValue().getIndex()];
|
int a = map[insn.getValue().getIndex()];
|
||||||
insn.setValue(program.variableAt(a));
|
insn.setValue(program.variableAt(a));
|
||||||
bind(insn.getReceiver().getIndex(), "@" + a + "::" + insn.getTargetType() + " " + insn.getDirection());
|
bind(insn.getReceiver().getIndex(), "@" + a + "::" + insn.getTargetType() + " " + insn.getDirection());
|
||||||
|
|
||||||
|
Number value = numericConstants[a];
|
||||||
|
if (value != null) {
|
||||||
|
switch (insn.getDirection()) {
|
||||||
|
case TO_INTEGER:
|
||||||
|
evaluatedConstant = value;
|
||||||
|
break;
|
||||||
|
case FROM_INTEGER: {
|
||||||
|
switch (insn.getTargetType()) {
|
||||||
|
case BYTE:
|
||||||
|
evaluatedConstant = value.intValue() << 24 >> 24;
|
||||||
|
break;
|
||||||
|
case SHORT:
|
||||||
|
evaluatedConstant = value.intValue() << 16 >> 16;
|
||||||
|
break;
|
||||||
|
case CHARACTER:
|
||||||
|
evaluatedConstant = value.intValue() & 0xFFFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
receiver = insn.getReceiver().getIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -49,7 +49,7 @@ import org.teavm.model.util.ProgramUtils;
|
||||||
|
|
||||||
public class Inlining {
|
public class Inlining {
|
||||||
private static final int DEFAULT_THRESHOLD = 15;
|
private static final int DEFAULT_THRESHOLD = 15;
|
||||||
private static final int MAX_DEPTH = 4;
|
private static final int MAX_DEPTH = 5;
|
||||||
|
|
||||||
public void apply(Program program, ClassReaderSource classSource) {
|
public void apply(Program program, ClassReaderSource classSource) {
|
||||||
List<PlanEntry> plan = buildPlan(program, classSource, 0);
|
List<PlanEntry> plan = buildPlan(program, classSource, 0);
|
||||||
|
@ -257,7 +257,7 @@ public class Inlining {
|
||||||
}
|
}
|
||||||
|
|
||||||
Program invokedProgram = ProgramUtils.copy(invokedMethod.getProgram());
|
Program invokedProgram = ProgramUtils.copy(invokedMethod.getProgram());
|
||||||
int complexityThreshold = DEFAULT_THRESHOLD - depth;
|
int complexityThreshold = DEFAULT_THRESHOLD - depth * 2;
|
||||||
if (ownComplexity < DEFAULT_THRESHOLD) {
|
if (ownComplexity < DEFAULT_THRESHOLD) {
|
||||||
complexityThreshold += DEFAULT_THRESHOLD;
|
complexityThreshold += DEFAULT_THRESHOLD;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user