811 lines · cpp
1//===-- RISCVCallingConv.cpp - RISC-V Custom CC Routines ------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the custom routines for the RISC-V Calling Convention.10//11//===----------------------------------------------------------------------===//12 13#include "RISCVCallingConv.h"14#include "RISCVSubtarget.h"15#include "llvm/IR/DataLayout.h"16#include "llvm/IR/Module.h"17#include "llvm/MC/MCRegister.h"18 19using namespace llvm;20 21// Calling Convention Implementation.22// The expectations for frontend ABI lowering vary from target to target.23// Ideally, an LLVM frontend would be able to avoid worrying about many ABI24// details, but this is a longer term goal. For now, we simply try to keep the25// role of the frontend as simple and well-defined as possible. The rules can26// be summarised as:27// * Never split up large scalar arguments. We handle them here.28// * If a hardfloat calling convention is being used, and the struct may be29// passed in a pair of registers (fp+fp, int+fp), and both registers are30// available, then pass as two separate arguments. If either the GPRs or FPRs31// are exhausted, then pass according to the rule below.32// * If a struct could never be passed in registers or directly in a stack33// slot (as it is larger than 2*XLEN and the floating point rules don't34// apply), then pass it using a pointer with the byval attribute.35// * If a struct is less than 2*XLEN, then coerce to either a two-element36// word-sized array or a 2*XLEN scalar (depending on alignment).37// * The frontend can determine whether a struct is returned by reference or38// not based on its size and fields. If it will be returned by reference, the39// frontend must modify the prototype so a pointer with the sret annotation is40// passed as the first argument. This is not necessary for large scalar41// returns.42// * Struct return values and varargs should be coerced to structs containing43// register-size fields in the same situations they would be for fixed44// arguments.45 46static const MCPhysReg ArgFPR16s[] = {RISCV::F10_H, RISCV::F11_H, RISCV::F12_H,47 RISCV::F13_H, RISCV::F14_H, RISCV::F15_H,48 RISCV::F16_H, RISCV::F17_H};49static const MCPhysReg ArgFPR32s[] = {RISCV::F10_F, RISCV::F11_F, RISCV::F12_F,50 RISCV::F13_F, RISCV::F14_F, RISCV::F15_F,51 RISCV::F16_F, RISCV::F17_F};52static const MCPhysReg ArgFPR64s[] = {RISCV::F10_D, RISCV::F11_D, RISCV::F12_D,53 RISCV::F13_D, RISCV::F14_D, RISCV::F15_D,54 RISCV::F16_D, RISCV::F17_D};55// This is an interim calling convention and it may be changed in the future.56static const MCPhysReg ArgVRs[] = {57 RISCV::V8, RISCV::V9, RISCV::V10, RISCV::V11, RISCV::V12, RISCV::V13,58 RISCV::V14, RISCV::V15, RISCV::V16, RISCV::V17, RISCV::V18, RISCV::V19,59 RISCV::V20, RISCV::V21, RISCV::V22, RISCV::V23};60static const MCPhysReg ArgVRM2s[] = {RISCV::V8M2, RISCV::V10M2, RISCV::V12M2,61 RISCV::V14M2, RISCV::V16M2, RISCV::V18M2,62 RISCV::V20M2, RISCV::V22M2};63static const MCPhysReg ArgVRM4s[] = {RISCV::V8M4, RISCV::V12M4, RISCV::V16M4,64 RISCV::V20M4};65static const MCPhysReg ArgVRM8s[] = {RISCV::V8M8, RISCV::V16M8};66static const MCPhysReg ArgVRN2M1s[] = {67 RISCV::V8_V9, RISCV::V9_V10, RISCV::V10_V11, RISCV::V11_V12,68 RISCV::V12_V13, RISCV::V13_V14, RISCV::V14_V15, RISCV::V15_V16,69 RISCV::V16_V17, RISCV::V17_V18, RISCV::V18_V19, RISCV::V19_V20,70 RISCV::V20_V21, RISCV::V21_V22, RISCV::V22_V23};71static const MCPhysReg ArgVRN3M1s[] = {72 RISCV::V8_V9_V10, RISCV::V9_V10_V11, RISCV::V10_V11_V12,73 RISCV::V11_V12_V13, RISCV::V12_V13_V14, RISCV::V13_V14_V15,74 RISCV::V14_V15_V16, RISCV::V15_V16_V17, RISCV::V16_V17_V18,75 RISCV::V17_V18_V19, RISCV::V18_V19_V20, RISCV::V19_V20_V21,76 RISCV::V20_V21_V22, RISCV::V21_V22_V23};77static const MCPhysReg ArgVRN4M1s[] = {78 RISCV::V8_V9_V10_V11, RISCV::V9_V10_V11_V12, RISCV::V10_V11_V12_V13,79 RISCV::V11_V12_V13_V14, RISCV::V12_V13_V14_V15, RISCV::V13_V14_V15_V16,80 RISCV::V14_V15_V16_V17, RISCV::V15_V16_V17_V18, RISCV::V16_V17_V18_V19,81 RISCV::V17_V18_V19_V20, RISCV::V18_V19_V20_V21, RISCV::V19_V20_V21_V22,82 RISCV::V20_V21_V22_V23};83static const MCPhysReg ArgVRN5M1s[] = {84 RISCV::V8_V9_V10_V11_V12, RISCV::V9_V10_V11_V12_V13,85 RISCV::V10_V11_V12_V13_V14, RISCV::V11_V12_V13_V14_V15,86 RISCV::V12_V13_V14_V15_V16, RISCV::V13_V14_V15_V16_V17,87 RISCV::V14_V15_V16_V17_V18, RISCV::V15_V16_V17_V18_V19,88 RISCV::V16_V17_V18_V19_V20, RISCV::V17_V18_V19_V20_V21,89 RISCV::V18_V19_V20_V21_V22, RISCV::V19_V20_V21_V22_V23};90static const MCPhysReg ArgVRN6M1s[] = {91 RISCV::V8_V9_V10_V11_V12_V13, RISCV::V9_V10_V11_V12_V13_V14,92 RISCV::V10_V11_V12_V13_V14_V15, RISCV::V11_V12_V13_V14_V15_V16,93 RISCV::V12_V13_V14_V15_V16_V17, RISCV::V13_V14_V15_V16_V17_V18,94 RISCV::V14_V15_V16_V17_V18_V19, RISCV::V15_V16_V17_V18_V19_V20,95 RISCV::V16_V17_V18_V19_V20_V21, RISCV::V17_V18_V19_V20_V21_V22,96 RISCV::V18_V19_V20_V21_V22_V23};97static const MCPhysReg ArgVRN7M1s[] = {98 RISCV::V8_V9_V10_V11_V12_V13_V14, RISCV::V9_V10_V11_V12_V13_V14_V15,99 RISCV::V10_V11_V12_V13_V14_V15_V16, RISCV::V11_V12_V13_V14_V15_V16_V17,100 RISCV::V12_V13_V14_V15_V16_V17_V18, RISCV::V13_V14_V15_V16_V17_V18_V19,101 RISCV::V14_V15_V16_V17_V18_V19_V20, RISCV::V15_V16_V17_V18_V19_V20_V21,102 RISCV::V16_V17_V18_V19_V20_V21_V22, RISCV::V17_V18_V19_V20_V21_V22_V23};103static const MCPhysReg ArgVRN8M1s[] = {RISCV::V8_V9_V10_V11_V12_V13_V14_V15,104 RISCV::V9_V10_V11_V12_V13_V14_V15_V16,105 RISCV::V10_V11_V12_V13_V14_V15_V16_V17,106 RISCV::V11_V12_V13_V14_V15_V16_V17_V18,107 RISCV::V12_V13_V14_V15_V16_V17_V18_V19,108 RISCV::V13_V14_V15_V16_V17_V18_V19_V20,109 RISCV::V14_V15_V16_V17_V18_V19_V20_V21,110 RISCV::V15_V16_V17_V18_V19_V20_V21_V22,111 RISCV::V16_V17_V18_V19_V20_V21_V22_V23};112static const MCPhysReg ArgVRN2M2s[] = {RISCV::V8M2_V10M2, RISCV::V10M2_V12M2,113 RISCV::V12M2_V14M2, RISCV::V14M2_V16M2,114 RISCV::V16M2_V18M2, RISCV::V18M2_V20M2,115 RISCV::V20M2_V22M2};116static const MCPhysReg ArgVRN3M2s[] = {117 RISCV::V8M2_V10M2_V12M2, RISCV::V10M2_V12M2_V14M2,118 RISCV::V12M2_V14M2_V16M2, RISCV::V14M2_V16M2_V18M2,119 RISCV::V16M2_V18M2_V20M2, RISCV::V18M2_V20M2_V22M2};120static const MCPhysReg ArgVRN4M2s[] = {121 RISCV::V8M2_V10M2_V12M2_V14M2, RISCV::V10M2_V12M2_V14M2_V16M2,122 RISCV::V12M2_V14M2_V16M2_V18M2, RISCV::V14M2_V16M2_V18M2_V20M2,123 RISCV::V16M2_V18M2_V20M2_V22M2};124static const MCPhysReg ArgVRN2M4s[] = {RISCV::V8M4_V12M4, RISCV::V12M4_V16M4,125 RISCV::V16M4_V20M4};126 127ArrayRef<MCPhysReg> RISCV::getArgGPRs(const RISCVABI::ABI ABI) {128 // The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except129 // the ILP32E ABI.130 static const MCPhysReg ArgIGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,131 RISCV::X13, RISCV::X14, RISCV::X15,132 RISCV::X16, RISCV::X17};133 // The GPRs used for passing arguments in the ILP32E/LP64E ABI.134 static const MCPhysReg ArgEGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,135 RISCV::X13, RISCV::X14, RISCV::X15};136 137 if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)138 return ArrayRef(ArgEGPRs);139 140 return ArrayRef(ArgIGPRs);141}142 143static ArrayRef<MCPhysReg> getArgGPR16s(const RISCVABI::ABI ABI) {144 // The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except145 // the ILP32E ABI.146 static const MCPhysReg ArgIGPRs[] = {RISCV::X10_H, RISCV::X11_H, RISCV::X12_H,147 RISCV::X13_H, RISCV::X14_H, RISCV::X15_H,148 RISCV::X16_H, RISCV::X17_H};149 // The GPRs used for passing arguments in the ILP32E/LP64E ABI.150 static const MCPhysReg ArgEGPRs[] = {RISCV::X10_H, RISCV::X11_H,151 RISCV::X12_H, RISCV::X13_H,152 RISCV::X14_H, RISCV::X15_H};153 154 if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)155 return ArrayRef(ArgEGPRs);156 157 return ArrayRef(ArgIGPRs);158}159 160static ArrayRef<MCPhysReg> getArgGPR32s(const RISCVABI::ABI ABI) {161 // The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except162 // the ILP32E ABI.163 static const MCPhysReg ArgIGPRs[] = {RISCV::X10_W, RISCV::X11_W, RISCV::X12_W,164 RISCV::X13_W, RISCV::X14_W, RISCV::X15_W,165 RISCV::X16_W, RISCV::X17_W};166 // The GPRs used for passing arguments in the ILP32E/LP64E ABI.167 static const MCPhysReg ArgEGPRs[] = {RISCV::X10_W, RISCV::X11_W,168 RISCV::X12_W, RISCV::X13_W,169 RISCV::X14_W, RISCV::X15_W};170 171 if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)172 return ArrayRef(ArgEGPRs);173 174 return ArrayRef(ArgIGPRs);175}176 177static ArrayRef<MCPhysReg> getFastCCArgGPRs(const RISCVABI::ABI ABI) {178 // The GPRs used for passing arguments in the FastCC, X5 and X6 might be used179 // for save-restore libcall, so we don't use them.180 // Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.181 static const MCPhysReg FastCCIGPRs[] = {182 RISCV::X10, RISCV::X11, RISCV::X12, RISCV::X13, RISCV::X14, RISCV::X15,183 RISCV::X16, RISCV::X17, RISCV::X28, RISCV::X29, RISCV::X30, RISCV::X31};184 185 // The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.186 static const MCPhysReg FastCCEGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,187 RISCV::X13, RISCV::X14, RISCV::X15};188 189 if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)190 return ArrayRef(FastCCEGPRs);191 192 return ArrayRef(FastCCIGPRs);193}194 195static ArrayRef<MCPhysReg> getFastCCArgGPRF16s(const RISCVABI::ABI ABI) {196 // The GPRs used for passing arguments in the FastCC, X5 and X6 might be used197 // for save-restore libcall, so we don't use them.198 // Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.199 static const MCPhysReg FastCCIGPRs[] = {200 RISCV::X10_H, RISCV::X11_H, RISCV::X12_H, RISCV::X13_H,201 RISCV::X14_H, RISCV::X15_H, RISCV::X16_H, RISCV::X17_H,202 RISCV::X28_H, RISCV::X29_H, RISCV::X30_H, RISCV::X31_H};203 204 // The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.205 static const MCPhysReg FastCCEGPRs[] = {RISCV::X10_H, RISCV::X11_H,206 RISCV::X12_H, RISCV::X13_H,207 RISCV::X14_H, RISCV::X15_H};208 209 if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)210 return ArrayRef(FastCCEGPRs);211 212 return ArrayRef(FastCCIGPRs);213}214 215static ArrayRef<MCPhysReg> getFastCCArgGPRF32s(const RISCVABI::ABI ABI) {216 // The GPRs used for passing arguments in the FastCC, X5 and X6 might be used217 // for save-restore libcall, so we don't use them.218 // Don't use X7 for fastcc, since Zicfilp uses X7 as the label register.219 static const MCPhysReg FastCCIGPRs[] = {220 RISCV::X10_W, RISCV::X11_W, RISCV::X12_W, RISCV::X13_W,221 RISCV::X14_W, RISCV::X15_W, RISCV::X16_W, RISCV::X17_W,222 RISCV::X28_W, RISCV::X29_W, RISCV::X30_W, RISCV::X31_W};223 224 // The GPRs used for passing arguments in the FastCC when using ILP32E/LP64E.225 static const MCPhysReg FastCCEGPRs[] = {RISCV::X10_W, RISCV::X11_W,226 RISCV::X12_W, RISCV::X13_W,227 RISCV::X14_W, RISCV::X15_W};228 229 if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E)230 return ArrayRef(FastCCEGPRs);231 232 return ArrayRef(FastCCIGPRs);233}234 235// Pass a 2*XLEN argument that has been split into two XLEN values through236// registers or the stack as necessary.237static bool CC_RISCVAssign2XLen(unsigned XLen, CCState &State, CCValAssign VA1,238 ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2,239 MVT ValVT2, MVT LocVT2,240 ISD::ArgFlagsTy ArgFlags2, bool EABI) {241 unsigned XLenInBytes = XLen / 8;242 const RISCVSubtarget &STI =243 State.getMachineFunction().getSubtarget<RISCVSubtarget>();244 ArrayRef<MCPhysReg> ArgGPRs = RISCV::getArgGPRs(STI.getTargetABI());245 246 if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {247 // At least one half can be passed via register.248 State.addLoc(CCValAssign::getReg(VA1.getValNo(), VA1.getValVT(), Reg,249 VA1.getLocVT(), CCValAssign::Full));250 } else {251 // Both halves must be passed on the stack, with proper alignment.252 // TODO: To be compatible with GCC's behaviors, we force them to have 4-byte253 // alignment. This behavior may be changed when RV32E/ILP32E is ratified.254 Align StackAlign(XLenInBytes);255 if (!EABI || XLen != 32)256 StackAlign = std::max(StackAlign, ArgFlags1.getNonZeroOrigAlign());257 State.addLoc(258 CCValAssign::getMem(VA1.getValNo(), VA1.getValVT(),259 State.AllocateStack(XLenInBytes, StackAlign),260 VA1.getLocVT(), CCValAssign::Full));261 State.addLoc(CCValAssign::getMem(262 ValNo2, ValVT2, State.AllocateStack(XLenInBytes, Align(XLenInBytes)),263 LocVT2, CCValAssign::Full));264 return false;265 }266 267 if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {268 // The second half can also be passed via register.269 State.addLoc(270 CCValAssign::getReg(ValNo2, ValVT2, Reg, LocVT2, CCValAssign::Full));271 } else {272 // The second half is passed via the stack, without additional alignment.273 State.addLoc(CCValAssign::getMem(274 ValNo2, ValVT2, State.AllocateStack(XLenInBytes, Align(XLenInBytes)),275 LocVT2, CCValAssign::Full));276 }277 278 return false;279}280 281static MCRegister allocateRVVReg(MVT ValVT, unsigned ValNo, CCState &State,282 const RISCVTargetLowering &TLI) {283 const TargetRegisterClass *RC = TLI.getRegClassFor(ValVT);284 if (RC == &RISCV::VRRegClass) {285 // Assign the first mask argument to V0.286 // This is an interim calling convention and it may be changed in the287 // future.288 if (ValVT.getVectorElementType() == MVT::i1)289 if (MCRegister Reg = State.AllocateReg(RISCV::V0))290 return Reg;291 return State.AllocateReg(ArgVRs);292 }293 if (RC == &RISCV::VRM2RegClass)294 return State.AllocateReg(ArgVRM2s);295 if (RC == &RISCV::VRM4RegClass)296 return State.AllocateReg(ArgVRM4s);297 if (RC == &RISCV::VRM8RegClass)298 return State.AllocateReg(ArgVRM8s);299 if (RC == &RISCV::VRN2M1RegClass)300 return State.AllocateReg(ArgVRN2M1s);301 if (RC == &RISCV::VRN3M1RegClass)302 return State.AllocateReg(ArgVRN3M1s);303 if (RC == &RISCV::VRN4M1RegClass)304 return State.AllocateReg(ArgVRN4M1s);305 if (RC == &RISCV::VRN5M1RegClass)306 return State.AllocateReg(ArgVRN5M1s);307 if (RC == &RISCV::VRN6M1RegClass)308 return State.AllocateReg(ArgVRN6M1s);309 if (RC == &RISCV::VRN7M1RegClass)310 return State.AllocateReg(ArgVRN7M1s);311 if (RC == &RISCV::VRN8M1RegClass)312 return State.AllocateReg(ArgVRN8M1s);313 if (RC == &RISCV::VRN2M2RegClass)314 return State.AllocateReg(ArgVRN2M2s);315 if (RC == &RISCV::VRN3M2RegClass)316 return State.AllocateReg(ArgVRN3M2s);317 if (RC == &RISCV::VRN4M2RegClass)318 return State.AllocateReg(ArgVRN4M2s);319 if (RC == &RISCV::VRN2M4RegClass)320 return State.AllocateReg(ArgVRN2M4s);321 llvm_unreachable("Unhandled register class for ValueType");322}323 324// Implements the RISC-V calling convention. Returns true upon failure.325bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT,326 CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,327 CCState &State, bool IsRet, Type *OrigTy) {328 const MachineFunction &MF = State.getMachineFunction();329 const DataLayout &DL = MF.getDataLayout();330 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();331 const RISCVTargetLowering &TLI = *Subtarget.getTargetLowering();332 333 unsigned XLen = Subtarget.getXLen();334 MVT XLenVT = Subtarget.getXLenVT();335 336 if (ArgFlags.isNest()) {337 // Static chain parameter must not be passed in normal argument registers,338 // so we assign t2/t3 for it as done in GCC's339 // __builtin_call_with_static_chain340 bool HasCFBranch =341 Subtarget.hasStdExtZicfilp() &&342 MF.getFunction().getParent()->getModuleFlag("cf-protection-branch");343 344 // Normal: t2, Branch control flow protection: t3345 const auto StaticChainReg = HasCFBranch ? RISCV::X28 : RISCV::X7;346 347 RISCVABI::ABI ABI = Subtarget.getTargetABI();348 if (HasCFBranch &&349 (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E))350 reportFatalUsageError(351 "Nested functions with control flow protection are not "352 "usable with ILP32E or LP64E ABI.");353 if (MCRegister Reg = State.AllocateReg(StaticChainReg)) {354 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));355 return false;356 }357 }358 359 // Any return value split in to more than two values can't be returned360 // directly. Vectors are returned via the available vector registers.361 if (!LocVT.isVector() && IsRet && ValNo > 1)362 return true;363 364 // UseGPRForF16_F32 if targeting one of the soft-float ABIs, if passing a365 // variadic argument, or if no F16/F32 argument registers are available.366 bool UseGPRForF16_F32 = true;367 // UseGPRForF64 if targeting soft-float ABIs or an FLEN=32 ABI, if passing a368 // variadic argument, or if no F64 argument registers are available.369 bool UseGPRForF64 = true;370 371 RISCVABI::ABI ABI = Subtarget.getTargetABI();372 switch (ABI) {373 default:374 llvm_unreachable("Unexpected ABI");375 case RISCVABI::ABI_ILP32:376 case RISCVABI::ABI_ILP32E:377 case RISCVABI::ABI_LP64:378 case RISCVABI::ABI_LP64E:379 break;380 case RISCVABI::ABI_ILP32F:381 case RISCVABI::ABI_LP64F:382 UseGPRForF16_F32 = ArgFlags.isVarArg();383 break;384 case RISCVABI::ABI_ILP32D:385 case RISCVABI::ABI_LP64D:386 UseGPRForF16_F32 = ArgFlags.isVarArg();387 UseGPRForF64 = ArgFlags.isVarArg();388 break;389 }390 391 if ((LocVT == MVT::f16 || LocVT == MVT::bf16) && !UseGPRForF16_F32) {392 if (MCRegister Reg = State.AllocateReg(ArgFPR16s)) {393 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));394 return false;395 }396 }397 398 if (LocVT == MVT::f32 && !UseGPRForF16_F32) {399 if (MCRegister Reg = State.AllocateReg(ArgFPR32s)) {400 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));401 return false;402 }403 }404 405 if (LocVT == MVT::f64 && !UseGPRForF64) {406 if (MCRegister Reg = State.AllocateReg(ArgFPR64s)) {407 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));408 return false;409 }410 }411 412 if ((ValVT == MVT::f16 && Subtarget.hasStdExtZhinxmin())) {413 if (MCRegister Reg = State.AllocateReg(getArgGPR16s(ABI))) {414 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));415 return false;416 }417 }418 419 if (ValVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {420 if (MCRegister Reg = State.AllocateReg(getArgGPR32s(ABI))) {421 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));422 return false;423 }424 }425 426 ArrayRef<MCPhysReg> ArgGPRs = RISCV::getArgGPRs(ABI);427 428 // Zdinx use GPR without a bitcast when possible.429 if (LocVT == MVT::f64 && XLen == 64 && Subtarget.hasStdExtZdinx()) {430 if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {431 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));432 return false;433 }434 }435 436 // FP smaller than XLen, uses custom GPR.437 if (LocVT == MVT::f16 || LocVT == MVT::bf16 ||438 (LocVT == MVT::f32 && XLen == 64)) {439 if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {440 LocVT = XLenVT;441 State.addLoc(442 CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));443 return false;444 }445 }446 447 // Bitcast FP to GPR if we can use a GPR register.448 if ((XLen == 32 && LocVT == MVT::f32) || (XLen == 64 && LocVT == MVT::f64)) {449 if (MCRegister Reg = State.AllocateReg(ArgGPRs)) {450 LocVT = XLenVT;451 LocInfo = CCValAssign::BCvt;452 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));453 return false;454 }455 }456 457 // If this is a variadic argument, the RISC-V calling convention requires458 // that it is assigned an 'even' or 'aligned' register if it has 8-byte459 // alignment (RV32) or 16-byte alignment (RV64). An aligned register should460 // be used regardless of whether the original argument was split during461 // legalisation or not. The argument will not be passed by registers if the462 // original type is larger than 2*XLEN, so the register alignment rule does463 // not apply.464 // TODO: To be compatible with GCC's behaviors, we don't align registers465 // currently if we are using ILP32E calling convention. This behavior may be466 // changed when RV32E/ILP32E is ratified.467 unsigned TwoXLenInBytes = (2 * XLen) / 8;468 if (ArgFlags.isVarArg() && ArgFlags.getNonZeroOrigAlign() == TwoXLenInBytes &&469 DL.getTypeAllocSize(OrigTy) == TwoXLenInBytes &&470 ABI != RISCVABI::ABI_ILP32E) {471 unsigned RegIdx = State.getFirstUnallocated(ArgGPRs);472 // Skip 'odd' register if necessary.473 if (RegIdx != std::size(ArgGPRs) && RegIdx % 2 == 1)474 State.AllocateReg(ArgGPRs);475 }476 477 SmallVectorImpl<CCValAssign> &PendingLocs = State.getPendingLocs();478 SmallVectorImpl<ISD::ArgFlagsTy> &PendingArgFlags =479 State.getPendingArgFlags();480 481 assert(PendingLocs.size() == PendingArgFlags.size() &&482 "PendingLocs and PendingArgFlags out of sync");483 484 // Handle passing f64 on RV32D with a soft float ABI or when floating point485 // registers are exhausted.486 if (XLen == 32 && LocVT == MVT::f64) {487 assert(PendingLocs.empty() && "Can't lower f64 if it is split");488 // Depending on available argument GPRS, f64 may be passed in a pair of489 // GPRs, split between a GPR and the stack, or passed completely on the490 // stack. LowerCall/LowerFormalArguments/LowerReturn must recognise these491 // cases.492 MCRegister Reg = State.AllocateReg(ArgGPRs);493 if (!Reg) {494 int64_t StackOffset = State.AllocateStack(8, Align(8));495 State.addLoc(496 CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));497 return false;498 }499 LocVT = MVT::i32;500 State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));501 MCRegister HiReg = State.AllocateReg(ArgGPRs);502 if (HiReg) {503 State.addLoc(504 CCValAssign::getCustomReg(ValNo, ValVT, HiReg, LocVT, LocInfo));505 } else {506 int64_t StackOffset = State.AllocateStack(4, Align(4));507 State.addLoc(508 CCValAssign::getCustomMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));509 }510 return false;511 }512 513 // Split arguments might be passed indirectly, so keep track of the pending514 // values. Split vectors are passed via a mix of registers and indirectly, so515 // treat them as we would any other argument.516 if (ValVT.isScalarInteger() && (ArgFlags.isSplit() || !PendingLocs.empty())) {517 LocVT = XLenVT;518 LocInfo = CCValAssign::Indirect;519 PendingLocs.push_back(520 CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo));521 PendingArgFlags.push_back(ArgFlags);522 if (!ArgFlags.isSplitEnd()) {523 return false;524 }525 }526 527 // If the split argument only had two elements, it should be passed directly528 // in registers or on the stack.529 if (ValVT.isScalarInteger() && ArgFlags.isSplitEnd() &&530 PendingLocs.size() <= 2) {531 assert(PendingLocs.size() == 2 && "Unexpected PendingLocs.size()");532 // Apply the normal calling convention rules to the first half of the533 // split argument.534 CCValAssign VA = PendingLocs[0];535 ISD::ArgFlagsTy AF = PendingArgFlags[0];536 PendingLocs.clear();537 PendingArgFlags.clear();538 return CC_RISCVAssign2XLen(539 XLen, State, VA, AF, ValNo, ValVT, LocVT, ArgFlags,540 ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E);541 }542 543 // Allocate to a register if possible, or else a stack slot.544 MCRegister Reg;545 unsigned StoreSizeBytes = XLen / 8;546 Align StackAlign = Align(XLen / 8);547 548 if (ValVT.isVector() || ValVT.isRISCVVectorTuple()) {549 Reg = allocateRVVReg(ValVT, ValNo, State, TLI);550 if (Reg) {551 // Fixed-length vectors are located in the corresponding scalable-vector552 // container types.553 if (ValVT.isFixedLengthVector()) {554 LocVT = TLI.getContainerForFixedLengthVector(LocVT);555 State.addLoc(556 CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));557 return false;558 }559 } else {560 // For return values, the vector must be passed fully via registers or561 // via the stack.562 // FIXME: The proposed vector ABI only mandates v8-v15 for return values,563 // but we're using all of them.564 if (IsRet)565 return true;566 // Try using a GPR to pass the address567 if ((Reg = State.AllocateReg(ArgGPRs))) {568 LocVT = XLenVT;569 LocInfo = CCValAssign::Indirect;570 } else if (ValVT.isScalableVector()) {571 LocVT = XLenVT;572 LocInfo = CCValAssign::Indirect;573 } else {574 StoreSizeBytes = ValVT.getStoreSize();575 // Align vectors to their element sizes, being careful for vXi1576 // vectors.577 StackAlign = MaybeAlign(ValVT.getScalarSizeInBits() / 8).valueOrOne();578 }579 }580 } else {581 Reg = State.AllocateReg(ArgGPRs);582 }583 584 int64_t StackOffset =585 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);586 587 // If we reach this point and PendingLocs is non-empty, we must be at the588 // end of a split argument that must be passed indirectly.589 if (!PendingLocs.empty()) {590 assert(ArgFlags.isSplitEnd() && "Expected ArgFlags.isSplitEnd()");591 assert(PendingLocs.size() > 2 && "Unexpected PendingLocs.size()");592 593 for (auto &It : PendingLocs) {594 if (Reg)595 It.convertToReg(Reg);596 else597 It.convertToMem(StackOffset);598 State.addLoc(It);599 }600 PendingLocs.clear();601 PendingArgFlags.clear();602 return false;603 }604 605 assert(((ValVT.isFloatingPoint() && !ValVT.isVector()) || LocVT == XLenVT ||606 (TLI.getSubtarget().hasVInstructions() &&607 (ValVT.isVector() || ValVT.isRISCVVectorTuple()))) &&608 "Expected an XLenVT or vector types at this stage");609 610 if (Reg) {611 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));612 return false;613 }614 615 State.addLoc(CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));616 return false;617}618 619// FastCC has less than 1% performance improvement for some particular620// benchmark. But theoretically, it may have benefit for some cases.621bool llvm::CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT,622 CCValAssign::LocInfo LocInfo,623 ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet,624 Type *OrigTy) {625 const MachineFunction &MF = State.getMachineFunction();626 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();627 const RISCVTargetLowering &TLI = *Subtarget.getTargetLowering();628 RISCVABI::ABI ABI = Subtarget.getTargetABI();629 630 if ((LocVT == MVT::f16 && Subtarget.hasStdExtZfhmin()) ||631 (LocVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin())) {632 static const MCPhysReg FPR16List[] = {633 RISCV::F10_H, RISCV::F11_H, RISCV::F12_H, RISCV::F13_H, RISCV::F14_H,634 RISCV::F15_H, RISCV::F16_H, RISCV::F17_H, RISCV::F0_H, RISCV::F1_H,635 RISCV::F2_H, RISCV::F3_H, RISCV::F4_H, RISCV::F5_H, RISCV::F6_H,636 RISCV::F7_H, RISCV::F28_H, RISCV::F29_H, RISCV::F30_H, RISCV::F31_H};637 if (MCRegister Reg = State.AllocateReg(FPR16List)) {638 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));639 return false;640 }641 }642 643 if (LocVT == MVT::f32 && Subtarget.hasStdExtF()) {644 static const MCPhysReg FPR32List[] = {645 RISCV::F10_F, RISCV::F11_F, RISCV::F12_F, RISCV::F13_F, RISCV::F14_F,646 RISCV::F15_F, RISCV::F16_F, RISCV::F17_F, RISCV::F0_F, RISCV::F1_F,647 RISCV::F2_F, RISCV::F3_F, RISCV::F4_F, RISCV::F5_F, RISCV::F6_F,648 RISCV::F7_F, RISCV::F28_F, RISCV::F29_F, RISCV::F30_F, RISCV::F31_F};649 if (MCRegister Reg = State.AllocateReg(FPR32List)) {650 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));651 return false;652 }653 }654 655 if (LocVT == MVT::f64 && Subtarget.hasStdExtD()) {656 static const MCPhysReg FPR64List[] = {657 RISCV::F10_D, RISCV::F11_D, RISCV::F12_D, RISCV::F13_D, RISCV::F14_D,658 RISCV::F15_D, RISCV::F16_D, RISCV::F17_D, RISCV::F0_D, RISCV::F1_D,659 RISCV::F2_D, RISCV::F3_D, RISCV::F4_D, RISCV::F5_D, RISCV::F6_D,660 RISCV::F7_D, RISCV::F28_D, RISCV::F29_D, RISCV::F30_D, RISCV::F31_D};661 if (MCRegister Reg = State.AllocateReg(FPR64List)) {662 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));663 return false;664 }665 }666 667 MVT XLenVT = Subtarget.getXLenVT();668 669 // Check if there is an available GPRF16 before hitting the stack.670 if ((LocVT == MVT::f16 && Subtarget.hasStdExtZhinxmin())) {671 if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRF16s(ABI))) {672 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));673 return false;674 }675 }676 677 // Check if there is an available GPRF32 before hitting the stack.678 if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {679 if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRF32s(ABI))) {680 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));681 return false;682 }683 }684 685 // Check if there is an available GPR before hitting the stack.686 if (LocVT == MVT::f64 && Subtarget.is64Bit() && Subtarget.hasStdExtZdinx()) {687 if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) {688 if (LocVT.getSizeInBits() != Subtarget.getXLen()) {689 LocVT = XLenVT;690 State.addLoc(691 CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));692 return false;693 }694 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));695 return false;696 }697 }698 699 ArrayRef<MCPhysReg> ArgGPRs = getFastCCArgGPRs(ABI);700 701 if (LocVT.isVector()) {702 if (MCRegister Reg = allocateRVVReg(ValVT, ValNo, State, TLI)) {703 // Fixed-length vectors are located in the corresponding scalable-vector704 // container types.705 if (LocVT.isFixedLengthVector()) {706 LocVT = TLI.getContainerForFixedLengthVector(LocVT);707 State.addLoc(708 CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));709 return false;710 }711 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));712 return false;713 }714 715 // Pass scalable vectors indirectly. Pass fixed vectors indirectly if we716 // have a free GPR.717 if (LocVT.isScalableVector() ||718 State.getFirstUnallocated(ArgGPRs) != ArgGPRs.size()) {719 LocInfo = CCValAssign::Indirect;720 LocVT = XLenVT;721 }722 }723 724 if (LocVT == XLenVT) {725 if (MCRegister Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) {726 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));727 return false;728 }729 }730 731 if (LocVT == XLenVT || LocVT == MVT::f16 || LocVT == MVT::bf16 ||732 LocVT == MVT::f32 || LocVT == MVT::f64 || LocVT.isFixedLengthVector()) {733 Align StackAlign = MaybeAlign(ValVT.getScalarSizeInBits() / 8).valueOrOne();734 int64_t Offset = State.AllocateStack(LocVT.getStoreSize(), StackAlign);735 State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));736 return false;737 }738 739 return true; // CC didn't match.740}741 742bool llvm::CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT,743 CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,744 Type *OrigTy, CCState &State) {745 if (ArgFlags.isNest()) {746 report_fatal_error(747 "Attribute 'nest' is not supported in GHC calling convention");748 }749 750 static const MCPhysReg GPRList[] = {751 RISCV::X9, RISCV::X18, RISCV::X19, RISCV::X20, RISCV::X21, RISCV::X22,752 RISCV::X23, RISCV::X24, RISCV::X25, RISCV::X26, RISCV::X27};753 754 if (LocVT == MVT::i32 || LocVT == MVT::i64) {755 // Pass in STG registers: Base, Sp, Hp, R1, R2, R3, R4, R5, R6, R7, SpLim756 // s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11757 if (MCRegister Reg = State.AllocateReg(GPRList)) {758 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));759 return false;760 }761 }762 763 const RISCVSubtarget &Subtarget =764 State.getMachineFunction().getSubtarget<RISCVSubtarget>();765 766 if (LocVT == MVT::f32 && Subtarget.hasStdExtF()) {767 // Pass in STG registers: F1, ..., F6768 // fs0 ... fs5769 static const MCPhysReg FPR32List[] = {RISCV::F8_F, RISCV::F9_F,770 RISCV::F18_F, RISCV::F19_F,771 RISCV::F20_F, RISCV::F21_F};772 if (MCRegister Reg = State.AllocateReg(FPR32List)) {773 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));774 return false;775 }776 }777 778 if (LocVT == MVT::f64 && Subtarget.hasStdExtD()) {779 // Pass in STG registers: D1, ..., D6780 // fs6 ... fs11781 static const MCPhysReg FPR64List[] = {RISCV::F22_D, RISCV::F23_D,782 RISCV::F24_D, RISCV::F25_D,783 RISCV::F26_D, RISCV::F27_D};784 if (MCRegister Reg = State.AllocateReg(FPR64List)) {785 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));786 return false;787 }788 }789 790 if (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) {791 static const MCPhysReg GPR32List[] = {792 RISCV::X9_W, RISCV::X18_W, RISCV::X19_W, RISCV::X20_W,793 RISCV::X21_W, RISCV::X22_W, RISCV::X23_W, RISCV::X24_W,794 RISCV::X25_W, RISCV::X26_W, RISCV::X27_W};795 if (MCRegister Reg = State.AllocateReg(GPR32List)) {796 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));797 return false;798 }799 }800 801 if (LocVT == MVT::f64 && Subtarget.hasStdExtZdinx() && Subtarget.is64Bit()) {802 if (MCRegister Reg = State.AllocateReg(GPRList)) {803 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));804 return false;805 }806 }807 808 report_fatal_error("No registers left in GHC calling convention");809 return true;810}811