Skip to content

Commit

Permalink
Switched optimizetempvarspass to use single use and def instr value i…
Browse files Browse the repository at this point in the history
…nstead of maintaining

temporary lists for all uses and defs.  This reduces number of arraylists from this pass
by 175000 while running rails console on an empty Rails app.
  • Loading branch information
enebo committed Jan 8, 2015
1 parent 200de99 commit e1ffae8
Showing 1 changed file with 23 additions and 30 deletions.
53 changes: 23 additions & 30 deletions core/src/main/java/org/jruby/ir/passes/OptimizeTempVarsPass.java
Expand Up @@ -51,38 +51,37 @@ private static void optimizeTmpVars(IRScope s) {
if (s.getCFG() != null) return;

// Pass 1: Analyze instructions and find use and def count of temporary variables
Map<TemporaryVariable, List<Instr>> tmpVarUses = new HashMap<TemporaryVariable, List<Instr>>();
Map<TemporaryVariable, List<Instr>> tmpVarDefs = new HashMap<TemporaryVariable, List<Instr>>();
Map<TemporaryVariable, Instr> tmpVarUses = new HashMap<>();
Map<TemporaryVariable, Instr> tmpVarDefs = new HashMap<>();
for (Instr i: s.getInstrs()) {
for (Variable v: i.getUsedVariables()) {
if (v instanceof TemporaryVariable) {
TemporaryVariable tv = (TemporaryVariable)v;
List<Instr> uses = tmpVarUses.get(tv);
if (uses == null) {
uses = new ArrayList<Instr>();
tmpVarUses.put(tv, uses);
Instr use = tmpVarUses.get(tv);
if (use == null) {
tmpVarUses.put(tv, i);
} else if (use != NopInstr.NOP) {
tmpVarUses.put(tv, NopInstr.NOP);
}
uses.add(i);
}
}
if (i instanceof ResultInstr) {
Variable v = ((ResultInstr)i).getResult();
if (v instanceof TemporaryVariable) {
TemporaryVariable tv = (TemporaryVariable)v;
List<Instr> defs = tmpVarDefs.get(tv);
Instr defs = tmpVarDefs.get(tv);
if (defs == null) {
defs = new ArrayList<Instr>();
tmpVarDefs.put(tv, defs);
} else if (defs != NopInstr.NOP) {
tmpVarDefs.put(tv, NopInstr.NOP);
}
defs.add(i);
}
}
}

// Pass 2: Transform code and do additional analysis:
// * If the result of this instr. has not been used, mark it dead
// * Find copies where constant values are set
Map<TemporaryVariable, Variable> removableCopies = new HashMap<TemporaryVariable, Variable>();
ListIterator<Instr> instrs = s.getInstrs().listIterator();
while (instrs.hasNext()) {
Instr i = instrs.next();
Expand All @@ -93,9 +92,9 @@ private static void optimizeTmpVars(IRScope s) {
// Deal with this code pattern:
// %v = ...
// %v not used anywhere
List<Instr> uses = tmpVarUses.get((TemporaryVariable)v);
List<Instr> defs = tmpVarDefs.get((TemporaryVariable)v);
if (uses == null) {
Instr use = tmpVarUses.get(v);
Instr def = tmpVarDefs.get(v);
if (use == null) {
if (i instanceof CopyInstr) {
i.markDead();
instrs.remove();
Expand All @@ -108,13 +107,8 @@ private static void optimizeTmpVars(IRScope s) {
// i.markUnusedResult();
}
}
// Deal with this code pattern:
// %v = <some-operand>
// .... %v ...
// %v not used or defined anywhere else
// So, %v can be replaced by the operand
else if ((uses.size() == 1) && (defs != null) && (defs.size() == 1) && (i instanceof CopyInstr)) {
Instr soleUse = uses.get(0);
// Replace <operand> in use from def if single-def and single-use: %v = <operand>; ... %v ...
else if (use != NopInstr.NOP && def != null && def != NopInstr.NOP && i instanceof CopyInstr) {
// Conservatively avoid optimizing return values since
// intervening cloned ensure block code can modify the
// copy source (if it is a variable).
Expand All @@ -126,16 +120,16 @@ else if ((uses.size() == 1) && (defs != null) && (defs.size() == 1) && (i instan
// v = 2
// return %v_1 <-- cannot be replaced with v
// ....
if (!(soleUse instanceof ReturnInstr)) {
if (!(use instanceof ReturnInstr)) {
CopyInstr ci = (CopyInstr)i;
Operand src = ci.getSource();
i.markDead();
instrs.remove();

// Fix up use
Map<Operand, Operand> copyMap = new HashMap<Operand, Operand>();
Map<Operand, Operand> copyMap = new HashMap<>();
copyMap.put(v, src);
soleUse.simplifyOperands(copyMap, true);
use.simplifyOperands(copyMap, true);
}
}
}
Expand All @@ -154,13 +148,12 @@ else if (i instanceof CopyInstr) {
Operand src = ci.getSource();
if (src instanceof TemporaryVariable) {
TemporaryVariable vsrc = (TemporaryVariable)src;
List<Instr> uses = tmpVarUses.get(vsrc);
List<Instr> defs = tmpVarDefs.get(vsrc);
if ((uses.size() == 1) && (defs.size() == 1)) {
Instr soleDef = defs.get(0);
if (!soleDef.isDead()) {
Instr use = tmpVarUses.get(vsrc);
Instr def = tmpVarDefs.get(vsrc);
if ((use != null && use != NopInstr.NOP) && (def != null && def != NopInstr.NOP)) {
if (!def.isDead()) {
// Fix up def
((ResultInstr)soleDef).updateResult(ci.getResult());
((ResultInstr) def).updateResult(ci.getResult());
ci.markDead();
instrs.remove();
}
Expand Down

0 comments on commit e1ffae8

Please sign in to comment.