LLVM 23.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 "RISCVCallingConv.h"
17#include "RISCVISelLowering.h"
19#include "RISCVSubtarget.h"
24
25using namespace llvm;
26
27namespace {
28
29struct RISCVOutgoingValueHandler : public CallLowering::OutgoingValueHandler {
30 RISCVOutgoingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,
31 MachineInstrBuilder MIB)
32 : OutgoingValueHandler(B, MRI), MIB(MIB),
33 Subtarget(MIRBuilder.getMF().getSubtarget<RISCVSubtarget>()) {}
34 Register getStackAddress(uint64_t MemSize, int64_t Offset,
35 MachinePointerInfo &MPO,
36 ISD::ArgFlagsTy Flags) override {
37 MachineFunction &MF = MIRBuilder.getMF();
38 LLT p0 = LLT::pointer(0, Subtarget.getXLen());
39 LLT sXLen = LLT::scalar(Subtarget.getXLen());
40
41 if (!SPReg)
42 SPReg = MIRBuilder.buildCopy(p0, Register(RISCV::X2)).getReg(0);
43
44 auto OffsetReg = MIRBuilder.buildConstant(sXLen, Offset);
45
46 auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);
47
49 return AddrReg.getReg(0);
50 }
51
52 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
53 const MachinePointerInfo &MPO,
54 const CCValAssign &VA) override {
55 MachineFunction &MF = MIRBuilder.getMF();
56 uint64_t LocMemOffset = VA.getLocMemOffset();
57
58 // TODO: Move StackAlignment to subtarget and share with FrameLowering.
59 auto MMO =
61 commonAlignment(Align(16), LocMemOffset));
62
63 Register ExtReg = extendRegister(ValVReg, VA);
64 MIRBuilder.buildStore(ExtReg, Addr, *MMO);
65 }
66
67 void assignValueToReg(Register ValVReg, Register PhysReg,
68 const CCValAssign &VA,
69 ISD::ArgFlagsTy Flags = {}) override {
70 Register ExtReg = extendRegister(ValVReg, VA);
71 MIRBuilder.buildCopy(PhysReg, ExtReg);
72 MIB.addUse(PhysReg, RegState::Implicit);
73 }
74
75 unsigned assignCustomValue(CallLowering::ArgInfo &Arg,
77 std::function<void()> *Thunk) override {
78 const CCValAssign &VA = VAs[0];
79 if ((VA.getLocVT() == MVT::i64 && VA.getValVT() == MVT::f32) ||
80 (VA.getLocVT().isInteger() && VA.getValVT() == MVT::f16)) {
81 Register PhysReg = VA.getLocReg();
82
83 auto assignFunc = [=]() {
84 auto Trunc = MIRBuilder.buildAnyExt(LLT(VA.getLocVT()), Arg.Regs[0]);
85 MIRBuilder.buildCopy(PhysReg, Trunc);
86 MIB.addUse(PhysReg, RegState::Implicit);
87 };
88
89 if (Thunk) {
90 *Thunk = std::move(assignFunc);
91 return 1;
92 }
93
94 assignFunc();
95 return 1;
96 }
97
98 assert(VAs.size() >= 2 && "Expected at least 2 VAs.");
99 const CCValAssign &VAHi = VAs[1];
100
101 assert(VAHi.needsCustom() && "Value doesn't need custom handling");
102 assert(VA.getValNo() == VAHi.getValNo() &&
103 "Values belong to different arguments");
104
105 assert(VA.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
106 VA.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
107 "unexpected custom value");
108
109 Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
110 MRI.createGenericVirtualRegister(LLT::scalar(32))};
111 MIRBuilder.buildUnmerge(NewRegs, Arg.Regs[0]);
112
113 if (VAHi.isMemLoc()) {
114 LLT MemTy(VAHi.getLocVT());
115
116 MachinePointerInfo MPO;
117 Register StackAddr = getStackAddress(
118 MemTy.getSizeInBytes(), VAHi.getLocMemOffset(), MPO, Arg.Flags[0]);
119
120 assignValueToAddress(NewRegs[1], StackAddr, MemTy, MPO,
121 const_cast<CCValAssign &>(VAHi));
122 }
123
124 auto assignFunc = [=]() {
125 assignValueToReg(NewRegs[0], VA.getLocReg(), VA);
126 if (VAHi.isRegLoc())
127 assignValueToReg(NewRegs[1], VAHi.getLocReg(), VAHi);
128 };
129
130 if (Thunk) {
131 *Thunk = std::move(assignFunc);
132 return 2;
133 }
134
135 assignFunc();
136 return 2;
137 }
138
139private:
140 MachineInstrBuilder MIB;
141
142 // Cache the SP register vreg if we need it more than once in this call site.
143 Register SPReg;
144
145 const RISCVSubtarget &Subtarget;
146};
147
148struct RISCVIncomingValueHandler : public CallLowering::IncomingValueHandler {
149 RISCVIncomingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)
150 : IncomingValueHandler(B, MRI),
151 Subtarget(MIRBuilder.getMF().getSubtarget<RISCVSubtarget>()) {}
152
153 Register getStackAddress(uint64_t MemSize, int64_t Offset,
154 MachinePointerInfo &MPO,
155 ISD::ArgFlagsTy Flags) override {
156 MachineFrameInfo &MFI = MIRBuilder.getMF().getFrameInfo();
157
158 int FI = MFI.CreateFixedObject(MemSize, Offset, /*Immutable=*/true);
159 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
160 return MIRBuilder.buildFrameIndex(LLT::pointer(0, Subtarget.getXLen()), FI)
161 .getReg(0);
162 }
163
164 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
165 const MachinePointerInfo &MPO,
166 const CCValAssign &VA) override {
167 MachineFunction &MF = MIRBuilder.getMF();
168 auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,
169 inferAlignFromPtrInfo(MF, MPO));
170 MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
171 }
172
173 void assignValueToReg(Register ValVReg, Register PhysReg,
174 const CCValAssign &VA,
175 ISD::ArgFlagsTy Flags = {}) override {
176 markPhysRegUsed(PhysReg);
177 IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
178 }
179
180 unsigned assignCustomValue(CallLowering::ArgInfo &Arg,
182 std::function<void()> *Thunk) override {
183 const CCValAssign &VA = VAs[0];
184 if ((VA.getLocVT() == MVT::i64 && VA.getValVT() == MVT::f32) ||
185 (VA.getLocVT().isInteger() && VA.getValVT() == MVT::f16)) {
186 Register PhysReg = VA.getLocReg();
187
188 markPhysRegUsed(PhysReg);
189
190 LLT LocTy(VA.getLocVT());
191 auto Copy = MIRBuilder.buildCopy(LocTy, PhysReg);
192
193 MIRBuilder.buildTrunc(Arg.Regs[0], Copy.getReg(0));
194 return 1;
195 }
196
197 assert(VAs.size() >= 2 && "Expected at least 2 VAs.");
198 const CCValAssign &VAHi = VAs[1];
199
200 assert(VAHi.needsCustom() && "Value doesn't need custom handling");
201 assert(VA.getValNo() == VAHi.getValNo() &&
202 "Values belong to different arguments");
203
204 assert(VA.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
205 VA.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
206 "unexpected custom value");
207
208 Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
209 MRI.createGenericVirtualRegister(LLT::scalar(32))};
210
211 if (VAHi.isMemLoc()) {
212 LLT MemTy(VAHi.getLocVT());
213
214 MachinePointerInfo MPO;
215 Register StackAddr = getStackAddress(
216 MemTy.getSizeInBytes(), VAHi.getLocMemOffset(), MPO, Arg.Flags[0]);
217
218 assignValueToAddress(NewRegs[1], StackAddr, MemTy, MPO,
219 const_cast<CCValAssign &>(VAHi));
220 }
221
222 assignValueToReg(NewRegs[0], VA.getLocReg(), VA);
223 if (VAHi.isRegLoc())
224 assignValueToReg(NewRegs[1], VAHi.getLocReg(), VAHi);
225
226 MIRBuilder.buildMergeLikeInstr(Arg.Regs[0], NewRegs);
227
228 return 2;
229 }
230
231 /// How the physical register gets marked varies between formal
232 /// parameters (it's a basic-block live-in), and a call instruction
233 /// (it's an implicit-def of the BL).
234 virtual void markPhysRegUsed(MCRegister PhysReg) = 0;
235
236private:
237 const RISCVSubtarget &Subtarget;
238};
239
240struct RISCVFormalArgHandler : public RISCVIncomingValueHandler {
241 RISCVFormalArgHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)
242 : RISCVIncomingValueHandler(B, MRI) {}
243
244 void markPhysRegUsed(MCRegister PhysReg) override {
245 MIRBuilder.getMRI()->addLiveIn(PhysReg);
246 MIRBuilder.getMBB().addLiveIn(PhysReg);
247 }
248};
249
250struct RISCVCallReturnHandler : public RISCVIncomingValueHandler {
251 RISCVCallReturnHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,
252 MachineInstrBuilder &MIB)
253 : RISCVIncomingValueHandler(B, MRI), MIB(MIB) {}
254
255 void markPhysRegUsed(MCRegister PhysReg) override {
256 MIB.addDef(PhysReg, RegState::Implicit);
257 }
258
259 MachineInstrBuilder MIB;
260};
261
262} // namespace
263
266
267/// Return true if scalable vector with ScalarTy is legal for lowering.
269 const RISCVSubtarget &Subtarget) {
270 if (EltTy->isPointerTy())
271 return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() : true;
272 if (EltTy->isIntegerTy(1) || EltTy->isIntegerTy(8) ||
273 EltTy->isIntegerTy(16) || EltTy->isIntegerTy(32))
274 return true;
275 if (EltTy->isIntegerTy(64))
276 return Subtarget.hasVInstructionsI64();
277 if (EltTy->isHalfTy())
278 return Subtarget.hasVInstructionsF16Minimal();
279 if (EltTy->isBFloatTy())
280 return Subtarget.hasVInstructionsBF16Minimal();
281 if (EltTy->isFloatTy())
282 return Subtarget.hasVInstructionsF32();
283 if (EltTy->isDoubleTy())
284 return Subtarget.hasVInstructionsF64();
285 return false;
286}
287
288// TODO: Support all argument types.
289// TODO: Remove IsLowerArgs argument by adding support for vectors in lowerCall.
290static bool isSupportedArgumentType(Type *T, const RISCVSubtarget &Subtarget,
291 bool IsLowerArgs = false) {
292 if (T->isIntegerTy())
293 return true;
294 if (T->isHalfTy() || T->isFloatTy() || T->isDoubleTy() || T->isFP128Ty())
295 return true;
296 if (T->isPointerTy())
297 return true;
298 if (T->isArrayTy())
299 return isSupportedArgumentType(T->getArrayElementType(), Subtarget,
300 IsLowerArgs);
301 // TODO: Support fixed vector types.
302 if (IsLowerArgs && T->isVectorTy() && Subtarget.hasVInstructions() &&
303 T->isScalableTy() &&
304 isLegalElementTypeForRVV(T->getScalarType(), Subtarget))
305 return true;
306 return false;
307}
308
309// TODO: Only integer, pointer and aggregate types are supported now.
310// TODO: Remove IsLowerRetVal argument by adding support for vectors in
311// lowerCall.
312static bool isSupportedReturnType(Type *T, const RISCVSubtarget &Subtarget,
313 bool IsLowerRetVal = false) {
314 if (T->isIntegerTy() || T->isFloatingPointTy() || T->isPointerTy())
315 return true;
316
317 if (T->isArrayTy())
318 return isSupportedReturnType(T->getArrayElementType(), Subtarget);
319
320 if (T->isStructTy()) {
321 auto StructT = cast<StructType>(T);
322 for (unsigned i = 0, e = StructT->getNumElements(); i != e; ++i)
323 if (!isSupportedReturnType(StructT->getElementType(i), Subtarget))
324 return false;
325 return true;
326 }
327
328 if (IsLowerRetVal && T->isVectorTy() && Subtarget.hasVInstructions() &&
329 T->isScalableTy() &&
330 isLegalElementTypeForRVV(T->getScalarType(), Subtarget))
331 return true;
332
333 return false;
334}
335
337 const Value *Val, ArrayRef<Register> VRegs,
338 FunctionLoweringInfo &FLI) const {
339 assert(!Val == VRegs.empty() && "Return value without a vreg");
340 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(RISCV::PseudoRET);
341
342 if (!FLI.CanLowerReturn) {
343 insertSRetStores(MIRBuilder, Val->getType(), VRegs, FLI.DemoteRegister);
344 } else if (!VRegs.empty()) {
345 const RISCVSubtarget &Subtarget =
346 MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();
347 if (!isSupportedReturnType(Val->getType(), Subtarget,
348 /*IsLowerRetVal=*/true))
349 return false;
350
351 MachineFunction &MF = MIRBuilder.getMF();
352 const DataLayout &DL = MF.getDataLayout();
353 const Function &F = MF.getFunction();
354 CallingConv::ID CC = F.getCallingConv();
355
356 ArgInfo OrigRetInfo(VRegs, Val->getType(), 0);
357 setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F);
358
359 SmallVector<ArgInfo, 4> SplitRetInfos;
360 splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, CC);
361
363 RISCVOutgoingValueHandler Handler(MIRBuilder, MF.getRegInfo(), Ret);
364
366 CCState CCInfo(CC, F.isVarArg(), MF, RetLocs, F.getContext());
367 if (!determineAssignments(Assigner, SplitRetInfos, CCInfo) ||
368 !handleAssignments(Handler, SplitRetInfos, CCInfo, RetLocs, MIRBuilder))
369 return false;
370
371 if (any_of(RetLocs, [](CCValAssign &VA) {
372 return VA.getLocVT().isScalableVector();
373 }))
375 }
376
377 MIRBuilder.insertInstr(Ret);
378 return true;
379}
380
382 CallingConv::ID CallConv,
384 bool IsVarArg) const {
386 CCState CCInfo(CallConv, IsVarArg, MF, RetLocs,
387 MF.getFunction().getContext());
388
389 return checkReturn(CCInfo, Outs, RetCC_RISCV);
390}
391
392/// If there are varargs that were passed in a0-a7, the data in those registers
393/// must be copied to the varargs save area on the stack.
394void RISCVCallLowering::saveVarArgRegisters(
396 IncomingValueAssigner &Assigner, CCState &CCInfo) const {
397 MachineFunction &MF = MIRBuilder.getMF();
398 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
399 unsigned XLenInBytes = Subtarget.getXLen() / 8;
402 unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);
403 MachineFrameInfo &MFI = MF.getFrameInfo();
405
406 // Size of the vararg save area. For now, the varargs save area is either
407 // zero or large enough to hold a0-a7.
408 int VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx);
409 int FI;
410
411 // If all registers are allocated, then all varargs must be passed on the
412 // stack and we don't need to save any argregs.
413 if (VarArgsSaveSize == 0) {
414 int VaArgOffset = Assigner.StackSize;
415 FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
416 } else {
417 int VaArgOffset = -VarArgsSaveSize;
418 FI = MFI.CreateFixedObject(VarArgsSaveSize, VaArgOffset, true);
419
420 // If saving an odd number of registers then create an extra stack slot to
421 // ensure that the frame pointer is 2*XLEN-aligned, which in turn ensures
422 // offsets to even-numbered registered remain 2*XLEN-aligned.
423 if (Idx % 2) {
424 MFI.CreateFixedObject(XLenInBytes,
425 VaArgOffset - static_cast<int>(XLenInBytes), true);
426 VarArgsSaveSize += XLenInBytes;
427 }
428
429 const LLT p0 = LLT::pointer(MF.getDataLayout().getAllocaAddrSpace(),
430 Subtarget.getXLen());
431 const LLT sXLen = LLT::scalar(Subtarget.getXLen());
432
433 auto FIN = MIRBuilder.buildFrameIndex(p0, FI);
434 auto Offset = MIRBuilder.buildConstant(
435 MRI.createGenericVirtualRegister(sXLen), XLenInBytes);
436
437 // Copy the integer registers that may have been used for passing varargs
438 // to the vararg save area.
439 const MVT XLenVT = Subtarget.getXLenVT();
440 for (unsigned I = Idx; I < ArgRegs.size(); ++I) {
441 const Register VReg = MRI.createGenericVirtualRegister(sXLen);
442 Handler.assignValueToReg(
443 VReg, ArgRegs[I],
445 ArgRegs[I], XLenVT, CCValAssign::Full));
446 auto MPO =
447 MachinePointerInfo::getFixedStack(MF, FI, (I - Idx) * XLenInBytes);
448 MIRBuilder.buildStore(VReg, FIN, MPO, inferAlignFromPtrInfo(MF, MPO));
449 FIN = MIRBuilder.buildPtrAdd(MRI.createGenericVirtualRegister(p0),
450 FIN.getReg(0), Offset);
451 }
452 }
453
454 // Record the frame index of the first variable argument which is a value
455 // necessary to G_VASTART.
456 RVFI->setVarArgsFrameIndex(FI);
457 RVFI->setVarArgsSaveSize(VarArgsSaveSize);
458}
459
461 const Function &F,
463 FunctionLoweringInfo &FLI) const {
464 MachineFunction &MF = MIRBuilder.getMF();
465
466 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
467 for (auto &Arg : F.args()) {
468 if (!isSupportedArgumentType(Arg.getType(), Subtarget,
469 /*IsLowerArgs=*/true))
470 return false;
471 }
472
474 const DataLayout &DL = MF.getDataLayout();
475 CallingConv::ID CC = F.getCallingConv();
476
477 SmallVector<ArgInfo, 32> SplitArgInfos;
478
479 // Insert the hidden sret parameter if the return value won't fit in the
480 // return registers.
481 if (!FLI.CanLowerReturn)
482 insertSRetIncomingArgument(F, SplitArgInfos, FLI.DemoteRegister, MRI, DL);
483
484 unsigned Index = 0;
485 for (auto &Arg : F.args()) {
486 // Construct the ArgInfo object from destination register and argument type.
487 ArgInfo AInfo(VRegs[Index], Arg.getType(), Index);
488 setArgFlags(AInfo, Index + AttributeList::FirstArgIndex, DL, F);
489
490 // Handle any required merging from split value types from physical
491 // registers into the desired VReg. ArgInfo objects are constructed
492 // correspondingly and appended to SplitArgInfos.
493 splitToValueTypes(AInfo, SplitArgInfos, DL, CC);
494
495 ++Index;
496 }
497
499 RISCVFormalArgHandler Handler(MIRBuilder, MF.getRegInfo());
500
502 CCState CCInfo(CC, F.isVarArg(), MIRBuilder.getMF(), ArgLocs, F.getContext());
503 if (!determineAssignments(Assigner, SplitArgInfos, CCInfo) ||
504 !handleAssignments(Handler, SplitArgInfos, CCInfo, ArgLocs, MIRBuilder))
505 return false;
506
507 if (any_of(ArgLocs,
508 [](CCValAssign &VA) { return VA.getLocVT().isScalableVector(); }))
510
511 if (F.isVarArg())
512 saveVarArgRegisters(MIRBuilder, Handler, Assigner, CCInfo);
513
514 return true;
515}
516
518 CallLoweringInfo &Info) const {
519 MachineFunction &MF = MIRBuilder.getMF();
520 const DataLayout &DL = MF.getDataLayout();
521 CallingConv::ID CC = Info.CallConv;
522
523 const RISCVSubtarget &Subtarget =
524 MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();
525 for (auto &AInfo : Info.OrigArgs) {
526 if (!isSupportedArgumentType(AInfo.Ty, Subtarget))
527 return false;
528 if (AInfo.Flags[0].isByVal())
529 return false;
530 }
531
532 if (!Info.OrigRet.Ty->isVoidTy() &&
533 !isSupportedReturnType(Info.OrigRet.Ty, Subtarget))
534 return false;
535
536 MachineInstrBuilder CallSeqStart =
537 MIRBuilder.buildInstr(RISCV::ADJCALLSTACKDOWN);
538
539 SmallVector<ArgInfo, 32> SplitArgInfos;
540 for (auto &AInfo : Info.OrigArgs) {
541 // Handle any required unmerging of split value types from a given VReg into
542 // physical registers. ArgInfo objects are constructed correspondingly and
543 // appended to SplitArgInfos.
544 splitToValueTypes(AInfo, SplitArgInfos, DL, CC);
545 }
546
547 // TODO: Support tail calls.
548 Info.IsTailCall = false;
549
550 // Select the recommended relocation type R_RISCV_CALL_PLT.
551 if (!Info.Callee.isReg())
552 Info.Callee.setTargetFlags(RISCVII::MO_CALL);
553
555 MIRBuilder
556 .buildInstrNoInsert(Info.Callee.isReg() ? RISCV::PseudoCALLIndirect
557 : RISCV::PseudoCALL)
558 .add(Info.Callee);
559 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
560 Call.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
561
562 OutgoingValueAssigner ArgAssigner(CC_RISCV);
563 RISCVOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), Call);
564 if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgInfos,
565 MIRBuilder, CC, Info.IsVarArg))
566 return false;
567
568 MIRBuilder.insertInstr(Call);
569
570 CallSeqStart.addImm(ArgAssigner.StackSize).addImm(0);
571 MIRBuilder.buildInstr(RISCV::ADJCALLSTACKUP)
572 .addImm(ArgAssigner.StackSize)
573 .addImm(0);
574
575 // If Callee is a reg, since it is used by a target specific
576 // instruction, it must have a register class matching the
577 // constraint of that instruction.
578 if (Call->getOperand(0).isReg())
580 *Subtarget.getInstrInfo(),
581 *Subtarget.getRegBankInfo(), *Call,
582 Call->getDesc(), Call->getOperand(0), 0);
583
584 if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) {
585 SmallVector<ArgInfo, 4> SplitRetInfos;
586 splitToValueTypes(Info.OrigRet, SplitRetInfos, DL, CC);
587
589 RISCVCallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Call);
590 if (!determineAndHandleAssignments(RetHandler, RetAssigner, SplitRetInfos,
591 MIRBuilder, CC, Info.IsVarArg))
592 return false;
593 }
594
595 if (!Info.CanLowerReturn)
596 insertSRetLoads(MIRBuilder, Info.OrigRet.Ty, Info.OrigRet.Regs,
597 Info.DemoteRegister, Info.DemoteStackIndex);
598
599 return true;
600}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
size - Get the array size.
Definition ArrayRef.h:142
bool empty() const
empty - Check if the array is empty.
Definition ArrayRef.h:137
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
bool needsCustom() const
int64_t getLocMemOffset() const
unsigned getValNo() const
void insertSRetLoads(MachineIRBuilder &MIRBuilder, Type *RetTy, ArrayRef< Register > VRegs, Register DemoteReg, int FI) const
Load the returned value from the stack into virtual registers in VRegs.
bool handleAssignments(ValueHandler &Handler, SmallVectorImpl< ArgInfo > &Args, CCState &CCState, SmallVectorImpl< CCValAssign > &ArgLocs, MachineIRBuilder &MIRBuilder, ArrayRef< Register > ThisReturnRegs={}) const
Use Handler to insert code to handle the argument/return values represented by Args.
void insertSRetIncomingArgument(const Function &F, SmallVectorImpl< ArgInfo > &SplitArgs, Register &DemoteReg, MachineRegisterInfo &MRI, const DataLayout &DL) const
Insert the hidden sret ArgInfo to the beginning of SplitArgs.
void splitToValueTypes(const ArgInfo &OrigArgInfo, SmallVectorImpl< ArgInfo > &SplitArgs, const DataLayout &DL, CallingConv::ID CallConv, SmallVectorImpl< TypeSize > *Offsets=nullptr) const
Break OrigArgInfo into one or more pieces the calling convention can process, returned in SplitArgs.
bool determineAndHandleAssignments(ValueHandler &Handler, ValueAssigner &Assigner, SmallVectorImpl< ArgInfo > &Args, MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, bool IsVarArg, ArrayRef< Register > ThisReturnRegs={}) const
Invoke ValueAssigner::assignArg on each of the given Args and then use Handler to move them to the as...
void insertSRetStores(MachineIRBuilder &MIRBuilder, Type *RetTy, ArrayRef< Register > VRegs, Register DemoteReg) const
Store the return value given by VRegs into stack starting at the offset specified in DemoteReg.
bool determineAssignments(ValueAssigner &Assigner, SmallVectorImpl< ArgInfo > &Args, CCState &CCInfo) const
Analyze the argument list in Args, using Assigner to populate CCInfo.
bool checkReturn(CCState &CCInfo, SmallVectorImpl< BaseArgInfo > &Outs, CCAssignFn *Fn) const
CallLowering(const TargetLowering *TLI)
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:64
unsigned getAllocaAddrSpace() const
Definition DataLayout.h:250
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Register DemoteRegister
DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg allocated to hold a pointer to ...
bool CanLowerReturn
CanLowerReturn - true iff the function's return value can be lowered to registers.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:358
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI 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
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
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 canLowerReturn(MachineFunction &MF, CallingConv::ID CallConv, SmallVectorImpl< BaseArgInfo > &Outs, bool IsVarArg) const override
This hook must be implemented to check whether the return values described by Outs can fit into the r...
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
bool hasVInstructionsF16Minimal() const
unsigned getXLen() const
const RISCVRegisterBankInfo * getRegBankInfo() const override
bool hasVInstructions() const
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
bool hasVInstructionsF32() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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:46
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:284
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition Type.h:155
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition Type.h:147
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
Definition Type.h:144
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition Type.h:158
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
unsigned getNumOperands() const
Definition User.h:229
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
CallInst * Call
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
ArrayRef< MCPhysReg > getArgGPRs(const RISCVABI::ABI ABI)
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
LLVM_ABI 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
CCAssignFn RetCC_RISCV
This is used for assigning return values to locations when making calls.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:201
CCAssignFn CC_RISCV
This is used for assigining arguments to locations when making calls.
LLVM_ABI Align inferAlignFromPtrInfo(MachineFunction &MF, const MachinePointerInfo &MPO)
Definition Utils.cpp:923
SmallVector< Register, 4 > Regs
SmallVector< ISD::ArgFlagsTy, 4 > Flags
Base class for ValueHandlers used for arguments coming into the current function, or for return value...
void assignValueToReg(Register ValVReg, Register PhysReg, const CCValAssign &VA, ISD::ArgFlagsTy Flags={}) override
Provides a default implementation for argument handling.
Base class for ValueHandlers used for arguments passed to a function call, or for return values.
uint64_t StackSize
The size of the currently allocated portion of the stack.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.