@@ -202,7 +202,8 @@ namespace {
202
202
bool isMoveImmediate (MachineInstr &MI, SmallSet<Register, 4 > &ImmDefRegs,
203
203
DenseMap<Register, MachineInstr *> &ImmDefMIs);
204
204
bool foldImmediate (MachineInstr &MI, SmallSet<Register, 4 > &ImmDefRegs,
205
- DenseMap<Register, MachineInstr *> &ImmDefMIs);
205
+ DenseMap<Register, MachineInstr *> &ImmDefMIs,
206
+ bool &Deleted);
206
207
207
208
// / Finds recurrence cycles, but only ones that formulated around
208
209
// / a def operand and a use operand that are tied. If there is a use
@@ -217,8 +218,11 @@ namespace {
217
218
// / set \p CopyMIs. If this virtual register was previously seen as a
218
219
// / copy, replace the uses of this copy with the previously seen copy's
219
220
// / destination register.
221
+ // / \p LocalMIs contains all previous seen instructions. An optimized away
222
+ // / instruction should be deleted from LocalMIs.
220
223
bool foldRedundantCopy (MachineInstr &MI,
221
- DenseMap<RegSubRegPair, MachineInstr *> &CopyMIs);
224
+ DenseMap<RegSubRegPair, MachineInstr *> &CopyMIs,
225
+ SmallPtrSetImpl<MachineInstr *> &LocalMIs);
222
226
223
227
// / Is the register \p Reg a non-allocatable physical register?
224
228
bool isNAPhysCopy (Register Reg);
@@ -1351,26 +1355,28 @@ bool PeepholeOptimizer::isMoveImmediate(
1351
1355
MachineInstr &MI, SmallSet<Register, 4 > &ImmDefRegs,
1352
1356
DenseMap<Register, MachineInstr *> &ImmDefMIs) {
1353
1357
const MCInstrDesc &MCID = MI.getDesc ();
1354
- if (!MI.isMoveImmediate ())
1355
- return false ;
1356
- if (MCID.getNumDefs () != 1 )
1358
+ if (MCID.getNumDefs () != 1 || !MI.getOperand (0 ).isReg ())
1357
1359
return false ;
1358
1360
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
- }
1361
+ if (!Reg.isVirtual ())
1362
+ return false ;
1364
1363
1365
- return false ;
1364
+ int64_t ImmVal;
1365
+ if (!MI.isMoveImmediate () && !TII->getConstValDefinedInReg (MI, Reg, ImmVal))
1366
+ return false ;
1367
+
1368
+ ImmDefMIs.insert (std::make_pair (Reg, &MI));
1369
+ ImmDefRegs.insert (Reg);
1370
+ return true ;
1366
1371
}
1367
1372
1368
1373
// / Try folding register operands that are defined by move immediate
1369
1374
// / instructions, i.e. a trivial constant folding optimization, if
1370
1375
// / and only if the def and use are in the same BB.
1371
1376
bool PeepholeOptimizer::foldImmediate (
1372
1377
MachineInstr &MI, SmallSet<Register, 4 > &ImmDefRegs,
1373
- DenseMap<Register, MachineInstr *> &ImmDefMIs) {
1378
+ DenseMap<Register, MachineInstr *> &ImmDefMIs, bool &Deleted) {
1379
+ Deleted = false ;
1374
1380
for (unsigned i = 0 , e = MI.getDesc ().getNumOperands (); i != e; ++i) {
1375
1381
MachineOperand &MO = MI.getOperand (i);
1376
1382
if (!MO.isReg () || MO.isDef ())
@@ -1384,6 +1390,19 @@ bool PeepholeOptimizer::foldImmediate(
1384
1390
assert (II != ImmDefMIs.end () && " couldn't find immediate definition" );
1385
1391
if (TII->FoldImmediate (MI, *II->second , Reg, MRI)) {
1386
1392
++NumImmFold;
1393
+ // FoldImmediate can delete ImmDefMI if MI was its only user. If ImmDefMI
1394
+ // is not deleted, and we happened to get a same MI, we can delete MI and
1395
+ // replace its users.
1396
+ if (MRI->getVRegDef (Reg) &&
1397
+ MI.isIdenticalTo (*II->second , MachineInstr::IgnoreVRegDefs)) {
1398
+ Register DstReg = MI.getOperand (0 ).getReg ();
1399
+ if (DstReg.isVirtual () &&
1400
+ MRI->getRegClass (DstReg) == MRI->getRegClass (Reg)) {
1401
+ MRI->replaceRegWith (DstReg, Reg);
1402
+ MI.eraseFromParent ();
1403
+ Deleted = true ;
1404
+ }
1405
+ }
1387
1406
return true ;
1388
1407
}
1389
1408
}
@@ -1405,7 +1424,8 @@ bool PeepholeOptimizer::foldImmediate(
1405
1424
//
1406
1425
// Should replace %2 uses with %1:sub1
1407
1426
bool PeepholeOptimizer::foldRedundantCopy (
1408
- MachineInstr &MI, DenseMap<RegSubRegPair, MachineInstr *> &CopyMIs) {
1427
+ MachineInstr &MI, DenseMap<RegSubRegPair, MachineInstr *> &CopyMIs,
1428
+ SmallPtrSetImpl<MachineInstr *> &LocalMIs) {
1409
1429
assert (MI.isCopy () && " expected a COPY machine instruction" );
1410
1430
1411
1431
Register SrcReg = MI.getOperand (1 ).getReg ();
@@ -1425,6 +1445,8 @@ bool PeepholeOptimizer::foldRedundantCopy(
1425
1445
}
1426
1446
1427
1447
MachineInstr *PrevCopy = CopyMIs.find (SrcPair)->second ;
1448
+ if (!LocalMIs.count (PrevCopy))
1449
+ return false ;
1428
1450
1429
1451
assert (SrcSubReg == PrevCopy->getOperand (1 ).getSubReg () &&
1430
1452
" Unexpected mismatching subreg!" );
@@ -1732,7 +1754,7 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
1732
1754
continue ;
1733
1755
}
1734
1756
1735
- if (MI->isCopy () && (foldRedundantCopy (*MI, CopySrcMIs) ||
1757
+ if (MI->isCopy () && (foldRedundantCopy (*MI, CopySrcMIs, LocalMIs ) ||
1736
1758
foldRedundantNAPhysCopy (*MI, NAPhysToVirtMIs))) {
1737
1759
LocalMIs.erase (MI);
1738
1760
LLVM_DEBUG (dbgs () << " Deleting redundant copy: " << *MI << " \n " );
@@ -1750,8 +1772,14 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
1750
1772
// next iteration sees the new instructions.
1751
1773
MII = MI;
1752
1774
++MII;
1753
- if (SeenMoveImm)
1754
- Changed |= foldImmediate (*MI, ImmDefRegs, ImmDefMIs);
1775
+ if (SeenMoveImm) {
1776
+ bool Deleted;
1777
+ Changed |= foldImmediate (*MI, ImmDefRegs, ImmDefMIs, Deleted);
1778
+ if (Deleted) {
1779
+ LocalMIs.erase (MI);
1780
+ continue ;
1781
+ }
1782
+ }
1755
1783
}
1756
1784
1757
1785
// Check whether MI is a load candidate for folding into a later
0 commit comments