@@ -305,7 +305,11 @@ namespace {
305
305
// / number if it is not zero. If DstReg is a physical register and the
306
306
// / existing subregister number of the def / use being updated is not zero,
307
307
// / make sure to set it to the correct physical subregister.
308
- void updateRegDefsUses (Register SrcReg, Register DstReg, unsigned SubIdx);
308
+ // /
309
+ // / If \p IsSubregToReg, we are coalescing a DstReg = SUBREG_TO_REG
310
+ // / SrcReg. This introduces an implicit-def of DstReg on coalesced users.
311
+ void updateRegDefsUses (Register SrcReg, Register DstReg, unsigned SubIdx,
312
+ bool IsSubregToReg);
309
313
310
314
// / If the given machine operand reads only undefined lanes add an undef
311
315
// / flag.
@@ -1328,8 +1332,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1328
1332
if (DstReg.isPhysical ()) {
1329
1333
Register NewDstReg = DstReg;
1330
1334
1331
- unsigned NewDstIdx = TRI->composeSubRegIndices (CP.getSrcIdx (),
1332
- DefMI->getOperand (0 ).getSubReg ());
1335
+ unsigned NewDstIdx = TRI->composeSubRegIndices (CP.getSrcIdx (), DefSubIdx);
1333
1336
if (NewDstIdx)
1334
1337
NewDstReg = TRI->getSubReg (DstReg, NewDstIdx);
1335
1338
@@ -1478,7 +1481,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1478
1481
MRI->setRegClass (DstReg, NewRC);
1479
1482
1480
1483
// Update machine operands and add flags.
1481
- updateRegDefsUses (DstReg, DstReg, DstIdx);
1484
+ updateRegDefsUses (DstReg, DstReg, DstIdx, false );
1482
1485
NewMI.getOperand (0 ).setSubReg (NewIdx);
1483
1486
// updateRegDefUses can add an "undef" flag to the definition, since
1484
1487
// it will replace DstReg with DstReg.DstIdx. If NewIdx is 0, make
@@ -1800,7 +1803,7 @@ void RegisterCoalescer::addUndefFlag(const LiveInterval &Int, SlotIndex UseIdx,
1800
1803
}
1801
1804
1802
1805
void RegisterCoalescer::updateRegDefsUses (Register SrcReg, Register DstReg,
1803
- unsigned SubIdx) {
1806
+ unsigned SubIdx, bool IsSubregToReg ) {
1804
1807
bool DstIsPhys = DstReg.isPhysical ();
1805
1808
LiveInterval *DstInt = DstIsPhys ? nullptr : &LIS->getInterval (DstReg);
1806
1809
@@ -1840,16 +1843,22 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
1840
1843
if (DstInt && !Reads && SubIdx && !UseMI->isDebugInstr ())
1841
1844
Reads = DstInt->liveAt (LIS->getInstructionIndex (*UseMI));
1842
1845
1846
+ bool FullDef = true ;
1847
+
1843
1848
// Replace SrcReg with DstReg in all UseMI operands.
1844
1849
for (unsigned i = 0 , e = Ops.size (); i != e; ++i) {
1845
1850
MachineOperand &MO = UseMI->getOperand (Ops[i]);
1846
1851
1847
1852
// Adjust <undef> flags in case of sub-register joins. We don't want to
1848
1853
// turn a full def into a read-modify-write sub-register def and vice
1849
1854
// versa.
1850
- if (SubIdx && MO.isDef ())
1855
+ if (SubIdx && MO.isDef ()) {
1851
1856
MO.setIsUndef (!Reads);
1852
1857
1858
+ if (!Reads)
1859
+ FullDef = false ;
1860
+ }
1861
+
1853
1862
// A subreg use of a partially undef (super) register may be a complete
1854
1863
// undef use now and then has to be marked that way.
1855
1864
if (MO.isUse () && !DstIsPhys) {
@@ -1881,6 +1890,25 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
1881
1890
MO.substVirtReg (DstReg, SubIdx, *TRI);
1882
1891
}
1883
1892
1893
+ if (IsSubregToReg && !FullDef) {
1894
+ // If the coalesed instruction doesn't fully define the register, we need
1895
+ // to preserve the original super register liveness for SUBREG_TO_REG.
1896
+ //
1897
+ // We pretended SUBREG_TO_REG was a regular copy for coalescing purposes,
1898
+ // but it introduces liveness for other subregisters. Downstream users may
1899
+ // have been relying on those bits, so we need to ensure their liveness is
1900
+ // captured with a def of other lanes.
1901
+
1902
+ // FIXME: Need to add new subrange if tracking subranges. We could also
1903
+ // skip adding this if we knew the other lanes are dead, and only for
1904
+ // other lanes.
1905
+
1906
+ assert (!MRI->shouldTrackSubRegLiveness (DstReg) &&
1907
+ " this should update subranges" );
1908
+ MachineInstrBuilder MIB (*MF, UseMI);
1909
+ MIB.addReg (DstReg, RegState::ImplicitDefine);
1910
+ }
1911
+
1884
1912
LLVM_DEBUG ({
1885
1913
dbgs () << " \t\t updated: " ;
1886
1914
if (!UseMI->isDebugInstr ())
@@ -2080,6 +2108,8 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
2080
2108
});
2081
2109
}
2082
2110
2111
+ const bool IsSubregToReg = CopyMI->isSubregToReg ();
2112
+
2083
2113
ShrinkMask = LaneBitmask::getNone ();
2084
2114
ShrinkMainRange = false ;
2085
2115
@@ -2147,9 +2177,12 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
2147
2177
2148
2178
// Rewrite all SrcReg operands to DstReg.
2149
2179
// Also update DstReg operands to include DstIdx if it is set.
2150
- if (CP.getDstIdx ())
2151
- updateRegDefsUses (CP.getDstReg (), CP.getDstReg (), CP.getDstIdx ());
2152
- updateRegDefsUses (CP.getSrcReg (), CP.getDstReg (), CP.getSrcIdx ());
2180
+ if (CP.getDstIdx ()) {
2181
+ assert (!IsSubregToReg && " can this happen?" );
2182
+ updateRegDefsUses (CP.getDstReg (), CP.getDstReg (), CP.getDstIdx (), false );
2183
+ }
2184
+ updateRegDefsUses (CP.getSrcReg (), CP.getDstReg (), CP.getSrcIdx (),
2185
+ IsSubregToReg);
2153
2186
2154
2187
// Shrink subregister ranges if necessary.
2155
2188
if (ShrinkMask.any ()) {
0 commit comments