LLVM 23.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 "ARCSelectionDAGInfo.h"
17#include "ARCSubtarget.h"
18#include "ARCTargetMachine.h"
27#include "llvm/IR/CallingConv.h"
28#include "llvm/IR/Intrinsics.h"
29#include "llvm/Support/Debug.h"
30#include <algorithm>
31
32#define DEBUG_TYPE "arc-lower"
33
34using namespace llvm;
35
36static SDValue lowerCallResult(SDValue Chain, SDValue InGlue,
37 const SmallVectorImpl<CCValAssign> &RVLocs,
38 SDLoc dl, SelectionDAG &DAG,
40
42 switch (isdCC) {
43 case ISD::SETUEQ:
44 return ARCCC::EQ;
45 case ISD::SETUGT:
46 return ARCCC::HI;
47 case ISD::SETUGE:
48 return ARCCC::HS;
49 case ISD::SETULT:
50 return ARCCC::LO;
51 case ISD::SETULE:
52 return ARCCC::LS;
53 case ISD::SETUNE:
54 return ARCCC::NE;
55 case ISD::SETEQ:
56 return ARCCC::EQ;
57 case ISD::SETGT:
58 return ARCCC::GT;
59 case ISD::SETGE:
60 return ARCCC::GE;
61 case ISD::SETLT:
62 return ARCCC::LT;
63 case ISD::SETLE:
64 return ARCCC::LE;
65 case ISD::SETNE:
66 return ARCCC::NE;
67 default:
68 llvm_unreachable("Unhandled ISDCC code.");
69 }
70}
71
72void ARCTargetLowering::ReplaceNodeResults(SDNode *N,
74 SelectionDAG &DAG) const {
75 LLVM_DEBUG(dbgs() << "[ARC-ISEL] ReplaceNodeResults ");
76 LLVM_DEBUG(N->dump(&DAG));
77 LLVM_DEBUG(dbgs() << "; use_count=" << N->use_size() << "\n");
78
79 switch (N->getOpcode()) {
81 if (N->getValueType(0) == MVT::i64) {
82 // We read the TIMER0 and zero-extend it to 64-bits as the intrinsic
83 // requires.
84 SDValue V =
86 DAG.getVTList(MVT::i32, MVT::Other), N->getOperand(0));
87 SDValue Op = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), MVT::i64, V);
88 Results.push_back(Op);
89 Results.push_back(V.getValue(1));
90 }
91 break;
92 default:
93 break;
94 }
95}
96
98 const ARCSubtarget &Subtarget)
99 : TargetLowering(TM, Subtarget), Subtarget(Subtarget) {
100 // Set up the register classes.
101 addRegisterClass(MVT::i32, &ARC::GPR32RegClass);
102
103 // Compute derived properties from the register classes
104 computeRegisterProperties(Subtarget.getRegisterInfo());
105
107
109
110 // Use i32 for setcc operations results (slt, sgt, ...).
113
114 for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
115 setOperationAction(Opc, MVT::i32, Expand);
116
117 // Operations to get us off of the ground.
118 // Basic.
124
129
130 // Need barrel shifter.
135
138
139 // Need multiplier
145
151
152 // Have pseudo instruction for frame addresses.
154 // Custom lower global addresses.
156
157 // Expand var-args ops.
162
163 // Other expansions
166
167 // Sign extend inreg
169
170 // TODO: Predicate these with `options.hasBitScan() ? Legal : Expand`
171 // when the HasBitScan predicate is available.
174
177 isTypeLegal(MVT::i64) ? Legal : Custom);
178
180}
181
182//===----------------------------------------------------------------------===//
183// Misc Lower Operation implementation
184//===----------------------------------------------------------------------===//
185
186SDValue ARCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
187 SDValue LHS = Op.getOperand(0);
188 SDValue RHS = Op.getOperand(1);
189 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
190 SDValue TVal = Op.getOperand(2);
191 SDValue FVal = Op.getOperand(3);
192 SDLoc dl(Op);
193 ARCCC::CondCode ArcCC = ISDCCtoARCCC(CC);
194 assert(LHS.getValueType() == MVT::i32 && "Only know how to SELECT_CC i32");
195 SDValue Cmp = DAG.getNode(ARCISD::CMP, dl, MVT::Glue, LHS, RHS);
196 return DAG.getNode(ARCISD::CMOV, dl, TVal.getValueType(), TVal, FVal,
197 DAG.getConstant(ArcCC, dl, MVT::i32), Cmp);
198}
199
200SDValue ARCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
201 SelectionDAG &DAG) const {
202 SDValue Op0 = Op.getOperand(0);
203 SDLoc dl(Op);
204 assert(Op.getValueType() == MVT::i32 &&
205 "Unhandled target sign_extend_inreg.");
206 // These are legal
207 unsigned Width = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits();
208 if (Width == 16 || Width == 8)
209 return Op;
210 if (Width >= 32) {
211 return {};
212 }
213 SDValue LS = DAG.getNode(ISD::SHL, dl, MVT::i32, Op0,
214 DAG.getConstant(32 - Width, dl, MVT::i32));
215 SDValue SR = DAG.getNode(ISD::SRA, dl, MVT::i32, LS,
216 DAG.getConstant(32 - Width, dl, MVT::i32));
217 return SR;
218}
219
220SDValue ARCTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
221 SDValue Chain = Op.getOperand(0);
222 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
223 SDValue LHS = Op.getOperand(2);
224 SDValue RHS = Op.getOperand(3);
225 SDValue Dest = Op.getOperand(4);
226 SDLoc dl(Op);
227 ARCCC::CondCode arcCC = ISDCCtoARCCC(CC);
228 assert(LHS.getValueType() == MVT::i32 && "Only know how to BR_CC i32");
229 return DAG.getNode(ARCISD::BRcc, dl, MVT::Other, Chain, Dest, LHS, RHS,
230 DAG.getConstant(arcCC, dl, MVT::i32));
231}
232
233SDValue ARCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
234 auto *N = cast<JumpTableSDNode>(Op);
235 SDValue GA = DAG.getTargetJumpTable(N->getIndex(), MVT::i32);
236 return DAG.getNode(ARCISD::GAWRAPPER, SDLoc(N), MVT::i32, GA);
237}
238
239#define GET_CALLING_CONV_IMPL
240#include "ARCGenCallingConv.inc"
241
242//===----------------------------------------------------------------------===//
243// Call Calling Convention Implementation
244//===----------------------------------------------------------------------===//
245
246/// ARC call implementation
247SDValue ARCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
248 SmallVectorImpl<SDValue> &InVals) const {
249 SelectionDAG &DAG = CLI.DAG;
250 SDLoc &dl = CLI.DL;
252 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
254 SDValue Chain = CLI.Chain;
255 SDValue Callee = CLI.Callee;
256 CallingConv::ID CallConv = CLI.CallConv;
257 bool IsVarArg = CLI.IsVarArg;
258 bool &IsTailCall = CLI.IsTailCall;
259
260 IsTailCall = false; // Do not support tail calls yet.
261
263 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
264 *DAG.getContext());
265
266 CCInfo.AnalyzeCallOperands(Outs, CC_ARC);
267
269 // Analyze return values to determine the number of bytes of stack required.
270 CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
271 *DAG.getContext());
272 RetCCInfo.AllocateStack(CCInfo.getStackSize(), Align(4));
273 RetCCInfo.AnalyzeCallResult(Ins, RetCC_ARC);
274
275 // Get a count of how many bytes are to be pushed on the stack.
276 unsigned NumBytes = RetCCInfo.getStackSize();
277
278 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
279
281 SmallVector<SDValue, 12> MemOpChains;
282
283 SDValue StackPtr;
284 // Walk the register/memloc assignments, inserting copies/loads.
285 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
286 CCValAssign &VA = ArgLocs[i];
287 SDValue Arg = OutVals[i];
288
289 // Promote the value if needed.
290 switch (VA.getLocInfo()) {
291 default:
292 llvm_unreachable("Unknown loc info!");
294 break;
296 Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
297 break;
299 Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
300 break;
302 Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
303 break;
304 }
305
306 // Arguments that can be passed on register must be kept at
307 // RegsToPass vector
308 if (VA.isRegLoc()) {
309 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
310 } else {
311 assert(VA.isMemLoc() && "Must be register or memory argument.");
312 if (!StackPtr.getNode())
313 StackPtr = DAG.getCopyFromReg(Chain, dl, ARC::SP,
315 // Calculate the stack position.
316 SDValue SOffset = DAG.getIntPtrConstant(VA.getLocMemOffset(), dl);
317 SDValue PtrOff = DAG.getNode(
318 ISD::ADD, dl, getPointerTy(DAG.getDataLayout()), StackPtr, SOffset);
319
320 SDValue Store =
321 DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
322 MemOpChains.push_back(Store);
323 IsTailCall = false;
324 }
325 }
326
327 // Transform all store nodes into one single node because
328 // all store nodes are independent of each other.
329 if (!MemOpChains.empty())
330 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
331
332 // Build a sequence of copy-to-reg nodes chained together with token
333 // chain and flag operands which copy the outgoing args into registers.
334 // The Glue in necessary since all emitted instructions must be
335 // stuck together.
336 SDValue Glue;
337 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
338 Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
339 RegsToPass[i].second, Glue);
340 Glue = Chain.getValue(1);
341 }
342
343 // If the callee is a GlobalAddress node (quite common, every direct call is)
344 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
345 // Likewise ExternalSymbol -> TargetExternalSymbol.
346 bool IsDirect = true;
347 if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
348 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
349 else if (auto *E = dyn_cast<ExternalSymbolSDNode>(Callee))
350 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
351 else
352 IsDirect = false;
353 // Branch + Link = #chain, #target_address, #opt_in_flags...
354 // = Chain, Callee, Reg#1, Reg#2, ...
355 //
356 // Returns a chain & a glue for retval copy to use.
357 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
359 Ops.push_back(Chain);
360 Ops.push_back(Callee);
361
362 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
363 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
364 RegsToPass[i].second.getValueType()));
365
366 // Add a register mask operand representing the call-preserved registers.
367 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
368 const uint32_t *Mask =
369 TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
370 assert(Mask && "Missing call preserved mask for calling convention");
371 Ops.push_back(DAG.getRegisterMask(Mask));
372
373 if (Glue.getNode())
374 Ops.push_back(Glue);
375
376 Chain = DAG.getNode(IsDirect ? ARCISD::BL : ARCISD::JL, dl, NodeTys, Ops);
377 Glue = Chain.getValue(1);
378
379 // Create the CALLSEQ_END node.
380 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, dl);
381 Glue = Chain.getValue(1);
382
383 // Handle result values, copying them out of physregs into vregs that we
384 // return.
385 if (IsTailCall)
386 return Chain;
387 return lowerCallResult(Chain, Glue, RVLocs, dl, DAG, InVals);
388}
389
390/// Lower the result values of a call into the appropriate copies out of
391/// physical registers / memory locations.
393 const SmallVectorImpl<CCValAssign> &RVLocs,
394 SDLoc dl, SelectionDAG &DAG,
395 SmallVectorImpl<SDValue> &InVals) {
396 SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs;
397 // Copy results out of physical registers.
398 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
399 const CCValAssign &VA = RVLocs[i];
400 if (VA.isRegLoc()) {
401 SDValue RetValue;
402 RetValue =
403 DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), Glue);
404 Chain = RetValue.getValue(1);
405 Glue = RetValue.getValue(2);
406 InVals.push_back(RetValue);
407 } else {
408 assert(VA.isMemLoc() && "Must be memory location.");
409 ResultMemLocs.push_back(
410 std::make_pair(VA.getLocMemOffset(), InVals.size()));
411
412 // Reserve space for this result.
413 InVals.push_back(SDValue());
414 }
415 }
416
417 // Copy results out of memory.
418 SmallVector<SDValue, 4> MemOpChains;
419 for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) {
420 int Offset = ResultMemLocs[i].first;
421 unsigned Index = ResultMemLocs[i].second;
422 SDValue StackPtr = DAG.getRegister(ARC::SP, MVT::i32);
423 SDValue SpLoc = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr,
424 DAG.getConstant(Offset, dl, MVT::i32));
425 SDValue Load =
426 DAG.getLoad(MVT::i32, dl, Chain, SpLoc, MachinePointerInfo());
427 InVals[Index] = Load;
428 MemOpChains.push_back(Load.getValue(1));
429 }
430
431 // Transform all loads nodes into one single node because
432 // all load nodes are independent of each other.
433 if (!MemOpChains.empty())
434 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
435
436 return Chain;
437}
438
439//===----------------------------------------------------------------------===//
440// Formal Arguments Calling Convention Implementation
441//===----------------------------------------------------------------------===//
442
443namespace {
444
445struct ArgDataPair {
446 SDValue SDV;
447 ISD::ArgFlagsTy Flags;
448};
449
450} // end anonymous namespace
451
452/// ARC formal arguments implementation
453SDValue ARCTargetLowering::LowerFormalArguments(
454 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
455 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
456 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
457 switch (CallConv) {
458 default:
459 llvm_unreachable("Unsupported calling convention");
460 case CallingConv::C:
462 return LowerCallArguments(Chain, CallConv, IsVarArg, Ins, dl, DAG, InVals);
463 }
464}
465
466/// Transform physical registers into virtual registers, and generate load
467/// operations for argument places on the stack.
468SDValue ARCTargetLowering::LowerCallArguments(
469 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
471 SmallVectorImpl<SDValue> &InVals) const {
472 MachineFunction &MF = DAG.getMachineFunction();
473 MachineFrameInfo &MFI = MF.getFrameInfo();
474 MachineRegisterInfo &RegInfo = MF.getRegInfo();
475 auto *AFI = MF.getInfo<ARCFunctionInfo>();
476
477 // Assign locations to all of the incoming arguments.
479 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
480 *DAG.getContext());
481
482 CCInfo.AnalyzeFormalArguments(Ins, CC_ARC);
483
484 unsigned StackSlotSize = 4;
485
486 if (!IsVarArg)
487 AFI->setReturnStackOffset(CCInfo.getStackSize());
488
489 // All getCopyFromReg ops must precede any getMemcpys to prevent the
490 // scheduler clobbering a register before it has been copied.
491 // The stages are:
492 // 1. CopyFromReg (and load) arg & vararg registers.
493 // 2. Chain CopyFromReg nodes into a TokenFactor.
494 // 3. Memcpy 'byVal' args & push final InVals.
495 // 4. Chain mem ops nodes into a TokenFactor.
496 SmallVector<SDValue, 4> CFRegNode;
499
500 // 1a. CopyFromReg (and load) arg registers.
501 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
502 CCValAssign &VA = ArgLocs[i];
503 SDValue ArgIn;
504
505 if (VA.isRegLoc()) {
506 // Arguments passed in registers
507 EVT RegVT = VA.getLocVT();
508 switch (RegVT.getSimpleVT().SimpleTy) {
509 default: {
510 LLVM_DEBUG(errs() << "LowerFormalArguments Unhandled argument type: "
511 << (unsigned)RegVT.getSimpleVT().SimpleTy << "\n");
512 llvm_unreachable("Unhandled LowerFormalArguments type.");
513 }
514 case MVT::i32:
515 unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);
516 RegInfo.addLiveIn(VA.getLocReg(), VReg);
517 ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
518 CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1));
519 }
520 } else {
521 // Only arguments passed on the stack should make it here.
522 assert(VA.isMemLoc());
523 // Load the argument to a virtual register
524 unsigned ObjSize = VA.getLocVT().getStoreSize();
525 assert((ObjSize <= StackSlotSize) && "Unhandled argument");
526
527 // Create the frame index object for this incoming parameter...
528 int FI = MFI.CreateFixedObject(ObjSize, VA.getLocMemOffset(), true);
529
530 // Create the SelectionDAG nodes corresponding to a load
531 // from this parameter
532 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
533 ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
535 }
536 const ArgDataPair ADP = {ArgIn, Ins[i].Flags};
537 ArgData.push_back(ADP);
538 }
539
540 // 1b. CopyFromReg vararg registers.
541 if (IsVarArg) {
542 // Argument registers
543 static const MCPhysReg ArgRegs[] = {ARC::R0, ARC::R1, ARC::R2, ARC::R3,
544 ARC::R4, ARC::R5, ARC::R6, ARC::R7};
545 auto *AFI = MF.getInfo<ARCFunctionInfo>();
546 unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs);
547 if (FirstVAReg < std::size(ArgRegs)) {
548 int Offset = 0;
549 // Save remaining registers, storing higher register numbers at a higher
550 // address
551 // There are (std::size(ArgRegs) - FirstVAReg) registers which
552 // need to be saved.
553 int VarFI = MFI.CreateFixedObject((std::size(ArgRegs) - FirstVAReg) * 4,
554 CCInfo.getStackSize(), true);
555 AFI->setVarArgsFrameIndex(VarFI);
556 SDValue FIN = DAG.getFrameIndex(VarFI, MVT::i32);
557 for (unsigned i = FirstVAReg; i < std::size(ArgRegs); i++) {
558 // Move argument from phys reg -> virt reg
559 unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);
560 RegInfo.addLiveIn(ArgRegs[i], VReg);
561 SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
562 CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1));
563 SDValue VAObj = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN,
564 DAG.getConstant(Offset, dl, MVT::i32));
565 // Move argument from virt reg -> stack
566 SDValue Store =
567 DAG.getStore(Val.getValue(1), dl, Val, VAObj, MachinePointerInfo());
568 MemOps.push_back(Store);
569 Offset += 4;
570 }
571 } else {
572 llvm_unreachable("Too many var args parameters.");
573 }
574 }
575
576 // 2. Chain CopyFromReg nodes into a TokenFactor.
577 if (!CFRegNode.empty())
578 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode);
579
580 // 3. Memcpy 'byVal' args & push final InVals.
581 // Aggregates passed "byVal" need to be copied by the callee.
582 // The callee will use a pointer to this copy, rather than the original
583 // pointer.
584 for (const auto &ArgDI : ArgData) {
585 if (ArgDI.Flags.isByVal() && ArgDI.Flags.getByValSize()) {
586 unsigned Size = ArgDI.Flags.getByValSize();
587 Align Alignment =
588 std::max(Align(StackSlotSize), ArgDI.Flags.getNonZeroByValAlign());
589 // Create a new object on the stack and copy the pointee into it.
590 int FI = MFI.CreateStackObject(Size, Alignment, false);
591 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
592 InVals.push_back(FIN);
593 MemOps.push_back(DAG.getMemcpy(
594 Chain, dl, FIN, ArgDI.SDV, DAG.getConstant(Size, dl, MVT::i32),
595 Alignment, Alignment, false, false, /*CI=*/nullptr, false,
596 MachinePointerInfo(), MachinePointerInfo()));
597 } else {
598 InVals.push_back(ArgDI.SDV);
599 }
600 }
601
602 // 4. Chain mem ops nodes into a TokenFactor.
603 if (!MemOps.empty()) {
604 MemOps.push_back(Chain);
605 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
606 }
607
608 return Chain;
609}
610
611//===----------------------------------------------------------------------===//
612// Return Value Calling Convention Implementation
613//===----------------------------------------------------------------------===//
614
615bool ARCTargetLowering::CanLowerReturn(
616 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
618 const Type *RetTy) const {
620 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
621 if (!CCInfo.CheckReturn(Outs, RetCC_ARC))
622 return false;
623 if (CCInfo.getStackSize() != 0 && IsVarArg)
624 return false;
625 return true;
626}
627
629ARCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
630 bool IsVarArg,
632 const SmallVectorImpl<SDValue> &OutVals,
633 const SDLoc &dl, SelectionDAG &DAG) const {
634 auto *AFI = DAG.getMachineFunction().getInfo<ARCFunctionInfo>();
635 MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
636
637 // CCValAssign - represent the assignment of
638 // the return value to a location
640
641 // CCState - Info about the registers and stack slot.
642 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
643 *DAG.getContext());
644
645 // Analyze return values.
646 if (!IsVarArg)
647 CCInfo.AllocateStack(AFI->getReturnStackOffset(), Align(4));
648
649 CCInfo.AnalyzeReturn(Outs, RetCC_ARC);
650
651 SDValue Glue;
652 SmallVector<SDValue, 4> RetOps(1, Chain);
653 SmallVector<SDValue, 4> MemOpChains;
654 // Handle return values that must be copied to memory.
655 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
656 CCValAssign &VA = RVLocs[i];
657 if (VA.isRegLoc())
658 continue;
659 assert(VA.isMemLoc());
660 if (IsVarArg) {
661 report_fatal_error("Can't return value from vararg function in memory");
662 }
663
664 int Offset = VA.getLocMemOffset();
665 unsigned ObjSize = VA.getLocVT().getStoreSize();
666 // Create the frame index object for the memory location.
667 int FI = MFI.CreateFixedObject(ObjSize, Offset, false);
668
669 // Create a SelectionDAG node corresponding to a store
670 // to this memory location.
671 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
672 MemOpChains.push_back(DAG.getStore(
673 Chain, dl, OutVals[i], FIN,
675 }
676
677 // Transform all store nodes into one single node because
678 // all stores are independent of each other.
679 if (!MemOpChains.empty())
680 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
681
682 // Now handle return values copied to registers.
683 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
684 CCValAssign &VA = RVLocs[i];
685 if (!VA.isRegLoc())
686 continue;
687 // Copy the result values into the output registers.
688 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);
689
690 // guarantee that all emitted copies are
691 // stuck together, avoiding something bad
692 Glue = Chain.getValue(1);
693 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
694 }
695
696 RetOps[0] = Chain; // Update chain.
697
698 // Add the glue if we have it.
699 if (Glue.getNode())
700 RetOps.push_back(Glue);
701
702 // What to do with the RetOps?
703 return DAG.getNode(ARCISD::RET, dl, MVT::Other, RetOps);
704}
705
706//===----------------------------------------------------------------------===//
707// Target Optimization Hooks
708//===----------------------------------------------------------------------===//
709
710SDValue ARCTargetLowering::PerformDAGCombine(SDNode *N,
711 DAGCombinerInfo &DCI) const {
712 return {};
713}
714
715//===----------------------------------------------------------------------===//
716// Addressing mode description hooks
717//===----------------------------------------------------------------------===//
718
719/// Return true if the addressing mode represented by AM is legal for this
720/// target, for a load/store of the specified type.
722 const AddrMode &AM, Type *Ty,
723 unsigned AS,
724 Instruction *I) const {
725 return AM.Scale == 0;
726}
727
728// Don't emit tail calls for the time being.
729bool ARCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
730 return false;
731}
732
733SDValue ARCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
734 const ARCRegisterInfo &ARI = *Subtarget.getRegisterInfo();
736 MachineFrameInfo &MFI = MF.getFrameInfo();
737 MFI.setFrameAddressIsTaken(true);
738
739 EVT VT = Op.getValueType();
740 SDLoc dl(Op);
741 assert(Op.getConstantOperandVal(0) == 0 &&
742 "Only support lowering frame addr of current frame.");
743 Register FrameReg = ARI.getFrameRegister(MF);
744 return DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
745}
746
747SDValue ARCTargetLowering::LowerGlobalAddress(SDValue Op,
748 SelectionDAG &DAG) const {
749 const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
750 const GlobalValue *GV = GN->getGlobal();
751 SDLoc dl(GN);
752 int64_t Offset = GN->getOffset();
753 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, Offset);
754 return DAG.getNode(ARCISD::GAWRAPPER, dl, MVT::i32, GA);
755}
756
759 auto *FuncInfo = MF.getInfo<ARCFunctionInfo>();
760
761 // vastart just stores the address of the VarArgsFrameIndex slot into the
762 // memory location argument.
763 SDLoc dl(Op);
765 SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
766 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
767 return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1),
769}
770
772 switch (Op.getOpcode()) {
774 return LowerGlobalAddress(Op, DAG);
775 case ISD::FRAMEADDR:
776 return LowerFRAMEADDR(Op, DAG);
777 case ISD::SELECT_CC:
778 return LowerSELECT_CC(Op, DAG);
779 case ISD::BR_CC:
780 return LowerBR_CC(Op, DAG);
782 return LowerSIGN_EXTEND_INREG(Op, DAG);
783 case ISD::JumpTable:
784 return LowerJumpTable(Op, DAG);
785 case ISD::VASTART:
786 return LowerVASTART(Op, DAG);
788 // As of LLVM 3.8, the lowering code insists that we customize it even
789 // though we've declared the i32 version as legal. This is because it only
790 // thinks i64 is the truly supported version. We've already converted the
791 // i64 version to a widened i32.
792 assert(Op.getSimpleValueType() == MVT::i32);
793 return Op;
794 default:
795 llvm_unreachable("unimplemented operand");
796 }
797}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
Register const TargetRegisterInfo * TRI
#define LLVM_DEBUG(...)
Definition Debug.h:119
Value * RHS
Value * LHS
ARCFunctionInfo - This class is derived from MachineFunction private ARC target-specific information ...
const ARCRegisterInfo * getRegisterInfo() const override
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)
CCState - This class holds information needed while lowering arguments and return values.
LLVM_ABI void AnalyzeCallResult(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeCallResult - Analyze the return values of a call, incorporating info about the passed values i...
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
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.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
This class represents a function call, abstracting a target machine's calling convention.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
const GlobalValue * getGlobal() const
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
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.
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.
LLVM_ABI 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...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
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...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI 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,...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
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).
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI 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 ...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
TargetLowering(const TargetLowering &)=delete
Primary interface to the complete machine description for the target machine.
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
LLVM Value Representation.
Definition Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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
@ 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.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADDC
Carry-setting nodes for multiple precision addition and subtraction.
Definition ISDOpcodes.h:294
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:863
@ GlobalAddress
Definition ISDOpcodes.h:88
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:706
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:821
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:898
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:729
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
Definition ISDOpcodes.h:110
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ ADDE
Carry-using nodes for multiple precision addition and subtraction.
Definition ISDOpcodes.h:304
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:573
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
#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:339
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI 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