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.regalloc;
014    
015    import java.util.HashSet;
016    
017    import org.jikesrvm.compilers.opt.DefUse;
018    import org.jikesrvm.compilers.opt.OptOptions;
019    import org.jikesrvm.compilers.opt.driver.CompilerPhase;
020    import org.jikesrvm.compilers.opt.ir.IR;
021    import org.jikesrvm.compilers.opt.ir.Instruction;
022    import org.jikesrvm.compilers.opt.ir.InstructionEnumeration;
023    import org.jikesrvm.compilers.opt.ir.Move;
024    import org.jikesrvm.compilers.opt.ir.Register;
025    import org.jikesrvm.compilers.opt.ir.operand.Operand;
026    import org.jikesrvm.compilers.opt.liveness.LiveAnalysis;
027    
028    /**
029     * Coalesce registers in move instructions where possible.
030     */
031    public class CoalesceMoves extends CompilerPhase {
032    
033      /**
034       *  verbose debugging flag
035       */
036      static final boolean DEBUG = false;
037    
038      /**
039       * Return this instance of this phase. This phase contains no
040       * per-compilation instance fields.
041       * @param ir not used
042       * @return this
043       */
044      public CompilerPhase newExecution(IR ir) {
045        return this;
046      }
047    
048      /**
049       * Should we perform this phase?
050       * @param options controlling compiler options
051       */
052      public final boolean shouldPerform(OptOptions options) {
053        return options.SSA_COALESCE_AFTER;
054      }
055    
056      /**
057       * Return a string name for this phase.
058       * @return "Coalesce Moves"
059       */
060      public final String getName() {
061        return "Coalesce Moves";
062      }
063    
064      /**
065       * perform the transformation
066       * @param ir the governing IR
067       */
068      public final void perform(IR ir) {
069        // Compute liveness.
070        LiveAnalysis live = new LiveAnalysis(false /* GC Maps */, false /* don't skip local
071                                                             propagation */);
072        live.perform(ir);
073    
074        // Compute def-use information.
075        DefUse.computeDU(ir);
076    
077        // Number the instructions
078        ir.numberInstructions();
079    
080        // Maintain a set of dead move instructions.
081        HashSet<Instruction> dead = new HashSet<Instruction>(5);
082    
083        // for each Move instruction ...
084        for (InstructionEnumeration e = ir.forwardInstrEnumerator(); e.hasMoreElements();) {
085          Instruction s = e.nextElement();
086          if (s.operator.isMove()) {
087            Register r = Move.getResult(s).asRegister().getRegister();
088            if (r.isSymbolic()) {
089              Operand val = Move.getVal(s);
090              if (val != null && val.isRegister()) {
091                Register r2 = val.asRegister().getRegister();
092                if (r2.isSymbolic()) {
093                  if (Coalesce.attempt(ir, live, r, r2)) {
094                    if (DEBUG) System.out.println("COALESCED " + r + " " + r2);
095                    dead.add(s);
096                  }
097                }
098              }
099            }
100          }
101        }
102    
103        // Now remove all dead Move instructions.
104        for (Instruction s : dead) {
105          DefUse.removeInstructionAndUpdateDU(s);
106        }
107      }
108    }