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 }