/** * 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()); }
/** * 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()); }
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; } }
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; } }
private void addMissingJumps() { for (BasicBlock bb: cfg.getBasicBlocks()) { boolean fallThrough = false; Label jumpLabel = null; for (Edge<BasicBlock> edge : cfg.getOutgoingEdges(bb)) { if (edge.getType() == EdgeType.FALL_THROUGH) { // Assume next BB will be correct fallThrough = true; } else if (edge.getType() == EdgeType.REGULAR || edge.getType() == EdgeType.EXIT) { // Not sure if we can have regular and fallthrough but only add regular if no fallthrough if (fallThrough) continue; jumpLabel = edge.getDestination().getData().getLabel(); } } if (fallThrough) continue; // we know this will just go to next BB already so no missing jump. if (jumpLabel == null) continue; // last instr does not transfer control so nothing to add. Instr lastInstr = bb.getLastInstr(); if (lastInstr != null && !lastInstr.transfersControl()) { bb.addInstr(new JumpInstr(jumpLabel)); } } }
private void addMissingJumps() { for (BasicBlock bb: cfg.getBasicBlocks()) { boolean fallThrough = false; Label jumpLabel = null; for (Edge<BasicBlock> edge : cfg.getOutgoingEdges(bb)) { if (edge.getType() == EdgeType.FALL_THROUGH) { // Assume next BB will be correct fallThrough = true; } else if (edge.getType() == EdgeType.REGULAR || edge.getType() == EdgeType.EXIT) { // Not sure if we can have regular and fallthrough but only add regular if no fallthrough if (fallThrough) continue; jumpLabel = edge.getDestination().getData().getLabel(); } } if (fallThrough) continue; // we know this will just go to next BB already so no missing jump. if (jumpLabel == null) continue; // last instr does not transfer control so nothing to add. Instr lastInstr = bb.getLastInstr(); if (lastInstr != null && !lastInstr.transfersControl()) { bb.addInstr(new JumpInstr(jumpLabel)); } } }