@@ -202,7 +202,8 @@ namespace {
202202    bool  isMoveImmediate (MachineInstr &MI, SmallSet<Register, 4 > &ImmDefRegs,
203203                         DenseMap<Register, MachineInstr *> &ImmDefMIs);
204204    bool  foldImmediate (MachineInstr &MI, SmallSet<Register, 4 > &ImmDefRegs,
205-                        DenseMap<Register, MachineInstr *> &ImmDefMIs);
205+                        DenseMap<Register, MachineInstr *> &ImmDefMIs,
206+                        bool  &Deleted);
206207
207208    // / Finds recurrence cycles, but only ones that formulated around
208209    // / a def operand and a use operand that are tied. If there is a use
@@ -217,8 +218,11 @@ namespace {
217218    // / set \p CopyMIs. If this virtual register was previously seen as a
218219    // / copy, replace the uses of this copy with the previously seen copy's
219220    // / destination register.
221+     // / \p LocalMIs contains all previous seen instructions. An optimized away
222+     // / instruction should be deleted from LocalMIs.
220223    bool  foldRedundantCopy (MachineInstr &MI,
221-                            DenseMap<RegSubRegPair, MachineInstr *> &CopyMIs);
224+                            DenseMap<RegSubRegPair, MachineInstr *> &CopyMIs,
225+                            SmallPtrSetImpl<MachineInstr *> &LocalMIs);
222226
223227    // / Is the register \p Reg a non-allocatable physical register?
224228    bool  isNAPhysCopy (Register Reg);
@@ -1351,26 +1355,28 @@ bool PeepholeOptimizer::isMoveImmediate(
13511355    MachineInstr &MI, SmallSet<Register, 4 > &ImmDefRegs,
13521356    DenseMap<Register, MachineInstr *> &ImmDefMIs) {
13531357  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 ())
13571359    return  false ;
13581360  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 ;
13641363
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 ;
13661371}
13671372
13681373// / Try folding register operands that are defined by move immediate
13691374// / instructions, i.e. a trivial constant folding optimization, if
13701375// / and only if the def and use are in the same BB.
13711376bool  PeepholeOptimizer::foldImmediate (
13721377    MachineInstr &MI, SmallSet<Register, 4 > &ImmDefRegs,
1373-     DenseMap<Register, MachineInstr *> &ImmDefMIs) {
1378+     DenseMap<Register, MachineInstr *> &ImmDefMIs, bool  &Deleted) {
1379+   Deleted = false ;
13741380  for  (unsigned  i = 0 , e = MI.getDesc ().getNumOperands (); i != e; ++i) {
13751381    MachineOperand &MO = MI.getOperand (i);
13761382    if  (!MO.isReg () || MO.isDef ())
@@ -1384,6 +1390,19 @@ bool PeepholeOptimizer::foldImmediate(
13841390    assert (II != ImmDefMIs.end () && " couldn't find immediate definition"  );
13851391    if  (TII->FoldImmediate (MI, *II->second , Reg, MRI)) {
13861392      ++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+       }
13871406      return  true ;
13881407    }
13891408  }
@@ -1405,7 +1424,8 @@ bool PeepholeOptimizer::foldImmediate(
14051424// 
14061425//  Should replace %2 uses with %1:sub1
14071426bool  PeepholeOptimizer::foldRedundantCopy (
1408-     MachineInstr &MI, DenseMap<RegSubRegPair, MachineInstr *> &CopyMIs) {
1427+     MachineInstr &MI, DenseMap<RegSubRegPair, MachineInstr *> &CopyMIs,
1428+     SmallPtrSetImpl<MachineInstr *> &LocalMIs) {
14091429  assert (MI.isCopy () && " expected a COPY machine instruction"  );
14101430
14111431  Register SrcReg = MI.getOperand (1 ).getReg ();
@@ -1425,6 +1445,8 @@ bool PeepholeOptimizer::foldRedundantCopy(
14251445  }
14261446
14271447  MachineInstr *PrevCopy = CopyMIs.find (SrcPair)->second ;
1448+   if  (!LocalMIs.count (PrevCopy))
1449+     return  false ;
14281450
14291451  assert (SrcSubReg == PrevCopy->getOperand (1 ).getSubReg () &&
14301452         " Unexpected mismatching subreg!"  );
@@ -1732,7 +1754,7 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
17321754        continue ;
17331755      }
17341756
1735-       if  (MI->isCopy () && (foldRedundantCopy (*MI, CopySrcMIs) ||
1757+       if  (MI->isCopy () && (foldRedundantCopy (*MI, CopySrcMIs, LocalMIs ) ||
17361758                           foldRedundantNAPhysCopy (*MI, NAPhysToVirtMIs))) {
17371759        LocalMIs.erase (MI);
17381760        LLVM_DEBUG (dbgs () << " Deleting redundant copy: "   << *MI << " \n "  );
@@ -1750,8 +1772,14 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
17501772        //  next iteration sees the new instructions.
17511773        MII = MI;
17521774        ++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+         }
17551783      }
17561784
17571785      //  Check whether MI is a load candidate for folding into a later
0 commit comments