/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/cpl1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt; import java.util.HashMap; import org.jikesrvm.VM; import org.jikesrvm.compilers.opt.ir.Move; import org.jikesrvm.compilers.opt.ir.OPT_BasicBlock; import org.jikesrvm.compilers.opt.ir.OPT_ConstantOperand; import org.jikesrvm.compilers.opt.ir.OPT_IR; import org.jikesrvm.compilers.opt.ir.OPT_Instruction; import org.jikesrvm.compilers.opt.ir.OPT_Operand; import org.jikesrvm.compilers.opt.ir.OPT_OperandEnumeration; import org.jikesrvm.compilers.opt.ir.OPT_Register; import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; /** * Perform local constant propagation for a factored basic block. * Orthogonal to the constant propagation performed in OPT_Simple * since here we use flow-sensitive analysis within a basic block. */ public class OPT_LocalConstantProp extends OPT_CompilerPhase { public final boolean shouldPerform(OPT_Options options) { return options.LOCAL_CONSTANT_PROP; } public final String getName() { return "Local ConstantProp"; } public void reportAdditionalStats() { VM.sysWrite(" "); VM.sysWrite(container.counter1 / container.counter2 * 100, 2); VM.sysWrite("% Infrequent BBs"); } /** * Return this instance of this phase. This phase contains no * per-compilation instance fields. * @param ir not used * @return this */ public OPT_CompilerPhase newExecution(OPT_IR ir) { return this; } /** * Perform Local Constant propagation for a method. * * @param ir the IR to optimize */ public void perform(OPT_IR ir) { // info is a mapping from OPT_Register to OPT_ConstantOperand. HashMap<OPT_Register, OPT_ConstantOperand> info = new HashMap<OPT_Register, OPT_ConstantOperand>(); boolean runBranchOpts = false; for (OPT_BasicBlock bb = ir.firstBasicBlockInCodeOrder(); bb != null; bb = bb.nextBasicBlockInCodeOrder()) { if (bb.isEmpty()) continue; container.counter2++; if (bb.getInfrequent()) { container.counter1++; if (ir.options.FREQ_FOCUS_EFFORT) continue; } // iterate over all instructions in the basic block for (OPT_Instruction s = bb.firstRealInstruction(), sentinel = bb.lastInstruction(); s != sentinel; s = s.nextInstructionInCodeOrder()) { if (!info.isEmpty()) { // PROPAGATE CONSTANTS int numUses = s.getNumberOfUses(); if (numUses > 0) { boolean didSomething = false; int numDefs = s.getNumberOfDefs(); for (int idx = numDefs; idx < numUses + numDefs; idx++) { OPT_Operand use = s.getOperand(idx); if (use instanceof OPT_RegisterOperand) { OPT_RegisterOperand rUse = (OPT_RegisterOperand) use; OPT_Operand value = info.get(rUse.getRegister()); if (value != null) { didSomething = true; s.putOperand(idx, value.copy()); } } } if (didSomething) OPT_Simplifier.simplify(ir.regpool, s); } // KILL for (OPT_OperandEnumeration e = s.getDefs(); e.hasMoreElements();) { OPT_Operand def = e.next(); if (def != null) { info.remove(((OPT_RegisterOperand) def).getRegister()); } } } // GEN if (Move.conforms(s) && Move.getVal(s).isConstant()) { info.put(Move.getResult(s).getRegister(), (OPT_ConstantOperand) Move.getVal(s)); } } info.clear(); runBranchOpts |= OPT_BranchSimplifier.simplify(bb, ir); } if (runBranchOpts) { new OPT_BranchOptimizations(0, true, false, false).perform(ir); } } }