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.Enumeration;
016    import java.util.HashSet;
017    
018    import org.jikesrvm.compilers.opt.DefUse;
019    import org.jikesrvm.compilers.opt.OptOptions;
020    import org.jikesrvm.compilers.opt.driver.CompilerPhase;
021    import org.jikesrvm.compilers.opt.ir.IR;
022    import org.jikesrvm.compilers.opt.ir.Instruction;
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      @Override
045      public CompilerPhase newExecution(IR ir) {
046        return this;
047      }
048    
049      /**
050       * Should we perform this phase?
051       * @return <code>true</code> iff move instructions should be
052       *  coalesced after leaving SSA
053       */
054      @Override
055      public final boolean shouldPerform(OptOptions options) {
056        return options.SSA_COALESCE_AFTER;
057      }
058    
059      /**
060       * Return a string name for this phase.
061       * @return "Coalesce Moves"
062       */
063      @Override
064      public final String getName() {
065        return "Coalesce Moves";
066      }
067    
068      @Override
069      public final void perform(IR ir) {
070        // Compute liveness.
071        LiveAnalysis live = new LiveAnalysis(false /* GC Maps */, false /* don't skip local
072                                                             propagation */);
073        live.perform(ir);
074    
075        // Compute def-use information.
076        DefUse.computeDU(ir);
077    
078        // Number the instructions
079        ir.numberInstructions();
080    
081        // Maintain a set of dead move instructions.
082        HashSet<Instruction> dead = new HashSet<Instruction>(5);
083    
084        // for each Move instruction ...
085        for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements();) {
086          Instruction s = e.nextElement();
087          if (s.operator.isMove()) {
088            Register r = Move.getResult(s).asRegister().getRegister();
089            if (r.isSymbolic()) {
090              Operand val = Move.getVal(s);
091              if (val != null && val.isRegister()) {
092                Register r2 = val.asRegister().getRegister();
093                if (r2.isSymbolic()) {
094                  if (Coalesce.attempt(ir, live, r, r2)) {
095                    if (DEBUG) System.out.println("COALESCED " + r + " " + r2);
096                    dead.add(s);
097                  }
098                }
099              }
100            }
101          }
102        }
103    
104        // Now remove all dead Move instructions.
105        for (Instruction s : dead) {
106          DefUse.removeInstructionAndUpdateDU(s);
107        }
108      }
109    }