summaryrefslogtreecommitdiff
path: root/lib/CodeGen/SplitKit.h
blob: bb4fca9084b424c22bdaaa543ed8ff026a86b58d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
//===-------- SplitKit.h - Toolkit for splitting live ranges ----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the SplitAnalysis class as well as mutator functions for
// live range splitting.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/CodeGen/SlotIndexes.h"

namespace llvm {

class LiveInterval;
class LiveIntervals;
class LiveRangeEdit;
class MachineInstr;
class MachineLoop;
class MachineLoopInfo;
class MachineRegisterInfo;
class TargetInstrInfo;
class TargetRegisterInfo;
class VirtRegMap;
class VNInfo;
class raw_ostream;

/// At some point we should just include MachineDominators.h:
class MachineDominatorTree;
template <class NodeT> class DomTreeNodeBase;
typedef DomTreeNodeBase<MachineBasicBlock> MachineDomTreeNode;


/// SplitAnalysis - Analyze a LiveInterval, looking for live range splitting
/// opportunities.
class SplitAnalysis {
public:
  const MachineFunction &MF;
  const LiveIntervals &LIS;
  const MachineLoopInfo &Loops;
  const TargetInstrInfo &TII;

  // Instructions using the the current register.
  typedef SmallPtrSet<const MachineInstr*, 16> InstrPtrSet;
  InstrPtrSet UsingInstrs;

  // Sorted slot indexes of using instructions.
  SmallVector<SlotIndex, 8> UseSlots;

  // The number of instructions using CurLI in each basic block.
  typedef DenseMap<const MachineBasicBlock*, unsigned> BlockCountMap;
  BlockCountMap UsingBlocks;

  // The number of basic block using CurLI in each loop.
  typedef DenseMap<const MachineLoop*, unsigned> LoopCountMap;
  LoopCountMap UsingLoops;

private:
  // Current live interval.
  const LiveInterval *CurLI;

  // Sumarize statistics by counting instructions using CurLI.
  void analyzeUses();

  /// canAnalyzeBranch - Return true if MBB ends in a branch that can be
  /// analyzed.
  bool canAnalyzeBranch(const MachineBasicBlock *MBB);

public:
  SplitAnalysis(const MachineFunction &mf, const LiveIntervals &lis,
                const MachineLoopInfo &mli);

  /// analyze - set CurLI to the specified interval, and analyze how it may be
  /// split.
  void analyze(const LiveInterval *li);

  /// clear - clear all data structures so SplitAnalysis is ready to analyze a
  /// new interval.
  void clear();

  /// hasUses - Return true if MBB has any uses of CurLI.
  bool hasUses(const MachineBasicBlock *MBB) const {
    return UsingBlocks.lookup(MBB);
  }

  typedef SmallPtrSet<const MachineBasicBlock*, 16> BlockPtrSet;
  typedef SmallPtrSet<const MachineLoop*, 16> LoopPtrSet;

  // Print a set of blocks with use counts.
  void print(const BlockPtrSet&, raw_ostream&) const;

  // Sets of basic blocks surrounding a machine loop.
  struct LoopBlocks {
    BlockPtrSet Loop;  // Blocks in the loop.
    BlockPtrSet Preds; // Loop predecessor blocks.
    BlockPtrSet Exits; // Loop exit blocks.

    void clear() {
      Loop.clear();
      Preds.clear();
      Exits.clear();
    }
  };

  // Print loop blocks with use counts.
  void print(const LoopBlocks&, raw_ostream&) const;

  // Calculate the block sets surrounding the loop.
  void getLoopBlocks(const MachineLoop *Loop, LoopBlocks &Blocks);

  /// LoopPeripheralUse - how is a variable used in and around a loop?
  /// Peripheral blocks are the loop predecessors and exit blocks.
  enum LoopPeripheralUse {
    ContainedInLoop,  // All uses are inside the loop.
    SinglePeripheral, // At most one instruction per peripheral block.
    MultiPeripheral,  // Multiple instructions in some peripheral blocks.
    OutsideLoop       // Uses outside loop periphery.
  };

