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.Iterator; 017 018 import org.jikesrvm.compilers.opt.DefUse; 019 import org.jikesrvm.compilers.opt.ir.BasicBlock; 020 import org.jikesrvm.compilers.opt.ir.IR; 021 import org.jikesrvm.compilers.opt.ir.Instruction; 022 import static org.jikesrvm.compilers.opt.ir.Operators.SPLIT; 023 import org.jikesrvm.compilers.opt.ir.Register; 024 import org.jikesrvm.compilers.opt.ir.Unary; 025 import org.jikesrvm.compilers.opt.ir.operand.Operand; 026 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 027 import org.jikesrvm.compilers.opt.liveness.LiveAnalysis; 028 029 /** 030 * Utility to help coalesce registers. 031 * 032 * @see CoalesceMoves 033 */ 034 class Coalesce { 035 036 /** 037 * Attempt to coalesce register r2 into register r1. If this is legal, 038 * <ul> 039 * <li> rewrite all defs and uses of r2 as defs and uses of r1 040 * <li> update the liveness information 041 * <li> update the def-use chains 042 * </ul> 043 * <strong>PRECONDITION </strong> def-use chains must be computed and valid. 044 * <strong>PRECONDITION </strong> instructions are numbered, with 045 * numbers stored in Instruction.scratch 046 * 047 * @param ir the governing IR 048 * @param live liveness information for the IR 049 * @param r1 050 * @param r2 051 * @return true if the transformation succeeded, false otherwise. 052 */ 053 public static boolean attempt(IR ir, LiveAnalysis live, Register r1, Register r2) { 054 055 // make sure r1 and r2 are not simultaneously live 056 if (isLiveAtDef(r2, r1, live)) return false; 057 if (isLiveAtDef(r1, r2, live)) return false; 058 059 // Liveness is OK. Check for SPLIT operations 060 if (split(r1, r2)) return false; 061 062 // Don't merge a register with itself 063 if (r1 == r2) return false; 064 065 // Update liveness information to reflect the merge. 066 live.merge(r1, r2); 067 068 // Merge the defs. 069 for (Enumeration<RegisterOperand> e = DefUse.defs(r2); e.hasMoreElements();) { 070 RegisterOperand def = e.nextElement(); 071 DefUse.removeDef(def); 072 def.setRegister(r1); 073 DefUse.recordDef(def); 074 } 075 // Merge the uses. 076 for (Enumeration<RegisterOperand> e = DefUse.uses(r2); e.hasMoreElements();) { 077 RegisterOperand use = e.nextElement(); 078 DefUse.removeUse(use); 079 use.setRegister(r1); 080 DefUse.recordUse(use); 081 } 082 return true; 083 } 084 085 /** 086 * Is register r1 live at any def of register r2? 087 * <p> 088 * <strong>PRECONDITION </strong> def-use chains must be computed and valid. 089 * <strong>PRECONDITION </strong> instructions are numbered, with 090 * numbers stored in Instruction.scratch 091 * 092 * <p> Note: this implementation is not efficient. The liveness data 093 * structures must be re-designed to support this efficiently. 094 */ 095 private static boolean isLiveAtDef(Register r1, Register r2, LiveAnalysis live) { 096 097 for (Iterator<LiveIntervalElement> e = live.iterateLiveIntervals(r1); e.hasNext();) { 098 LiveIntervalElement elem = e.next(); 099 BasicBlock bb = elem.getBasicBlock(); 100 Instruction begin = (elem.getBegin() == null) ? bb.firstInstruction() : elem.getBegin(); 101 Instruction end = (elem.getEnd() == null) ? bb.lastInstruction() : elem.getEnd(); 102 int low = begin.scratch; 103 int high = end.scratch; 104 for (Enumeration<RegisterOperand> defs = DefUse.defs(r2); defs.hasMoreElements();) { 105 Operand def = defs.nextElement(); 106 int n = def.instruction.scratch; 107 if (n >= low && n < high) { 108 return true; 109 } 110 } 111 } 112 113 // no conflict was found. 114 return false; 115 } 116 117 /** 118 * Is there an instruction r1 = split r2 or r2 = split r1?? 119 */ 120 private static boolean split(Register r1, Register r2) { 121 for (Enumeration<RegisterOperand> e = DefUse.defs(r1); e.hasMoreElements();) { 122 RegisterOperand def = e.nextElement(); 123 Instruction s = def.instruction; 124 if (s.operator == SPLIT) { 125 Operand rhs = Unary.getVal(s); 126 if (rhs.similar(def)) return true; 127 } 128 } 129 for (Enumeration<RegisterOperand> e = DefUse.defs(r2); e.hasMoreElements();) { 130 RegisterOperand def = e.nextElement(); 131 Instruction s = def.instruction; 132 if (s.operator == SPLIT) { 133 Operand rhs = Unary.getVal(s); 134 if (rhs.similar(def)) return true; 135 } 136 } 137 return false; 138 } 139 }