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 */ 013package org.jikesrvm.compilers.opt.liveness; 014 015import java.util.HashMap; 016 017import org.jikesrvm.compilers.opt.ir.BasicBlock; 018import org.jikesrvm.compilers.opt.ir.Instruction; 019import org.jikesrvm.compilers.opt.ir.Register; 020import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 021import org.jikesrvm.compilers.opt.regalloc.LiveIntervalElement; 022 023/** 024 * This class contains liveness information. 025 */ 026public final class LiveInterval { 027 028 private static final boolean DEBUG = false; 029 030 private final HashMap<BasicBlock, LiveIntervalElement> liveIntervals; 031 032 public LiveInterval() { 033 liveIntervals = new HashMap<BasicBlock, LiveIntervalElement>(); 034 } 035 036 /** 037 * This method iterates over each element in the the passed live set. 038 * For each element, it checks if an existing live interval node for 039 * the basic block passed exists. If one does not exist, it creates 040 * a node with the end instruction being "inst". If one already exists 041 * no action is taken. 042 * 043 * @param set the set of registers, encoded as a LiveSet object 044 * @param block the basic block 045 * @param inst the instruction where the register's live range ends, 046 * null represents the end of the basic block 047 */ 048 public void createEndLiveRange(LiveSet set, BasicBlock block, Instruction inst) { 049 if (DEBUG) { 050 if (inst == null) { 051 System.out.println("The following are live on exit of block " + block.getNumber() + "\n" + set); 052 } else { 053 System.out.println("The following are live ending at inst\n " + 054 inst + 055 " for block " + 056 block.getNumber() + 057 "\n" + 058 set); 059 } 060 } 061 062 LiveSetEnumerator lsEnum = set.enumerator(); 063 while (lsEnum.hasMoreElements()) { 064 RegisterOperand regOp = lsEnum.nextElement(); 065 createEndLiveRange(regOp.getRegister(), block, inst); 066 } 067 } 068 069 /** 070 * This method checks if an existing unresolved live interval node, i.e., 071 * one that has an end instruction, but no beginning instruction, is present 072 * for the register and basic block passed. If one does not exist, it 073 * creates a node with the end instruction being <code>inst</code>. If one 074 * already exists no action is taken. 075 * 076 * @param reg The register 077 * @param block The basic block 078 * @param inst The end instruction to use, if we have to create a neode. 079 */ 080 public void createEndLiveRange(Register reg, BasicBlock block, Instruction inst) { 081 082 if (DEBUG) { 083 System.out.println("Marking Register " + 084 reg + 085 "'s live range as ENDing at instruction\n " + 086 inst + 087 " in block #" + 088 block.getNumber()); 089 printLiveIntervalList(block); 090 } 091 092 if (!containsUnresolvedElement(block, reg)) { 093 LiveIntervalElement elem = new LiveIntervalElement(reg, null, inst); 094 prependLiveIntervalElement(block, elem); 095 } 096 } 097 098 private void prependLiveIntervalElement(BasicBlock block, 099 LiveIntervalElement elem) { 100 elem.setNext(liveIntervals.get(block)); 101 liveIntervals.put(block, elem); 102 } 103 104 /** 105 * This method finds the LiveInterval node for the register and basic block 106 * passed. It then sets the begin instruction to the instruction passed 107 * and moves the node to the proper place on the list block list. 108 * (The block list is sorted by "begin" instruction. 109 * 110 * @param reg the register of interest 111 * @param inst the "begin" instruction 112 * @param block the basic block of interest 113 */ 114 public void setStartLiveRange(Register reg, Instruction inst, BasicBlock block) { 115 if (DEBUG) { 116 System.out.println("Marking Register " + 117 reg + 118 "'s live range as STARTing at instruction\n " + 119 inst + 120 " in block #" + 121 block.getNumber()); 122 } 123 124 LiveIntervalElement prev = null; 125 LiveIntervalElement elem = getFirstLiveIntervalElement(block); 126 while (elem != null) { 127 if (elem.getRegister() == reg && elem.getBegin() == null) { 128 break; 129 } 130 131 prev = elem; 132 elem = elem.getNext(); 133 } 134 135 if (elem != null) { 136 elem.setBegin(inst); 137 138 // we want the list sorted by "begin" instruction. Since 139 // we are *assuming* that we are called in a traversal that is 140 // visiting instructions backwards, the instr passed will always 141 // be the most recent. Thus, we move "elem" to the front of the list. 142 if (prev != null) { 143 // remove elem from current position 144 prev.setNext(elem.getNext()); 145 146 // add it to the begining 147 prependLiveIntervalElement(block, elem); 148 } 149 150 // if prev == null, the element is already first in the list! 151 } else { 152 // if we didn't find it, it means we have a def that is not later 153 // used, i.e., a dead assignment. This may exist because the 154 // instruction has side effects such as a function call or a PEI 155 // In this case, we create a LiveIntervalElement node with begining 156 // and ending instruction "inst" 157 LiveIntervalElement newElem = new LiveIntervalElement(reg, inst, inst); 158 prependLiveIntervalElement(block, newElem); 159 } 160 161 if (DEBUG) { 162 System.out.println("after add"); 163 printLiveIntervalList(block); 164 } 165 } 166 167 /** 168 * This method finds any LiveInterval node that does not have a start 169 * instruction (it is null) and moves this node to the front of the list. 170 * 171 * @param block the basic block of interest 172 */ 173 public void moveUpwardExposedRegsToFront(BasicBlock block) { 174 175 LiveIntervalElement prev = getFirstLiveIntervalElement(block); 176 if (prev == null) { 177 return; 178 } 179 180 // The first element is already at the front, so move on to the next one 181 LiveIntervalElement elem = prev.getNext(); 182 183 while (elem != null) { 184 if (elem.getBegin() == null) { 185 // remove elem from current position 186 prev.setNext(elem.getNext()); 187 188 // add it to the begining, se 189 prependLiveIntervalElement(block, elem); 190 191 // the next victum is the *new* one after prev 192 elem = prev.getNext(); 193 } else { 194 prev = elem; 195 elem = elem.getNext(); 196 } 197 } 198 } 199 200 /** 201 * Check to see if an unresolved LiveIntervalElement node for the register 202 * passed exists for the basic block passed. 203 * 204 * @param block the block 205 * @param reg the register of interest 206 * @return <code>true</code> if it does or <code>false</code> 207 * if it does not 208 */ 209 private boolean containsUnresolvedElement(BasicBlock block, Register reg) { 210 211 if (DEBUG) { 212 System.out.println("containsUnresolvedElement called, block: " + block + " register: " + reg); 213 printLiveIntervalList(block); 214 } 215 216 for (LiveIntervalElement elem = getFirstLiveIntervalElement(block); elem != null; elem = elem.getNext()) { 217 // if we got an element, down case it to LiveIntervalElement 218 if (elem.getRegister() == reg && elem.getBegin() == null) { 219 return true; 220 } 221 } 222 return false; 223 } 224 225 public LiveIntervalElement getFirstLiveIntervalElement(BasicBlock bb) { 226 return liveIntervals.get(bb); 227 } 228 229 public LiveIntervalEnumeration enumerateLiveIntervals(BasicBlock bb) { 230 return new LiveIntervalEnumeration(liveIntervals.get(bb)); 231 } 232 233 /** 234 * Print the live intervals for a block. 235 * 236 * @param block the block 237 */ 238 public void printLiveIntervalList(BasicBlock block) { 239 System.out.println("Live Interval List for " + block); 240 for (LiveIntervalElement elem = getFirstLiveIntervalElement(block); elem != null; elem = elem.getNext()) { 241 System.out.println(" " + elem); 242 } 243 } 244}