  /// analyzeLoopPeripheralUse - Return an enum describing how CurLI is used in
  /// and around the Loop.
  LoopPeripheralUse analyzeLoopPeripheralUse(const LoopBlocks&);

  /// getCriticalExits - It may be necessary to partially break critical edges
  /// leaving the loop if an exit block has phi uses of CurLI. Collect the exit
  /// blocks that need special treatment into CriticalExits.
  void getCriticalExits(const LoopBlocks &Blocks, BlockPtrSet &CriticalExits);

  /// canSplitCriticalExits - Return true if it is possible to insert new exit
  /// blocks before the blocks in CriticalExits.
  bool canSplitCriticalExits(const LoopBlocks &Blocks,
                             BlockPtrSet &CriticalExits);

  /// getCriticalPreds - Get the set of loop predecessors with critical edges to
  /// blocks outside the loop that have CurLI live in. We don't have to break
  /// these edges, but they do require special treatment.
  void getCriticalPreds(const LoopBlocks &Blocks, BlockPtrSet &CriticalPreds);

  /// getSplitLoops - Get the set of loops that have CurLI uses and would be
  /// profitable to split.
  void getSplitLoops(LoopPtrSet&);

  /// getBestSplitLoop - Return the loop where CurLI may best be split to a
  /// separate register, or NULL.
  const MachineLoop *getBestSplitLoop();

  /// isBypassLoop - Return true if CurLI is live through Loop and has no uses
  /// inside the loop. Bypass loops are candidates for splitting because it can
  /// prevent interference inside the loop.
  bool isBypassLoop(const MachineLoop *Loop);

  /// getBypassLoops - Get all the maximal bypass loops. These are the bypass
  /// loops whose parent is not a bypass loop.
  void getBypassLoops(LoopPtrSet&);

  /// getMultiUseBlocks - Add basic blocks to Blocks that may benefit from
  /// having CurLI split to a new live interval. Return true if Blocks can be
  /// passed to SplitEditor::splitSingleBlocks.
  bool getMultiUseBlocks(BlockPtrSet &Blocks);

  /// getBlockForInsideSplit - If CurLI is contained inside a single basic
  /// block, and it would pay to subdivide the interval inside that block,
  /// return it. Otherwise return NULL. The returned block can be passed to
  /// SplitEditor::splitInsideBlock.
  const MachineBasicBlock *getBlockForInsideSplit();
};


/// LiveIntervalMap - Map values from a large LiveInterval into a small
/// interval that is a subset. Insert phi-def values as needed. This class is
/// used by SplitEditor to create new smaller LiveIntervals.
///
/// ParentLI is the larger interval, LI is the subset interval. Every value
/// in LI corresponds to exactly one value in ParentLI, and the live range
/// of the value is contained within the live range of the ParentLI value.
/// Values in ParentLI may map to any number of OpenLI values, including 0.
class LiveIntervalMap {
  LiveIntervals &LIS;
  MachineDominatorTree &MDT;

  // The parent interval is never changed.
  const LiveInterval &ParentLI;

  // The child interval's values are fully contained inside ParentLI values.
  LiveInterval *LI;

  typedef DenseMap<const VNInfo*, VNInfo*> ValueMap;

  // Map ParentLI values to simple values in LI that are defined at the same
  // SlotIndex, or NULL for ParentLI values that have complex LI defs.
  // Note there is a difference between values mapping to NULL (complex), and
  // values not present (unknown/unmapped).
  ValueMap Values;

  typedef std::pair<VNInfo*, MachineDomTreeNode*> LiveOutPair;
  typedef DenseMap<MachineBasicBlock*,LiveOutPair> LiveOutMap;

