LLVM 18.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
37public:
38 RISCVOutgoingValueAssigner(
39 RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet)
40 : CallLowering::OutgoingValueAssigner(nullptr),
41 RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {}
42
43 bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
45 const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
46 CCState &State) override {
48 const DataLayout &DL = MF.getDataLayout();
49 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
50
51 if (RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,
52 LocInfo, Flags, State, Info.IsFixed, IsRet, Info.Ty,
53 *Subtarget.getTargetLowering(),
54 /*FirstMaskArgument=*/std::nullopt))
55 return true;
56
57 StackSize = State.getStackSize();
58 return false;
59 }
60};
61
62struct RISCVOutgoingValueHandler : public CallLowering::OutgoingValueHandler {
63 RISCVOutgoingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,
65 : OutgoingValueHandler(B, MRI), MIB(MIB),
66 Subtarget(MIRBuilder.getMF().getSubtarget<RISCVSubtarget>()) {}
67 Register getStackAddress(uint64_t MemSize, int64_t Offset,
69 ISD::ArgFlagsTy Flags) override {
70 MachineFunction &MF = MIRBuilder.getMF();
71 LLT p0 = LLT::pointer(0, Subtarget.getXLen());
72 LLT sXLen = LLT::scalar(Subtarget.getXLen());
73
74 if (!SPReg)
75 SPReg = MIRBuilder.buildCopy(p0, Register(RISCV::X2)).getReg(0);
76
77 auto OffsetReg = MIRBuilder.buildConstant(sXLen, Offset);
78
79 auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);
80
82 return AddrReg.getReg(0);
83 }
84
85 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
86 const MachinePointerInfo &MPO,
87 const CCValAssign &VA) override {
88 MachineFunction &MF = MIRBuilder.getMF();
89 uint64_t LocMemOffset = VA.getLocMemOffset();
90
91 // TODO: Move StackAlignment to subtarget and share with FrameLowering.
92 auto MMO =
94 commonAlignment(Align(16), LocMemOffset));
95
96 Register ExtReg = extendRegister(ValVReg, VA);
97 MIRBuilder.buildStore(ExtReg, Addr, *MMO);
98 }
99
100 void assignValueToReg(Register ValVReg, Register PhysReg,
101 const CCValAssign &VA) override {
102 // If we're passing an f32 value into an i64, anyextend before copying.
103 if (VA.getLocVT() == MVT::i64 && VA.getValVT() == MVT::f32)
104 ValVReg = MIRBuilder.buildAnyExt(LLT::scalar(64), ValVReg).getReg(0);
105
106 Register ExtReg = extendRegister(ValVReg, VA);
107 MIRBuilder.buildCopy(PhysReg, ExtReg);
108 MIB.addUse(PhysReg, RegState::Implicit);
109 }
110
113 std::function<void()> *Thunk) override {
114 assert(VAs.size() >= 2 && "Expected at least 2 VAs.");
115 const CCValAssign &VALo = VAs[0];
116 const CCValAssign &VAHi = VAs[1];
117
118 assert(VAHi.needsCustom() && "Value doesn't need custom handling");
119 assert(VALo.getValNo() == VAHi.getValNo() &&
120 "Values belong to different arguments");
121
122 assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
123 VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
124 "unexpected custom value");
125
126 Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
127 MRI.createGenericVirtualRegister(LLT::scalar(32))};
128 MIRBuilder.buildUnmerge(NewRegs, Arg.Regs[0]);
129
130 if (VAHi.isMemLoc()) {
131 LLT MemTy(VAHi.getLocVT());
132
134 Register StackAddr = getStackAddress(
135 MemTy.getSizeInBytes(), VAHi.getLocMemOffset(), MPO, Arg.Flags[0]);
136
137 assignValueToAddress(NewRegs[1], StackAddr, MemTy, MPO,
138 const_cast<CCValAssign &>(VAHi));
139 }
140
141 auto assignFunc = [=]() {
142 assignValueToReg(NewRegs[0], VALo.getLocReg(), VALo);
143 if (VAHi.isRegLoc())
144 assignValueToReg(NewRegs[1], VAHi.getLocReg(), VAHi);
145 };
146
147 if (Thunk) {
148 *Thunk = assignFunc;
149 return 1;
150 }
151
152 assignFunc();
153 return 1;
154 }
155
156private:
158
159 // Cache the SP register vreg if we need it more than once in this call site.
160 Register SPReg;
161
162 const RISCVSubtarget &Subtarget;
163};
164
165struct RISCVIncomingValueAssigner : public CallLowering::IncomingValueAssigner {
166private:
167 // The function used internally to assign args - we ignore the AssignFn stored
168 // by IncomingValueAssigner since RISC-V implements its CC using a custom
169 // function with a different signature.
171
172 // Whether this is assigning args from a return.
173 bool IsRet;
174
175public:
176 RISCVIncomingValueAssigner(
177 RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet)
178 : CallLowering::IncomingValueAssigner(nullptr),
179 RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {}
180
181 bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
182 CCValAssign::LocInfo LocInfo,
183 const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
184 CCState &State) override {
186 const DataLayout &DL = MF.getDataLayout();
187 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
188
189 if (LocVT.isScalableVector())
191
192 if (RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,
193 LocInfo, Flags, State, /*IsFixed=*/true, IsRet, Info.Ty,
194 *Subtarget.getTargetLowering(),
195 /*FirstMaskArgument=*/std::nullopt))
196 return true;
197
198 StackSize = State.getStackSize();
199 return false;
200 }
201};
202
203struct RISCVIncomingValueHandler : public CallLowering::IncomingValueHandler {
204 RISCVIncomingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)
205 : IncomingValueHandler(B, MRI),
206 Subtarget(MIRBuilder.getMF().getSubtarget<RISCVSubtarget>()) {}
207
208 Register getStackAddress(uint64_t MemSize, int64_t Offset,
210 ISD::ArgFlagsTy Flags) override {
211 MachineFrameInfo &MFI = MIRBuilder.getMF().getFrameInfo();
212
213 int FI = MFI.CreateFixedObject(MemSize, Offset, /*Immutable=*/true);
214 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
215 return MIRBuilder.buildFrameIndex(LLT::pointer(0, Subtarget.getXLen()), FI)
216 .getReg(0);
217 }
218
219 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
220 const MachinePointerInfo &MPO,
221 const CCValAssign &VA) override {
222 MachineFunction &MF = MIRBuilder.getMF();
223 auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,
224 inferAlignFromPtrInfo(MF, MPO));
225 MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
226 }
227
228 void assignValueToReg(Register ValVReg, Register PhysReg,
229 const CCValAssign &VA) override {
230 markPhysRegUsed(PhysReg);
231 IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
232 }
233
236 std::function<void()> *Thunk) override {
237 assert(VAs.size() >= 2 && "Expected at least 2 VAs.");
238 const CCValAssign &VALo = VAs[0];
239 const CCValAssign &VAHi = VAs[1];
240
241 assert(VAHi.needsCustom() && "Value doesn't need custom handling");
242 assert(VALo.getValNo() == VAHi.getValNo() &&
243 "Values belong to different arguments");
244
245 assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&
246 VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&
247 "unexpected custom value");
248
249 Register NewRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
250 MRI.createGenericVirtualRegister(LLT::scalar(32))};
251
252 if (VAHi.isMemLoc()) {
253 LLT MemTy(VAHi.getLocVT());
254
256 Register StackAddr = getStackAddress(
257 MemTy.getSizeInBytes(), VAHi.getLocMemOffset(), MPO, Arg.Flags[0]);
258
259 assignValueToAddress(NewRegs[1], StackAddr, MemTy, MPO,
260 const_cast<CCValAssign &>(VAHi));
261 }
262
263 assignValueToReg(NewRegs[0], VALo.getLocReg(), VALo);
264 if (VAHi.isRegLoc())
265 assignValueToReg(NewRegs[1], VAHi.getLocReg(), VAHi);
266
267 MIRBuilder.buildMergeLikeInstr(Arg.Regs[0], NewRegs);
268
269 return 1;
270 }
271
272 /// How the physical register gets marked varies between formal
273 /// parameters (it's a basic-block live-in), and a call instruction
274 /// (it's an implicit-def of the BL).
275 virtual void markPhysRegUsed(MCRegister PhysReg) = 0;
276
277private:
278 const RISCVSubtarget &Subtarget;
279};
280
281struct RISCVFormalArgHandler : public RISCVIncomingValueHandler {
282 RISCVFormalArgHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)
283 : RISCVIncomingValueHandler(B, MRI) {}
284
285 void markPhysRegUsed(MCRegister PhysReg) override {
286 MIRBuilder.getMRI()->addLiveIn(PhysReg);
287 MIRBuilder.getMBB().addLiveIn(PhysReg);
288 }
289};
290
291struct RISCVCallReturnHandler : public RISCVIncomingValueHandler {
292 RISCVCallReturnHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,
294 : RISCVIncomingValueHandler(B, MRI), MIB(MIB) {}
295
296 void markPhysRegUsed(MCRegister PhysReg) override {
297 MIB.addDef(PhysReg, RegState::Implicit);
298 }
299
301};
302
303} // namespace
304
306 : CallLowering(&TLI) {}
307
308/// Return true if scalable vector with ScalarTy is legal for lowering.
310 const RISCVSubtarget &Subtarget) {
311 if (EltTy->isPointerTy())
312 return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() : true;
313 if (EltTy->isIntegerTy(1) || EltTy->isIntegerTy(8) ||
314 EltTy->isIntegerTy(16) || EltTy->isIntegerTy(32))
315 return true;
316 if (EltTy->isIntegerTy(64))
317 return Subtarget.hasVInstructionsI64();
318 if (EltTy->isHalfTy())
319 return Subtarget.hasVInstructionsF16();
320 if (EltTy->isBFloatTy())
321 return Subtarget.hasVInstructionsBF16();
322 if (EltTy->isFloatTy())
323 return Subtarget.hasVInstructionsF32();
324 if (EltTy->isDoubleTy())
325 return Subtarget.hasVInstructionsF64();
326 return false;
327}
328
329// TODO: Support all argument types.
330// TODO: Remove IsLowerArgs argument by adding support for vectors in lowerCall.
331static bool isSupportedArgumentType(Type *T, const RISCVSubtarget &Subtarget,
332 bool IsLowerArgs = false) {
333 // TODO: Integers larger than 2*XLen are passed indirectly which is not
334 // supported yet.
335 if (T->isIntegerTy())
336 return T->getIntegerBitWidth() <= Subtarget.getXLen() * 2;
337 if (T->isFloatTy() || T->isDoubleTy())
338 return true;
339 if (T->isPointerTy())
340 return true;
341 // TODO: Support fixed vector types.
342 if (IsLowerArgs && T->isVectorTy() && Subtarget.hasVInstructions() &&
343 T->isScalableTy() &&
344 isLegalElementTypeForRVV(T->getScalarType(), Subtarget))
345 return true;
346 return false;
347}
348
349// TODO: Only integer, pointer and aggregate types are supported now.
350// TODO: Remove IsLowerRetVal argument by adding support for vectors in
351// lowerCall.
352static bool isSupportedReturnType(Type *T, const RISCVSubtarget &Subtarget,
353 bool IsLowerRetVal = false) {
354 // TODO: Integers larger than 2*XLen are passed indirectly which is not
355 // supported yet.
356 if (T->isIntegerTy())
357 return T->getIntegerBitWidth() <= Subtarget.getXLen() * 2;
358 if (T->isFloatTy() || T->isDoubleTy())
359 return true;
360 if (T->isPointerTy())
361 return true;
362
363 if (T->isArrayTy())
364 return isSupportedReturnType(T->getArrayElementType(), Subtarget);
365
366 if (T->isStructTy()) {
367 auto StructT = cast<StructType>(T);
368 for (unsigned i = 0, e = StructT->getNumElements(); i != e; ++i)
369 if (!isSupportedReturnType(StructT->getElementType(i), Subtarget))
370 return false;
371 return true;
372 }
373
374 if (IsLowerRetVal && T->isVectorTy() && Subtarget.hasVInstructions() &&
375 T->isScalableTy() &&
376 isLegalElementTypeForRVV(T->getScalarType(), Subtarget))
377 return true;
378
379 return false;
380}
381
382bool RISCVCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
383 const Value *Val,
384 ArrayRef<Register> VRegs,
385 MachineInstrBuilder &Ret) const {
386 if (!Val)
387 return true;
388
389 const RISCVSubtarget &Subtarget =
390 MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();
391 if (!isSupportedReturnType(Val->getType(), Subtarget, /*IsLowerRetVal=*/true))
392 return false;
393
394 MachineFunction &MF = MIRBuilder.getMF();
395 const DataLayout &DL = MF.getDataLayout();
396 const Function &F = MF.getFunction();
397 CallingConv::ID CC = F.getCallingConv();
398
399 ArgInfo OrigRetInfo(VRegs, Val->getType(), 0);
401
402 SmallVector<ArgInfo, 4> SplitRetInfos;
403 splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, CC);
404
405 RISCVOutgoingValueAssigner Assigner(
407 /*IsRet=*/true);
408 RISCVOutgoingValueHandler Handler(MIRBuilder, MF.getRegInfo(), Ret);
409 return determineAndHandleAssignments(Handler, Assigner, SplitRetInfos,
410 MIRBuilder, CC, F.isVarArg());
411}
412
414 const Value *Val, ArrayRef<Register> VRegs,
415 FunctionLoweringInfo &FLI) const {
416 assert(!Val == VRegs.empty() && "Return value without a vreg");
417 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(RISCV::PseudoRET);
418
419 if (!lowerReturnVal(MIRBuilder, Val, VRegs, Ret))
420 return false;
421
422 MIRBuilder.insertInstr(Ret);
423 return true;
424}
425
427 const Function &F,
429 FunctionLoweringInfo &FLI) const {
430 // Early exit if there are no arguments.
431 if (F.arg_empty())
432 return true;
433
434 // TODO: Support vararg functions.
435 if (F.isVarArg())
436 return false;
437
438 const RISCVSubtarget &Subtarget =
439 MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();
440 for (auto &Arg : F.args()) {
441 if (!isSupportedArgumentType(Arg.getType(), Subtarget,
442 /*IsLowerArgs=*/true))
443 return false;
444 }
445
446 MachineFunction &MF = MIRBuilder.getMF();
447 const DataLayout &DL = MF.getDataLayout();
448 CallingConv::ID CC = F.getCallingConv();
449
450 SmallVector<ArgInfo, 32> SplitArgInfos;
451 unsigned Index = 0;
452 for (auto &Arg : F.args()) {
453 // Construct the ArgInfo object from destination register and argument type.
454 ArgInfo AInfo(VRegs[Index], Arg.getType(), Index);
456
457 // Handle any required merging from split value types from physical
458 // registers into the desired VReg. ArgInfo objects are constructed
459 // correspondingly and appended to SplitArgInfos.
460 splitToValueTypes(AInfo, SplitArgInfos, DL, CC);
461
462 ++Index;
463 }
464
465 RISCVIncomingValueAssigner Assigner(
467 /*IsRet=*/false);
468 RISCVFormalArgHandler Handler(MIRBuilder, MF.getRegInfo());
469
470 return determineAndHandleAssignments(Handler, Assigner, SplitArgInfos,
471 MIRBuilder, CC, F.isVarArg());
472}
473
475 CallLoweringInfo &Info) const {
476 MachineFunction &MF = MIRBuilder.getMF();
477 const DataLayout &DL = MF.getDataLayout();
478 const Function &F = MF.getFunction();
479 CallingConv::ID CC = F.getCallingConv();
480
481 const RISCVSubtarget &Subtarget =
482 MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();
483 for (auto &AInfo : Info.OrigArgs) {
484 if (!isSupportedArgumentType(AInfo.Ty, Subtarget))
485 return false;
486 }
487
488 if (!Info.OrigRet.Ty->isVoidTy() &&
489 !isSupportedReturnType(Info.OrigRet.Ty, Subtarget))
490 return false;
491
492 MachineInstrBuilder CallSeqStart =
493 MIRBuilder.buildInstr(RISCV::ADJCALLSTACKDOWN);
494
495 SmallVector<ArgInfo, 32> SplitArgInfos;
497 for (auto &AInfo : Info.OrigArgs) {
498 // Handle any required unmerging of split value types from a given VReg into
499 // physical registers. ArgInfo objects are constructed correspondingly and
500 // appended to SplitArgInfos.
501 splitToValueTypes(AInfo, SplitArgInfos, DL, CC);
502 }
503
504 // TODO: Support tail calls.
505 Info.IsTailCall = false;
506
507 // Select the recommended relocation type R_RISCV_CALL_PLT.
508 if (!Info.Callee.isReg())
509 Info.Callee.setTargetFlags(RISCVII::MO_PLT);
510
512 MIRBuilder
513 .buildInstrNoInsert(Info.Callee.isReg() ? RISCV::PseudoCALLIndirect
514 : RISCV::PseudoCALL)
515 .add(Info.Callee);
516 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
517 Call.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
518
519 RISCVOutgoingValueAssigner ArgAssigner(
521 /*IsRet=*/false);
522 RISCVOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), Call);
523 if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgInfos,
524 MIRBuilder, CC, Info.IsVarArg))
525 return false;
526
527 MIRBuilder.insertInstr(Call);
528
529 CallSeqStart.addImm(ArgAssigner.StackSize).addImm(0);
530 MIRBuilder.buildInstr(RISCV::ADJCALLSTACKUP)
531 .addImm(ArgAssigner.StackSize)
532 .addImm(0);
533
534 // If Callee is a reg, since it is used by a target specific
535 // instruction, it must have a register class matching the
536 // constraint of that instruction.
537 if (Call->getOperand(0).isReg())
539 *Subtarget.getInstrInfo(),
540 *Subtarget.getRegBankInfo(), *Call,
541 Call->getDesc(), Call->getOperand(0), 0);
542
543 if (Info.OrigRet.Ty->isVoidTy())
544 return true;
545
546 SmallVector<ArgInfo, 4> SplitRetInfos;
547 splitToValueTypes(Info.OrigRet, SplitRetInfos, DL, CC);
548
549 RISCVIncomingValueAssigner RetAssigner(
551 /*IsRet=*/true);
552 RISCVCallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Call);
553 if (!determineAndHandleAssignments(RetHandler, RetAssigner, SplitRetInfos,
554 MIRBuilder, CC, Info.IsVarArg))
555 return false;
556
557 return true;
558}
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
uint64_t Addr
#define F(x, y, z)
Definition: MD5.cpp:55
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
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
bool needsCustom() const
bool isMemLoc() const
int64_t getLocMemOffset() const
unsigned getValNo() const
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.
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:110
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:49
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
Definition: LowLevelType.h:193
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.
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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, 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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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 buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildInstrNoInsert(unsigned Opcode)
Build but don't insert <empty> = Opcode <empty>.
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
const RegisterBankInfo * getRegBankInfo() const override
bool hasVInstructionsI64() const
bool hasVInstructionsF64() const
unsigned getXLen() const
bool hasVInstructionsF16() const
bool hasVInstructionsBF16() const
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, std::optional< unsigned > FirstMaskArgument)
RISCVCCAssignFn - This target-specific function extends the default CCValAssign with additional infor...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
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:255
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition: Type.h:154
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition: Type.h:146
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
Definition: Type.h:143
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition: Type.h:157
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:228
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, std::optional< unsigned > FirstMaskArgument)
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, std::optional< unsigned > FirstMaskArgument)
@ 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:440
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:53
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:716
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
Helper struct shared between Function Specialization and SCCP Solver.
Definition: SCCPSolver.h:41
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:320
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:336
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:188
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:297
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:34
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.