/* * 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 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_RegisterOperand; /** * Global code placement comes in two flavours. The first is loop * invariant code motion (LICM), the second is global common sub * expression elimination (GCSE).<p> * * LICM is applied to HIR and LIR, GCSE only to LIR and before * LICM.<p> * * Both algorithms run on SSA and use the dominator tree to determine * positions for operations. That's why these operations are called * code placement instead of code motion. <p> * * There is no code yet to deal with partial redundancies. */ final class OPT_GCP extends OPT_OptimizationPlanCompositeElement { /** * Makes sure we are in SSA and have global value numbers at hand. * Then execute the transformations. */ OPT_GCP() { super("Global Code Placement", new OPT_OptimizationPlanElement[]{ // 1. Set up IR state to control SSA translation as needed new OPT_OptimizationPlanAtomicElement(new GCPPreparation()), // 2. Get the desired SSA form new OPT_OptimizationPlanAtomicElement(new OPT_EnterSSA()), // 3. Perform global CSE new OPT_OptimizationPlanAtomicElement(new OPT_GlobalCSE()), // 4. Repair SSA new OPT_OptimizationPlanAtomicElement(new OPT_EnterSSA()), // 5. Perform Loop Invariant Code Motion new OPT_OptimizationPlanAtomicElement(new OPT_LICM()), // 6. Finalize GCP new OPT_OptimizationPlanAtomicElement(new GCPFinalization())}); } /** * Redefine shouldPerform so that none of the subphases will occur * unless we pass through this test. */ public boolean shouldPerform(OPT_Options options) { if (options.getOptLevel() < 2) { return false; } return options.GCP || options.VERBOSE_GCP || options.GCSE; } static boolean tooBig(OPT_IR ir) { boolean res = false; if (ir.getMaxBasicBlockNumber() > 1000) { //VM.sysWrite (ir.method.toString() + " is too large\n"); res = true; } return res; } /** * This class sets up the IR state prior to entering SSA for GCP */ private static class GCPPreparation extends OPT_CompilerPhase { /** * 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; } /** * Should this phase perform? * @param options */ public final boolean shouldPerform(OPT_Options options) { return options.GCP || options.VERBOSE_GCP || options.GCSE; } /** * Return the name of the phase */ public final String getName() { return "GCP Preparation"; } /** * perform the phase * @param ir */ public final void perform(OPT_IR ir) { boolean dont = false; //VM.sysWrite("> " + ir.method + "\n"); if (ir.hasReachableExceptionHandlers()) { //VM.sysWrite("has exceptionhandlers\n"); dont = true; } if (OPT_GCP.tooBig(ir)) { dont = true; } if (dont) { ir.options.SSA = false; return; } ir.desiredSSAOptions = new OPT_SSAOptions(); // register in the IR the SSA properties we need for GCP if (ir.IRStage == OPT_IR.LIR) { ir.desiredSSAOptions.setScalarsOnly(true); ir.desiredSSAOptions.setBackwards(false); ir.desiredSSAOptions.setInsertUsePhis(false); ir.desiredSSAOptions.setInsertPEIDeps(false); ir.desiredSSAOptions.setHeapTypes(null); } else { // HIR options ir.desiredSSAOptions.setScalarsOnly(false); ir.desiredSSAOptions.setBackwards(true); ir.desiredSSAOptions.setInsertUsePhis(true); ir.desiredSSAOptions.setInsertPEIDeps(!ir.options.LICM_IGNORE_PEI); ir.desiredSSAOptions.setHeapTypes(null); } } } /** * This class sets up the IR state prior to entering SSA for GCP */ private static class GCPFinalization extends OPT_CompilerPhase { /** * 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; } /** * Should this phase perform? * @param options */ public final boolean shouldPerform(OPT_Options options) { return options.GCP || options.VERBOSE_GCP || options.GCSE; } /** * Return the name of the phase */ public final String getName() { return "GCP Finalization"; } /** * perform the phase * @param ir */ public final void perform(OPT_IR ir) { ir.options.SSA = true; //VM.sysWrite("< " + ir.method + "\n"); // register in the IR the SSA properties GCP preserves if (ir != null && !OPT_GCP.tooBig(ir) && !ir.hasReachableExceptionHandlers() && ir.actualSSAOptions != null) { if (ir.IRStage == OPT_IR.LIR) { ir.actualSSAOptions.setScalarsOnly(true); ir.actualSSAOptions.setBackwards(false); ir.actualSSAOptions.setInsertUsePhis(false); ir.actualSSAOptions.setInsertPEIDeps(false); ir.actualSSAOptions.setHeapTypes(null); } else { // HIR options ir.actualSSAOptions.setScalarsOnly(false); ir.actualSSAOptions.setBackwards(true); ir.actualSSAOptions.setInsertUsePhis(true); ir.actualSSAOptions.setInsertPEIDeps(true); ir.actualSSAOptions.setHeapTypes(null); } } } } static boolean usesOrDefsPhysicalRegisterOrAddressType(OPT_Instruction inst) { for (int i = inst.getNumberOfOperands() - 1; i >= 0; --i) { OPT_Operand op = inst.getOperand(i); if (op instanceof OPT_RegisterOperand) { if (op.asRegister().getType().isWordType() || op.asRegister().getRegister().isPhysical()) { return true; } } } return false; } }