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 boolean eliminate;
|
||||
private int[] map;
|
||||
private Number[] numericConstants;
|
||||
private Number evaluatedConstant;
|
||||
private int receiver;
|
||||
private Program program;
|
||||
private int currentBlockIndex;
|
||||
private DominatorTree domTree;
|
||||
|
@ -46,6 +49,7 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
domTree = GraphUtils.buildDominatorTree(cfg);
|
||||
Graph dom = GraphUtils.buildDominatorGraph(domTree, cfg.size());
|
||||
map = new int[program.variableCount()];
|
||||
numericConstants = new Number[program.variableCount()];
|
||||
for (int i = 0; i < map.length; ++i) {
|
||||
map[i] = i;
|
||||
}
|
||||
|
@ -86,12 +90,35 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
}
|
||||
}*/
|
||||
for (int i = 0; i < block.getInstructions().size(); ++i) {
|
||||
evaluatedConstant = null;
|
||||
Instruction currentInsn = block.getInstructions().get(i);
|
||||
currentInsn.acceptVisitor(optimizer);
|
||||
if (eliminate) {
|
||||
affected = true;
|
||||
block.getInstructions().set(i, new EmptyInstruction());
|
||||
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)) {
|
||||
|
@ -157,18 +184,22 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
|
||||
@Override
|
||||
public void visit(IntegerConstantInstruction insn) {
|
||||
numericConstants[insn.getReceiver().getIndex()] = insn.getConstant();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LongConstantInstruction insn) {
|
||||
numericConstants[insn.getReceiver().getIndex()] = insn.getConstant();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(FloatConstantInstruction insn) {
|
||||
numericConstants[insn.getReceiver().getIndex()] = insn.getConstant();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DoubleConstantInstruction insn) {
|
||||
numericConstants[insn.getReceiver().getIndex()] = insn.getConstant();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -232,6 +263,189 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
if (commutative) {
|
||||
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
|
||||
|
@ -239,6 +453,26 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
int a = map[insn.getOperand().getIndex()];
|
||||
insn.setOperand(program.variableAt(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
|
||||
|
@ -259,6 +493,26 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
int a = map[insn.getValue().getIndex()];
|
||||
insn.setValue(program.variableAt(a));
|
||||
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
|
||||
|
@ -266,6 +520,30 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
int a = map[insn.getValue().getIndex()];
|
||||
insn.setValue(program.variableAt(a));
|
||||
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
|
||||
|
|
|
@ -49,7 +49,7 @@ import org.teavm.model.util.ProgramUtils;
|
|||
|
||||
public class Inlining {
|
||||
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) {
|
||||
List<PlanEntry> plan = buildPlan(program, classSource, 0);
|
||||
|
@ -257,7 +257,7 @@ public class Inlining {
|
|||
}
|
||||
|
||||
Program invokedProgram = ProgramUtils.copy(invokedMethod.getProgram());
|
||||
int complexityThreshold = DEFAULT_THRESHOLD - depth;
|
||||
int complexityThreshold = DEFAULT_THRESHOLD - depth * 2;
|
||||
if (ownComplexity < DEFAULT_THRESHOLD) {
|
||||
complexityThreshold += DEFAULT_THRESHOLD;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user