@@ -39,24 +39,25 @@ namespace {
39
39
class MachineLateInstrsCleanup : public MachineFunctionPass {
40
40
const TargetRegisterInfo *TRI = nullptr ;
41
41
const TargetInstrInfo *TII = nullptr ;
42
- const MachineRegisterInfo *MRI = nullptr ;
43
42
44
- // Data structure to map regs to their definitions per MBB.
43
+ // Data structures to map regs to their definitions and kills per MBB.
45
44
struct Reg2MIMap : public SmallDenseMap <Register, MachineInstr *> {
46
45
bool hasIdentical (Register Reg, MachineInstr *ArgMI) {
47
46
MachineInstr *MI = lookup (Reg);
48
47
return MI && MI->isIdenticalTo (*ArgMI);
49
48
}
50
49
};
50
+ typedef SmallDenseMap<Register, TinyPtrVector<MachineInstr *>> Reg2MIVecMap;
51
51
std::vector<Reg2MIMap> RegDefs;
52
+ std::vector<Reg2MIVecMap> RegKills;
52
53
53
54
// Walk through the instructions in MBB and remove any redundant
54
55
// instructions.
55
56
bool processBlock (MachineBasicBlock *MBB);
56
57
57
58
void removeRedundantDef (MachineInstr *MI);
58
- void updateLiveInLists (Register Reg, MachineBasicBlock *MBB,
59
- BitVector &VisitedPreds, MachineInstr *ToRemoveMI);
59
+ void clearKillsForDef (Register Reg, MachineBasicBlock *MBB,
60
+ BitVector &VisitedPreds, MachineInstr *ToRemoveMI);
60
61
61
62
public:
62
63
static char ID; // Pass identification, replacement for typeid
@@ -93,10 +94,11 @@ bool MachineLateInstrsCleanup::runOnMachineFunction(MachineFunction &MF) {
93
94
94
95
TRI = MF.getSubtarget ().getRegisterInfo ();
95
96
TII = MF.getSubtarget ().getInstrInfo ();
96
- MRI = &MF.getRegInfo ();
97
97
98
98
RegDefs.clear ();
99
99
RegDefs.resize (MF.getNumBlockIDs ());
100
+ RegKills.clear ();
101
+ RegKills.resize (MF.getNumBlockIDs ());
100
102
101
103
// Visit all MBBs in an order that maximises the reuse from predecessors.
102
104
bool Changed = false ;
@@ -109,36 +111,41 @@ bool MachineLateInstrsCleanup::runOnMachineFunction(MachineFunction &MF) {
109
111
110
112
// Clear any preceding kill flag on Reg after removing a redundant
111
113
// definition.
112
- void MachineLateInstrsCleanup::updateLiveInLists (Register Reg,
114
+ void MachineLateInstrsCleanup::clearKillsForDef (Register Reg,
113
115
MachineBasicBlock *MBB,
114
116
BitVector &VisitedPreds,
115
117
MachineInstr *ToRemoveMI) {
116
118
VisitedPreds.set (MBB->getNumber ());
117
119
120
+ // Clear kill flag(s) in MBB, that have been seen after the preceding
121
+ // definition. If Reg or one of its subregs was killed, it would actually
122
+ // be ok to stop after removing that (and any other) kill-flag, but it
123
+ // doesn't seem noticeably faster while it would be a bit more complicated.
124
+ Reg2MIVecMap &MBBKills = RegKills[MBB->getNumber ()];
125
+ if (MBBKills.contains (Reg))
126
+ for (auto *KillMI : MBBKills[Reg])
127
+ KillMI->clearRegisterKills (Reg, TRI);
128
+
118
129
// Definition in current MBB: done.
119
130
Reg2MIMap &MBBDefs = RegDefs[MBB->getNumber ()];
120
131
MachineInstr *DefMI = MBBDefs[Reg];
121
132
assert (DefMI->isIdenticalTo (*ToRemoveMI) && " Previous def not identical?" );
122
133
if (DefMI->getParent () == MBB)
123
134
return ;
124
135
125
- // If the earlier def is not in MBB, it has now become live in. Continue in
126
- // predecessors until the defining MBB has been reached.
136
+ // If an earlier def is not in MBB, continue in predecessors.
127
137
if (!MBB->isLiveIn (Reg))
128
138
MBB->addLiveIn (Reg);
129
139
assert (!MBB->pred_empty () && " Predecessor def not found!" );
130
140
for (MachineBasicBlock *Pred : MBB->predecessors ())
131
141
if (!VisitedPreds.test (Pred->getNumber ()))
132
- updateLiveInLists (Reg, Pred, VisitedPreds, ToRemoveMI);
142
+ clearKillsForDef (Reg, Pred, VisitedPreds, ToRemoveMI);
133
143
}
134
144
135
145
void MachineLateInstrsCleanup::removeRedundantDef (MachineInstr *MI) {
136
146
Register Reg = MI->getOperand (0 ).getReg ();
137
- // Clear any and all kill flags.
138
- for (MCPhysReg SReg : TRI->superregs_inclusive (Reg))
139
- MRI->clearKillFlags (SReg);
140
147
BitVector VisitedPreds (MI->getMF ()->getNumBlockIDs ());
141
- updateLiveInLists (Reg, MI->getParent (), VisitedPreds, MI);
148
+ clearKillsForDef (Reg, MI->getParent (), VisitedPreds, MI);
142
149
MI->eraseFromParent ();
143
150
++NumRemoved;
144
151
}
@@ -174,6 +181,7 @@ static bool isCandidate(const MachineInstr *MI, Register &DefedReg,
174
181
bool MachineLateInstrsCleanup::processBlock (MachineBasicBlock *MBB) {
175
182
bool Changed = false ;
176
183
Reg2MIMap &MBBDefs = RegDefs[MBB->getNumber ()];
184
+ Reg2MIVecMap &MBBKills = RegKills[MBB->getNumber ()];
177
185
178
186
// Find reusable definitions in the predecessor(s).
179
187
if (!MBB->pred_empty () && !MBB->isEHPad () &&
@@ -200,6 +208,7 @@ bool MachineLateInstrsCleanup::processBlock(MachineBasicBlock *MBB) {
200
208
// it) are valid.
201
209
if (MI.modifiesRegister (FrameReg, TRI)) {
202
210
MBBDefs.clear ();
211
+ MBBKills.clear ();
203
212
continue ;
204
213
}
205
214
@@ -218,15 +227,20 @@ bool MachineLateInstrsCleanup::processBlock(MachineBasicBlock *MBB) {
218
227
// Clear any entries in map that MI clobbers.
219
228
for (auto DefI : llvm::make_early_inc_range (MBBDefs)) {
220
229
Register Reg = DefI.first ;
221
- if (MI.modifiesRegister (Reg, TRI))
230
+ if (MI.modifiesRegister (Reg, TRI)) {
222
231
MBBDefs.erase (Reg);
232
+ MBBKills.erase (Reg);
233
+ } else if (MI.findRegisterUseOperandIdx (Reg, TRI, true /* isKill*/ ) != -1 )
234
+ // Keep track of all instructions that fully or partially kills Reg.
235
+ MBBKills[Reg].push_back (&MI);
223
236
}
224
237
225
238
// Record this MI for potential later reuse.
226
239
if (IsCandidate) {
227
240
LLVM_DEBUG (dbgs () << " Found interesting instruction in "
228
241
<< printMBBReference (*MBB) << " : " << MI;);
229
242
MBBDefs[DefedReg] = &MI;
243
+ assert (!MBBKills.count (DefedReg) && " Should already have been removed." );
230
244
}
231
245
}
232
246
0 commit comments