@@ -62,6 +62,107 @@ static RegisterRegAlloc fastRegAlloc("fast", "fast register allocator",
62
62
63
63
namespace {
64
64
65
+ // / Assign ascending index for instructions in machine basic block. The index
66
+ // / can be used to determine dominance between instructions in same MBB.
67
+ class InstrPosIndexes {
68
+ public:
69
+ void init (const MachineBasicBlock &MBB) {
70
+ CurMBB = &MBB;
71
+ Instr2PosIndex.clear ();
72
+ uint64_t LastIndex = 0 ;
73
+ for (const MachineInstr &MI : MBB) {
74
+ LastIndex += InstrDist;
75
+ Instr2PosIndex[&MI] = LastIndex;
76
+ }
77
+ }
78
+
79
+ // / Set \p Index to index of \p MI. If \p MI is new inserted, it try to assign
80
+ // / index without affecting existing instruction's index. Return true if all
81
+ // / instructions index has been reassigned.
82
+ bool getIndex (const MachineInstr &MI, uint64_t &Index) {
83
+ assert (MI.getParent () == CurMBB && " MI is not in CurMBB" );
84
+ if (Instr2PosIndex.count (&MI)) {
85
+ Index = Instr2PosIndex[&MI];
86
+ return false ;
87
+ }
88
+
89
+ // Distance is the number of consecutive unassigned instructions including
90
+ // MI. Start is the first instruction of them. End is the next of last
91
+ // instruction of them.
92
+ // e.g.
93
+ // |Instruction| A | B | C | MI | D | E |
94
+ // | Index | 1024 | | | | | 2048 |
95
+ //
96
+ // In this case, B, C, MI, D are unassigned. Distance is 4, Start is B, End
97
+ // is E.
98
+ unsigned Distance = 1 ;
99
+ MachineBasicBlock::const_iterator Start = MI.getIterator (),
100
+ End = std::next (Start);
101
+ while (Start != CurMBB->begin () &&
102
+ !Instr2PosIndex.count (&*std::prev (Start))) {
103
+ --Start;
104
+ ++Distance;
105
+ }
106
+ while (End != CurMBB->end () && !Instr2PosIndex.count (&*(End))) {
107
+ ++End;
108
+ ++Distance;
109
+ }
110
+
111
+ // LastIndex is initialized to last used index prior to MI or zero.
112
+ // In previous example, LastIndex is 1024, EndIndex is 2048;
113
+ uint64_t LastIndex =
114
+ Start == CurMBB->begin () ? 0 : Instr2PosIndex.at (&*std::prev (Start));
115
+ uint64_t Step;
116
+ if (End == CurMBB->end ())
117
+ Step = static_cast <uint64_t >(InstrDist);
118
+ else {
119
+ // No instruction uses index zero.
120
+ uint64_t EndIndex = Instr2PosIndex.at (&*End);
121
+ assert (EndIndex > LastIndex && " Index must be ascending order" );
122
+ unsigned NumAvailableIndexes = EndIndex - LastIndex - 1 ;
123
+ // We want index gap between two adjacent MI is as same as possible. Given
124
+ // total A available indexes, D is number of consecutive unassigned
125
+ // instructions, S is the step.
126
+ // |<- S-1 -> MI <- S-1 -> MI <- A-S*D ->|
127
+ // There're S-1 available indexes between unassigned instruction and its
128
+ // predecessor. There're A-S*D available indexes between the last
129
+ // unassigned instruction and its successor.
130
+ // Ideally, we want
131
+ // S-1 = A-S*D
132
+ // then
133
+ // S = (A+1)/(D+1)
134
+ // An valid S must be integer greater than zero, so
135
+ // S <= (A+1)/(D+1)
136
+ // =>
137
+ // A-S*D >= 0
138
+ // That means we can safely use (A+1)/(D+1) as step.
139
+ // In previous example, Step is 204, Index of B, C, MI, D is 1228, 1432,
140
+ // 1636, 1840.
141
+ Step = (NumAvailableIndexes + 1 ) / (Distance + 1 );
142
+ }
143
+
144
+ // Reassign index for all instructions if number of new inserted
145
+ // instructions exceed slot or all instructions are new.
146
+ if (LLVM_UNLIKELY (!Step || (!LastIndex && Step == InstrDist))) {
147
+ init (*CurMBB);
148
+ Index = Instr2PosIndex.at (&MI);
149
+ return true ;
150
+ }
151
+
152
+ for (auto I = Start; I != End; ++I) {
153
+ LastIndex += Step;
154
+ Instr2PosIndex[&*I] = LastIndex;
155
+ }
156
+ Index = Instr2PosIndex.at (&MI);
157
+ return false ;
158
+ }
159
+
160
+ private:
161
+ enum { InstrDist = 1024 };
162
+ const MachineBasicBlock *CurMBB = nullptr ;
163
+ DenseMap<const MachineInstr *, uint64_t > Instr2PosIndex;
164
+ };
165
+
65
166
class RegAllocFast : public MachineFunctionPass {
66
167
public:
67
168
static char ID;
@@ -153,6 +254,9 @@ class RegAllocFast : public MachineFunctionPass {
153
254
// Register masks attached to the current instruction.
154
255
SmallVector<const uint32_t *> RegMasks;
155
256
257
+ // Assign index for each instruction to quickly determine dominance.
258
+ InstrPosIndexes PosIndexes;
259
+
156
260
void setPhysRegState (MCPhysReg PhysReg, unsigned NewState);
157
261
bool isPhysRegFree (MCPhysReg PhysReg) const ;
158
262
@@ -339,18 +443,13 @@ int RegAllocFast::getStackSpaceFor(Register VirtReg) {
339
443
return FrameIdx;
340
444
}
341
445
342
- static bool dominates (MachineBasicBlock &MBB,
343
- MachineBasicBlock::const_iterator A,
344
- MachineBasicBlock::const_iterator B) {
345
- auto MBBEnd = MBB.end ();
346
- if (B == MBBEnd)
347
- return true ;
348
-
349
- MachineBasicBlock::const_iterator I = MBB.begin ();
350
- for (; &*I != A && &*I != B; ++I)
351
- ;
352
-
353
- return &*I == A;
446
+ static bool dominates (InstrPosIndexes &PosIndexes, const MachineInstr &A,
447
+ const MachineInstr &B) {
448
+ uint64_t IndexA, IndexB;
449
+ PosIndexes.getIndex (A, IndexA);
450
+ if (LLVM_UNLIKELY (PosIndexes.getIndex (B, IndexB)))
451
+ PosIndexes.getIndex (A, IndexA);
452
+ return IndexA < IndexB;
354
453
}
355
454
356
455
// / Returns false if \p VirtReg is known to not live out of the current block.
@@ -371,7 +470,7 @@ bool RegAllocFast::mayLiveOut(Register VirtReg) {
371
470
MayLiveAcrossBlocks.set (Register::virtReg2Index (VirtReg));
372
471
return true ;
373
472
} else {
374
- if (!SelfLoopDef || dominates (*MBB , DefInst. getIterator (), SelfLoopDef))
473
+ if (!SelfLoopDef || dominates (PosIndexes , DefInst, * SelfLoopDef))
375
474
SelfLoopDef = &DefInst;
376
475
}
377
476
}
@@ -396,7 +495,7 @@ bool RegAllocFast::mayLiveOut(Register VirtReg) {
396
495
// Try to handle some simple cases to avoid spilling and reloading every
397
496
// value inside a self looping block.
398
497
if (SelfLoopDef == &UseInst ||
399
- !dominates (*MBB, SelfLoopDef-> getIterator () , UseInst. getIterator () )) {
498
+ !dominates (PosIndexes, * SelfLoopDef, UseInst)) {
400
499
MayLiveAcrossBlocks.set (Register::virtReg2Index (VirtReg));
401
500
return true ;
402
501
}
@@ -1565,6 +1664,7 @@ void RegAllocFast::allocateBasicBlock(MachineBasicBlock &MBB) {
1565
1664
this ->MBB = &MBB;
1566
1665
LLVM_DEBUG (dbgs () << " \n Allocating " << MBB);
1567
1666
1667
+ PosIndexes.init (MBB);
1568
1668
RegUnitStates.assign (TRI->getNumRegUnits (), regFree);
1569
1669
assert (LiveVirtRegs.empty () && " Mapping not cleared from last block?" );
1570
1670
0 commit comments