  // LiveOutCache - Map each basic block where LI is live out to the live-out
  // value and its defining block. One of these conditions shall be true:
  //
  //  1. !LiveOutCache.count(MBB)
  //  2. LiveOutCache[MBB].second.getNode() == MBB
  //  3. forall P in preds(MBB): LiveOutCache[P] == LiveOutCache[MBB]
  //
  // This is only a cache, the values can be computed as:
  //
  //  VNI = LI->getVNInfoAt(LIS.getMBBEndIdx(MBB))
  //  Node = mbt_[LIS.getMBBFromIndex(VNI->def)]
  //
  // The cache is also used as a visiteed set by mapValue().
  LiveOutMap LiveOutCache;

  // Dump the live-out cache to dbgs().
  void dumpCache();

public:
  LiveIntervalMap(LiveIntervals &lis,
                  MachineDominatorTree &mdt,
                  const LiveInterval &parentli)
    : LIS(lis), MDT(mdt), ParentLI(parentli), LI(0) {}

  /// reset - clear all data structures and start a new live interval.
  void reset(LiveInterval *);

  /// getLI - return the current live interval.
  LiveInterval *getLI() const { return LI; }

  /// defValue - define a value in LI from the ParentLI value VNI and Idx.
  /// Idx does not have to be ParentVNI->def, but it must be contained within
  /// ParentVNI's live range in ParentLI.
  /// Return the new LI value.
  VNInfo *defValue(const VNInfo *ParentVNI, SlotIndex Idx);

  /// mapValue - map ParentVNI to the corresponding LI value at Idx. It is
  /// assumed that ParentVNI is live at Idx.
  /// If ParentVNI has not been defined by defValue, it is assumed that
  /// ParentVNI->def dominates Idx.
  /// If ParentVNI has been defined by defValue one or more times, a value that
  /// dominates Idx will be returned. This may require creating extra phi-def
  /// values and adding live ranges to LI.
  /// If simple is not NULL, *simple will indicate if ParentVNI is a simply
  /// mapped value.
  VNInfo *mapValue(const VNInfo *ParentVNI, SlotIndex Idx, bool *simple = 0);

  // extendTo - Find the last LI value defined in MBB at or before Idx. The
  // parentli is assumed to be live at Idx. Extend the live range to include
  // Idx. Return the found VNInfo, or NULL.
  VNInfo *extendTo(const MachineBasicBlock *MBB, SlotIndex Idx);

  /// isMapped - Return true is ParentVNI is a known mapped value. It may be a
  /// simple 1-1 mapping or a complex mapping to later defs.
  bool isMapped(const VNInfo *ParentVNI) const {
    return Values.count(ParentVNI);
  }

  /// isComplexMapped - Return true if ParentVNI has received new definitions
  /// with defValue.
  bool isComplexMapped(const VNInfo *ParentVNI) const;

  // addSimpleRange - Add a simple range from ParentLI to LI.
  // ParentVNI must be live in the [Start;End) interval.
  void addSimpleRange(SlotIndex Start, SlotIndex End, const VNInfo *ParentVNI);

  /// addRange - Add live ranges to LI where [Start;End) intersects ParentLI.
  /// All needed values whose def is not inside [Start;End) must be defined
  /// beforehand so mapValue will work.
  void addRange(SlotIndex Start, SlotIndex End);
};


/// SplitEditor - Edit machine code and LiveIntervals for live range
/// splitting.
///
/// - Create a SplitEditor from a SplitAnalysis.
/// - Start a new live interval with openIntv.
/// - Mark the places where the new interval is entered using enterIntv*
/// - Mark the ranges where the new interval is used with useIntv* 
/// - Mark the places where the interval is exited with exitIntv*.
/// - Finish the current interval with closeIntv and repeat from 2.
/// - Rewrite instructions with finish().
///
class SplitEditor {
  SplitAnalysis &sa_;
  LiveIntervals &LIS;
  VirtRegMap &VRM;
  MachineRegisterInfo &MRI;
  const TargetInstrInfo &TII;
  const TargetRegisterInfo &TRI;

