Skip to content

Commit bc91f3c

Browse files
authored
[RISCV] Add 32 bit GPR sub-register for Zfinx. (#108336)
This patches adds a 32 bit register class for use with Zfinx instructions. This makes them more similar to F instructions and allows us to only spill 32 bits. I've added CodeGenOnly instructions for load/store using GPRF32 as that gave better results than insert_subreg/extract_subreg. Function arguments use this new GPRF32 register class for f32 arguments with Zfinx. Eliminating the need to use RISCVISD::FMV* nodes. This is similar to #107446 which adds a 16 bit register class.
1 parent 0004fba commit bc91f3c

22 files changed

+900
-359
lines changed

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,14 @@ struct RISCVOperand final : public MCParsedAsmOperand {
485485
RISCVMCRegisterClasses[RISCV::GPRF16RegClassID].contains(Reg.RegNum);
486486
}
487487

488+
bool isGPRF32() const {
489+
return Kind == KindTy::Register &&
490+
RISCVMCRegisterClasses[RISCV::GPRF32RegClassID].contains(Reg.RegNum);
491+
}
492+
488493
bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
489494
bool isGPRAsFPR16() const { return isGPRF16() && Reg.IsGPRAsFPR; }
495+
bool isGPRAsFPR32() const { return isGPRF32() && Reg.IsGPRAsFPR; }
490496
bool isGPRPairAsFPR() const { return isGPRPair() && Reg.IsGPRAsFPR; }
491497

492498
bool isGPRPair() const {
@@ -1352,6 +1358,10 @@ unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
13521358
Op.Reg.RegNum = Reg - RISCV::X0 + RISCV::X0_H;
13531359
return Match_Success;
13541360
}
1361+
if (Kind == MCK_GPRAsFPR32 && Op.isGPRAsFPR()) {
1362+
Op.Reg.RegNum = Reg - RISCV::X0 + RISCV::X0_W;
1363+
return Match_Success;
1364+
}
13551365

13561366
// There are some GPRF64AsFPR instructions that have no RV32 equivalent. We
13571367
// reject them at parsing thinking we should match as GPRPairAsFPR for RV32.

llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,19 @@ static DecodeStatus DecodeGPRF16RegisterClass(MCInst &Inst, uint32_t RegNo,
9494
return MCDisassembler::Success;
9595
}
9696

97+
static DecodeStatus DecodeGPRF32RegisterClass(MCInst &Inst, uint32_t RegNo,
98+
uint64_t Address,
99+
const MCDisassembler *Decoder) {
100+
bool IsRVE = Decoder->getSubtargetInfo().hasFeature(RISCV::FeatureStdExtE);
101+
102+
if (RegNo >= 32 || (IsRVE && RegNo >= 16))
103+
return MCDisassembler::Fail;
104+
105+
MCRegister Reg = RISCV::X0_W + RegNo;
106+
Inst.addOperand(MCOperand::createReg(Reg));
107+
return MCDisassembler::Success;
108+
}
109+
97110
static DecodeStatus DecodeGPRX1X5RegisterClass(MCInst &Inst, uint32_t RegNo,
98111
uint64_t Address,
99112
const MCDisassembler *Decoder) {

llvm/lib/Target/RISCV/RISCVCallingConv.cpp

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,23 @@ static ArrayRef<MCPhysReg> getArgGPR16s(const RISCVABI::ABI ABI) {
156156
return ArrayRef(ArgIGPRs);
157157
}
158158

159+
static ArrayRef<MCPhysReg> getArgGPR32s(const RISCVABI::ABI ABI) {
160+
// The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except
161+
// the ILP32E ABI.
162+
static const MCPhysReg ArgIGPRs[] = {RISCV::X10_W, RISCV::X11_W, RISCV::X12_W,
163+
RISCV::X13_W, RISCV::X14_W, RISCV::X15_W,
164+
RISCV::X16_W, RISCV::X17_W};
165+
// The GPRs used for passing arguments in the ILP32E/LP64E ABI.
166+
static const MCPhysReg ArgEGPRs[] = {RISCV::X10_W, RISCV::X11_W,
167+
RISCV::X12_W, RISCV::X13_W,
168+
RISCV::X14_W, RISCV::X15_W};
169+
170+
if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)
171+
return ArrayRef(ArgEGPRs);
172+
173+
return ArrayRef(ArgIGPRs);
174+
}
175+
159176
static ArrayRef<MCPhysReg> getFastCCArgGPRs(const RISCVABI::ABI ABI) {
160177
// The GPRs used for passing arguments in the FastCC, X5 and X6 might be used
161178
// for save-restore libcall, so we don't use them.
@@ -194,6 +211,26 @@ static ArrayRef<MCPhysReg> getFastCCArgGPRF16s(const RISCVABI::ABI ABI) {
194211
return ArrayRef(FastCCIGPRs);
195212
}
196213

214+
static ArrayRef<MCPhysReg> getFastCCArgGPRF32s(const RISCVABI::ABI ABI) {
215+
// The GPRs used for passing arguments in the FastCC, X5 and X6 might be used
216+
// for save-restore libcall, so we don't use them.
217+
// Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.
218+
static const MCPhysReg FastCCIGPRs[] = {
219+
RISCV::X10_W, RISCV::X11_W, RISCV::X12_W, RISCV::X13_W,
220+
RISCV::X14_W, RISCV::X15_W, RISCV::X16_W, RISCV::X17_W,
221+
RISCV::X28_W, RISCV::X29_W, RISCV::X30_W, RISCV::X31_W};
222+
223+
// The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.
224+
static const MCPhysReg FastCCEGPRs[] = {RISCV::X10_W, RISCV::X11_W,
225+
RISCV::X12_W, RISCV::X13_W,
226+
RISCV::X14_W, RISCV::X15_W};
227+
228+
if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)
229+
return ArrayRef(FastCCEGPRs);
230+
231+
return ArrayRef(FastCCIGPRs);
232+
}
233+
197234
// Pass a 2*XLEN argument that has been split into two XLEN values through
198235
// registers or the stack as necessary.
199236
static bool CC_RISCVAssign2XLen(unsigned XLen, CCState &State, CCValAssign VA1,
@@ -364,11 +401,17 @@ bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT,
364401
}
365402
}
366403

