@@ -10954,6 +10954,8 @@ bool X86InstrInfo::isLegalToSpill2Reg(Register Reg,
1095410954 switch (unsigned Bits = TRI->getRegSizeInBits (Reg, *MRI)) {
1095510955 case 64 :
1095610956 case 32 :
10957+ case 16 :
10958+ case 8 :
1095710959 return true ;
1095810960 }
1095910961 return false ;
@@ -11049,6 +11051,8 @@ bool X86InstrInfo::isSpill2RegProfitable(const MachineInstr *MI,
1104911051
1105011052static unsigned getInsertOrExtractOpcode (unsigned Bits, bool Insert) {
1105111053 switch (Bits) {
11054+ case 8 :
11055+ case 16 :
1105211056 case 32 :
1105311057 return Insert ? X86::MOVDI2PDIrr : X86::MOVPDI2DIrr;
1105411058 case 64 :
@@ -11058,6 +11062,36 @@ static unsigned getInsertOrExtractOpcode(unsigned Bits, bool Insert) {
1105811062 }
1105911063}
1106011064
11065+ // / \Returns the subreg index for a getting a subregister of \p SubregBits from
11066+ // / a register of \p RegBits.
11067+ static unsigned spill2RegGetSubregIdx (unsigned RegBits, unsigned SubregBits) {
11068+ assert (RegBits > SubregBits && " From expected to cover To" );
11069+ switch (SubregBits) {
11070+ case 32 :
11071+ return X86::sub_32bit;
11072+ case 16 :
11073+ return X86::sub_16bit;
11074+ case 8 :
11075+ return X86::sub_8bit;
11076+ default :
11077+ llvm_unreachable (" FIXME" );
11078+ }
11079+ }
11080+
11081+ std::optional<MCRegister>
11082+ X86InstrInfo::getMovdCompatibleReg (MCRegister OldReg, uint32_t OldRegBits,
11083+ const TargetRegisterInfo *TRI) const {
11084+ if (OldRegBits != 8 && OldRegBits != 16 )
11085+ return std::nullopt ;
11086+ // The register class of the register that movd can handle.
11087+ const TargetRegisterClass *NewRegClass =
11088+ TRI->getRegClass (X86::GR32RegClassID);
11089+ unsigned NewRegBits = TRI->getRegSizeInBits (*NewRegClass);
11090+ unsigned SubIdx = spill2RegGetSubregIdx (NewRegBits, OldRegBits);
11091+ MCRegister NewReg = TRI->getMatchingSuperReg (OldReg, SubIdx, NewRegClass);
11092+ return NewReg;
11093+ }
11094+
1106111095MachineInstr *X86InstrInfo::spill2RegInsertToVectorReg (
1106211096 Register DstReg, Register SrcReg, int OperationBits, MachineBasicBlock *MBB,
1106311097 MachineBasicBlock::iterator InsertBeforeIt,
@@ -11066,6 +11100,12 @@ MachineInstr *X86InstrInfo::spill2RegInsertToVectorReg(
1106611100 unsigned InsertOpcode =
1106711101 getInsertOrExtractOpcode (OperationBits, true /* insert*/ );
1106811102 const MCInstrDesc &InsertMCID = get (InsertOpcode);
11103+ // `movd` does not support 8/16 bit operands. Instead, we use a 32-bit
11104+ // register. For example:
11105+ // $al = ...
11106+ // $xmm0 = MOVPDI2DIrr $eax
11107+ if (auto NewReg = getMovdCompatibleReg (SrcReg, OperationBits, TRI))
11108+ SrcReg = *NewReg;
1106911109 MachineInstr *InsertMI =
1107011110 BuildMI (*MBB, InsertBeforeIt, DL, InsertMCID, DstReg).addReg (SrcReg);
1107111111 return InsertMI;
@@ -11079,6 +11119,12 @@ MachineInstr *X86InstrInfo::spill2RegExtractFromVectorReg(
1107911119 unsigned ExtractOpcode =
1108011120 getInsertOrExtractOpcode (OperationBits, false /* extract*/ );
1108111121 const MCInstrDesc &ExtractMCID = get (ExtractOpcode);
11122+ // `movd` does not support 8/16 bit operands. Instead, we use a 32-bit
11123+ // register. For example:
11124+ // $eax = MOVPDI2DIrr $xmm0
11125+ // ... = $al
11126+ if (auto NewReg = getMovdCompatibleReg (DstReg, OperationBits, TRI))
11127+ DstReg = *NewReg;
1108211128 MachineInstr *ExtractMI =
1108311129 BuildMI (*InsertMBB, InsertBeforeIt, DL, ExtractMCID, DstReg)
1108411130 .addReg (SrcReg);
0 commit comments