  /// Edit - The current parent register and new intervals created.
  LiveRangeEdit &Edit;

  /// DupLI - Created as a copy of CurLI, ranges are carved out as new
  /// intervals get added through openIntv / closeIntv. This is used to avoid
  /// editing CurLI.
  LiveIntervalMap DupLI;

  /// Currently open LiveInterval.
  LiveIntervalMap OpenLI;

  /// defFromParent - Define Reg from ParentVNI at UseIdx using either
  /// rematerialization or a COPY from parent. Return the new value.
  VNInfo *defFromParent(LiveIntervalMap &Reg,
                        VNInfo *ParentVNI,
                        SlotIndex UseIdx,
                        MachineBasicBlock &MBB,
                        MachineBasicBlock::iterator I);

  /// intervalsLiveAt - Return true if any member of intervals_ is live at Idx.
  bool intervalsLiveAt(SlotIndex Idx) const;

  /// Values in CurLI whose live range has been truncated when entering an open
  /// li.
  SmallPtrSet<const VNInfo*, 8> truncatedValues;

  /// addTruncSimpleRange - Add the given simple range to DupLI after
  /// truncating any overlap with intervals_.
  void addTruncSimpleRange(SlotIndex Start, SlotIndex End, VNInfo *VNI);

  /// criticalPreds_ - Set of basic blocks where both dupli and OpenLI should be
  /// live out because of a critical edge.
  SplitAnalysis::BlockPtrSet criticalPreds_;

  /// computeRemainder - Compute the dupli liveness as the complement of all the
  /// new intervals.
  void computeRemainder();

  /// rewrite - Rewrite all uses of reg to use the new registers.
  void rewrite(unsigned reg);

public:
  /// Create a new SplitEditor for editing the LiveInterval analyzed by SA.
  /// Newly created intervals will be appended to newIntervals.
  SplitEditor(SplitAnalysis &SA, LiveIntervals&, VirtRegMap&,
              MachineDominatorTree&, LiveRangeEdit&);

  /// getAnalysis - Get the corresponding analysis.
  SplitAnalysis &getAnalysis() { return sa_; }

  /// Create a new virtual register and live interval.
  void openIntv();

  /// enterIntvBefore - Enter OpenLI before the instruction at Idx. If CurLI is
  /// not live before Idx, a COPY is not inserted.
  void enterIntvBefore(SlotIndex Idx);

  /// enterIntvAtEnd - Enter OpenLI at the end of MBB.
  void enterIntvAtEnd(MachineBasicBlock &MBB);

  /// useIntv - indicate that all instructions in MBB should use OpenLI.
  void useIntv(const MachineBasicBlock &MBB);

  /// useIntv - indicate that all instructions in range should use OpenLI.
  void useIntv(SlotIndex Start, SlotIndex End);

  /// leaveIntvAfter - Leave OpenLI after the instruction at Idx.
  void leaveIntvAfter(SlotIndex Idx);

  /// leaveIntvAtTop - Leave the interval at the top of MBB.
  /// Currently, only one value can leave the interval.
  void leaveIntvAtTop(MachineBasicBlock &MBB);

  /// closeIntv - Indicate that we are done editing the currently open
  /// LiveInterval, and ranges can be trimmed.
  void closeIntv();

  /// finish - after all the new live ranges have been created, compute the
  /// remaining live range, and rewrite instructions to use the new registers.
  void finish();

  // ===--- High level methods ---===

  /// splitAroundLoop - Split CurLI into a separate live interval inside
  /// the loop.
  void splitAroundLoop(const MachineLoop*);

  /// splitSingleBlocks - Split CurLI into a separate live interval inside each
  /// basic block in Blocks.
  void splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks);

  /// splitInsideBlock - Split CurLI into multiple intervals inside MBB.
  void splitInsideBlock(const MachineBasicBlock *);
};

}