404+
if (ValVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {
405+
if (MCRegister Reg = State.AllocateReg(getArgGPR32s(ABI))) {
406+
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
407+
return false;
408+
}
409+
}
410+
367411
ArrayRef<MCPhysReg> ArgGPRs = RISCV::getArgGPRs(ABI);
368412

369-
// Zfinx/Zdinx use GPR without a bitcast when possible.
370-
if ((LocVT == MVT::f32 && XLen == 32 && Subtarget.hasStdExtZfinx()) ||
371-
(LocVT == MVT::f64 && XLen == 64 && Subtarget.hasStdExtZdinx())) {
413+
// Zdinx use GPR without a bitcast when possible.
414+
if (LocVT == MVT::f64 && XLen == 64 && Subtarget.hasStdExtZdinx()) {
372415
if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {
373416
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
374417
return false;
@@ -616,10 +659,16 @@ bool llvm::CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT,
616659
}
617660
}
618661

662+
// Check if there is an available GPRF32 before hitting the stack.
663+
if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {
664+
if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRF32s(ABI))) {
665+
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
666+
return false;
667+
}
668+
}
669+
619670
// Check if there is an available GPR before hitting the stack.
620-
if ((LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) ||
621-
(LocVT == MVT::f64 && Subtarget.is64Bit() &&
622-
Subtarget.hasStdExtZdinx())) {
671+
if (LocVT == MVT::f64 && Subtarget.is64Bit() && Subtarget.hasStdExtZdinx()) {
623672
if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) {
624673
if (LocVT.getSizeInBits() != Subtarget.getXLen()) {
625674
LocVT = XLenVT;
@@ -723,9 +772,18 @@ bool llvm::CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT,
723772
}
724773
}
725774

726-
if ((LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) ||
727-
(LocVT == MVT::f64 && Subtarget.hasStdExtZdinx() &&
728-
Subtarget.is64Bit())) {
775+
if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {
776+
static const MCPhysReg GPR32List[] = {
777+
RISCV::X9_W, RISCV::X18_W, RISCV::X19_W, RISCV::X20_W,
778+
RISCV::X21_W, RISCV::X22_W, RISCV::X23_W, RISCV::X24_W,
779+
RISCV::X25_W, RISCV::X26_W, RISCV::X27_W};
780+
if (MCRegister Reg = State.AllocateReg(GPR32List)) {
781+
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
782+
return false;
783+
}
784+
}
785+
786+
if (LocVT == MVT::f64 && Subtarget.hasStdExtZdinx() && Subtarget.is64Bit()) {
729787
if (MCRegister Reg = State.AllocateReg(GPRList)) {
730788
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
731789
return false;

llvm/lib/Target/RISCV/RISCVDeadRegisterDefinitions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ bool RISCVDeadRegisterDefinitions::runOnMachineFunction(MachineFunction &MF) {
9797
const TargetRegisterClass *RC = TII->getRegClass(Desc, I, TRI, MF);
9898
if (RC && RC->contains(RISCV::X0)) {
9999
X0Reg = RISCV::X0;
100+
} else if (RC && RC->contains(RISCV::X0_W)) {
101+
X0Reg = RISCV::X0_W;
100102
} else if (RC && RC->contains(RISCV::X0_H)) {
101103
X0Reg = RISCV::X0_H;
102104
} else {

llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ class RISCVExpandPseudo : public MachineFunctionPass {
5050
MachineBasicBlock::iterator MBBI, unsigned Opcode);
5151
bool expandMV_FPR16INX(MachineBasicBlock &MBB,
5252
MachineBasicBlock::iterator MBBI);
53+
bool expandMV_FPR32INX(MachineBasicBlock &MBB,
54+
MachineBasicBlock::iterator MBBI);
5355
bool expandRV32ZdinxStore(MachineBasicBlock &MBB,
5456
MachineBasicBlock::iterator MBBI);
5557
bool expandRV32ZdinxLoad(MachineBasicBlock &MBB,
@@ -108,6 +110,8 @@ bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
108110
switch (MBBI->getOpcode()) {
109111
case RISCV::PseudoMV_FPR16INX:
110112
return expandMV_FPR16INX(MBB, MBBI);
113+
case RISCV::PseudoMV_FPR32INX:
114+
return expandMV_FPR32INX(MBB, MBBI);
111115
case RISCV::PseudoRV32ZdinxSD:
112116
return expandRV32ZdinxStore(MBB, MBBI);
113117
case RISCV::PseudoRV32ZdinxLD:
@@ -287,6 +291,23 @@ bool RISCVExpandPseudo::expandMV_FPR16INX(MachineBasicBlock &MBB,
287291
return true;
288292
}
289293

294+
bool RISCVExpandPseudo::expandMV_FPR32INX(MachineBasicBlock &MBB,
295+
MachineBasicBlock::iterator MBBI) {
296+
DebugLoc DL = MBBI->getDebugLoc();
297+
const TargetRegisterInfo *TRI = STI->getRegisterInfo();
298+
Register DstReg = TRI->getMatchingSuperReg(
299+
MBBI->getOperand(0).getReg(), RISCV::sub_32, &RISCV::GPRRegClass);
300+
Register SrcReg = TRI->getMatchingSuperReg(
301+
MBBI->getOperand(1).getReg(), RISCV::sub_32, &RISCV::GPRRegClass);
302+
303+
BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DstReg)
304+
.addReg(SrcReg, getKillRegState(MBBI->getOperand(1).isKill()))
305+
.addImm(0);
306+
307+
MBBI->eraseFromParent(); // The pseudo instruction is gone now.
308+
return true;
309+
}
310+
290311
// This function expands the PseudoRV32ZdinxSD for storing a double-precision
291312
// floating-point value into memory by generating an equivalent instruction
292313
// sequence for RV32.

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,9 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
931931
if (VT.SimpleTy == MVT::f16 && Opc == RISCV::COPY) {
932932
Res =
933933
CurDAG->getTargetExtractSubreg(RISCV::sub_16, DL, VT, Imm).getNode();
934+
} else if (VT.SimpleTy == MVT::f32 && Opc == RISCV::COPY) {
935+
Res =
936+
CurDAG->getTargetExtractSubreg(RISCV::sub_32, DL, VT, Imm).getNode();
934937
} else if (Opc == RISCV::FCVT_D_W_IN32X || Opc == RISCV::FCVT_D_W)
935938
Res = CurDAG->getMachineNode(
936939
Opc, DL, VT, Imm,

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ Register RISCVInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
110110
MemBytes = 2;
111111
break;
112112
case RISCV::LW:
113+
case RISCV::LW_INX:
113114
case RISCV::FLW:
114115
case RISCV::LWU:
115116
MemBytes = 4;
@@ -150,6 +151,7 @@ Register RISCVInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
150151
MemBytes = 2;
151152
break;
152153
case RISCV::SW:
154+
case RISCV::SW_INX:
153155
case RISCV::FSW:
154156
MemBytes = 4;
155157
break;
@@ -471,6 +473,13 @@ void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
471473
return;
472474
}
473475

476+
if (RISCV::GPRF32RegClass.contains(DstReg, SrcReg)) {
477+
BuildMI(MBB, MBBI, DL, get(RISCV::PseudoMV_FPR32INX), DstReg)
478+
.addReg(SrcReg,
479+
getKillRegState(KillSrc) | getRenamableRegState(RenamableSrc));
480+
return;
481+
}
482+
474483
if (RISCV::GPRPairRegClass.contains(DstReg, SrcReg)) {
475484
// Emit an ADDI for both parts of GPRPair.
476485
BuildMI(MBB, MBBI, DL, get(RISCV::ADDI),
@@ -595,6 +604,9 @@ void RISCVInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
595604
} else if (RISCV::GPRF16RegClass.hasSubClassEq(RC)) {
596605
Opcode = RISCV::SH_INX;
597606
IsScalableVector = false;
607+
} else if (RISCV::GPRF32RegClass.hasSubClassEq(RC)) {
608+
Opcode = RISCV::SW_INX;
609+
IsScalableVector = false;
598610
} else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
599611
Opcode = RISCV::PseudoRV32ZdinxSD;
600612
IsScalableVector = false;
@@ -681,6 +693,9 @@ void RISCVInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
681693
} else if (RISCV::GPRF16RegClass.hasSubClassEq(RC)) {
682694
Opcode = RISCV::LH_INX;
683695
IsScalableVector = false;
696+
} else if (RISCV::GPRF32RegClass.hasSubClassEq(RC)) {
697+
Opcode = RISCV::LW_INX;
698+
IsScalableVector = false;
684699
} else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
685700
Opcode = RISCV::PseudoRV32ZdinxLD;
686701
IsScalableVector = false;
@@ -1554,6 +1569,7 @@ unsigned RISCVInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
15541569

15551570
switch (Opcode) {
15561571
case RISCV::PseudoMV_FPR16INX:
1572+
case RISCV::PseudoMV_FPR32INX:
15571573
// MV is always compressible to either c.mv or c.li rd, 0.
15581574
return STI.hasStdExtCOrZca() ? 2 : 4;
15591575
case TargetOpcode::STACKMAP:
@@ -2614,6 +2630,7 @@ bool RISCVInstrInfo::canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg,
26142630
case RISCV::LH_INX:
26152631
case RISCV::LHU:
26162632
case RISCV::LW:
2633+
case RISCV::LW_INX:
26172634
case RISCV::LWU:
26182635
case RISCV::LD:
26192636
case RISCV::FLH:
@@ -2623,6 +2640,7 @@ bool RISCVInstrInfo::canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg,
26232640
case RISCV::SH:
26242641
case RISCV::SH_INX:
26252642
case RISCV::SW:
2643+
case RISCV::SW_INX:
26262644
case RISCV::SD:
26272645
case RISCV::FSH:
26282646
case RISCV::FSW:
@@ -2692,9 +2710,11 @@ bool RISCVInstrInfo::getMemOperandsWithOffsetWidth(
26922710
case RISCV::SH_INX:
26932711
case RISCV::FSH:
26942712
case RISCV::LW:
2713+
case RISCV::LW_INX:
26952714
case RISCV::LWU:
26962715
case RISCV::FLW:
26972716
case RISCV::SW:
2717+
case RISCV::SW_INX:
26982718
case RISCV::FSW:
26992719
case RISCV::LD:
27002720
case RISCV::FLD:

0 commit comments

Comments
 (0)