@@ -149,7 +149,8 @@ namespace {
149
149
class ValueTrackerResult ;
150
150
class RecurrenceInstr ;
151
151
152
- class PeepholeOptimizer : public MachineFunctionPass {
152
+ class PeepholeOptimizer : public MachineFunctionPass ,
153
+ private MachineFunction::Delegate {
153
154
const TargetInstrInfo *TII = nullptr ;
154
155
const TargetRegisterInfo *TRI = nullptr ;
155
156
MachineRegisterInfo *MRI = nullptr ;
@@ -202,7 +203,8 @@ namespace {
202
203
bool isMoveImmediate (MachineInstr &MI, SmallSet<Register, 4 > &ImmDefRegs,
203
204
DenseMap<Register, MachineInstr *> &ImmDefMIs);
204
205
bool foldImmediate (MachineInstr &MI, SmallSet<Register, 4 > &ImmDefRegs,
205
- DenseMap<Register, MachineInstr *> &ImmDefMIs);
206
+ DenseMap<Register, MachineInstr *> &ImmDefMIs,
207
+ bool &Deleted);
206
208
207
209
// / Finds recurrence cycles, but only ones that formulated around
208
210
// / a def operand and a use operand that are tied. If there is a use
@@ -214,11 +216,10 @@ namespace {
214
216
215
217
// / If copy instruction \p MI is a virtual register copy or a copy of a
216
218
// / constant physical register to a virtual register, track it in the
217
- // / set \p CopyMIs . If this virtual register was previously seen as a
219
+ // / set CopySrcMIs . If this virtual register was previously seen as a
218
220
// / copy, replace the uses of this copy with the previously seen copy's
219
221
// / destination register.
220
- bool foldRedundantCopy (MachineInstr &MI,
221
- DenseMap<RegSubRegPair, MachineInstr *> &CopyMIs);
222
+ bool foldRedundantCopy (MachineInstr &MI);
222
223
223
224
// / Is the register \p Reg a non-allocatable physical register?
224
225
bool isNAPhysCopy (Register Reg);
@@ -255,6 +256,49 @@ namespace {
255
256
256
257
MachineInstr &rewriteSource (MachineInstr &CopyLike,
257
258
RegSubRegPair Def, RewriteMapTy &RewriteMap);
259
+
260
+ // Set of copies to virtual registers keyed by source register. Never
261
+ // holds any physreg which requires def tracking.
262
+ DenseMap<RegSubRegPair, MachineInstr *> CopySrcMIs;
263
+
264
+ // MachineFunction::Delegate implementation. Used to maintain CopySrcMIs.
265
+ void MF_HandleInsertion (MachineInstr &MI) override {
266
+ return ;
267
+ }
268
+
269
+ bool getCopySrc (MachineInstr &MI, RegSubRegPair &SrcPair) {
270
+ if (!MI.isCopy ())
271
+ return false ;
272
+
273
+ Register SrcReg = MI.getOperand (1 ).getReg ();
274
+ unsigned SrcSubReg = MI.getOperand (1 ).getSubReg ();
275
+ if (!SrcReg.isVirtual () && !MRI->isConstantPhysReg (SrcReg))
276
+ return false ;
277
+
278
+ SrcPair = RegSubRegPair (SrcReg, SrcSubReg);
279
+ return true ;
280
+ }
281
+
282
+ // If a COPY instruction is to be deleted or changed, we should also remove
283
+ // it from CopySrcMIs.
284
+ void deleteChangedCopy (MachineInstr &MI) {
285
+ RegSubRegPair SrcPair;
286
+ if (!getCopySrc (MI, SrcPair))
287
+ return ;
288
+
289
+ auto It = CopySrcMIs.find (SrcPair);
290
+ if (It != CopySrcMIs.end () && It->second == &MI)
291
+ CopySrcMIs.erase (It);
292
+ }
293
+
294
+ void MF_HandleRemoval (MachineInstr &MI) override {
295
+ deleteChangedCopy (MI);
296
+ }
297
+
298
+ void MF_HandleChangeDesc (MachineInstr &MI, const MCInstrDesc &TID) override
299
+ {
300
+ deleteChangedCopy (MI);
301
+ }
258
302
};
259
303
260
304
// / Helper class to hold instructions that are inside recurrence cycles.
@@ -1351,26 +1395,28 @@ bool PeepholeOptimizer::isMoveImmediate(
1351
1395
MachineInstr &MI, SmallSet<Register, 4 > &ImmDefRegs,
1352
1396
DenseMap<Register, MachineInstr *> &ImmDefMIs) {
1353
1397
const MCInstrDesc &MCID = MI.getDesc ();
1354
- if (!MI.isMoveImmediate ())
1355
- return false ;
1356
- if (MCID.getNumDefs () != 1 )
1398
+ if (MCID.getNumDefs () != 1 || !MI.getOperand (0 ).isReg ())
1357
1399
return false ;
1358
1400
Register Reg = MI.getOperand (0 ).getReg ();
1359
- if (Reg.isVirtual ()) {
1360
- ImmDefMIs.insert (std::make_pair (Reg, &MI));
1361
- ImmDefRegs.insert (Reg);
1362
- return true ;
1363
- }
1401
+ if (!Reg.isVirtual ())
1402
+ return false ;
1364
1403
1365
- return false ;
1404
+ int64_t ImmVal;
1405
+ if (!MI.isMoveImmediate () && !TII->getConstValDefinedInReg (MI, Reg, ImmVal))
1406
+ return false ;
1407
+
1408
+ ImmDefMIs.insert (std::make_pair (Reg, &MI));
1409
+ ImmDefRegs.insert (Reg);
1410
+ return true ;
1366
1411
}
1367
1412
1368
1413
// / Try folding register operands that are defined by move immediate
1369
1414
// / instructions, i.e. a trivial constant folding optimization, if
1370
1415
// / and only if the def and use are in the same BB.
1371
1416
bool PeepholeOptimizer::foldImmediate (
1372
1417
MachineInstr &MI, SmallSet<Register, 4 > &ImmDefRegs,
1373
- DenseMap<Register, MachineInstr *> &ImmDefMIs) {
1418
+ DenseMap<Register, MachineInstr *> &ImmDefMIs, bool &Deleted) {
1419
+ Deleted = false ;
1374
1420
for (unsigned i = 0 , e = MI.getDesc ().getNumOperands (); i != e; ++i) {
1375
1421
MachineOperand &MO = MI.getOperand (i);
1376
1422
if (!MO.isReg () || MO.isDef ())
@@ -1384,6 +1430,19 @@ bool PeepholeOptimizer::foldImmediate(
1384
1430
assert (II != ImmDefMIs.end () && " couldn't find immediate definition" );
1385
1431
if (TII->FoldImmediate (MI, *II->second , Reg, MRI)) {
1386
1432
++NumImmFold;
1433
+ // FoldImmediate can delete ImmDefMI if MI was its only user. If ImmDefMI
1434
+ // is not deleted, and we happened to get a same MI, we can delete MI and
1435
+ // replace its users.
1436
+ if (MRI->getVRegDef (Reg) &&
1437
+ MI.isIdenticalTo (*II->second , MachineInstr::IgnoreVRegDefs)) {
1438
+ Register DstReg = MI.getOperand (0 ).getReg ();
1439
+ if (DstReg.isVirtual () &&
1440
+ MRI->getRegClass (DstReg) == MRI->getRegClass (Reg)) {
1441
+ MRI->replaceRegWith (DstReg, Reg);
1442
+ MI.eraseFromParent ();
1443
+ Deleted = true ;
1444
+ }
1445
+ }
1387
1446
return true ;
1388
1447
}
1389
1448
}
@@ -1404,29 +1463,25 @@ bool PeepholeOptimizer::foldImmediate(
1404
1463
// %2 = COPY %0:sub1
1405
1464
//
1406
1465
// Should replace %2 uses with %1:sub1
1407
- bool PeepholeOptimizer::foldRedundantCopy (
1408
- MachineInstr &MI, DenseMap<RegSubRegPair, MachineInstr *> &CopyMIs) {
1466
+ bool PeepholeOptimizer::foldRedundantCopy (MachineInstr &MI) {
1409
1467
assert (MI.isCopy () && " expected a COPY machine instruction" );
1410
1468
1411
- Register SrcReg = MI.getOperand (1 ).getReg ();
1412
- unsigned SrcSubReg = MI.getOperand (1 ).getSubReg ();
1413
- if (!SrcReg.isVirtual () && !MRI->isConstantPhysReg (SrcReg))
1469
+ RegSubRegPair SrcPair;
1470
+ if (!getCopySrc (MI, SrcPair))
1414
1471
return false ;
1415
1472
1416
1473
Register DstReg = MI.getOperand (0 ).getReg ();
1417
1474
if (!DstReg.isVirtual ())
1418
1475
return false ;
1419
1476
1420
- RegSubRegPair SrcPair (SrcReg, SrcSubReg);
1421
-
1422
- if (CopyMIs.insert (std::make_pair (SrcPair, &MI)).second ) {
1477
+ if (CopySrcMIs.insert (std::make_pair (SrcPair, &MI)).second ) {
1423
1478
// First copy of this reg seen.
1424
1479
return false ;
1425
1480
}
1426
1481
1427
- MachineInstr *PrevCopy = CopyMIs .find (SrcPair)->second ;
1482
+ MachineInstr *PrevCopy = CopySrcMIs .find (SrcPair)->second ;
1428
1483
1429
- assert (SrcSubReg == PrevCopy->getOperand (1 ).getSubReg () &&
1484
+ assert (SrcPair. SubReg == PrevCopy->getOperand (1 ).getSubReg () &&
1430
1485
" Unexpected mismatching subreg!" );
1431
1486
1432
1487
Register PrevDstReg = PrevCopy->getOperand (0 ).getReg ();
@@ -1617,6 +1672,7 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
1617
1672
MRI = &MF.getRegInfo ();
1618
1673
DT = Aggressive ? &getAnalysis<MachineDominatorTree>() : nullptr ;
1619
1674
MLI = &getAnalysis<MachineLoopInfo>();
1675
+ MF.setDelegate (this );
1620
1676
1621
1677
bool Changed = false ;
1622
1678
@@ -1641,9 +1697,7 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
1641
1697
// without any intervening re-definition of $physreg.
1642
1698
DenseMap<Register, MachineInstr *> NAPhysToVirtMIs;
1643
1699
1644
- // Set of copies to virtual registers keyed by source register. Never
1645
- // holds any physreg which requires def tracking.
1646
- DenseMap<RegSubRegPair, MachineInstr *> CopySrcMIs;
1700
+ CopySrcMIs.clear ();
1647
1701
1648
1702
bool IsLoopHeader = MLI->isLoopHeader (&MBB);
1649
1703
@@ -1732,7 +1786,7 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
1732
1786
continue ;
1733
1787
}
1734
1788
1735
- if (MI->isCopy () && (foldRedundantCopy (*MI, CopySrcMIs ) ||
1789
+ if (MI->isCopy () && (foldRedundantCopy (*MI) ||
1736
1790
foldRedundantNAPhysCopy (*MI, NAPhysToVirtMIs))) {
1737
1791
LocalMIs.erase (MI);
1738
1792
LLVM_DEBUG (dbgs () << " Deleting redundant copy: " << *MI << " \n " );
@@ -1750,8 +1804,14 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
1750
1804
// next iteration sees the new instructions.
1751
1805
MII = MI;
1752
1806
++MII;
1753
- if (SeenMoveImm)
1754
- Changed |= foldImmediate (*MI, ImmDefRegs, ImmDefMIs);
1807
+ if (SeenMoveImm) {
1808
+ bool Deleted;
1809
+ Changed |= foldImmediate (*MI, ImmDefRegs, ImmDefMIs, Deleted);
1810
+ if (Deleted) {
1811
+ LocalMIs.erase (MI);
1812
+ continue ;
1813
+ }
1814
+ }
1755
1815
}
1756
1816
1757
1817
// Check whether MI is a load candidate for folding into a later
@@ -1815,6 +1875,7 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
1815
1875
}
1816
1876
}
1817
1877
1878
+ MF.resetDelegate (this );
1818
1879
return Changed;
1819
1880
}
1820
1881
0 commit comments