@@ -306,7 +306,11 @@ namespace {
306
306
// / number if it is not zero. If DstReg is a physical register and the
307
307
// / existing subregister number of the def / use being updated is not zero,
308
308
// / make sure to set it to the correct physical subregister.
309
- void updateRegDefsUses (Register SrcReg, Register DstReg, unsigned SubIdx);
309
+ // /
310
+ // / If \p IsSubregToReg, we are coalescing a DstReg = SUBREG_TO_REG
311
+ // / SrcReg. This introduces an implicit-def of DstReg on coalesced users.
312
+ void updateRegDefsUses (Register SrcReg, Register DstReg, unsigned SubIdx,
313
+ bool IsSubregToReg);
310
314
311
315
// / If the given machine operand reads only undefined lanes add an undef
312
316
// / flag.
@@ -1516,7 +1520,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
1516
1520
MRI->setRegClass (DstReg, NewRC);
1517
1521
1518
1522
// Update machine operands and add flags.
1519
- updateRegDefsUses (DstReg, DstReg, DstIdx);
1523
+ updateRegDefsUses (DstReg, DstReg, DstIdx, false );
1520
1524
NewMI.getOperand (0 ).setSubReg (NewIdx);
1521
1525
// updateRegDefUses can add an "undef" flag to the definition, since
1522
1526
// it will replace DstReg with DstReg.DstIdx. If NewIdx is 0, make
@@ -1857,7 +1861,7 @@ void RegisterCoalescer::addUndefFlag(const LiveInterval &Int, SlotIndex UseIdx,
1857
1861
}
1858
1862
1859
1863
void RegisterCoalescer::updateRegDefsUses (Register SrcReg, Register DstReg,
1860
- unsigned SubIdx) {
1864
+ unsigned SubIdx, bool IsSubregToReg ) {
1861
1865
bool DstIsPhys = DstReg.isPhysical ();
1862
1866
LiveInterval *DstInt = DstIsPhys ? nullptr : &LIS->getInterval (DstReg);
1863
1867
@@ -1900,16 +1904,22 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
1900
1904
if (DstInt && !Reads && SubIdx && !UseMI->isDebugInstr ())
1901
1905
Reads = DstInt->liveAt (LIS->getInstructionIndex (*UseMI));
1902
1906
1907
+ bool FullDef = true ;
1908
+
1903
1909
// Replace SrcReg with DstReg in all UseMI operands.
1904
1910
for (unsigned Op : Ops) {
1905
1911
MachineOperand &MO = UseMI->getOperand (Op);
1906
1912
1907
1913
// Adjust <undef> flags in case of sub-register joins. We don't want to
1908
1914
// turn a full def into a read-modify-write sub-register def and vice
1909
1915
// versa.
1910
- if (SubIdx && MO.isDef ())
1916
+ if (SubIdx && MO.isDef ()) {
1911
1917
MO.setIsUndef (!Reads);
1912
1918
1919
+ if (!Reads)
1920
+ FullDef = false ;
1921
+ }
1922
+
1913
1923
// A subreg use of a partially undef (super) register may be a complete
1914
1924
// undef use now and then has to be marked that way.
1915
1925
if (MO.isUse () && !MO.isUndef () && !DstIsPhys) {
@@ -1941,6 +1951,25 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
1941
1951
MO.substVirtReg (DstReg, SubIdx, *TRI);
1942
1952
}
1943
1953
1954
+ if (IsSubregToReg && !FullDef) {
1955
+ // If the coalesed instruction doesn't fully define the register, we need
1956
+ // to preserve the original super register liveness for SUBREG_TO_REG.
1957
+ //
1958
+ // We pretended SUBREG_TO_REG was a regular copy for coalescing purposes,
1959
+ // but it introduces liveness for other subregisters. Downstream users may
1960
+ // have been relying on those bits, so we need to ensure their liveness is
1961
+ // captured with a def of other lanes.
1962
+
1963
+ // FIXME: Need to add new subrange if tracking subranges. We could also
1964
+ // skip adding this if we knew the other lanes are dead, and only for
1965
+ // other lanes.
1966
+
1967
+ assert (!MRI->shouldTrackSubRegLiveness (DstReg) &&
1968
+ " this should update subranges" );
1969
+ MachineInstrBuilder MIB (*MF, UseMI);
1970
+ MIB.addReg (DstReg, RegState::ImplicitDefine);
1971
+ }
1972
+
1944
1973
LLVM_DEBUG ({
1945
1974
dbgs () << " \t\t updated: " ;
1946
1975
if (!UseMI->isDebugInstr ())
@@ -2142,6 +2171,8 @@ bool RegisterCoalescer::joinCopy(
2142
2171
});
2143
2172
}
2144
2173
2174
+ const bool IsSubregToReg = CopyMI->isSubregToReg ();
2175
+
2145
2176
ShrinkMask = LaneBitmask::getNone ();
2146
2177
ShrinkMainRange = false ;
2147
2178
@@ -2211,9 +2242,12 @@ bool RegisterCoalescer::joinCopy(
2211
2242
2212
2243
// Rewrite all SrcReg operands to DstReg.
2213
2244
// Also update DstReg operands to include DstIdx if it is set.
2214
- if (CP.getDstIdx ())
2215
- updateRegDefsUses (CP.getDstReg (), CP.getDstReg (), CP.getDstIdx ());
2216
- updateRegDefsUses (CP.getSrcReg (), CP.getDstReg (), CP.getSrcIdx ());
2245
+ if (CP.getDstIdx ()) {
2246
+ assert (!IsSubregToReg && " can this happen?" );
2247
+ updateRegDefsUses (CP.getDstReg (), CP.getDstReg (), CP.getDstIdx (), false );
2248
+ }
2249
+ updateRegDefsUses (CP.getSrcReg (), CP.getDstReg (), CP.getSrcIdx (),
2250
+ IsSubregToReg);
2217
2251
2218
2252
// Shrink subregister ranges if necessary.
2219
2253
if (ShrinkMask.any ()) {
0 commit comments