@@ -217,7 +217,8 @@ class InlineSpiller : public Spiller {
217217 bool coalesceStackAccess (MachineInstr *MI, Register Reg);
218218 bool foldMemoryOperand (ArrayRef<std::pair<MachineInstr *, unsigned >>,
219219 MachineInstr *LoadMI = nullptr );
220- void insertReload (Register VReg, SlotIndex, MachineBasicBlock::iterator MI);
220+ void insertReload (Register VReg, unsigned SubReg, SlotIndex,
221+ MachineBasicBlock::iterator MI);
221222 void insertSpill (Register VReg, bool isKill, MachineBasicBlock::iterator MI);
222223
223224 void spillAroundUses (Register Reg);
@@ -1112,14 +1113,14 @@ foldMemoryOperand(ArrayRef<std::pair<MachineInstr *, unsigned>> Ops,
11121113 return true ;
11131114}
11141115
1115- void InlineSpiller::insertReload (Register NewVReg,
1116+ void InlineSpiller::insertReload (Register NewVReg, unsigned SubReg,
11161117 SlotIndex Idx,
11171118 MachineBasicBlock::iterator MI) {
11181119 MachineBasicBlock &MBB = *MI->getParent ();
11191120
11201121 MachineInstrSpan MIS (MI, &MBB);
11211122 TII.loadRegFromStackSlot (MBB, MI, NewVReg, StackSlot,
1122- MRI.getRegClass (NewVReg), &TRI, Register ());
1123+ MRI.getRegClass (NewVReg), &TRI, Register (), SubReg );
11231124
11241125 LIS.InsertMachineInstrRangeInMaps (MIS.begin (), MI);
11251126
@@ -1248,18 +1249,50 @@ void InlineSpiller::spillAroundUses(Register Reg) {
12481249
12491250 // Create a new virtual register for spill/fill.
12501251 // FIXME: Infer regclass from instruction alone.
1251- Register NewVReg = Edit->createFrom (Reg);
1252+
1253+ unsigned SubReg = 0 ;
1254+ LaneBitmask CoveringLanes = LaneBitmask::getNone ();
1255+ // Identify the subreg use(s). Skip if the instruction defines the register.
1256+ // For copy bundles, get the covering lane masks.
1257+ if (TRI.shouldEnableSubRegSpillRestore () && !RI.Writes ) {
1258+ for (auto [MI, OpIdx] : Ops) {
1259+ const MachineOperand &MO = MI->getOperand (OpIdx);
1260+ assert (MO.isReg () && MO.getReg () == Reg);
1261+ if (MO.isUse ()) {
1262+ SubReg = MO.getSubReg ();
1263+ CoveringLanes |= TRI.getSubRegIndexLaneMask (SubReg);
1264+ }
1265+ }
1266+ }
1267+
1268+ const TargetRegisterClass *OrigRC = MRI.getRegClass (Reg);
1269+ if (MI.isBundled () && CoveringLanes.any ()) {
1270+ CoveringLanes = LaneBitmask (bit_ceil (CoveringLanes.getAsInteger ()) - 1 );
1271+ // Get the covering subreg index including the missing indices in the
1272+ // identified small range. Even if this is suboptimal, it is advantageous
1273+ // when the higher subreg components are not really involved in the bundle
1274+ // copy as we emit the subreg reload rather than the one for the entire
1275+ // tuple.
1276+ SubReg = TRI.getSubRegIdxFromLaneMask (CoveringLanes);
1277+ }
1278+
1279+ const TargetRegisterClass *NewRC =
1280+ SubReg ? TRI.getSubRegisterClass (OrigRC, SubReg) : nullptr ;
1281+ Register NewVReg = Edit->createFrom (Reg, NewRC);
12521282
12531283 if (RI.Reads )
1254- insertReload (NewVReg, Idx, &MI);
1284+ insertReload (NewVReg, SubReg, Idx, &MI);
12551285
12561286 // Rewrite instruction operands.
12571287 bool hasLiveDef = false ;
12581288 for (const auto &OpPair : Ops) {
12591289 MachineOperand &MO = OpPair.first ->getOperand (OpPair.second );
12601290 MO.setReg (NewVReg);
12611291 if (MO.isUse ()) {
1262- if (!OpPair.first ->isRegTiedToDefOperand (OpPair.second ))
1292+ if (SubReg && !MI.isBundled ())
1293+ MO.setSubReg (0 );
1294+ if (!OpPair.first ->isRegTiedToDefOperand (OpPair.second ) ||
1295+ (SubReg && !MI.isBundled ()))
12631296 MO.setIsKill ();
12641297 } else {
12651298 if (!MO.isDead ())
0 commit comments