Chris Lattner | a3b8b5c | 2004-07-23 17:56:30 +0000 | [diff] [blame] | 1 | //===-- LiveIntervalAnalysis.h - Live Interval Analysis ---------*- C++ -*-===// |
Alkis Evlogimenos | ff0cbe1 | 2003-11-20 03:32:25 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by the LLVM research group and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
Chris Lattner | 6b92906 | 2004-07-19 02:13:59 +0000 | [diff] [blame] | 10 | // This file implements the LiveInterval analysis pass. Given some numbering of |
| 11 | // each the machine instructions (in this implemention depth-first order) an |
| 12 | // interval [i, j) is said to be a live interval for register v if there is no |
| 13 | // instruction with number j' > j such that v is live at j' abd there is no |
| 14 | // instruction with number i' < i such that v is live at i'. In this |
| 15 | // implementation intervals can have holes, i.e. an interval might look like |
| 16 | // [1,20), [50,65), [1000,1001). |
Alkis Evlogimenos | ff0cbe1 | 2003-11-20 03:32:25 +0000 | [diff] [blame] | 17 | // |
| 18 | //===----------------------------------------------------------------------===// |
| 19 | |
Chris Lattner | a3b8b5c | 2004-07-23 17:56:30 +0000 | [diff] [blame] | 20 | #ifndef LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H |
| 21 | #define LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H |
Alkis Evlogimenos | ff0cbe1 | 2003-11-20 03:32:25 +0000 | [diff] [blame] | 22 | |
| 23 | #include "llvm/CodeGen/MachineFunctionPass.h" |
Chris Lattner | 779a651 | 2005-09-21 04:18:25 +0000 | [diff] [blame] | 24 | #include "llvm/CodeGen/LiveInterval.h" |
Evan Cheng | 61de82d | 2007-02-15 05:59:24 +0000 | [diff] [blame] | 25 | #include "llvm/ADT/BitVector.h" |
Evan Cheng | 20b0abc | 2007-04-17 20:32:26 +0000 | [diff] [blame] | 26 | #include "llvm/ADT/DenseMap.h" |
Chris Lattner | 94c002a | 2007-02-01 05:32:05 +0000 | [diff] [blame] | 27 | #include "llvm/ADT/IndexedMap.h" |
Evan Cheng | 549f27d3 | 2007-08-13 23:45:17 +0000 | [diff] [blame] | 28 | #include "llvm/ADT/SmallPtrSet.h" |
| 29 | #include "llvm/ADT/SmallVector.h" |
Evan Cheng | f3bb2e6 | 2007-09-05 21:46:51 +0000 | [diff] [blame] | 30 | #include "llvm/Support/Allocator.h" |
Alkis Evlogimenos | ff0cbe1 | 2003-11-20 03:32:25 +0000 | [diff] [blame] | 31 | |
| 32 | namespace llvm { |
| 33 | |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 34 | class LiveVariables; |
| 35 | class MRegisterInfo; |
Chris Lattner | f768bba | 2005-03-09 23:05:19 +0000 | [diff] [blame] | 36 | class TargetInstrInfo; |
Evan Cheng | 20b0abc | 2007-04-17 20:32:26 +0000 | [diff] [blame] | 37 | class TargetRegisterClass; |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 38 | class VirtRegMap; |
Evan Cheng | 4ca980e | 2007-10-17 02:10:22 +0000 | [diff] [blame^] | 39 | typedef std::pair<unsigned, MachineBasicBlock*> IdxMBBPair; |
Alkis Evlogimenos | ff0cbe1 | 2003-11-20 03:32:25 +0000 | [diff] [blame] | 40 | |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 41 | class LiveIntervals : public MachineFunctionPass { |
| 42 | MachineFunction* mf_; |
| 43 | const TargetMachine* tm_; |
| 44 | const MRegisterInfo* mri_; |
Chris Lattner | f768bba | 2005-03-09 23:05:19 +0000 | [diff] [blame] | 45 | const TargetInstrInfo* tii_; |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 46 | LiveVariables* lv_; |
Alkis Evlogimenos | ff0cbe1 | 2003-11-20 03:32:25 +0000 | [diff] [blame] | 47 | |
Evan Cheng | f3bb2e6 | 2007-09-05 21:46:51 +0000 | [diff] [blame] | 48 | /// Special pool allocator for VNInfo's (LiveInterval val#). |
| 49 | /// |
| 50 | BumpPtrAllocator VNInfoAllocator; |
| 51 | |
Evan Cheng | 549f27d3 | 2007-08-13 23:45:17 +0000 | [diff] [blame] | 52 | /// MBB2IdxMap - The indexes of the first and last instructions in the |
| 53 | /// specified basic block. |
| 54 | std::vector<std::pair<unsigned, unsigned> > MBB2IdxMap; |
David Greene | 2513330 | 2007-06-08 17:18:56 +0000 | [diff] [blame] | 55 | |
Evan Cheng | 4ca980e | 2007-10-17 02:10:22 +0000 | [diff] [blame^] | 56 | /// Idx2MBBMap - Sorted list of pairs of index of first instruction |
| 57 | /// and MBB id. |
| 58 | std::vector<IdxMBBPair> Idx2MBBMap; |
| 59 | |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 60 | typedef std::map<MachineInstr*, unsigned> Mi2IndexMap; |
| 61 | Mi2IndexMap mi2iMap_; |
Alkis Evlogimenos | ff0cbe1 | 2003-11-20 03:32:25 +0000 | [diff] [blame] | 62 | |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 63 | typedef std::vector<MachineInstr*> Index2MiMap; |
| 64 | Index2MiMap i2miMap_; |
Alkis Evlogimenos | 843b160 | 2004-02-15 10:24:21 +0000 | [diff] [blame] | 65 | |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 66 | typedef std::map<unsigned, LiveInterval> Reg2IntervalMap; |
| 67 | Reg2IntervalMap r2iMap_; |
Alkis Evlogimenos | ff0cbe1 | 2003-11-20 03:32:25 +0000 | [diff] [blame] | 68 | |
Evan Cheng | 61de82d | 2007-02-15 05:59:24 +0000 | [diff] [blame] | 69 | BitVector allocatableRegs_; |
Evan Cheng | 88d1f58 | 2007-03-01 02:03:03 +0000 | [diff] [blame] | 70 | |
Evan Cheng | 549f27d3 | 2007-08-13 23:45:17 +0000 | [diff] [blame] | 71 | std::vector<MachineInstr*> ClonedMIs; |
| 72 | |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 73 | public: |
Nick Lewycky | ecd94c8 | 2007-05-06 13:37:16 +0000 | [diff] [blame] | 74 | static char ID; // Pass identification, replacement for typeid |
Devang Patel | 794fd75 | 2007-05-01 21:15:47 +0000 | [diff] [blame] | 75 | LiveIntervals() : MachineFunctionPass((intptr_t)&ID) {} |
| 76 | |
Chris Lattner | f7da2c7 | 2006-08-24 22:43:55 +0000 | [diff] [blame] | 77 | struct InstrSlots { |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 78 | enum { |
| 79 | LOAD = 0, |
| 80 | USE = 1, |
| 81 | DEF = 2, |
| 82 | STORE = 3, |
Chris Lattner | 410354f | 2006-02-22 16:23:43 +0000 | [diff] [blame] | 83 | NUM = 4 |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 84 | }; |
Alkis Evlogimenos | ff0cbe1 | 2003-11-20 03:32:25 +0000 | [diff] [blame] | 85 | }; |
| 86 | |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 87 | static unsigned getBaseIndex(unsigned index) { |
| 88 | return index - (index % InstrSlots::NUM); |
| 89 | } |
| 90 | static unsigned getBoundaryIndex(unsigned index) { |
| 91 | return getBaseIndex(index + InstrSlots::NUM - 1); |
| 92 | } |
| 93 | static unsigned getLoadIndex(unsigned index) { |
| 94 | return getBaseIndex(index) + InstrSlots::LOAD; |
| 95 | } |
| 96 | static unsigned getUseIndex(unsigned index) { |
| 97 | return getBaseIndex(index) + InstrSlots::USE; |
| 98 | } |
| 99 | static unsigned getDefIndex(unsigned index) { |
| 100 | return getBaseIndex(index) + InstrSlots::DEF; |
| 101 | } |
| 102 | static unsigned getStoreIndex(unsigned index) { |
| 103 | return getBaseIndex(index) + InstrSlots::STORE; |
| 104 | } |
| 105 | |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 106 | typedef Reg2IntervalMap::iterator iterator; |
Chris Lattner | 70ca358 | 2004-09-30 15:59:17 +0000 | [diff] [blame] | 107 | typedef Reg2IntervalMap::const_iterator const_iterator; |
| 108 | const_iterator begin() const { return r2iMap_.begin(); } |
| 109 | const_iterator end() const { return r2iMap_.end(); } |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 110 | iterator begin() { return r2iMap_.begin(); } |
| 111 | iterator end() { return r2iMap_.end(); } |
| 112 | unsigned getNumIntervals() const { return r2iMap_.size(); } |
| 113 | |
| 114 | LiveInterval &getInterval(unsigned reg) { |
| 115 | Reg2IntervalMap::iterator I = r2iMap_.find(reg); |
| 116 | assert(I != r2iMap_.end() && "Interval does not exist for register"); |
| 117 | return I->second; |
| 118 | } |
| 119 | |
| 120 | const LiveInterval &getInterval(unsigned reg) const { |
| 121 | Reg2IntervalMap::const_iterator I = r2iMap_.find(reg); |
| 122 | assert(I != r2iMap_.end() && "Interval does not exist for register"); |
| 123 | return I->second; |
| 124 | } |
| 125 | |
Evan Cheng | b371f45 | 2007-02-19 21:49:54 +0000 | [diff] [blame] | 126 | bool hasInterval(unsigned reg) const { |
Evan Cheng | 88d1f58 | 2007-03-01 02:03:03 +0000 | [diff] [blame] | 127 | return r2iMap_.count(reg); |
Evan Cheng | b371f45 | 2007-02-19 21:49:54 +0000 | [diff] [blame] | 128 | } |
| 129 | |
Chris Lattner | 428b92e | 2006-09-15 03:57:23 +0000 | [diff] [blame] | 130 | /// getMBBStartIdx - Return the base index of the first instruction in the |
| 131 | /// specified MachineBasicBlock. |
| 132 | unsigned getMBBStartIdx(MachineBasicBlock *MBB) const { |
| 133 | return getMBBStartIdx(MBB->getNumber()); |
| 134 | } |
Chris Lattner | 428b92e | 2006-09-15 03:57:23 +0000 | [diff] [blame] | 135 | unsigned getMBBStartIdx(unsigned MBBNo) const { |
| 136 | assert(MBBNo < MBB2IdxMap.size() && "Invalid MBB number!"); |
Evan Cheng | 549f27d3 | 2007-08-13 23:45:17 +0000 | [diff] [blame] | 137 | return MBB2IdxMap[MBBNo].first; |
| 138 | } |
| 139 | |
| 140 | /// getMBBEndIdx - Return the store index of the last instruction in the |
| 141 | /// specified MachineBasicBlock. |
| 142 | unsigned getMBBEndIdx(MachineBasicBlock *MBB) const { |
| 143 | return getMBBEndIdx(MBB->getNumber()); |
| 144 | } |
| 145 | unsigned getMBBEndIdx(unsigned MBBNo) const { |
| 146 | assert(MBBNo < MBB2IdxMap.size() && "Invalid MBB number!"); |
| 147 | return MBB2IdxMap[MBBNo].second; |
Chris Lattner | 428b92e | 2006-09-15 03:57:23 +0000 | [diff] [blame] | 148 | } |
| 149 | |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 150 | /// getInstructionIndex - returns the base index of instr |
| 151 | unsigned getInstructionIndex(MachineInstr* instr) const { |
| 152 | Mi2IndexMap::const_iterator it = mi2iMap_.find(instr); |
| 153 | assert(it != mi2iMap_.end() && "Invalid instruction!"); |
| 154 | return it->second; |
| 155 | } |
| 156 | |
| 157 | /// getInstructionFromIndex - given an index in any slot of an |
| 158 | /// instruction return a pointer the instruction |
| 159 | MachineInstr* getInstructionFromIndex(unsigned index) const { |
| 160 | index /= InstrSlots::NUM; // convert index to vector index |
| 161 | assert(index < i2miMap_.size() && |
| 162 | "index does not correspond to an instruction"); |
| 163 | return i2miMap_[index]; |
| 164 | } |
David Greene | 2513330 | 2007-06-08 17:18:56 +0000 | [diff] [blame] | 165 | |
Evan Cheng | 4ca980e | 2007-10-17 02:10:22 +0000 | [diff] [blame^] | 166 | /// findLiveInMBBs - Given a live range, if the value of the range |
| 167 | /// is live in any MBB returns true as well as the list of basic blocks |
| 168 | /// where the value is live in. |
| 169 | bool findLiveInMBBs(const LiveRange &LR, |
| 170 | SmallVector<MachineBasicBlock*, 4> &MBBs) const; |
| 171 | |
David Greene | 2513330 | 2007-06-08 17:18:56 +0000 | [diff] [blame] | 172 | // Interval creation |
| 173 | |
| 174 | LiveInterval &getOrCreateInterval(unsigned reg) { |
| 175 | Reg2IntervalMap::iterator I = r2iMap_.find(reg); |
| 176 | if (I == r2iMap_.end()) |
| 177 | I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg))); |
| 178 | return I->second; |
| 179 | } |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 180 | |
David Greene | 2513330 | 2007-06-08 17:18:56 +0000 | [diff] [blame] | 181 | std::vector<LiveInterval*> addIntervalsForSpills(const LiveInterval& i, |
Evan Cheng | 549f27d3 | 2007-08-13 23:45:17 +0000 | [diff] [blame] | 182 | VirtRegMap& vrm, unsigned reg); |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 183 | |
David Greene | 2513330 | 2007-06-08 17:18:56 +0000 | [diff] [blame] | 184 | // Interval removal |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 185 | |
David Greene | 2513330 | 2007-06-08 17:18:56 +0000 | [diff] [blame] | 186 | void removeInterval(unsigned Reg) { |
| 187 | r2iMap_.erase(Reg); |
Bill Wendling | 5c7e326 | 2006-12-17 05:15:13 +0000 | [diff] [blame] | 188 | } |
Chris Lattner | 70ca358 | 2004-09-30 15:59:17 +0000 | [diff] [blame] | 189 | |
Evan Cheng | 30cac02 | 2007-02-22 23:03:39 +0000 | [diff] [blame] | 190 | /// isRemoved - returns true if the specified machine instr has been |
| 191 | /// removed. |
| 192 | bool isRemoved(MachineInstr* instr) const { |
Evan Cheng | 7d35c0e | 2007-02-22 23:52:23 +0000 | [diff] [blame] | 193 | return !mi2iMap_.count(instr); |
Evan Cheng | 30cac02 | 2007-02-22 23:03:39 +0000 | [diff] [blame] | 194 | } |
| 195 | |
Chris Lattner | f7da2c7 | 2006-08-24 22:43:55 +0000 | [diff] [blame] | 196 | /// RemoveMachineInstrFromMaps - This marks the specified machine instr as |
| 197 | /// deleted. |
| 198 | void RemoveMachineInstrFromMaps(MachineInstr *MI) { |
| 199 | // remove index -> MachineInstr and |
| 200 | // MachineInstr -> index mappings |
| 201 | Mi2IndexMap::iterator mi2i = mi2iMap_.find(MI); |
| 202 | if (mi2i != mi2iMap_.end()) { |
| 203 | i2miMap_[mi2i->second/InstrSlots::NUM] = 0; |
| 204 | mi2iMap_.erase(mi2i); |
| 205 | } |
| 206 | } |
David Greene | 2513330 | 2007-06-08 17:18:56 +0000 | [diff] [blame] | 207 | |
Evan Cheng | f3bb2e6 | 2007-09-05 21:46:51 +0000 | [diff] [blame] | 208 | BumpPtrAllocator& getVNInfoAllocator() { return VNInfoAllocator; } |
| 209 | |
David Greene | 2513330 | 2007-06-08 17:18:56 +0000 | [diff] [blame] | 210 | virtual void getAnalysisUsage(AnalysisUsage &AU) const; |
| 211 | virtual void releaseMemory(); |
| 212 | |
| 213 | /// runOnMachineFunction - pass entry point |
| 214 | virtual bool runOnMachineFunction(MachineFunction&); |
| 215 | |
| 216 | /// print - Implement the dump method. |
| 217 | virtual void print(std::ostream &O, const Module* = 0) const; |
| 218 | void print(std::ostream *O, const Module* M = 0) const { |
| 219 | if (O) print(*O, M); |
| 220 | } |
| 221 | |
| 222 | private: |
Chris Lattner | 428b92e | 2006-09-15 03:57:23 +0000 | [diff] [blame] | 223 | /// computeIntervals - Compute live intervals. |
Chris Lattner | c7695eb | 2006-09-14 06:42:17 +0000 | [diff] [blame] | 224 | void computeIntervals(); |
Chris Lattner | 6bda49f | 2006-09-02 05:26:01 +0000 | [diff] [blame] | 225 | |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 226 | /// handleRegisterDef - update intervals for a register def |
| 227 | /// (calls handlePhysicalRegisterDef and |
| 228 | /// handleVirtualRegisterDef) |
Chris Lattner | 6b128bd | 2006-09-03 08:07:11 +0000 | [diff] [blame] | 229 | void handleRegisterDef(MachineBasicBlock *MBB, |
| 230 | MachineBasicBlock::iterator MI, unsigned MIIdx, |
Chris Lattner | f38a05d | 2006-01-29 07:59:37 +0000 | [diff] [blame] | 231 | unsigned reg); |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 232 | |
| 233 | /// handleVirtualRegisterDef - update intervals for a virtual |
| 234 | /// register def |
Chris Lattner | 6b128bd | 2006-09-03 08:07:11 +0000 | [diff] [blame] | 235 | void handleVirtualRegisterDef(MachineBasicBlock *MBB, |
| 236 | MachineBasicBlock::iterator MI, |
| 237 | unsigned MIIdx, |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 238 | LiveInterval& interval); |
| 239 | |
Chris Lattner | f768bba | 2005-03-09 23:05:19 +0000 | [diff] [blame] | 240 | /// handlePhysicalRegisterDef - update intervals for a physical register |
Chris Lattner | f7da2c7 | 2006-08-24 22:43:55 +0000 | [diff] [blame] | 241 | /// def. |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 242 | void handlePhysicalRegisterDef(MachineBasicBlock* mbb, |
| 243 | MachineBasicBlock::iterator mi, |
Chris Lattner | 6b128bd | 2006-09-03 08:07:11 +0000 | [diff] [blame] | 244 | unsigned MIIdx, |
Chris Lattner | 91725b7 | 2006-08-31 05:54:43 +0000 | [diff] [blame] | 245 | LiveInterval &interval, |
| 246 | unsigned SrcReg); |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 247 | |
Evan Cheng | b371f45 | 2007-02-19 21:49:54 +0000 | [diff] [blame] | 248 | /// handleLiveInRegister - Create interval for a livein register. |
Jim Laskey | 9b25b8c | 2007-02-21 22:41:17 +0000 | [diff] [blame] | 249 | void handleLiveInRegister(MachineBasicBlock* mbb, |
| 250 | unsigned MIIdx, |
Evan Cheng | 24a3cc4 | 2007-04-25 07:30:23 +0000 | [diff] [blame] | 251 | LiveInterval &interval, bool isAlias = false); |
Evan Cheng | b371f45 | 2007-02-19 21:49:54 +0000 | [diff] [blame] | 252 | |
Evan Cheng | 549f27d3 | 2007-08-13 23:45:17 +0000 | [diff] [blame] | 253 | /// isReMaterializable - Returns true if the definition MI of the specified |
| 254 | /// val# of the specified interval is re-materializable. |
Evan Cheng | 7ecb38b | 2007-08-29 20:45:00 +0000 | [diff] [blame] | 255 | bool isReMaterializable(const LiveInterval &li, const VNInfo *ValNo, |
Evan Cheng | 549f27d3 | 2007-08-13 23:45:17 +0000 | [diff] [blame] | 256 | MachineInstr *MI); |
| 257 | |
Evan Cheng | 35b35c5 | 2007-08-30 05:52:20 +0000 | [diff] [blame] | 258 | /// tryFoldMemoryOperand - Attempts to fold either a spill / restore from |
| 259 | /// slot / to reg or any rematerialized load into ith operand of specified |
| 260 | /// MI. If it is successul, MI is updated with the newly created MI and |
| 261 | /// returns true. |
| 262 | bool tryFoldMemoryOperand(MachineInstr* &MI, VirtRegMap &vrm, |
Evan Cheng | 32dfbea | 2007-10-12 08:50:34 +0000 | [diff] [blame] | 263 | MachineInstr *DefMI, unsigned index, unsigned i, |
| 264 | bool isSS, int slot, unsigned reg); |
Evan Cheng | 549f27d3 | 2007-08-13 23:45:17 +0000 | [diff] [blame] | 265 | |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 266 | static LiveInterval createInterval(unsigned Reg); |
| 267 | |
Alkis Evlogimenos | 1a8ea01 | 2004-08-04 09:46:26 +0000 | [diff] [blame] | 268 | void printRegName(unsigned reg) const; |
| 269 | }; |
| 270 | |
Alkis Evlogimenos | ff0cbe1 | 2003-11-20 03:32:25 +0000 | [diff] [blame] | 271 | } // End llvm namespace |
| 272 | |
| 273 | #endif |