Skip to content

Commit ec90ba0

Browse files
committed
[RISCV] Add 32 bit GPR sub-register for Zfinx.
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. I'm using FSGNJ for GPRF32 copy with Zfinx as that gave better results from MachineCopyPropagation. 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 llvm#107446 which adds a 16 bit register class.
1 parent cca3217 commit ec90ba0

22 files changed

+899
-356
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: 66 additions & 6 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/ILP64E 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/ILP64E.
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,6 +772,17 @@ bool llvm::CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT,
723772
}
724773
}
725774

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+
726786
if ((LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) ||
727787
(LocVT == MVT::f64 && Subtarget.hasStdExtZdinx() &&
728788
Subtarget.is64Bit())) {

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)