@@ -1615,6 +1615,59 @@ void GCNSchedStage::revertScheduling() {
1615
1615
DAG.Regions [RegionIdx] = std::pair (DAG.RegionBegin , DAG.RegionEnd );
1616
1616
}
1617
1617
1618
+ // / allUsesAvailableAt - Return true if all registers used by InstToRemat at
1619
+ // / OriginalIdx are also available with the same value at RematIdx.
1620
+ bool PreRARematStage::allUsesAvailableAt (const MachineInstr *InstToRemat,
1621
+ SlotIndex OriginalIdx,
1622
+ SlotIndex RematIdx) const {
1623
+
1624
+ LiveIntervals *LIS = DAG.LIS ;
1625
+ MachineRegisterInfo &MRI = DAG.MRI ;
1626
+ OriginalIdx = OriginalIdx.getRegSlot (true );
1627
+ RematIdx = std::max (RematIdx, RematIdx.getRegSlot (true ));
1628
+ for (const MachineOperand &MO : InstToRemat->operands ()) {
1629
+ if (!MO.isReg () || !MO.getReg () || !MO.readsReg ())
1630
+ continue ;
1631
+
1632
+ if (!MO.getReg ().isVirtual ())
1633
+ continue ;
1634
+
1635
+ LiveInterval &LI = LIS->getInterval (MO.getReg ());
1636
+ const VNInfo *OVNI = LI.getVNInfoAt (OriginalIdx);
1637
+ assert (OVNI);
1638
+
1639
+ // Don't allow rematerialization immediately after the original def.
1640
+ // It would be incorrect if InstToRemat redefines the register.
1641
+ // See PR14098.
1642
+ if (SlotIndex::isSameInstr (OriginalIdx, RematIdx))
1643
+ return false ;
1644
+
1645
+ if (OVNI != LI.getVNInfoAt (RematIdx))
1646
+ return false ;
1647
+
1648
+ // Check that subrange is live at RematIdx.
1649
+ if (LI.hasSubRanges ()) {
1650
+ const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo ();
1651
+ unsigned SubReg = MO.getSubReg ();
1652
+ LaneBitmask LM = SubReg ? TRI->getSubRegIndexLaneMask (SubReg)
1653
+ : MRI.getMaxLaneMaskForVReg (MO.getReg ());
1654
+ for (LiveInterval::SubRange &SR : LI.subranges ()) {
1655
+ if ((SR.LaneMask & LM).none ())
1656
+ continue ;
1657
+ if (!SR.liveAt (RematIdx))
1658
+ return false ;
1659
+
1660
+ // Early exit if all used lanes are checked. No need to continue.
1661
+ LM &= ~SR.LaneMask ;
1662
+ if (LM.none ())
1663
+ break ;
1664
+ }
1665
+ assert (LM.none ());
1666
+ }
1667
+ }
1668
+ return true ;
1669
+ }
1670
+
1618
1671
void PreRARematStage::collectRematerializableInstructions () {
1619
1672
const SIRegisterInfo *SRI = static_cast <const SIRegisterInfo *>(DAG.TRI );
1620
1673
for (unsigned I = 0 , E = DAG.MRI .getNumVirtRegs (); I != E; ++I) {
@@ -1629,7 +1682,7 @@ void PreRARematStage::collectRematerializableInstructions() {
1629
1682
1630
1683
MachineOperand *Op = DAG.MRI .getOneDef (Reg);
1631
1684
MachineInstr *Def = Op->getParent ();
1632
- if (Op->getSubReg () != 0 || !isTriviallyReMaterializable (*Def))
1685
+ if (Op->getSubReg () != 0 || !DAG. TII -> isTriviallyReMaterializable (*Def))
1633
1686
continue ;
1634
1687
1635
1688
MachineInstr *UseI = &*DAG.MRI .use_instr_nodbg_begin (Reg);
@@ -1644,8 +1697,13 @@ void PreRARematStage::collectRematerializableInstructions() {
1644
1697
auto It = DAG.LiveIns [I].find (Reg);
1645
1698
if (It != DAG.LiveIns [I].end () && !It->second .none ()) {
1646
1699
if (DAG.RegionsWithMinOcc [I]) {
1647
- RematerializableInsts[I][Def] = UseI;
1648
- AddedToRematList = true ;
1700
+ SlotIndex DefIdx = DAG.LIS ->getInstructionIndex (*Def);
1701
+ SlotIndex UseIdx =
1702
+ DAG.LIS ->getInstructionIndex (*UseI).getRegSlot (true );
1703
+ if (allUsesAvailableAt (Def, DefIdx, UseIdx)) {
1704
+ RematerializableInsts[I][Def] = UseI;
1705
+ AddedToRematList = true ;
1706
+ }
1649
1707
}
1650
1708
1651
1709
// Collect regions with rematerializable reg as live-in to avoid
@@ -1719,6 +1777,27 @@ bool PreRARematStage::sinkTriviallyRematInsts(const GCNSubtarget &ST,
1719
1777
Register DefReg = Def->getOperand (0 ).getReg ();
1720
1778
TotalSinkableRegs +=
1721
1779
SIRegisterInfo::getNumCoveredRegs (NewLiveIns[I][DefReg]);
1780
+ #ifdef EXPENSIVE_CHECKS
1781
+ // All uses are known to be available / live at the remat point. Thus, the
1782
+ // uses should already be live in to the region.
1783
+ for (MachineOperand &MO : Def->operands ()) {
1784
+ if (!MO.isReg () || !MO.getReg () || !MO.readsReg ())
1785
+ continue ;
1786
+
1787
+ Register UseReg = MO.getReg ();
1788
+ if (!UseReg.isVirtual ())
1789
+ continue ;
1790
+
1791
+ LiveInterval &LI = LIS->getInterval (UseReg);
1792
+ LaneBitmask LM = DAG.MRI .getMaxLaneMaskForVReg (MO.getReg ());
1793
+ if (LI.hasSubRanges () && MO.getSubReg ())
1794
+ LM = DAG.TRI ->getSubRegIndexLaneMask (MO.getSubReg ());
1795
+
1796
+ assert (NewLiveIns[I].contains (UseReg));
1797
+ LaneBitmask LiveInMask = NewLiveIns[I][UseReg];
1798
+ assert ((LiveInMask & LM) == LM);
1799
+ }
1800
+ #endif
1722
1801
}
1723
1802
int VGPRsAfterSink = VGPRUsage - TotalSinkableRegs;
1724
1803
unsigned OptimisticOccupancy = ST.getOccupancyWithNumVGPRs (VGPRsAfterSink);
@@ -1842,18 +1921,6 @@ bool PreRARematStage::sinkTriviallyRematInsts(const GCNSubtarget &ST,
1842
1921
return true ;
1843
1922
}
1844
1923
1845
- // Copied from MachineLICM
1846
- bool PreRARematStage::isTriviallyReMaterializable (const MachineInstr &MI) {
1847
- if (!DAG.TII ->isTriviallyReMaterializable (MI))
1848
- return false ;
1849
-
1850
- for (const MachineOperand &MO : MI.all_uses ())
1851
- if (MO.getReg ().isVirtual ())
1852
- return false ;
1853
-
1854
- return true ;
1855
- }
1856
-
1857
1924
// When removing, we will have to check both beginning and ending of the region.
1858
1925
// When inserting, we will only have to check if we are inserting NewMI in front
1859
1926
// of a scheduling region and do not need to check the ending since we will only
0 commit comments