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 }