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     */
013    package org.jikesrvm.compilers.opt.ssa;
014    
015    import static org.jikesrvm.compilers.opt.ir.Operators.*;
016    
017    import java.lang.reflect.Constructor;
018    import java.util.Enumeration;
019    import java.util.HashMap;
020    
021    import org.jikesrvm.VM;
022    import org.jikesrvm.compilers.opt.DefUse;
023    import org.jikesrvm.compilers.opt.OptOptions;
024    import org.jikesrvm.compilers.opt.Simple;
025    import org.jikesrvm.compilers.opt.controlflow.DominatorTree;
026    import org.jikesrvm.compilers.opt.controlflow.DominatorTreeNode;
027    import org.jikesrvm.compilers.opt.driver.CompilerPhase;
028    import org.jikesrvm.compilers.opt.ir.BBend;
029    import org.jikesrvm.compilers.opt.ir.BasicBlock;
030    import org.jikesrvm.compilers.opt.ir.GuardResultCarrier;
031    import org.jikesrvm.compilers.opt.ir.IR;
032    import org.jikesrvm.compilers.opt.ir.Instruction;
033    import org.jikesrvm.compilers.opt.ir.Register;
034    import org.jikesrvm.compilers.opt.ir.ResultCarrier;
035    import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
036    import org.jikesrvm.compilers.opt.util.TreeNode;
037    
038    /**
039     * This class provides global common sub expression elimination.
040     */
041    public final class GlobalCSE extends CompilerPhase {
042    
043      /** Output debug messages */
044      public boolean verbose = true;
045      /** Cache of IR being processed by this phase */
046      private IR ir;
047      /** Cache of the value numbers from the IR  */
048      private GlobalValueNumberState valueNumbers;
049      /**
050       * Cache of dominator tree that should be computed prior to this
051       * phase
052       */
053      private DominatorTree dominator;
054      /**
055       * Available expressions. From Muchnick, "an expression
056       * <em>exp</em>is said to be </em>available</em> at the entry to a
057       * basic block if along every control-flow path from the entry block
058       * to this block there is an evaluation of exp that is not
059       * subsequently killed by having one or more of its operands
060       * assigned a new value." Our available expressions are a mapping
061       * from a value number to the first instruction to define it as we
062       * traverse the dominator tree.
063       */
064      private final HashMap<Integer, Instruction> avail;
065    
066      /**
067       * Constructor
068       */
069      public GlobalCSE() {
070        avail = new HashMap<Integer, Instruction>();
071      }
072    
073      /**
074       * Redefine shouldPerform so that none of the subphases will occur
075       * unless we pass through this test.
076       */
077      @Override
078      public boolean shouldPerform(OptOptions options) {
079        return options.SSA_GCSE;
080      }
081    
082      /**
083       * Constructor for this compiler phase
084       */
085      private static final Constructor<CompilerPhase> constructor = getCompilerPhaseConstructor(GlobalCSE.class);
086    
087      /**
088       * Get a constructor object for this compiler phase
089       * @return compiler phase constructor
090       */
091      @Override
092      public Constructor<CompilerPhase> getClassConstructor() {
093        return constructor;
094      }
095    
096      /**
097       * Returns the name of the phase
098       */
099      @Override
100      public String getName() {
101        return "Global CSE";
102      }
103    
104      /**
105       * Perform the GlobalCSE compiler phase
106       */
107      @Override
108      public void perform(IR ir) {
109        // conditions to leave early
110        if (ir.hasReachableExceptionHandlers() || GCP.tooBig(ir)) {
111          return;
112        }
113        // cache useful values
114        verbose = ir.options.DEBUG_GCP;
115        this.ir = ir;
116        dominator = ir.HIRInfo.dominatorTree;
117    
118        // perform GVN
119        (new GlobalValueNumber()).perform(ir);
120        valueNumbers = ir.HIRInfo.valueNumbers;
121    
122        if (verbose) VM.sysWrite("in GCSE for " + ir.method + "\n");
123    
124        // compute DU and perform copy propagation
125        DefUse.computeDU(ir);
126        Simple.copyPropagation(ir);
127        DefUse.computeDU(ir);
128    
129        // perform GCSE starting at the entry block
130        globalCSE(ir.firstBasicBlockInCodeOrder());
131    
132        if (VM.VerifyAssertions) {
133          VM._assert(avail.isEmpty(), avail.toString());
134        }
135        ir.actualSSAOptions.setScalarValid(false);
136      }
137    
138      /**
139       * Recursively descend over all blocks dominated by b. For each
140       * instruction in the block, if it defines a GVN then record it in
141       * the available expressions. If the GVN already exists in the
142       * available expressions then eliminate the instruction and change
143       * all uses of the result of the instruction to be uses of the first
144       * instruction to define the result of this expression.
145       * @param b the current block to process
146       */
147      private void globalCSE(BasicBlock b) {
148        Instruction next, inst;
149        // Iterate over instructions in b
150        inst = b.firstInstruction();
151        while (!BBend.conforms(inst)) {
152          next = inst.nextInstructionInCodeOrder();
153          // check instruction is safe for GCSE, {@see shouldCSE}
154          if (!shouldCSE(inst)) {
155            inst = next;
156            continue;
157          }
158          // check the instruction defines a result
159          RegisterOperand result = getResult(inst);
160          if (result == null) {
161            inst = next;
162            continue;
163          }
164          // get the value number for this result. The value number for
165          // the same sub-expression is shared by all results showing they
166          // can be eliminated. If the value number is UNKNOWN the result
167          // is negative.
168          int vn = valueNumbers.getValueNumber(result);
169          if (vn < 0) {
170            inst = next;
171            continue;
172          }
173          // was this the first definition of the value number?
174          Integer Vn = vn;
175          Instruction former = avail.get(Vn);
176          if (former == null) {
177            // first occurance of value number, record it in the available
178            // expressions
179            avail.put(Vn, inst);
180          } else {
181            // this value number has been seen before so we can use the
182            // earlier version
183            // NB instead of trying to repair Heap SSA, we rebuild it
184            // after CSE
185    
186            // relink scalar dependencies - make all uses of the current
187            // instructions result use the first definition of the result
188            // by the earlier expression
189            RegisterOperand formerDef = getResult(former);
190            Register reg = result.getRegister();
191            formerDef.getRegister().setSpansBasicBlock();
192            Enumeration<RegisterOperand> uses = DefUse.uses(reg);
193            while (uses.hasMoreElements()) {
194              RegisterOperand use = uses.nextElement();
195              DefUse.transferUse(use, formerDef);
196            }
197            if (verbose) {
198              VM.sysWrite("using      " + former + "\n" + "instead of " + inst + "\n");
199            }
200            // remove the redundant instruction
201            inst.remove();
202          }
203          inst = next;
204        } // end of instruction iteration
205        // Recurse over all blocks that this block dominates
206        Enumeration<TreeNode> e = dominator.getChildren(b);
207        while (e.hasMoreElements()) {
208          DominatorTreeNode n = (DominatorTreeNode) e.nextElement();
209          BasicBlock bl = n.getBlock();
210          // don't process infrequently executed basic blocks
211          if (ir.options.FREQ_FOCUS_EFFORT && bl.getInfrequent()) continue;
212          globalCSE(bl);
213        }
214        // Iterate over instructions in this basic block removing
215        // available expressions that had been created for this block
216        inst = b.firstInstruction();
217        while (!BBend.conforms(inst)) {
218          next = inst.nextInstructionInCodeOrder();
219          if (!shouldCSE(inst)) {
220            inst = next;
221            continue;
222          }
223          RegisterOperand result = getResult(inst);
224          if (result == null) {
225            inst = next;
226            continue;
227          }
228          int vn = valueNumbers.getValueNumber(result);
229          if (vn < 0) {
230            inst = next;
231            continue;
232          }
233          Integer Vn = vn;
234          Instruction former = avail.get(Vn);
235          if (former == inst) {
236            avail.remove(Vn);
237          }
238          inst = next;
239        }
240      }
241    
242      /**
243       * Get the result operand of the instruction
244       * @param inst
245       */
246      private RegisterOperand getResult(Instruction inst) {
247        if (ResultCarrier.conforms(inst)) {
248          return ResultCarrier.getResult(inst);
249        }
250        if (GuardResultCarrier.conforms(inst)) {
251          return GuardResultCarrier.getGuardResult(inst);
252        }
253        return null;
254      }
255    
256      /**
257       * should this instruction be cse'd  ?
258       * @param inst
259       */
260      private boolean shouldCSE(Instruction inst) {
261    
262        if ((inst.isAllocation()) ||
263            inst.isDynamicLinkingPoint() ||
264            inst.isImplicitLoad() ||
265            inst.isImplicitStore() ||
266            inst.operator.opcode >= ARCH_INDEPENDENT_END_opcode) {
267          return false;
268        }
269    
270        switch (inst.operator.opcode) {
271          case INT_MOVE_opcode:
272          case LONG_MOVE_opcode:
273          case CHECKCAST_opcode:
274          case CHECKCAST_NOTNULL_opcode:
275          case CHECKCAST_UNRESOLVED_opcode:
276          case MUST_IMPLEMENT_INTERFACE_opcode:
277          case INSTANCEOF_opcode:
278          case INSTANCEOF_NOTNULL_opcode:
279          case INSTANCEOF_UNRESOLVED_opcode:
280          case PI_opcode:
281          case FLOAT_MOVE_opcode:
282          case DOUBLE_MOVE_opcode:
283          case REF_MOVE_opcode:
284          case GUARD_MOVE_opcode:
285          case GUARD_COMBINE_opcode:
286          case TRAP_IF_opcode:
287          case REF_ADD_opcode:
288          case INT_ADD_opcode:
289          case LONG_ADD_opcode:
290          case FLOAT_ADD_opcode:
291          case DOUBLE_ADD_opcode:
292          case REF_SUB_opcode:
293          case INT_SUB_opcode:
294          case LONG_SUB_opcode:
295          case FLOAT_SUB_opcode:
296          case DOUBLE_SUB_opcode:
297          case INT_MUL_opcode:
298          case LONG_MUL_opcode:
299          case FLOAT_MUL_opcode:
300          case DOUBLE_MUL_opcode:
301          case INT_DIV_opcode:
302          case LONG_DIV_opcode:
303          case FLOAT_DIV_opcode:
304          case DOUBLE_DIV_opcode:
305          case INT_REM_opcode:
306          case LONG_REM_opcode:
307          case FLOAT_REM_opcode:
308          case DOUBLE_REM_opcode:
309          case INT_NEG_opcode:
310          case LONG_NEG_opcode:
311          case FLOAT_NEG_opcode:
312          case DOUBLE_NEG_opcode:
313          case REF_SHL_opcode:
314          case INT_SHL_opcode:
315          case LONG_SHL_opcode:
316          case REF_SHR_opcode:
317          case INT_SHR_opcode:
318          case LONG_SHR_opcode:
319          case REF_USHR_opcode:
320          case INT_USHR_opcode:
321          case LONG_USHR_opcode:
322          case REF_AND_opcode:
323          case INT_AND_opcode:
324          case LONG_AND_opcode:
325          case REF_OR_opcode:
326          case INT_OR_opcode:
327          case LONG_OR_opcode:
328          case REF_XOR_opcode:
329          case INT_XOR_opcode:
330          case REF_NOT_opcode:
331          case INT_NOT_opcode:
332          case LONG_NOT_opcode:
333          case LONG_XOR_opcode:
334          case INT_2LONG_opcode:
335          case INT_2FLOAT_opcode:
336          case INT_2DOUBLE_opcode:
337          case INT_2ADDRSigExt_opcode:
338          case INT_2ADDRZerExt_opcode:
339          case LONG_2ADDR_opcode:
340          case ADDR_2INT_opcode:
341          case ADDR_2LONG_opcode:
342          case LONG_2INT_opcode:
343          case LONG_2FLOAT_opcode:
344          case LONG_2DOUBLE_opcode:
345          case FLOAT_2INT_opcode:
346          case FLOAT_2LONG_opcode:
347          case FLOAT_2DOUBLE_opcode:
348          case DOUBLE_2INT_opcode:
349          case DOUBLE_2LONG_opcode:
350          case DOUBLE_2FLOAT_opcode:
351          case INT_2BYTE_opcode:
352          case INT_2USHORT_opcode:
353          case INT_2SHORT_opcode:
354          case LONG_CMP_opcode:
355          case FLOAT_CMPL_opcode:
356          case FLOAT_CMPG_opcode:
357          case DOUBLE_CMPL_opcode:
358          case DOUBLE_CMPG_opcode:
359          case NULL_CHECK_opcode:
360          case BOUNDS_CHECK_opcode:
361          case INT_ZERO_CHECK_opcode:
362          case LONG_ZERO_CHECK_opcode:
363          case OBJARRAY_STORE_CHECK_opcode:
364          case OBJARRAY_STORE_CHECK_NOTNULL_opcode:
365          case BOOLEAN_NOT_opcode:
366          case BOOLEAN_CMP_INT_opcode:
367          case BOOLEAN_CMP_ADDR_opcode:
368          case FLOAT_AS_INT_BITS_opcode:
369          case INT_BITS_AS_FLOAT_opcode:
370          case DOUBLE_AS_LONG_BITS_opcode:
371          case LONG_BITS_AS_DOUBLE_opcode:
372          case ARRAYLENGTH_opcode:
373          case GET_OBJ_TIB_opcode:
374          case GET_CLASS_TIB_opcode:
375          case GET_TYPE_FROM_TIB_opcode:
376          case GET_SUPERCLASS_IDS_FROM_TIB_opcode:
377          case GET_DOES_IMPLEMENT_FROM_TIB_opcode:
378          case GET_ARRAY_ELEMENT_TIB_FROM_TIB_opcode:
379            return !(GCP.usesOrDefsPhysicalRegisterOrAddressType(inst));
380        }
381        return false;
382      }
383    }