LLVM 20.0.0git
RISCVCallLowering.cpp
Go to the documentation of this file.
1//===-- RISCVCallLowering.cpp - Call lowering -------------------*- C++ -*-===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// This file implements the lowering of LLVM calls to machine code calls for
11/// GlobalISel.
12//
13//===----------------------------------------------------------------------===//
14
15#include "RISCVCallLowering.h"
16#include "RISCVISelLowering.h"
18#include "RISCVSubtarget.h"
22
23using namespace llvm;
24
25namespace {
26
27struct RISCVOutgoingValueAssigner : public CallLowering::OutgoingValueAssigner {
28private:
29 // The function used internally to assign args - we ignore the AssignFn stored
30 // by OutgoingValueAssigner since RISC-V implements its CC using a custom
31 // function with a different signature.
33
34 // Whether this is assigning args for a return.
35 bool IsRet;
36
37 RVVArgDispatcher &RVVDispatcher;
38
39public:
40 RISCVOutgoingValueAssigner(
41 RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet,
42 RVVArgDispatcher &RVVDispatcher)
43 : CallLowering::OutgoingValueAssigner(nullptr),
44 RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet),
45 RVVDispatcher(RVVDispatcher) {}
46
47 bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
49 const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
50 CCState &State) override {
52 const DataLayout &DL = MF.getDataLayout();
53 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
54
55 if (RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,
56 LocInfo, Flags, State, Info.IsFixed, IsRet, Info.Ty,
57 *Subtarget.getTargetLowering(), RVVDispatcher))
58 return true;
59
60 StackSize = State.getStackSize();
61 return false;
62 }
63};
64
65struct RISCVOutgoingValueHandler : public CallLowering::OutgoingValueHandler {
66 RISCVOutgoingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,
68 : OutgoingValueHandler(B, MRI), MIB(MIB),
69 Subtarget(MIRBuilder.getMF().getSubtarget<RISCVSubtarget>()) {}
70 Register getStackAddress(uint64_t MemSize, int64_t Offset,
72 ISD::ArgFlagsTy Flags) override {
73 MachineFunction &MF = MIRBuilder.getMF();
74 LLT p0 = LLT::pointer(0, Subtarget.getXLen());
75 LLT sXLen = LLT::scalar(Subtarget.getXLen());
76
77 if (!SPReg)
78 SPReg = MIRBuilder.buildCopy(p0, Register(RISCV::X2)).getReg(0);
79
80 auto OffsetReg = MIRBuilder.buildConstant(sXLen, Offset);
81
82 auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);
83
85 return AddrReg.getReg(0);
86 }
87
88 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
89 const MachinePointerInfo &MPO,
90 const CCValAssign &VA) override {
91 MachineFunction &MF = MIRBuilder.getMF();
92 uint64_t LocMemOffset = VA.getLocMemOffset();
93
94 // TODO: Move StackAlignment to subtarget and share with FrameLowering.
95 auto MMO =
97 commonAlignment(Align(16), LocMemOffset));
98
99 Register ExtReg = extendRegister(ValVReg, VA);
100 MIRBuilder.buildStore(ExtReg, Addr, *MMO);
101 }
102
103 void assignValueToReg(Register ValVReg, Register PhysReg,
104 const CCValAssign &VA) override {
105 // If we're passing a smaller fp value into a larger integer register,
106 // anyextend before copying.
107 if ((VA.getLocVT() == MVT::i64 && VA.getValVT() == MVT::f32) ||
108 ((VA.getLocVT() == MVT::i32 || VA.getLocVT() == MVT::i64) &&
109 VA.getValVT() == MVT::f16)) {
110 LLT DstTy = LLT::scalar(VA.getLocVT().getSizeInBits());
111 ValVReg = MIRBuilder.buildAnyExt(DstTy, ValVReg).getReg(0);
112 }
113
114 Register ExtReg = extendRegister(ValVReg, VA);
115 MIRBuilder.buildCopy(PhysReg, ExtReg);
116 MIB.addUse(PhysReg, RegState::Implicit);
117 }
118
121 std::function<void()> *Thunk) override {
122 assert(VAs.size() >= 2 && "Expected at least 2 VAs.");
123 const CCValAssign &VALo = VAs[0];
124 const CCValAssign &VAHi = VAs[1];
125
126 assert(VAHi.needsCustom() && "Value doesn't need custom handling");
127 assert(VALo.getValNo() == VAHi.getValNo() &&
128 "Values belong to different arguments");
129
130 assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
131 VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
132 "unexpected custom value");
133
134 Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
135 MRI.createGenericVirtualRegister(LLT::scalar(32))};
136 MIRBuilder.buildUnmerge(NewRegs, Arg.Regs[0]);
137
138 if (VAHi.isMemLoc()) {
139 LLT MemTy(VAHi.getLocVT());
140
142 Register StackAddr = getStackAddress(
143 MemTy.getSizeInBytes(), VAHi.getLocMemOffset(), MPO, Arg.Flags[0]);
144
145 assignValueToAddress(NewRegs[1], StackAddr, MemTy, MPO,
146 const_cast<CCValAssign &>(VAHi));
147 }
148
149 auto assignFunc = [=]() {
150 assignValueToReg(NewRegs[0], VALo.getLocReg(), VALo);
151 if (VAHi.isRegLoc())
152 assignValueToReg(NewRegs[1], VAHi.getLocReg(), VAHi);
153 };
154
155 if (Thunk) {
156 *Thunk = assignFunc;
157 return 2;
158 }
159
160 assignFunc();
161 return 2;
162 }
163
164private:
166
167 // Cache the SP register vreg if we need it more than once in this call site.
168 Register SPReg;
169
170 const RISCVSubtarget &Subtarget;
171};
172
173struct RISCVIncomingValueAssigner : public CallLowering::IncomingValueAssigner {
174private:
175 // The function used internally to assign args - we ignore the AssignFn stored
176 // by IncomingValueAssigner since RISC-V implements its CC using a custom
177 // function with a different signature.
179
180 // Whether this is assigning args from a return.
181 bool IsRet;
182
183 RVVArgDispatcher &RVVDispatcher;
184
185public:
186 RISCVIncomingValueAssigner(
187 RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet,
188 RVVArgDispatcher &RVVDispatcher)
189 : CallLowering::IncomingValueAssigner(nullptr),
190 RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet),
191 RVVDispatcher(RVVDispatcher) {}
192
193 bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
194 CCValAssign::LocInfo LocInfo,
195 const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
196 CCState &State) override {
198 const DataLayout &DL = MF.getDataLayout();
199 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
200
201 if (LocVT.isScalableVector())
203
204 if (RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,
205 LocInfo, Flags, State, /*IsFixed=*/true, IsRet, Info.Ty,
206 *Subtarget.getTargetLowering(), RVVDispatcher))
207 return true;
208
209 StackSize = State.getStackSize();
210 return false;
211 }
212};
213
214struct RISCVIncomingValueHandler : public CallLowering::IncomingValueHandler {
215 RISCVIncomingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)
216 : IncomingValueHandler(B, MRI),
217 Subtarget(MIRBuilder.getMF().getSubtarget<RISCVSubtarget>()) {}
218
219 Register getStackAddress(uint64_t MemSize, int64_t Offset,
221 ISD::ArgFlagsTy Flags) override {
222 MachineFrameInfo &MFI = MIRBuilder.getMF().getFrameInfo();
223
224 int FI = MFI.CreateFixedObject(MemSize, Offset, /*Immutable=*/true);
225 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
226 return MIRBuilder.buildFrameIndex(LLT::pointer(0, Subtarget.getXLen()), FI)
227 .getReg(0);
228 }
229
230 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
231 const MachinePointerInfo &MPO,
232 const CCValAssign &VA) override {
233 MachineFunction &MF = MIRBuilder.getMF();
234 auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,
235 inferAlignFromPtrInfo(MF, MPO));
236 MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
237 }
238
239 void assignValueToReg(Register ValVReg, Register PhysReg,
240 const CCValAssign &VA) override {
241 markPhysRegUsed(PhysReg);
242 IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
243 }
244
247 std::function<void()> *Thunk) override {
248 assert(VAs.size() >= 2 && "Expected at least 2 VAs.");
249 const CCValAssign &VALo = VAs[0];
250 const CCValAssign &VAHi = VAs[1];
251
252 assert(VAHi.needsCustom() && "Value doesn't need custom handling");
253 assert(VALo.getValNo() == VAHi.getValNo() &&
254 "Values belong to different arguments");
255
256 assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
257 VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
258 "unexpected custom value");
259
260 Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
261 MRI.createGenericVirtualRegister(LLT::scalar(32))};
262
263 if (VAHi.isMemLoc()) {
264 LLT MemTy(VAHi.getLocVT());
265
267 Register StackAddr = getStackAddress(
268 MemTy.getSizeInBytes(), VAHi.getLocMemOffset(), MPO, Arg.Flags[0]);
269
270 assignValueToAddress(NewRegs[1], StackAddr, MemTy, MPO,
271 const_cast<CCValAssign &>(VAHi));
272 }
273
274 assignValueToReg(NewRegs[0], VALo.getLocReg(), VALo);
275 if (VAHi.isRegLoc())
276 assignValueToReg(NewRegs[1], VAHi.getLocReg(), VAHi);
277
278 MIRBuilder.buildMergeLikeInstr(Arg.Regs[0], NewRegs);
279
280 return 2;
281 }
282
283 /// How the physical register gets marked varies between formal
284 /// parameters (it's a basic-block live-in), and a call instruction
285 /// (it's an implicit-def of the BL).
286 virtual void markPhysRegUsed(MCRegister PhysReg) = 0;
287
288private:
289 const RISCVSubtarget &Subtarget;
290};
291
292struct RISCVFormalArgHandler : public RISCVIncomingValueHandler {
293 RISCVFormalArgHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)
294 : RISCVIncomingValueHandler(B, MRI) {}
295
296 void markPhysRegUsed(MCRegister PhysReg) override {
297 MIRBuilder.getMRI()->addLiveIn(PhysReg);
298 MIRBuilder.getMBB().addLiveIn(PhysReg);
299 }
300};
301
302struct RISCVCallReturnHandler : public RISCVIncomingValueHandler {
303 RISCVCallReturnHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,
305 : RISCVIncomingValueHandler(B, MRI), MIB(MIB) {}
306
307 void markPhysRegUsed(MCRegister PhysReg) override {
308 MIB.addDef(PhysReg, RegState::Implicit);
309 }
310
312};
313
314} // namespace
315
317 : CallLowering(&TLI) {}
318
319/// Return true if scalable vector with ScalarTy is legal for lowering.
321 const RISCVSubtarget &Subtarget) {
322 if (EltTy->isPointerTy())
323 return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() : true;
324 if (EltTy->isIntegerTy(1) || EltTy->isIntegerTy(8) ||
325 EltTy->isIntegerTy(16) || EltTy->isIntegerTy(32))
326 return true;
327 if (EltTy->isIntegerTy(64))
328 return Subtarget.hasVInstructionsI64();
329 if (EltTy->isHalfTy())
330 return Subtarget.hasVInstructionsF16();
331 if (EltTy->isBFloatTy())
332 return Subtarget.hasVInstructionsBF16Minimal();
333 if (EltTy->isFloatTy())
334 return Subtarget.hasVInstructionsF32();
335 if (EltTy->isDoubleTy())
336 return Subtarget.hasVInstructionsF64();
337 return false;
338}
339
340// TODO: Support all argument types.
341// TODO: Remove IsLowerArgs argument by adding support for vectors in lowerCall.
342static bool isSupportedArgumentType(Type *T, const RISCVSubtarget &Subtarget,
343 bool IsLowerArgs = false) {
344 if (T->isIntegerTy())
345 return true;
346 if (T->isHalfTy() || T->isFloatTy() || T->isDoubleTy())
347 return true;
348 if (T->isPointerTy())
349 return true;
350 // TODO: Support fixed vector types.
351 if (IsLowerArgs && T->isVectorTy() && Subtarget.hasVInstructions() &&
352 T->isScalableTy() &&
353 isLegalElementTypeForRVV(T->getScalarType(), Subtarget))
354 return true;
355 return false;
356}
357
358// TODO: Only integer, pointer and aggregate types are supported now.
359// TODO: Remove IsLowerRetVal argument by adding support for vectors in
360// lowerCall.
361static bool isSupportedReturnType(Type *T, const RISCVSubtarget &Subtarget,
362 bool IsLowerRetVal = false) {
363 // TODO: Integers larger than 2*XLen are passed indirectly which is not
364 // supported yet.
365 if (T->isIntegerTy())
366 return T->getIntegerBitWidth() <= Subtarget.getXLen() * 2;
367 if (T->isHalfTy() || T->isFloatTy() || T->isDoubleTy())
368 return true;
369 if (T->isPointerTy())
370 return true;
371
372 if (T->isArrayTy())
373 return isSupportedReturnType(T->getArrayElementType(), Subtarget);
374
375 if (T->isStructTy()) {
376 auto StructT = cast<StructType>(T);
377 for (unsigned i = 0, e = StructT->getNumElements(); i != e; ++i)
378 if (!isSupportedReturnType(StructT->getElementType(i), Subtarget))
379 return false;
380 return true;
381 }
382
383 if (IsLowerRetVal && T->isVectorTy() && Subtarget.hasVInstructions() &&
384 T->isScalableTy() &&
385 isLegalElementTypeForRVV(T->getScalarType(), Subtarget))
386 return true;
387
388 return false;
389}
390
392 const Value *Val, ArrayRef<Register> VRegs,
393 FunctionLoweringInfo &FLI) const {
394 assert(!Val == VRegs.empty() && "Return value without a vreg");
395 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(RISCV::PseudoRET);
396
397 if (!VRegs.empty()) {
398 const RISCVSubtarget &Subtarget =
399 MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();
400 if (!isSupportedReturnType(Val->getType(), Subtarget, /*IsLowerRetVal=*/true))
401 return false;
402
403 MachineFunction &MF = MIRBuilder.getMF();
404 const DataLayout &DL = MF.getDataLayout();
405 const Function &F = MF.getFunction();
406 CallingConv::ID CC = F.getCallingConv();
407
408 ArgInfo OrigRetInfo(VRegs, Val->getType(), 0);
410
411 SmallVector<ArgInfo, 4> SplitRetInfos;
412 splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, CC);
413
414 RVVArgDispatcher Dispatcher{&MF, getTLI<RISCVTargetLowering>(),
415 ArrayRef(F.getReturnType())};
416 RISCVOutgoingValueAssigner Assigner(
418 /*IsRet=*/true, Dispatcher);
419 RISCVOutgoingValueHandler Handler(MIRBuilder, MF.getRegInfo(), Ret);
420 if (!determineAndHandleAssignments(Handler, Assigner, SplitRetInfos,
421 MIRBuilder, CC, F.isVarArg()))
422 return false;
423 }
424
425 MIRBuilder.insertInstr(Ret);
426 return true;
427}
428
429/// If there are varargs that were passed in a0-a7, the data in those registers
430/// must be copied to the varargs save area on the stack.
431void RISCVCallLowering::saveVarArgRegisters(
433 IncomingValueAssigner &Assigner, CCState &CCInfo) const {
434 MachineFunction &MF = MIRBuilder.getMF();
435 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
436 unsigned XLenInBytes = Subtarget.getXLen() / 8;
439 unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);
440 MachineFrameInfo &MFI = MF.getFrameInfo();
442
443 // Size of the vararg save area. For now, the varargs save area is either
444 // zero or large enough to hold a0-a7.
445 int VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx);
446 int FI;
447
448 // If all registers are allocated, then all varargs must be passed on the
449 // stack and we don't need to save any argregs.
450 if (VarArgsSaveSize == 0) {
451 int VaArgOffset = Assigner.StackSize;
452 FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
453 } else {
454 int VaArgOffset = -VarArgsSaveSize;
455 FI = MFI.CreateFixedObject(VarArgsSaveSize, VaArgOffset, true);
456
457 // If saving an odd number of registers then create an extra stack slot to
458 // ensure that the frame pointer is 2*XLEN-aligned, which in turn ensures
459 // offsets to even-numbered registered remain 2*XLEN-aligned.
460 if (Idx % 2) {
461 MFI.CreateFixedObject(XLenInBytes,
462 VaArgOffset - static_cast<int>(XLenInBytes), true);
463 VarArgsSaveSize += XLenInBytes;
464 }
465
467 Subtarget.getXLen());
468 const LLT sXLen = LLT::scalar(Subtarget.getXLen());
469
470 auto FIN = MIRBuilder.buildFrameIndex(p0, FI);
471 auto Offset = MIRBuilder.buildConstant(
472 MRI.createGenericVirtualRegister(sXLen), XLenInBytes);
473
474 // Copy the integer registers that may have been used for passing varargs
475 // to the vararg save area.
476 const MVT XLenVT = Subtarget.getXLenVT();
477 for (unsigned I = Idx; I < ArgRegs.size(); ++I) {
478 const Register VReg = MRI.createGenericVirtualRegister(sXLen);
479 Handler.assignValueToReg(
480 VReg, ArgRegs[I],
482 ArgRegs[I], XLenVT, CCValAssign::Full));
483 auto MPO =
484 MachinePointerInfo::getFixedStack(MF, FI, (I - Idx) * XLenInBytes);
485 MIRBuilder.buildStore(VReg, FIN, MPO, inferAlignFromPtrInfo(MF, MPO));
486 FIN = MIRBuilder.buildPtrAdd(MRI.createGenericVirtualRegister(p0),
487 FIN.getReg(0), Offset);
488 }
489 }
490
491 // Record the frame index of the first variable argument which is a value
492 // necessary to G_VASTART.
493 RVFI->setVarArgsFrameIndex(FI);
494 RVFI->setVarArgsSaveSize(VarArgsSaveSize);
495}
496
498 const Function &F,
500 FunctionLoweringInfo &FLI) const {
501 // Early exit if there are no arguments. varargs are not part of F.args() but
502 // must be lowered.
503 if (F.arg_empty() && !F.isVarArg())
504 return true;
505
506 const RISCVSubtarget &Subtarget =
507 MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();
508 for (auto &Arg : F.args()) {
509 if (!isSupportedArgumentType(Arg.getType(), Subtarget,
510 /*IsLowerArgs=*/true))
511 return false;
512 }
513
514 MachineFunction &MF = MIRBuilder.getMF();
515 const DataLayout &DL = MF.getDataLayout();
516 CallingConv::ID CC = F.getCallingConv();
517
518 SmallVector<ArgInfo, 32> SplitArgInfos;
519 SmallVector<Type *, 4> TypeList;
520 unsigned Index = 0;
521 for (auto &Arg : F.args()) {
522 // Construct the ArgInfo object from destination register and argument type.
523 ArgInfo AInfo(VRegs[Index], Arg.getType(), Index);
525
526 // Handle any required merging from split value types from physical
527 // registers into the desired VReg. ArgInfo objects are constructed
528 // correspondingly and appended to SplitArgInfos.
529 splitToValueTypes(AInfo, SplitArgInfos, DL, CC);
530
531 TypeList.push_back(Arg.getType());
532
533 ++Index;
534 }
535
536 RVVArgDispatcher Dispatcher{&MF, getTLI<RISCVTargetLowering>(),
537 ArrayRef(TypeList)};
538 RISCVIncomingValueAssigner Assigner(
540 /*IsRet=*/false, Dispatcher);
541 RISCVFormalArgHandler Handler(MIRBuilder, MF.getRegInfo());
542
544 CCState CCInfo(CC, F.isVarArg(), MIRBuilder.getMF(), ArgLocs, F.getContext());
545 if (!determineAssignments(Assigner, SplitArgInfos, CCInfo) ||
546 !handleAssignments(Handler, SplitArgInfos, CCInfo, ArgLocs, MIRBuilder))
547 return false;
548
549 if (F.isVarArg())
550 saveVarArgRegisters(MIRBuilder, Handler, Assigner, CCInfo);
551
552 return true;
553}
554
556 CallLoweringInfo &Info) const {
557 MachineFunction &MF = MIRBuilder.getMF();
558 const DataLayout &DL = MF.getDataLayout();
559 const Function &F = MF.getFunction();
560 CallingConv::ID CC = F.getCallingConv();
561
562 const RISCVSubtarget &Subtarget =
563 MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();
564 for (auto &AInfo : Info.OrigArgs) {
565 if (!isSupportedArgumentType(AInfo.Ty, Subtarget))
566 return false;
567 }
568
569 if (!Info.OrigRet.Ty->isVoidTy() &&
570 !isSupportedReturnType(Info.OrigRet.Ty, Subtarget))
571 return false;
572
573 MachineInstrBuilder CallSeqStart =
574 MIRBuilder.buildInstr(RISCV::ADJCALLSTACKDOWN);
575
576 SmallVector<ArgInfo, 32> SplitArgInfos;
578 SmallVector<Type *, 4> TypeList;
579 for (auto &AInfo : Info.OrigArgs) {
580 // Handle any required unmerging of split value types from a given VReg into
581 // physical registers. ArgInfo objects are constructed correspondingly and
582 // appended to SplitArgInfos.
583 splitToValueTypes(AInfo, SplitArgInfos, DL, CC);
584 TypeList.push_back(AInfo.Ty);
585 }
586
587 // TODO: Support tail calls.
588 Info.IsTailCall = false;
589
590 // Select the recommended relocation type R_RISCV_CALL_PLT.
591 if (!Info.Callee.isReg())
592 Info.Callee.setTargetFlags(RISCVII::MO_CALL);
593
595 MIRBuilder
596 .buildInstrNoInsert(Info.Callee.isReg() ? RISCV::PseudoCALLIndirect
597 : RISCV::PseudoCALL)
598 .add(Info.Callee);
599 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
600 Call.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
601
602 RVVArgDispatcher ArgDispatcher{&MF, getTLI<RISCVTargetLowering>(),
603 ArrayRef(TypeList)};
604 RISCVOutgoingValueAssigner ArgAssigner(
606 /*IsRet=*/false, ArgDispatcher);
607 RISCVOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), Call);
608 if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgInfos,
609 MIRBuilder, CC, Info.IsVarArg))
610 return false;
611
612 MIRBuilder.insertInstr(Call);
613
614 CallSeqStart.addImm(ArgAssigner.StackSize).addImm(0);
615 MIRBuilder.buildInstr(RISCV::ADJCALLSTACKUP)
616 .addImm(ArgAssigner.StackSize)
617 .addImm(0);
618
619 // If Callee is a reg, since it is used by a target specific
620 // instruction, it must have a register class matching the
621 // constraint of that instruction.
622 if (Call->getOperand(0).isReg())
624 *Subtarget.getInstrInfo(),
625 *Subtarget.getRegBankInfo(), *Call,
626 Call->getDesc(), Call->getOperand(0), 0);
627
628 if (Info.OrigRet.Ty->isVoidTy())
629 return true;
630
631 SmallVector<ArgInfo, 4> SplitRetInfos;
632 splitToValueTypes(Info.OrigRet, SplitRetInfos, DL, CC);
633
634 RVVArgDispatcher RetDispatcher{&MF, getTLI<RISCVTargetLowering>(),
635 ArrayRef(F.getReturnType())};
636 RISCVIncomingValueAssigner RetAssigner(
638 /*IsRet=*/true, RetDispatcher);
639 RISCVCallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Call);
640 if (!determineAndHandleAssignments(RetHandler, RetAssigner, SplitRetInfos,
641 MIRBuilder, CC, Info.IsVarArg))
642 return false;
643
644 return true;
645}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
uint64_t Addr
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineIRBuilder class.
unsigned const TargetRegisterInfo * TRI
static bool isSupportedReturnType(Type *T)
static bool isSupportedArgumentType(Type *T)
static bool isLegalElementTypeForRVV(Type *EltTy, const RISCVSubtarget &Subtarget)
Return true if scalable vector with ScalarTy is legal for lowering.
This file describes how to lower LLVM calls to machine code calls.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:160
CCState - This class holds information needed while lowering arguments and return values.
MachineFunction & getMachineFunction() const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
CCValAssign - Represent assignment of one arg/retval to a location.
bool isRegLoc() const
Register getLocReg() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, unsigned RegNo, MVT LocVT, LocInfo HTP, bool IsCustom=false)
bool needsCustom() const
bool isMemLoc() const
int64_t getLocMemOffset() const
unsigned getValNo() const
bool handleAssignments(ValueHandler &Handler, SmallVectorImpl< ArgInfo > &Args, CCState &CCState, SmallVectorImpl< CCValAssign > &ArgLocs, MachineIRBuilder &MIRBuilder, ArrayRef< Register > ThisReturnRegs=std::nullopt) const
Use Handler to insert code to handle the argument/return values represented by Args.
bool determineAndHandleAssignments(ValueHandler &Handler, ValueAssigner &Assigner, SmallVectorImpl< ArgInfo > &Args, MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, bool IsVarArg, ArrayRef< Register > ThisReturnRegs=std::nullopt) const
Invoke ValueAssigner::assignArg on each of the given Args and then use Handler to move them to the as...
void splitToValueTypes(const ArgInfo &OrigArgInfo, SmallVectorImpl< ArgInfo > &SplitArgs, const DataLayout &DL, CallingConv::ID CallConv, SmallVectorImpl< uint64_t > *Offsets=nullptr) const
Break OrigArgInfo into one or more pieces the calling convention can process, returned in SplitArgs.
bool determineAssignments(ValueAssigner &Assigner, SmallVectorImpl< ArgInfo > &Args, CCState &CCInfo) const
Analyze the argument list in Args, using Assigner to populate CCInfo.
void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, const FuncInfoTy &FuncInfo) const
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
unsigned getAllocaAddrSpace() const
Definition: DataLayout.h:233
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:42
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
Definition: LowLevelType.h:57
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
Definition: LowLevelType.h:203
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Machine Value Type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Helper class to build MachineInstr.
MachineInstrBuilder insertInstr(MachineInstrBuilder MIB)
Insert an existing instruction at the insertion point.
MachineInstrBuilder buildPtrAdd(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_PTR_ADD Op0, Op1.
MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildFrameIndex(const DstOp &Res, int Idx)
Build and insert Res = G_FRAME_INDEX Idx.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildInstrNoInsert(unsigned Opcode)
Build but don't insert <empty> = Opcode <empty>.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool lowerReturn(MachineIRBuilder &MIRBuiler, const Value *Val, ArrayRef< Register > VRegs, FunctionLoweringInfo &FLI) const override
This hook behaves as the extended lowerReturn function, but for targets that do not support swifterro...
bool lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const override
This hook must be implemented to lower the given call instruction, including argument and return valu...
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef< ArrayRef< Register > > VRegs, FunctionLoweringInfo &FLI) const override
This hook must be implemented to lower the incoming (formal) arguments, described by VRegs,...
RISCVCallLowering(const RISCVTargetLowering &TLI)
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
RISCVABI::ABI getTargetABI() const
bool hasVInstructionsI64() const
bool hasVInstructionsF64() const
bool hasVInstructionsBF16Minimal() const
unsigned getXLen() const
bool hasVInstructionsF16() const
const RISCVRegisterBankInfo * getRegBankInfo() const override
bool hasVInstructions() const
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
const RISCVTargetLowering * getTargetLowering() const override
bool hasVInstructionsF32() const
bool RISCVCCAssignFn(const DataLayout &DL, RISCVABI::ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, RVVArgDispatcher &RVVDispatcher)
RISCVCCAssignFn - This target-specific function extends the default CCValAssign with additional infor...
As per the spec, the rules for passing vector arguments are as follows:
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:251
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition: Type.h:153
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition: Type.h:145
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
Definition: Type.h:142
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition: Type.h:156
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:224
unsigned getNumOperands() const
Definition: User.h:191
LLVM Value Representation.
Definition: Value.h:74
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:41
bool CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, RVVArgDispatcher &RVVDispatcher)
bool CC_RISCV_FastCC(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, RVVArgDispatcher &RVVDispatcher)
ArrayRef< MCPhysReg > getArgGPRs(const RISCVABI::ABI ABI)
@ Implicit
Not emitted register (e.g. carry, or temporary result).
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
Definition: Utils.cpp:56
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition: Alignment.h:212
Align inferAlignFromPtrInfo(MachineFunction &MF, const MachinePointerInfo &MPO)
Definition: Utils.cpp:893
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
SmallVector< Register, 4 > Regs
Definition: CallLowering.h:63
SmallVector< ISD::ArgFlagsTy, 4 > Flags
Definition: CallLowering.h:51
Base class for ValueHandlers used for arguments coming into the current function, or for return value...
Definition: CallLowering.h:331
void assignValueToReg(Register ValVReg, Register PhysReg, const CCValAssign &VA) override
Provides a default implementation for argument handling.
Base class for ValueHandlers used for arguments passed to a function call, or for return values.
Definition: CallLowering.h:347
virtual bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, const ArgInfo &Info, ISD::ArgFlagsTy Flags, CCState &State)
Wrap call to (typically tablegenerated CCAssignFn).
Definition: CallLowering.h:199
virtual Register getStackAddress(uint64_t MemSize, int64_t Offset, MachinePointerInfo &MPO, ISD::ArgFlagsTy Flags)=0
Materialize a VReg containing the address of the specified stack-based object.
virtual void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO, const CCValAssign &VA)=0
The specified value has been assigned to a stack location.
Register extendRegister(Register ValReg, const CCValAssign &VA, unsigned MaxSizeBits=0)
Extend a register to the location type given in VA, capped at extending to at most MaxSize bits.
virtual unsigned assignCustomValue(ArgInfo &Arg, ArrayRef< CCValAssign > VAs, std::function< void()> *Thunk=nullptr)
Handle custom values, which may be passed into one or more of VAs.
Definition: CallLowering.h:308
virtual void assignValueToReg(Register ValVReg, Register PhysReg, const CCValAssign &VA)=0
The specified value has been assigned to a physical register, handle the appropriate COPY (either to ...
Extended Value Type.
Definition: ValueTypes.h:35
This class contains a discriminated union of information about pointers in memory operands,...
static MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.