LLVM 20.0.0git
ARCISelLowering.cpp
Go to the documentation of this file.
1//===- ARCISelLowering.cpp - ARC DAG Lowering Impl --------------*- 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// This file implements the ARCTargetLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "ARCISelLowering.h"
14#include "ARC.h"
16#include "ARCSubtarget.h"
17#include "ARCTargetMachine.h"
26#include "llvm/IR/CallingConv.h"
27#include "llvm/IR/Intrinsics.h"
28#include "llvm/Support/Debug.h"
29#include <algorithm>
30
31#define DEBUG_TYPE "arc-lower"
32
33using namespace llvm;
34
35static SDValue lowerCallResult(SDValue Chain, SDValue InGlue,
36 const SmallVectorImpl<CCValAssign> &RVLocs,
37 SDLoc dl, SelectionDAG &DAG,
39
41 switch (isdCC) {
42 case ISD::SETUEQ:
43 return ARCCC::EQ;
44 case ISD::SETUGT:
45 return ARCCC::HI;
46 case ISD::SETUGE:
47 return ARCCC::HS;
48 case ISD::SETULT:
49 return ARCCC::LO;
50 case ISD::SETULE:
51 return ARCCC::LS;
52 case ISD::SETUNE:
53 return ARCCC::NE;
54 case ISD::SETEQ:
55 return ARCCC::EQ;
56 case ISD::SETGT:
57 return ARCCC::GT;
58 case ISD::SETGE:
59 return ARCCC::GE;
60 case ISD::SETLT:
61 return ARCCC::LT;
62 case ISD::SETLE:
63 return ARCCC::LE;
64 case ISD::SETNE:
65 return ARCCC::NE;
66 default:
67 llvm_unreachable("Unhandled ISDCC code.");
68 }
69}
70
71void ARCTargetLowering::ReplaceNodeResults(SDNode *N,
73 SelectionDAG &DAG) const {
74 LLVM_DEBUG(dbgs() << "[ARC-ISEL] ReplaceNodeResults ");
75 LLVM_DEBUG(N->dump(&DAG));
76 LLVM_DEBUG(dbgs() << "; use_count=" << N->use_size() << "\n");
77
78 switch (N->getOpcode()) {
80 if (N->getValueType(0) == MVT::i64) {
81 // We read the TIMER0 and zero-extend it to 64-bits as the intrinsic
82 // requires.
83 SDValue V =
85 DAG.getVTList(MVT::i32, MVT::Other), N->getOperand(0));
86 SDValue Op = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), MVT::i64, V);
87 Results.push_back(Op);
88 Results.push_back(V.getValue(1));
89 }
90 break;
91 default:
92 break;
93 }
94}
95
97 const ARCSubtarget &Subtarget)
98 : TargetLowering(TM), Subtarget(Subtarget) {
99 // Set up the register classes.
100 addRegisterClass(MVT::i32, &ARC::GPR32RegClass);
101
102 // Compute derived properties from the register classes
104
106
108
109 // Use i32 for setcc operations results (slt, sgt, ...).
112
113 for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
114 setOperationAction(Opc, MVT::i32, Expand);
115
116 // Operations to get us off of the ground.
117 // Basic.
123
128
129 // Need barrel shifter.
134
137
138 // Need multiplier
144
150
151 // Have pseudo instruction for frame addresses.
153 // Custom lower global addresses.
155
156 // Expand var-args ops.
161
162 // Other expansions
165
166 // Sign extend inreg
168
169 // TODO: Predicate these with `options.hasBitScan() ? Legal : Expand`
170 // when the HasBitScan predicate is available.
173
176 isTypeLegal(MVT::i64) ? Legal : Custom);
177
179}
180
181const char *ARCTargetLowering::getTargetNodeName(unsigned Opcode) const {
182 switch (Opcode) {
183 case ARCISD::BL:
184 return "ARCISD::BL";
185 case ARCISD::CMOV:
186 return "ARCISD::CMOV";
187 case ARCISD::CMP:
188 return "ARCISD::CMP";
189 case ARCISD::BRcc:
190 return "ARCISD::BRcc";
191 case ARCISD::RET:
192 return "ARCISD::RET";
194 return "ARCISD::GAWRAPPER";
195 }
196 return nullptr;
197}
198
199//===----------------------------------------------------------------------===//
200// Misc Lower Operation implementation
201//===----------------------------------------------------------------------===//
202
203SDValue ARCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
204 SDValue LHS = Op.getOperand(0);
205 SDValue RHS = Op.getOperand(1);
206 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
207 SDValue TVal = Op.getOperand(2);
208 SDValue FVal = Op.getOperand(3);
209 SDLoc dl(Op);
211 assert(LHS.getValueType() == MVT::i32 && "Only know how to SELECT_CC i32");
212 SDValue Cmp = DAG.getNode(ARCISD::CMP, dl, MVT::Glue, LHS, RHS);
213 return DAG.getNode(ARCISD::CMOV, dl, TVal.getValueType(), TVal, FVal,
214 DAG.getConstant(ArcCC, dl, MVT::i32), Cmp);
215}
216
217SDValue ARCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
218 SelectionDAG &DAG) const {
219 SDValue Op0 = Op.getOperand(0);
220 SDLoc dl(Op);
221 assert(Op.getValueType() == MVT::i32 &&
222 "Unhandled target sign_extend_inreg.");
223 // These are legal
224 unsigned Width = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits();
225 if (Width == 16 || Width == 8)
226 return Op;
227 if (Width >= 32) {
228 return {};
229 }
230 SDValue LS = DAG.getNode(ISD::SHL, dl, MVT::i32, Op0,
231 DAG.getConstant(32 - Width, dl, MVT::i32));
232 SDValue SR = DAG.getNode(ISD::SRA, dl, MVT::i32, LS,
233 DAG.getConstant(32 - Width, dl, MVT::i32));
234 return SR;
235}
236
237SDValue ARCTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
238 SDValue Chain = Op.getOperand(0);
239 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
240 SDValue LHS = Op.getOperand(2);
241 SDValue RHS = Op.getOperand(3);
242 SDValue Dest = Op.getOperand(4);
243 SDLoc dl(Op);
245 assert(LHS.getValueType() == MVT::i32 && "Only know how to BR_CC i32");
246 return DAG.getNode(ARCISD::BRcc, dl, MVT::Other, Chain, Dest, LHS, RHS,
247 DAG.getConstant(arcCC, dl, MVT::i32));
248}
249
250SDValue ARCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
251 auto *N = cast<JumpTableSDNode>(Op);
252 SDValue GA = DAG.getTargetJumpTable(N->getIndex(), MVT::i32);
253 return DAG.getNode(ARCISD::GAWRAPPER, SDLoc(N), MVT::i32, GA);
254}
255
256#include "ARCGenCallingConv.inc"
257
258//===----------------------------------------------------------------------===//
259// Call Calling Convention Implementation
260//===----------------------------------------------------------------------===//
261
262/// ARC call implementation
263SDValue ARCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
264 SmallVectorImpl<SDValue> &InVals) const {
265 SelectionDAG &DAG = CLI.DAG;
266 SDLoc &dl = CLI.DL;
268 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
270 SDValue Chain = CLI.Chain;
271 SDValue Callee = CLI.Callee;
272 CallingConv::ID CallConv = CLI.CallConv;
273 bool IsVarArg = CLI.IsVarArg;
274 bool &IsTailCall = CLI.IsTailCall;
275
276 IsTailCall = false; // Do not support tail calls yet.
277
279 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
280 *DAG.getContext());
281
282 CCInfo.AnalyzeCallOperands(Outs, CC_ARC);
283
285 // Analyze return values to determine the number of bytes of stack required.
286 CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
287 *DAG.getContext());
288 RetCCInfo.AllocateStack(CCInfo.getStackSize(), Align(4));
289 RetCCInfo.AnalyzeCallResult(Ins, RetCC_ARC);
290
291 // Get a count of how many bytes are to be pushed on the stack.
292 unsigned NumBytes = RetCCInfo.getStackSize();
293
294 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
295
297 SmallVector<SDValue, 12> MemOpChains;
298
300 // Walk the register/memloc assignments, inserting copies/loads.
301 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
302 CCValAssign &VA = ArgLocs[i];
303 SDValue Arg = OutVals[i];
304
305 // Promote the value if needed.
306 switch (VA.getLocInfo()) {
307 default:
308 llvm_unreachable("Unknown loc info!");
310 break;
312 Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
313 break;
315 Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
316 break;
318 Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
319 break;
320 }
321
322 // Arguments that can be passed on register must be kept at
323 // RegsToPass vector
324 if (VA.isRegLoc()) {
325 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
326 } else {
327 assert(VA.isMemLoc() && "Must be register or memory argument.");
328 if (!StackPtr.getNode())
329 StackPtr = DAG.getCopyFromReg(Chain, dl, ARC::SP,
331 // Calculate the stack position.
332 SDValue SOffset = DAG.getIntPtrConstant(VA.getLocMemOffset(), dl);
333 SDValue PtrOff = DAG.getNode(
334 ISD::ADD, dl, getPointerTy(DAG.getDataLayout()), StackPtr, SOffset);
335
336 SDValue Store =
337 DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
338 MemOpChains.push_back(Store);
339 IsTailCall = false;
340 }
341 }
342
343 // Transform all store nodes into one single node because
344 // all store nodes are independent of each other.
345 if (!MemOpChains.empty())
346 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
347
348 // Build a sequence of copy-to-reg nodes chained together with token
349 // chain and flag operands which copy the outgoing args into registers.
350 // The Glue in necessary since all emitted instructions must be
351 // stuck together.
352 SDValue Glue;
353 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
354 Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
355 RegsToPass[i].second, Glue);
356 Glue = Chain.getValue(1);
357 }
358
359 // If the callee is a GlobalAddress node (quite common, every direct call is)
360 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
361 // Likewise ExternalSymbol -> TargetExternalSymbol.
362 bool IsDirect = true;
363 if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
364 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
365 else if (auto *E = dyn_cast<ExternalSymbolSDNode>(Callee))
366 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
367 else
368 IsDirect = false;
369 // Branch + Link = #chain, #target_address, #opt_in_flags...
370 // = Chain, Callee, Reg#1, Reg#2, ...
371 //
372 // Returns a chain & a glue for retval copy to use.
373 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
375 Ops.push_back(Chain);
376 Ops.push_back(Callee);
377
378 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
379 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
380 RegsToPass[i].second.getValueType()));
381
382 // Add a register mask operand representing the call-preserved registers.
383 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
384 const uint32_t *Mask =
385 TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
386 assert(Mask && "Missing call preserved mask for calling convention");
387 Ops.push_back(DAG.getRegisterMask(Mask));
388
389 if (Glue.getNode())
390 Ops.push_back(Glue);
391
392 Chain = DAG.getNode(IsDirect ? ARCISD::BL : ARCISD::JL, dl, NodeTys, Ops);
393 Glue = Chain.getValue(1);
394
395 // Create the CALLSEQ_END node.
396 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, dl);
397 Glue = Chain.getValue(1);
398
399 // Handle result values, copying them out of physregs into vregs that we
400 // return.
401 if (IsTailCall)
402 return Chain;
403 return lowerCallResult(Chain, Glue, RVLocs, dl, DAG, InVals);
404}
405
406/// Lower the result values of a call into the appropriate copies out of
407/// physical registers / memory locations.
409 const SmallVectorImpl<CCValAssign> &RVLocs,
410 SDLoc dl, SelectionDAG &DAG,
411 SmallVectorImpl<SDValue> &InVals) {
412 SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs;
413 // Copy results out of physical registers.
414 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
415 const CCValAssign &VA = RVLocs[i];
416 if (VA.isRegLoc()) {
417 SDValue RetValue;
418 RetValue =
419 DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), Glue);
420 Chain = RetValue.getValue(1);
421 Glue = RetValue.getValue(2);
422 InVals.push_back(RetValue);
423 } else {
424 assert(VA.isMemLoc() && "Must be memory location.");
425 ResultMemLocs.push_back(
426 std::make_pair(VA.getLocMemOffset(), InVals.size()));
427
428 // Reserve space for this result.
429 InVals.push_back(SDValue());
430 }
431 }
432
433 // Copy results out of memory.
434 SmallVector<SDValue, 4> MemOpChains;
435 for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) {
436 int Offset = ResultMemLocs[i].first;
437 unsigned Index = ResultMemLocs[i].second;
438 SDValue StackPtr = DAG.getRegister(ARC::SP, MVT::i32);
439 SDValue SpLoc = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr,
440 DAG.getConstant(Offset, dl, MVT::i32));
441 SDValue Load =
442 DAG.getLoad(MVT::i32, dl, Chain, SpLoc, MachinePointerInfo());
443 InVals[Index] = Load;
444 MemOpChains.push_back(Load.getValue(1));
445 }
446
447 // Transform all loads nodes into one single node because
448 // all load nodes are independent of each other.
449 if (!MemOpChains.empty())
450 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
451
452 return Chain;
453}
454
455//===----------------------------------------------------------------------===//
456// Formal Arguments Calling Convention Implementation
457//===----------------------------------------------------------------------===//
458
459namespace {
460
461struct ArgDataPair {
462 SDValue SDV;
464};
465
466} // end anonymous namespace
467
468/// ARC formal arguments implementation
469SDValue ARCTargetLowering::LowerFormalArguments(
470 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
471 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
472 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
473 switch (CallConv) {
474 default:
475 llvm_unreachable("Unsupported calling convention");
476 case CallingConv::C:
478 return LowerCallArguments(Chain, CallConv, IsVarArg, Ins, dl, DAG, InVals);
479 }
480}
481
482/// Transform physical registers into virtual registers, and generate load
483/// operations for argument places on the stack.
484SDValue ARCTargetLowering::LowerCallArguments(
485 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
487 SmallVectorImpl<SDValue> &InVals) const {
489 MachineFrameInfo &MFI = MF.getFrameInfo();
491 auto *AFI = MF.getInfo<ARCFunctionInfo>();
492
493 // Assign locations to all of the incoming arguments.
495 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
496 *DAG.getContext());
497
498 CCInfo.AnalyzeFormalArguments(Ins, CC_ARC);
499
500 unsigned StackSlotSize = 4;
501
502 if (!IsVarArg)
503 AFI->setReturnStackOffset(CCInfo.getStackSize());
504
505 // All getCopyFromReg ops must precede any getMemcpys to prevent the
506 // scheduler clobbering a register before it has been copied.
507 // The stages are:
508 // 1. CopyFromReg (and load) arg & vararg registers.
509 // 2. Chain CopyFromReg nodes into a TokenFactor.
510 // 3. Memcpy 'byVal' args & push final InVals.
511 // 4. Chain mem ops nodes into a TokenFactor.
512 SmallVector<SDValue, 4> CFRegNode;
515
516 // 1a. CopyFromReg (and load) arg registers.
517 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
518 CCValAssign &VA = ArgLocs[i];
519 SDValue ArgIn;
520
521 if (VA.isRegLoc()) {
522 // Arguments passed in registers
523 EVT RegVT = VA.getLocVT();
524 switch (RegVT.getSimpleVT().SimpleTy) {
525 default: {
526 LLVM_DEBUG(errs() << "LowerFormalArguments Unhandled argument type: "
527 << (unsigned)RegVT.getSimpleVT().SimpleTy << "\n");
528 llvm_unreachable("Unhandled LowerFormalArguments type.");
529 }
530 case MVT::i32:
531 unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);
532 RegInfo.addLiveIn(VA.getLocReg(), VReg);
533 ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
534 CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1));
535 }
536 } else {
537 // Only arguments passed on the stack should make it here.
538 assert(VA.isMemLoc());
539 // Load the argument to a virtual register
540 unsigned ObjSize = VA.getLocVT().getStoreSize();
541 assert((ObjSize <= StackSlotSize) && "Unhandled argument");
542
543 // Create the frame index object for this incoming parameter...
544 int FI = MFI.CreateFixedObject(ObjSize, VA.getLocMemOffset(), true);
545
546 // Create the SelectionDAG nodes corresponding to a load
547 // from this parameter
548 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
549 ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
551 }
552 const ArgDataPair ADP = {ArgIn, Ins[i].Flags};
553 ArgData.push_back(ADP);
554 }
555
556 // 1b. CopyFromReg vararg registers.
557 if (IsVarArg) {
558 // Argument registers
559 static const MCPhysReg ArgRegs[] = {ARC::R0, ARC::R1, ARC::R2, ARC::R3,
560 ARC::R4, ARC::R5, ARC::R6, ARC::R7};
561 auto *AFI = MF.getInfo<ARCFunctionInfo>();
562 unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs);
563 if (FirstVAReg < std::size(ArgRegs)) {
564 int Offset = 0;
565 // Save remaining registers, storing higher register numbers at a higher
566 // address
567 // There are (std::size(ArgRegs) - FirstVAReg) registers which
568 // need to be saved.
569 int VarFI = MFI.CreateFixedObject((std::size(ArgRegs) - FirstVAReg) * 4,
570 CCInfo.getStackSize(), true);
571 AFI->setVarArgsFrameIndex(VarFI);
572 SDValue FIN = DAG.getFrameIndex(VarFI, MVT::i32);
573 for (unsigned i = FirstVAReg; i < std::size(ArgRegs); i++) {
574 // Move argument from phys reg -> virt reg
575 unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);
576 RegInfo.addLiveIn(ArgRegs[i], VReg);
577 SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
578 CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1));
579 SDValue VAObj = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN,
580 DAG.getConstant(Offset, dl, MVT::i32));
581 // Move argument from virt reg -> stack
582 SDValue Store =
583 DAG.getStore(Val.getValue(1), dl, Val, VAObj, MachinePointerInfo());
584 MemOps.push_back(Store);
585 Offset += 4;
586 }
587 } else {
588 llvm_unreachable("Too many var args parameters.");
589 }
590 }
591
592 // 2. Chain CopyFromReg nodes into a TokenFactor.
593 if (!CFRegNode.empty())
594 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode);
595
596 // 3. Memcpy 'byVal' args & push final InVals.
597 // Aggregates passed "byVal" need to be copied by the callee.
598 // The callee will use a pointer to this copy, rather than the original
599 // pointer.
600 for (const auto &ArgDI : ArgData) {
601 if (ArgDI.Flags.isByVal() && ArgDI.Flags.getByValSize()) {
602 unsigned Size = ArgDI.Flags.getByValSize();
603 Align Alignment =
604 std::max(Align(StackSlotSize), ArgDI.Flags.getNonZeroByValAlign());
605 // Create a new object on the stack and copy the pointee into it.
606 int FI = MFI.CreateStackObject(Size, Alignment, false);
607 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
608 InVals.push_back(FIN);
609 MemOps.push_back(DAG.getMemcpy(
610 Chain, dl, FIN, ArgDI.SDV, DAG.getConstant(Size, dl, MVT::i32),
611 Alignment, false, false, /*CI=*/nullptr, false, MachinePointerInfo(),
613 } else {
614 InVals.push_back(ArgDI.SDV);
615 }
616 }
617
618 // 4. Chain mem ops nodes into a TokenFactor.
619 if (!MemOps.empty()) {
620 MemOps.push_back(Chain);
621 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
622 }
623
624 return Chain;
625}
626
627//===----------------------------------------------------------------------===//
628// Return Value Calling Convention Implementation
629//===----------------------------------------------------------------------===//
630
631bool ARCTargetLowering::CanLowerReturn(
632 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
633 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
635 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
636 if (!CCInfo.CheckReturn(Outs, RetCC_ARC))
637 return false;
638 if (CCInfo.getStackSize() != 0 && IsVarArg)
639 return false;
640 return true;
641}
642
644ARCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
645 bool IsVarArg,
647 const SmallVectorImpl<SDValue> &OutVals,
648 const SDLoc &dl, SelectionDAG &DAG) const {
649 auto *AFI = DAG.getMachineFunction().getInfo<ARCFunctionInfo>();
651
652 // CCValAssign - represent the assignment of
653 // the return value to a location
655
656 // CCState - Info about the registers and stack slot.
657 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
658 *DAG.getContext());
659
660 // Analyze return values.
661 if (!IsVarArg)
662 CCInfo.AllocateStack(AFI->getReturnStackOffset(), Align(4));
663
664 CCInfo.AnalyzeReturn(Outs, RetCC_ARC);
665
666 SDValue Glue;
667 SmallVector<SDValue, 4> RetOps(1, Chain);
668 SmallVector<SDValue, 4> MemOpChains;
669 // Handle return values that must be copied to memory.
670 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
671 CCValAssign &VA = RVLocs[i];
672 if (VA.isRegLoc())
673 continue;
674 assert(VA.isMemLoc());
675 if (IsVarArg) {
676 report_fatal_error("Can't return value from vararg function in memory");
677 }
678
679 int Offset = VA.getLocMemOffset();
680 unsigned ObjSize = VA.getLocVT().getStoreSize();
681 // Create the frame index object for the memory location.
682 int FI = MFI.CreateFixedObject(ObjSize, Offset, false);
683
684 // Create a SelectionDAG node corresponding to a store
685 // to this memory location.
686 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
687 MemOpChains.push_back(DAG.getStore(
688 Chain, dl, OutVals[i], FIN,
690 }
691
692 // Transform all store nodes into one single node because
693 // all stores are independent of each other.
694 if (!MemOpChains.empty())
695 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
696
697 // Now handle return values copied to registers.
698 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
699 CCValAssign &VA = RVLocs[i];
700 if (!VA.isRegLoc())
701 continue;
702 // Copy the result values into the output registers.
703 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);
704
705 // guarantee that all emitted copies are
706 // stuck together, avoiding something bad
707 Glue = Chain.getValue(1);
708 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
709 }
710
711 RetOps[0] = Chain; // Update chain.
712
713 // Add the glue if we have it.
714 if (Glue.getNode())
715 RetOps.push_back(Glue);
716
717 // What to do with the RetOps?
718 return DAG.getNode(ARCISD::RET, dl, MVT::Other, RetOps);
719}
720
721//===----------------------------------------------------------------------===//
722// Target Optimization Hooks
723//===----------------------------------------------------------------------===//
724
725SDValue ARCTargetLowering::PerformDAGCombine(SDNode *N,
726 DAGCombinerInfo &DCI) const {
727 return {};
728}
729
730//===----------------------------------------------------------------------===//
731// Addressing mode description hooks
732//===----------------------------------------------------------------------===//
733
734/// Return true if the addressing mode represented by AM is legal for this
735/// target, for a load/store of the specified type.
737 const AddrMode &AM, Type *Ty,
738 unsigned AS,
739 Instruction *I) const {
740 return AM.Scale == 0;
741}
742
743// Don't emit tail calls for the time being.
744bool ARCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
745 return false;
746}
747
748SDValue ARCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
749 const ARCRegisterInfo &ARI = *Subtarget.getRegisterInfo();
751 MachineFrameInfo &MFI = MF.getFrameInfo();
752 MFI.setFrameAddressIsTaken(true);
753
754 EVT VT = Op.getValueType();
755 SDLoc dl(Op);
756 assert(Op.getConstantOperandVal(0) == 0 &&
757 "Only support lowering frame addr of current frame.");
758 Register FrameReg = ARI.getFrameRegister(MF);
759 return DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
760}
761
762SDValue ARCTargetLowering::LowerGlobalAddress(SDValue Op,
763 SelectionDAG &DAG) const {
764 const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
765 const GlobalValue *GV = GN->getGlobal();
766 SDLoc dl(GN);
767 int64_t Offset = GN->getOffset();
768 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, Offset);
769 return DAG.getNode(ARCISD::GAWRAPPER, dl, MVT::i32, GA);
770}
771
774 auto *FuncInfo = MF.getInfo<ARCFunctionInfo>();
775
776 // vastart just stores the address of the VarArgsFrameIndex slot into the
777 // memory location argument.
778 SDLoc dl(Op);
780 SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
781 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
782 return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1),
784}
785
787 switch (Op.getOpcode()) {
789 return LowerGlobalAddress(Op, DAG);
790 case ISD::FRAMEADDR:
791 return LowerFRAMEADDR(Op, DAG);
792 case ISD::SELECT_CC:
793 return LowerSELECT_CC(Op, DAG);
794 case ISD::BR_CC:
795 return LowerBR_CC(Op, DAG);
797 return LowerSIGN_EXTEND_INREG(Op, DAG);
798 case ISD::JumpTable:
799 return LowerJumpTable(Op, DAG);
800 case ISD::VASTART:
801 return LowerVASTART(Op, DAG);
803 // As of LLVM 3.8, the lowering code insists that we customize it even
804 // though we've declared the i32 version as legal. This is because it only
805 // thinks i64 is the truly supported version. We've already converted the
806 // i64 version to a widened i32.
807 assert(Op.getSimpleValueType() == MVT::i32);
808 return Op;
809 default:
810 llvm_unreachable("unimplemented operand");
811 }
812}
static ARCCC::CondCode ISDCCtoARCCC(ISD::CondCode isdCC)
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static SDValue lowerCallResult(SDValue Chain, SDValue InGlue, const SmallVectorImpl< CCValAssign > &RVLocs, SDLoc dl, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals)
Lower the result values of a call into the appropriate copies out of physical registers / memory loca...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Size
#define I(x, y, z)
Definition: MD5.cpp:58
#define G(x, y, z)
Definition: MD5.cpp:56
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Value * RHS
Value * LHS
ARCFunctionInfo - This class is derived from MachineFunction private ARC target-specific information ...
const ARCRegisterInfo * getRegisterInfo() const override
Definition: ARCSubtarget.h:58
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
Provide custom lowering hooks for some operations.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
ARCTargetLowering(const TargetMachine &TM, const ARCSubtarget &Subtarget)
const char * getTargetNodeName(unsigned Opcode) const override
This method returns the name of a target specific DAG node.
CCState - This class holds information needed while lowering arguments and return values.
CCValAssign - Represent assignment of one arg/retval to a location.
bool isRegLoc() const
Register getLocReg() const
LocInfo getLocInfo() const
bool isMemLoc() const
int64_t getLocMemOffset() const
This class represents a function call, abstracting a target machine's calling convention.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
const GlobalValue * getGlobal() const
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
SimpleValueType SimpleTy
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
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.
int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:226
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
Definition: SelectionDAG.h:736
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), AAResults *AA=nullptr)
SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
const TargetLowering & getTargetLoweringInfo() const
Definition: SelectionDAG.h:493
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
Definition: SelectionDAG.h:746
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
const DataLayout & getDataLayout() const
Definition: SelectionDAG.h:487
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
SDValue getRegister(unsigned Reg, EVT VT)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N)
Definition: SelectionDAG.h:787
SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
MachineFunction & getMachineFunction() const
Definition: SelectionDAG.h:482
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
Definition: SelectionDAG.h:813
SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
SDValue getRegisterMask(const uint32_t *RegMask)
LLVMContext * getContext() const
Definition: SelectionDAG.h:500
SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
Definition: SelectionDAG.h:570
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
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
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:77
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
LLVM Value Representation.
Definition: Value.h:74
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:121
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:41
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
Definition: ISDOpcodes.h:1194
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
Definition: ISDOpcodes.h:1190
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
Definition: ISDOpcodes.h:1223
@ ADDC
Carry-setting nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:276
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:246
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Definition: ISDOpcodes.h:1099
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition: ISDOpcodes.h:813
@ GlobalAddress
Definition: ISDOpcodes.h:78
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
Definition: ISDOpcodes.h:1480
@ SIGN_EXTEND
Conversion operators.
Definition: ISDOpcodes.h:804
@ BR_CC
BR_CC - Conditional branch.
Definition: ISDOpcodes.h:1145
@ BR_JT
BR_JT - Jumptable branch.
Definition: ISDOpcodes.h:1124
@ UNDEF
UNDEF - An undefined node.
Definition: ISDOpcodes.h:218
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
Definition: ISDOpcodes.h:1219
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:673
@ SHL
Shift and rotation operations.
Definition: ISDOpcodes.h:734
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition: ISDOpcodes.h:810
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition: ISDOpcodes.h:771
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition: ISDOpcodes.h:848
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition: ISDOpcodes.h:696
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
Definition: ISDOpcodes.h:100
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
Definition: ISDOpcodes.h:1250
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:708
@ ADDE
Carry-using nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:286
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition: ISDOpcodes.h:52
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
Definition: ISDOpcodes.h:1214
@ BRCOND
BRCOND - Conditional branch.
Definition: ISDOpcodes.h:1138
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
Definition: ISDOpcodes.h:1603
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
#define N
Register getFrameRegister(const MachineFunction &MF) const override
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
Extended Value Type.
Definition: ValueTypes.h:35
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition: ValueTypes.h:307
This class contains a discriminated union of information about pointers in memory operands,...
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals