001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.compilers.opt; 014 015import java.util.Enumeration; 016import java.util.HashMap; 017import org.jikesrvm.VM; 018import org.jikesrvm.compilers.opt.controlflow.BranchOptimizations; 019import org.jikesrvm.compilers.opt.controlflow.BranchSimplifier; 020import org.jikesrvm.compilers.opt.driver.CompilerPhase; 021import org.jikesrvm.compilers.opt.ir.Move; 022import org.jikesrvm.compilers.opt.ir.BasicBlock; 023import org.jikesrvm.compilers.opt.ir.IR; 024import org.jikesrvm.compilers.opt.ir.Instruction; 025import org.jikesrvm.compilers.opt.ir.Register; 026import org.jikesrvm.compilers.opt.ir.operand.ConstantOperand; 027import org.jikesrvm.compilers.opt.ir.operand.Operand; 028import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 029 030/** 031 * Perform local constant propagation for a factored basic block. 032 * Orthogonal to the constant propagation performed in Simple 033 * since here we use flow-sensitive analysis within a basic block. 034 */ 035public class LocalConstantProp extends CompilerPhase { 036 037 @Override 038 public final boolean shouldPerform(OptOptions options) { 039 return options.LOCAL_CONSTANT_PROP; 040 } 041 042 @Override 043 public final String getName() { 044 return "Local ConstantProp"; 045 } 046 047 @Override 048 public void reportAdditionalStats() { 049 VM.sysWrite(" "); 050 VM.sysWrite(container.counter1 / container.counter2 * 100, 2); 051 VM.sysWrite("% Infrequent BBs"); 052 } 053 054 /** 055 * Return this instance of this phase. This phase contains no 056 * per-compilation instance fields. 057 * @param ir not used 058 * @return this 059 */ 060 @Override 061 public CompilerPhase newExecution(IR ir) { 062 return this; 063 } 064 065 /** 066 * Perform Local Constant propagation for a method. 067 * 068 * @param ir the IR to optimize 069 */ 070 @Override 071 public void perform(IR ir) { 072 // info is a mapping from Register to ConstantOperand. 073 HashMap<Register, ConstantOperand> info = new HashMap<Register, ConstantOperand>(); 074 boolean runBranchOpts = false; 075 076 /* Visit each basic block and apply the optimization */ 077 for (BasicBlock bb = ir.firstBasicBlockInCodeOrder(); bb != null; bb = bb.nextBasicBlockInCodeOrder()) { 078 if (bb.isEmpty()) continue; /* skip over trivial blocks */ 079 container.counter2++; 080 if (bb.getInfrequent()) { 081 container.counter1++; 082 if (ir.options.FREQ_FOCUS_EFFORT) continue; 083 } 084 085 /* Iterate over all instructions in the basic block */ 086 for (Instruction s = bb.firstRealInstruction(), next, sentinel = bb.lastInstruction(); s != sentinel; s = next) { 087 next = s.nextInstructionInCodeOrder(); 088 089 /* Do we known anything ? */ 090 if (!info.isEmpty()) { 091 /* Transform: attempt to propagate constants */ 092 int numUses = s.getNumberOfPureUses(); 093 if (numUses > 0) { 094 boolean didSomething = false; 095 int numDefs = s.getNumberOfDefs(); 096 for (int idx = numDefs; idx < numUses + numDefs; idx++) { 097 Operand use = s.getOperand(idx); 098 if (use instanceof RegisterOperand) { 099 RegisterOperand rUse = (RegisterOperand)use; 100 Operand value = info.get(rUse.getRegister()); 101 if (value != null) { 102 didSomething = true; 103 s.putOperand(idx, value.copy()); 104 } 105 } 106 } 107 if (didSomething) { 108 Simplifier.simplify(ir.IRStage == IR.HIR, ir.regpool, ir.options, s); 109 } 110 } 111 112 /* KILL: Remove bindings for all registers defined by this instruction */ 113 for (Enumeration<Operand> e = s.getDefs(); e.hasMoreElements();) { 114 Operand def = e.nextElement(); 115 if (def != null) { 116 /* Don't bother special casing the case where we are defining another constant; GEN will handle that */ 117 /* Don't attempt to remove redundant assignments; let dead code elimination handle that */ 118 Register defReg = ((RegisterOperand)def).getRegister(); 119 info.remove(defReg); 120 } 121 } 122 } 123 124 /* GEN: If this is a move operation with a constant RHS, then it defines a constant */ 125 if (Move.conforms(s) && Move.getVal(s).isConstant()) { 126 info.put(Move.getResult(s).getRegister(), (ConstantOperand)Move.getVal(s)); 127 } 128 } 129 130 /* End of basic block; clean up and prepare for next block */ 131 info.clear(); 132 runBranchOpts |= BranchSimplifier.simplify(bb, ir); 133 } 134 135 /* End of IR. If we simplified a branch instruction, then run branch optimizations */ 136 if (runBranchOpts) { 137 new BranchOptimizations(0, true, false, false).perform(ir); 138 } 139 140 } 141}