public boolean canRaiseException() { return operation.canRaiseException(); }
public boolean hasSideEffects() { return operation.hasSideEffects(); }
Operation(int flags) { this.flags = flags; if (this.isArgReceive()) { this.opClass = OpClass.ARG_OP; } else if (this.isBranch()) { this.opClass = OpClass.BRANCH_OP; } else if (this.isBookKeepingOp()) { this.opClass = OpClass.BOOK_KEEPING_OP; } else if (this.isCall()) { this.opClass = OpClass.CALL_OP; } else { this.opClass = OpClass.OTHER_OP; } }
public static void runLocalOptsOnInstrArray(IRScope s, Instr[] instrs) { // Reset value map if this instruction is the start/end of a basic block Map<Operand,Operand> valueMap = new HashMap<>(); Map<Variable,List<Variable>> simplificationMap = new HashMap<>(); for (int i = 0; i < instrs.length; i++) { Instr instr = instrs[i]; Instr newInstr = optInstr(s, instr, valueMap, simplificationMap); if (newInstr != instr) { instrs[i] = newInstr; } // If the call has been optimized away in the previous step, it is no longer a hard boundary for opts! // // Right now, calls are considered hard boundaries for optimization and // information cannot be propagated across them! // // SSS FIXME: Rather than treat all calls with a broad brush, what we need // is to capture different attributes about a call : // - uses closures // - known call target // - can modify scope, // - etc. // // This information is present in instruction flags on CallBase. Use it! Operation iop = instr.getOperation(); if (iop.startsBasicBlock() || iop.endsBasicBlock() || (iop.isCall() && !instr.isDead())) { valueMap = new HashMap<>(); simplificationMap = new HashMap<>(); } } }
public boolean canBeDeleted(IRScope s) { if (hasSideEffects() || getOperation().isDebugOp() || getOperation().canRaiseException() || transfersControl()) { return false; } else if (this instanceof ResultInstr) { Variable r = ((ResultInstr)this).getResult(); if (s.bindingHasEscaped() && !r.getName().equals(Variable.BLOCK)) { // If the binding of this scope has escaped, then we have to preserve writes to // all local variables because anyone who uses the binding might query any of the // local variables from the binding. This is safe, but extremely conservative. return !(r instanceof LocalVariable); } else if (s.usesEval() && r.getName().equals(Variable.BLOCK)) { // If this scope (or any nested scope) has any evals, then the eval might have a yield which // would use %block. In that scenario, we cannot delete the '%block = recv_closure' instruction. // This is safe, but conservative. return false; } else if (s.usesZSuper() && getOperation().isArgReceive()) { // If this scope (or any nested scope) has a ZSuperInstr, then the arguments of this // scope could be used by any of those ZSuper instructions. If so, we cannot delete // the argument receive. return false; } else { return true; } } else { return true; } }
} else if (iop.endsBasicBlock()) { bbEnded = true; currBB.addInstr(i); } else if (i instanceof JumpInstr) { tgt = ((JumpInstr) i).getJumpTarget(); } else if (iop.isReturn()) { // BREAK, RETURN, CLOSURE_RETURN tgt = null; returnBBs.add(currBB);
public static void instrTick(Operation operation) { if (operation.modifiesCode()) codeModificationsCount++; /* Counter cnt = opStats.get(operation); if (cnt == null) { cnt = new Counter(); opStats.put(operation, cnt); } cnt.count++; */ } }
if (i.getOperation().isReturn()) dirtyVars.clear();
/** * Can this instruction be deleted? LVA will preserve instructions based on whether operands (variables) * are living but even if there are no living variables then the instruction itself may not be able to be removed * during DCE for other reasons (like if it unconditionally has a side-effect) */ public boolean isDeletable() { return !(hasSideEffects() || operation.isDebugOp() || canRaiseException() || transfersControl()); }
if (iop.isCall() && !instr.isDead()) { valueMap = new HashMap<>(); simplificationMap = new HashMap<>();
public static void runLocalOptsOnInstrArray(IRScope s, Instr[] instrs) { // Reset value map if this instruction is the start/end of a basic block Map<Operand,Operand> valueMap = new HashMap<>(); Map<Variable,List<Variable>> simplificationMap = new HashMap<>(); for (int i = 0; i < instrs.length; i++) { Instr instr = instrs[i]; Instr newInstr = optInstr(s, instr, valueMap, simplificationMap); if (newInstr != instr) { instrs[i] = newInstr; } // If the call has been optimized away in the previous step, it is no longer a hard boundary for opts! // // Right now, calls are considered hard boundaries for optimization and // information cannot be propagated across them! // // SSS FIXME: Rather than treat all calls with a broad brush, what we need // is to capture different attributes about a call : // - uses closures // - known call target // - can modify scope, // - etc. // // This information is present in instruction flags on CallBase. Use it! Operation iop = instr.getOperation(); if (iop.startsBasicBlock() || iop.endsBasicBlock() || (iop.isCall() && !instr.isDead())) { valueMap = new HashMap<>(); simplificationMap = new HashMap<>(); } } }
public boolean canBeDeleted(IRScope s) { if (hasSideEffects() || getOperation().isDebugOp() || getOperation().canRaiseException() || transfersControl()) { return false; } else if (this instanceof ResultInstr) { Variable r = ((ResultInstr)this).getResult(); if (s.bindingHasEscaped() && !r.getName().equals(Variable.BLOCK)) { // If the binding of this scope has escaped, then we have to preserve writes to // all local variables because anyone who uses the binding might query any of the // local variables from the binding. This is safe, but extremely conservative. return !(r instanceof LocalVariable); } else if (s.usesEval() && r.getName().equals(Variable.BLOCK)) { // If this scope (or any nested scope) has any evals, then the eval might have a yield which // would use %block. In that scenario, we cannot delete the '%block = recv_closure' instruction. // This is safe, but conservative. return false; } else if (s.usesZSuper() && getOperation().isArgReceive()) { // If this scope (or any nested scope) has a ZSuperInstr, then the arguments of this // scope could be used by any of those ZSuper instructions. If so, we cannot delete // the argument receive. return false; } else { return true; } } else { return true; } }
} else if (iop.endsBasicBlock()) { bbEnded = true; currBB.addInstr(i); } else if (i instanceof JumpInstr) { tgt = ((JumpInstr) i).getJumpTarget(); } else if (iop.isReturn()) { // BREAK, RETURN, CLOSURE_RETURN tgt = null; returnBBs.add(currBB);
public static void instrTick(Operation operation) { if (operation.modifiesCode()) codeModificationsCount++; /* Counter cnt = opStats.get(operation); if (cnt == null) { cnt = new Counter(); opStats.put(operation, cnt); } cnt.count++; */ } }
if (i.getOperation().isReturn()) dirtyVars.clear();
/** * Can this instruction be deleted? LVA will preserve instructions based on whether operands (variables) * are living but even if there are no living variables then the instruction itself may not be able to be removed * during DCE for other reasons (like if it unconditionally has a side-effect) */ public boolean isDeletable() { return !(hasSideEffects() || operation.isDebugOp() || canRaiseException() || transfersControl()); }
if (iop.isCall() && !instr.isDead()) { valueMap = new HashMap<>(); simplificationMap = new HashMap<>();
Operation(int flags) { this.flags = flags; if (this.isArgReceive()) { this.opClass = OpClass.ARG_OP; } else if (this.isBranch()) { this.opClass = OpClass.BRANCH_OP; } else if (this.isBookKeepingOp()) { this.opClass = OpClass.BOOK_KEEPING_OP; } else if (this.isCall()) { this.opClass = OpClass.CALL_OP; } else { this.opClass = OpClass.OTHER_OP; } }
Instr i = instrs.next(); Operation iop = i.getOperation(); if (preCFG && iop.startsBasicBlock()) { valueMap = new HashMap<Operand,Operand>(); simplificationMap = new HashMap<Variable,List<Variable>>(); if ((preCFG && iop.endsBasicBlock()) || (iop.isCall() && !i.isDead())) { valueMap = new HashMap<Operand,Operand>(); simplificationMap = new HashMap<Variable,List<Variable>>();
} else if (iop.endsBasicBlock()) { bbEnded = true; currBB.addInstr(i); } else if (i instanceof JumpInstr) { tgt = ((JumpInstr) i).getJumpTarget(); } else if (iop.isReturn()) { // BREAK, RETURN, CLOSURE_RETURN tgt = null; returnBBs.add(currBB);