@@ -49,8 +49,17 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
4949 RISCVABI::ABI ABI = Subtarget.getTargetABI ();
5050 assert (ABI != RISCVABI::ABI_Unknown && " Improperly initialised target ABI" );
5151
52- if (ABI != RISCVABI::ABI_ILP32 && ABI != RISCVABI::ABI_LP64)
52+ switch (ABI) {
53+ default :
5354 report_fatal_error (" Don't know how to lower this ABI" );
55+ case RISCVABI::ABI_ILP32:
56+ case RISCVABI::ABI_ILP32F:
57+ case RISCVABI::ABI_ILP32D:
58+ case RISCVABI::ABI_LP64:
59+ case RISCVABI::ABI_LP64F:
60+ case RISCVABI::ABI_LP64D:
61+ break ;
62+ }
5463
5564 MVT XLenVT = Subtarget.getXLenVT ();
5665
@@ -981,6 +990,14 @@ static const MCPhysReg ArgGPRs[] = {
981990 RISCV::X10, RISCV::X11, RISCV::X12, RISCV::X13,
982991 RISCV::X14, RISCV::X15, RISCV::X16, RISCV::X17
983992};
993+ static const MCPhysReg ArgFPR32s[] = {
994+ RISCV::F10_32, RISCV::F11_32, RISCV::F12_32, RISCV::F13_32,
995+ RISCV::F14_32, RISCV::F15_32, RISCV::F16_32, RISCV::F17_32
996+ };
997+ static const MCPhysReg ArgFPR64s[] = {
998+ RISCV::F10_64, RISCV::F11_64, RISCV::F12_64, RISCV::F13_64,
999+ RISCV::F14_64, RISCV::F15_64, RISCV::F16_64, RISCV::F17_64
1000+ };
9841001
9851002// Pass a 2*XLEN argument that has been split into two XLEN values through
9861003// registers or the stack as necessary.
@@ -1021,9 +1038,10 @@ static bool CC_RISCVAssign2XLen(unsigned XLen, CCState &State, CCValAssign VA1,
10211038}
10221039
10231040// Implements the RISC-V calling convention. Returns true upon failure.
1024- static bool CC_RISCV (const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
1025- CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
1026- CCState &State, bool IsFixed, bool IsRet, Type *OrigTy) {
1041+ static bool CC_RISCV (const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
1042+ MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo,
1043+ ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed,
1044+ bool IsRet, Type *OrigTy) {
10271045 unsigned XLen = DL.getLargestLegalIntTypeSizeInBits ();
10281046 assert (XLen == 32 || XLen == 64 );
10291047 MVT XLenVT = XLen == 32 ? MVT::i32 : MVT::i64 ;
@@ -1033,10 +1051,42 @@ static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
10331051 if (IsRet && ValNo > 1 )
10341052 return true ;
10351053
1036- if (ValVT == MVT::f32 ) {
1054+ // UseGPRForF32 if targeting one of the soft-float ABIs, if passing a
1055+ // variadic argument, or if no F32 argument registers are available.
1056+ bool UseGPRForF32 = true ;
1057+ // UseGPRForF64 if targeting soft-float ABIs or an FLEN=32 ABI, if passing a
1058+ // variadic argument, or if no F64 argument registers are available.
1059+ bool UseGPRForF64 = true ;
1060+
1061+ switch (ABI) {
1062+ default :
1063+ llvm_unreachable (" Unexpected ABI" );
1064+ case RISCVABI::ABI_ILP32:
1065+ case RISCVABI::ABI_LP64:
1066+ break ;
1067+ case RISCVABI::ABI_ILP32F:
1068+ case RISCVABI::ABI_LP64F:
1069+ UseGPRForF32 = !IsFixed;
1070+ break ;
1071+ case RISCVABI::ABI_ILP32D:
1072+ case RISCVABI::ABI_LP64D:
1073+ UseGPRForF32 = !IsFixed;
1074+ UseGPRForF64 = !IsFixed;
1075+ break ;
1076+ }
1077+
1078+ if (State.getFirstUnallocated (ArgFPR32s) == array_lengthof (ArgFPR32s))
1079+ UseGPRForF32 = true ;
1080+ if (State.getFirstUnallocated (ArgFPR64s) == array_lengthof (ArgFPR64s))
1081+ UseGPRForF64 = true ;
1082+
1083+ // From this point on, rely on UseGPRForF32, UseGPRForF64 and similar local
1084+ // variables rather than directly checking against the target ABI.
1085+
1086+ if (UseGPRForF32 && ValVT == MVT::f32 ) {
10371087 LocVT = XLenVT;
10381088 LocInfo = CCValAssign::BCvt;
1039- } else if (XLen == 64 && ValVT == MVT::f64 ) {
1089+ } else if (UseGPRForF64 && XLen == 64 && ValVT == MVT::f64 ) {
10401090 LocVT = MVT::i64 ;
10411091 LocInfo = CCValAssign::BCvt;
10421092 }
@@ -1064,8 +1114,9 @@ static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
10641114 assert (PendingLocs.size () == PendingArgFlags.size () &&
10651115 " PendingLocs and PendingArgFlags out of sync" );
10661116
1067- // Handle passing f64 on RV32D with a soft float ABI.
1068- if (XLen == 32 && ValVT == MVT::f64 ) {
1117+ // Handle passing f64 on RV32D with a soft float ABI or when floating point
1118+ // registers are exhausted.
1119+ if (UseGPRForF64 && XLen == 32 && ValVT == MVT::f64 ) {
10691120 assert (!ArgFlags.isSplit () && PendingLocs.empty () &&
10701121 " Can't lower f64 if it is split" );
10711122 // Depending on available argument GPRS, f64 may be passed in a pair of
@@ -1114,7 +1165,13 @@ static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
11141165 }
11151166
11161167 // Allocate to a register if possible, or else a stack slot.
1117- unsigned Reg = State.AllocateReg (ArgGPRs);
1168+ unsigned Reg;
1169+ if (ValVT == MVT::f32 && !UseGPRForF32)
1170+ Reg = State.AllocateReg (ArgFPR32s, ArgFPR64s);
1171+ else if (ValVT == MVT::f64 && !UseGPRForF64)
1172+ Reg = State.AllocateReg (ArgFPR64s, ArgFPR32s);
1173+ else
1174+ Reg = Reg = State.AllocateReg (ArgGPRs);
11181175 unsigned StackOffset = Reg ? 0 : State.AllocateStack (XLen / 8 , XLen / 8 );
11191176
11201177 // If we reach this point and PendingLocs is non-empty, we must be at the
@@ -1135,7 +1192,8 @@ static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
11351192 return false ;
11361193 }
11371194
1138- assert (LocVT == XLenVT && " Expected an XLenVT at this stage" );
1195+ assert ((!UseGPRForF32 || !UseGPRForF64 || LocVT == XLenVT) &&
1196+ " Expected an XLenVT at this stage" );
11391197
11401198 if (Reg) {
11411199 State.addLoc (CCValAssign::getReg (ValNo, ValVT, Reg, LocVT, LocInfo));
@@ -1167,7 +1225,8 @@ void RISCVTargetLowering::analyzeInputArgs(
11671225 else if (Ins[i].isOrigArg ())
11681226 ArgTy = FType->getParamType (Ins[i].getOrigArgIndex ());
11691227
1170- if (CC_RISCV (MF.getDataLayout (), i, ArgVT, ArgVT, CCValAssign::Full,
1228+ RISCVABI::ABI ABI = MF.getSubtarget <RISCVSubtarget>().getTargetABI ();
1229+ if (CC_RISCV (MF.getDataLayout (), ABI, i, ArgVT, ArgVT, CCValAssign::Full,
11711230 ArgFlags, CCInfo, /* IsRet=*/ true , IsRet, ArgTy)) {
11721231 LLVM_DEBUG (dbgs () << " InputArg #" << i << " has unhandled type "
11731232 << EVT (ArgVT).getEVTString () << ' \n ' );
@@ -1187,7 +1246,8 @@ void RISCVTargetLowering::analyzeOutputArgs(
11871246 ISD::ArgFlagsTy ArgFlags = Outs[i].Flags ;
11881247 Type *OrigTy = CLI ? CLI->getArgs ()[Outs[i].OrigArgIndex ].Ty : nullptr ;
11891248
1190- if (CC_RISCV (MF.getDataLayout (), i, ArgVT, ArgVT, CCValAssign::Full,
1249+ RISCVABI::ABI ABI = MF.getSubtarget <RISCVSubtarget>().getTargetABI ();
1250+ if (CC_RISCV (MF.getDataLayout (), ABI, i, ArgVT, ArgVT, CCValAssign::Full,
11911251 ArgFlags, CCInfo, Outs[i].IsFixed , IsRet, OrigTy)) {
11921252 LLVM_DEBUG (dbgs () << " OutputArg #" << i << " has unhandled type "
11931253 << EVT (ArgVT).getEVTString () << " \n " );
@@ -1224,8 +1284,24 @@ static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain,
12241284 MachineRegisterInfo &RegInfo = MF.getRegInfo ();
12251285 EVT LocVT = VA.getLocVT ();
12261286 SDValue Val;
1287+ const TargetRegisterClass *RC;
1288+
1289+ switch (LocVT.getSimpleVT ().SimpleTy ) {
1290+ default :
1291+ llvm_unreachable (" Unexpected register type" );
1292+ case MVT::i32 :
1293+ case MVT::i64 :
1294+ RC = &RISCV::GPRRegClass;
1295+ break ;
1296+ case MVT::f32 :
1297+ RC = &RISCV::FPR32RegClass;
1298+ break ;
1299+ case MVT::f64 :
1300+ RC = &RISCV::FPR64RegClass;
1301+ break ;
1302+ }
12271303
1228- unsigned VReg = RegInfo.createVirtualRegister (&RISCV::GPRRegClass );
1304+ unsigned VReg = RegInfo.createVirtualRegister (RC );
12291305 RegInfo.addLiveIn (VA.getLocReg (), VReg);
12301306 Val = DAG.getCopyFromReg (Chain, DL, VReg, LocVT);
12311307
@@ -1802,8 +1878,9 @@ bool RISCVTargetLowering::CanLowerReturn(
18021878 for (unsigned i = 0 , e = Outs.size (); i != e; ++i) {
18031879 MVT VT = Outs[i].VT ;
18041880 ISD::ArgFlagsTy ArgFlags = Outs[i].Flags ;
1805- if (CC_RISCV (MF.getDataLayout (), i, VT, VT, CCValAssign::Full, ArgFlags,
1806- CCInfo, /* IsFixed=*/ true , /* IsRet=*/ true , nullptr ))
1881+ RISCVABI::ABI ABI = MF.getSubtarget <RISCVSubtarget>().getTargetABI ();
1882+ if (CC_RISCV (MF.getDataLayout (), ABI, i, VT, VT, CCValAssign::Full,
1883+ ArgFlags, CCInfo, /* IsFixed=*/ true , /* IsRet=*/ true , nullptr ))
18071884 return false ;
18081885 }
18091886 return true ;
0 commit comments