LLVM 18.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}
178
179const char *ARCTargetLowering::getTargetNodeName(unsigned Opcode) const {
180 switch (Opcode) {
181 case ARCISD::BL:
182 return "ARCISD::BL";
183 case ARCISD::CMOV:
184 return "ARCISD::CMOV";
185 case ARCISD::CMP:
186 return "ARCISD::CMP";
187 case ARCISD::BRcc:
188 return "ARCISD::BRcc";
189 case ARCISD::RET:
190 return "ARCISD::RET";
192 return "ARCISD::GAWRAPPER";
193 }
194 return nullptr;
195}
196
197//===----------------------------------------------------------------------===//
198// Misc Lower Operation implementation
199//===----------------------------------------------------------------------===//
200
201SDValue ARCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
202 SDValue LHS = Op.getOperand(0);
203 SDValue RHS = Op.getOperand(1);
204 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
205 SDValue TVal = Op.getOperand(2);
206 SDValue FVal = Op.getOperand(3);
207 SDLoc dl(Op);
209 assert(LHS.getValueType() == MVT::i32 && "Only know how to SELECT_CC i32");
210 SDValue Cmp = DAG.getNode(ARCISD::CMP, dl, MVT::Glue, LHS, RHS);
211 return DAG.getNode(ARCISD::CMOV, dl, TVal.getValueType(), TVal, FVal,
212 DAG.getConstant(ArcCC, dl, MVT::i32), Cmp);
213}
214
215SDValue ARCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
216 SelectionDAG &DAG) const {
217 SDValue Op0 = Op.getOperand(0);
218 SDLoc dl(Op);
219 assert(Op.getValueType() == MVT::i32 &&
220 "Unhandled target sign_extend_inreg.");
221 // These are legal
222 unsigned Width = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits();
223 if (Width == 16 || Width == 8)
224 return Op;
225 if (Width >= 32) {
226 return {};
227 }
228 SDValue LS = DAG.getNode(ISD::SHL, dl, MVT::i32, Op0,
229 DAG.getConstant(32 - Width, dl, MVT::i32));
230 SDValue SR = DAG.getNode(ISD::SRA, dl, MVT::i32, LS,
231 DAG.getConstant(32 - Width, dl, MVT::i32));
232 return SR;
233}
234
235SDValue ARCTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
236 SDValue Chain = Op.getOperand(0);
237 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
238 SDValue LHS = Op.getOperand(2);
239 SDValue RHS = Op.getOperand(3);
240 SDValue Dest = Op.getOperand(4);
241 SDLoc dl(Op);
243 assert(LHS.getValueType() == MVT::i32 && "Only know how to BR_CC i32");
244 return DAG.getNode(ARCISD::BRcc, dl, MVT::Other, Chain, Dest, LHS, RHS,
245 DAG.getConstant(arcCC, dl, MVT::i32));
246}
247
248SDValue ARCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
249 auto *N = cast<JumpTableSDNode>(Op);
250 SDValue GA = DAG.getTargetJumpTable(N->getIndex(), MVT::i32);
251 return DAG.getNode(ARCISD::GAWRAPPER, SDLoc(N), MVT::i32, GA);
252}
253
254#include "ARCGenCallingConv.inc"
255
256//===----------------------------------------------------------------------===//
257// Call Calling Convention Implementation
258//===----------------------------------------------------------------------===//
259
260/// ARC call implementation
261SDValue ARCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
262 SmallVectorImpl<SDValue> &InVals) const {
263 SelectionDAG &DAG = CLI.DAG;
264 SDLoc &dl = CLI.DL;
266 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
268 SDValue Chain = CLI.Chain;
269 SDValue Callee = CLI.Callee;
270 CallingConv::ID CallConv = CLI.CallConv;
271 bool IsVarArg = CLI.IsVarArg;
272 bool &IsTailCall = CLI.IsTailCall;
273
274 IsTailCall = false; // Do not support tail calls yet.
275
277 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
278 *DAG.getContext());
279
280 CCInfo.AnalyzeCallOperands(Outs, CC_ARC);
281
283 // Analyze return values to determine the number of bytes of stack required.
284 CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
285 *DAG.getContext());
286 RetCCInfo.AllocateStack(CCInfo.getStackSize(), Align(4));
287 RetCCInfo.AnalyzeCallResult(Ins, RetCC_ARC);
288
289 // Get a count of how many bytes are to be pushed on the stack.
290 unsigned NumBytes = RetCCInfo.getStackSize();
291
292 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
293
295 SmallVector<SDValue, 12> MemOpChains;
296
298 // Walk the register/memloc assignments, inserting copies/loads.
299 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
300 CCValAssign &VA = ArgLocs[i];
301 SDValue Arg = OutVals[i];
302
303 // Promote the value if needed.
304 switch (VA.getLocInfo()) {
305 default:
306 llvm_unreachable("Unknown loc info!");
308 break;
310 Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
311 break;
313 Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
314 break;
316 Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
317 break;
318 }
319
320 // Arguments that can be passed on register must be kept at
321 // RegsToPass vector
322 if (VA.isRegLoc()) {
323 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
324 } else {
325 assert(VA.isMemLoc() && "Must be register or memory argument.");
326 if (!StackPtr.getNode())
327 StackPtr = DAG.getCopyFromReg(Chain, dl, ARC::SP,
329 // Calculate the stack position.
330 SDValue SOffset = DAG.getIntPtrConstant(VA.getLocMemOffset(), dl);
331 SDValue PtrOff = DAG.getNode(
332 ISD::ADD, dl, getPointerTy(DAG.getDataLayout()), StackPtr, SOffset);
333
334 SDValue Store =
335 DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
336 MemOpChains.push_back(Store);
337 IsTailCall = false;
338 }
339 }
340
341 // Transform all store nodes into one single node because
342 // all store nodes are independent of each other.
343 if (!MemOpChains.empty())
344 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
345
346 // Build a sequence of copy-to-reg nodes chained together with token
347 // chain and flag operands which copy the outgoing args into registers.
348 // The Glue in necessary since all emitted instructions must be
349 // stuck together.
350 SDValue Glue;
351 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
352 Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
353 RegsToPass[i].second, Glue);
354 Glue = Chain.getValue(1);
355 }
356
357 // If the callee is a GlobalAddress node (quite common, every direct call is)
358 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
359 // Likewise ExternalSymbol -> TargetExternalSymbol.
360 bool IsDirect = true;
361 if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
362 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
363 else if (auto *E = dyn_cast<ExternalSymbolSDNode>(Callee))
364 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
365 else
366 IsDirect = false;
367 // Branch + Link = #chain, #target_address, #opt_in_flags...
368 // = Chain, Callee, Reg#1, Reg#2, ...
369 //
370 // Returns a chain & a glue for retval copy to use.
371 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
373 Ops.push_back(Chain);
374 Ops.push_back(Callee);
375
376 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
377 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
378 RegsToPass[i].second.getValueType()));
379
380 // Add a register mask operand representing the call-preserved registers.
381 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
382 const uint32_t *Mask =
383 TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
384 assert(Mask && "Missing call preserved mask for calling convention");
385 Ops.push_back(DAG.getRegisterMask(Mask));
386
387 if (Glue.getNode())
388 Ops.push_back(Glue);
389
390 Chain = DAG.getNode(IsDirect ? ARCISD::BL : ARCISD::JL, dl, NodeTys, Ops);
391 Glue = Chain.getValue(1);
392
393 // Create the CALLSEQ_END node.
394 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, dl);
395 Glue = Chain.getValue(1);
396
397 // Handle result values, copying them out of physregs into vregs that we
398 // return.
399 if (IsTailCall)
400 return Chain;
401 return lowerCallResult(Chain, Glue, RVLocs, dl, DAG, InVals);
402}
403
404/// Lower the result values of a call into the appropriate copies out of
405/// physical registers / memory locations.
407 const SmallVectorImpl<CCValAssign> &RVLocs,
408 SDLoc dl, SelectionDAG &DAG,
409 SmallVectorImpl<SDValue> &InVals) {
410 SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs;
411 // Copy results out of physical registers.
412 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
413 const CCValAssign &VA = RVLocs[i];
414 if (VA.isRegLoc()) {
415 SDValue RetValue;
416 RetValue =
417 DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), Glue);
418 Chain = RetValue.getValue(1);
419 Glue = RetValue.getValue(2);
420 InVals.push_back(RetValue);
421 } else {
422 assert(VA.isMemLoc() && "Must be memory location.");
423 ResultMemLocs.push_back(
424 std::make_pair(VA.getLocMemOffset(), InVals.size()));
425
426 // Reserve space for this result.
427 InVals.push_back(SDValue());
428 }
429 }
430
431 // Copy results out of memory.
432 SmallVector<SDValue, 4> MemOpChains;
433 for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) {
434 int Offset = ResultMemLocs[i].first;
435 unsigned Index = ResultMemLocs[i].second;
436 SDValue StackPtr = DAG.getRegister(ARC::SP, MVT::i32);
437 SDValue SpLoc = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr,
438 DAG.getConstant(Offset, dl, MVT::i32));
439 SDValue Load =
440 DAG.getLoad(MVT::i32, dl, Chain, SpLoc, MachinePointerInfo());
441 InVals[Index] = Load;
442 MemOpChains.push_back(Load.getValue(1));
443 }
444
445 // Transform all loads nodes into one single node because
446 // all load nodes are independent of each other.
447 if (!MemOpChains.empty())
448 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
449
450 return Chain;
451}
452
453//===----------------------------------------------------------------------===//
454// Formal Arguments Calling Convention Implementation
455//===----------------------------------------------------------------------===//
456
457namespace {
458
459struct ArgDataPair {
460 SDValue SDV;
462};
463
464} // end anonymous namespace
465
466/// ARC formal arguments implementation
467SDValue ARCTargetLowering::LowerFormalArguments(
468 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
469 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
470 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
471 switch (CallConv) {
472 default:
473 llvm_unreachable("Unsupported calling convention");
474 case CallingConv::C:
476 return LowerCallArguments(Chain, CallConv, IsVarArg, Ins, dl, DAG, InVals);
477 }
478}
479
480/// Transform physical registers into virtual registers, and generate load
481/// operations for argument places on the stack.
482SDValue ARCTargetLowering::LowerCallArguments(
483 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
485 SmallVectorImpl<SDValue> &InVals) const {
487 MachineFrameInfo &MFI = MF.getFrameInfo();
489 auto *AFI = MF.getInfo<ARCFunctionInfo>();
490
491 // Assign locations to all of the incoming arguments.
493 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
494 *DAG.getContext());
495
496 CCInfo.AnalyzeFormalArguments(Ins, CC_ARC);
497
498 unsigned StackSlotSize = 4;
499
500 if (!IsVarArg)
501 AFI->setReturnStackOffset(CCInfo.getStackSize());
502
503 // All getCopyFromReg ops must precede any getMemcpys to prevent the
504 // scheduler clobbering a register before it has been copied.
505 // The stages are:
506 // 1. CopyFromReg (and load) arg & vararg registers.
507 // 2. Chain CopyFromReg nodes into a TokenFactor.
508 // 3. Memcpy 'byVal' args & push final InVals.
509 // 4. Chain mem ops nodes into a TokenFactor.
510 SmallVector<SDValue, 4> CFRegNode;
513
514 // 1a. CopyFromReg (and load) arg registers.
515 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
516 CCValAssign &VA = ArgLocs[i];
517 SDValue ArgIn;
518
519 if (VA.isRegLoc()) {
520 // Arguments passed in registers
521 EVT RegVT = VA.getLocVT();
522 switch (RegVT.getSimpleVT().SimpleTy) {
523 default: {
524 LLVM_DEBUG(errs() << "LowerFormalArguments Unhandled argument type: "
525 << (unsigned)RegVT.getSimpleVT().SimpleTy << "\n");
526 llvm_unreachable("Unhandled LowerFormalArguments type.");
527 }
528 case MVT::i32:
529 unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);
530 RegInfo.addLiveIn(VA.getLocReg(), VReg);
531 ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
532 CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1));
533 }
534 } else {
535 // Only arguments passed on the stack should make it here.
536 assert(VA.isMemLoc());
537 // Load the argument to a virtual register
538 unsigned ObjSize = VA.getLocVT().getStoreSize();
539 assert((ObjSize <= StackSlotSize) && "Unhandled argument");
540
541 // Create the frame index object for this incoming parameter...
542 int FI = MFI.CreateFixedObject(ObjSize, VA.getLocMemOffset(), true);
543
544 // Create the SelectionDAG nodes corresponding to a load
545 // from this parameter
546 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
547 ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
549 }
550 const ArgDataPair ADP = {ArgIn, Ins[i].Flags};
551 ArgData.push_back(ADP);
552 }
553
554 // 1b. CopyFromReg vararg registers.
555 if (IsVarArg) {
556 // Argument registers
557 static const MCPhysReg ArgRegs[] = {ARC::R0, ARC::R1, ARC::R2, ARC::R3,
558 ARC::R4, ARC::R5, ARC::R6, ARC::R7};
559 auto *AFI = MF.getInfo<ARCFunctionInfo>();
560 unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs);
561 if (FirstVAReg < std::size(ArgRegs)) {
562 int Offset = 0;
563 // Save remaining registers, storing higher register numbers at a higher
564 // address
565 // There are (std::size(ArgRegs) - FirstVAReg) registers which
566 // need to be saved.
567 int VarFI = MFI.CreateFixedObject((std::size(ArgRegs) - FirstVAReg) * 4,
568 CCInfo.getStackSize(), true);
569 AFI->setVarArgsFrameIndex(VarFI);
570 SDValue FIN = DAG.getFrameIndex(VarFI, MVT::i32);
571 for (unsigned i = FirstVAReg; i < std::size(ArgRegs); i++) {
572 // Move argument from phys reg -> virt reg
573 unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);
574 RegInfo.addLiveIn(ArgRegs[i], VReg);
575 SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
576 CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1));
577 SDValue VAObj = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN,
578 DAG.getConstant(Offset, dl, MVT::i32));
579 // Move argument from virt reg -> stack
580 SDValue Store =
581 DAG.getStore(Val.getValue(1), dl, Val, VAObj, MachinePointerInfo());
582 MemOps.push_back(Store);
583 Offset += 4;
584 }
585 } else {
586 llvm_unreachable("Too many var args parameters.");
587 }
588 }
589
590 // 2. Chain CopyFromReg nodes into a TokenFactor.
591 if (!CFRegNode.empty())
592 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode);
593
594 // 3. Memcpy 'byVal' args & push final InVals.
595 // Aggregates passed "byVal" need to be copied by the callee.
596 // The callee will use a pointer to this copy, rather than the original
597 // pointer.
598 for (const auto &ArgDI : ArgData) {
599 if (ArgDI.Flags.isByVal() && ArgDI.Flags.getByValSize()) {
600 unsigned Size = ArgDI.Flags.getByValSize();
601 Align Alignment =
602 std::max(Align(StackSlotSize), ArgDI.Flags.getNonZeroByValAlign());
603 // Create a new object on the stack and copy the pointee into it.
604 int FI = MFI.CreateStackObject(Size, Alignment, false);
605 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
606 InVals.push_back(FIN);
607 MemOps.push_back(DAG.getMemcpy(
608 Chain, dl, FIN, ArgDI.SDV, DAG.getConstant(Size, dl, MVT::i32),
609 Alignment, false, false, false, MachinePointerInfo(),
611 } else {
612 InVals.push_back(ArgDI.SDV);
613 }
614 }
615
616 // 4. Chain mem ops nodes into a TokenFactor.
617 if (!MemOps.empty()) {
618 MemOps.push_back(Chain);
619 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
620 }
621
622 return Chain;
623}
624
625//===----------------------------------------------------------------------===//
626// Return Value Calling Convention Implementation
627//===----------------------------------------------------------------------===//
628
629bool ARCTargetLowering::CanLowerReturn(
630 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
631 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
633 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
634 if (!CCInfo.CheckReturn(Outs, RetCC_ARC))
635 return false;
636 if (CCInfo.getStackSize() != 0 && IsVarArg)
637 return false;
638 return true;
639}
640
642ARCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
643 bool IsVarArg,
645 const SmallVectorImpl<SDValue> &OutVals,
646 const SDLoc &dl, SelectionDAG &DAG) const {
647 auto *AFI = DAG.getMachineFunction().getInfo<ARCFunctionInfo>();
649
650 // CCValAssign - represent the assignment of
651 // the return value to a location
653
654 // CCState - Info about the registers and stack slot.
655 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
656 *DAG.getContext());
657
658 // Analyze return values.
659 if (!IsVarArg)
660 CCInfo.AllocateStack(AFI->getReturnStackOffset(), Align(4));
661
662 CCInfo.AnalyzeReturn(Outs, RetCC_ARC);
663
664 SDValue Glue;
665 SmallVector<SDValue, 4> RetOps(1, Chain);
666 SmallVector<SDValue, 4> MemOpChains;
667 // Handle return values that must be copied to memory.
668 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
669 CCValAssign &VA = RVLocs[i];
670 if (VA.isRegLoc())
671 continue;
672 assert(VA.isMemLoc());
673 if (IsVarArg) {
674 report_fatal_error("Can't return value from vararg function in memory");
675 }
676
677 int Offset = VA.getLocMemOffset();
678 unsigned ObjSize = VA.getLocVT().getStoreSize();
679 // Create the frame index object for the memory location.
680 int FI = MFI.CreateFixedObject(ObjSize, Offset, false);
681
682 // Create a SelectionDAG node corresponding to a store
683 // to this memory location.
684 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
685 MemOpChains.push_back(DAG.getStore(
686 Chain, dl, OutVals[i], FIN,
688 }
689
690 // Transform all store nodes into one single node because
691 // all stores are independent of each other.
692 if (!MemOpChains.empty())
693 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
694
695 // Now handle return values copied to registers.
696 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
697 CCValAssign &VA = RVLocs[i];
698 if (!VA.isRegLoc())
699 continue;
700 // Copy the result values into the output registers.
701 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);
702
703 // guarantee that all emitted copies are
704 // stuck together, avoiding something bad
705 Glue = Chain.getValue(1);
706 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
707 }
708
709 RetOps[0] = Chain; // Update chain.
710
711 // Add the glue if we have it.
712 if (Glue.getNode())
713 RetOps.push_back(Glue);
714
715 // What to do with the RetOps?
716 return DAG.getNode(ARCISD::RET, dl, MVT::Other, RetOps);
717}
718
719//===----------------------------------------------------------------------===//
720// Target Optimization Hooks
721//===----------------------------------------------------------------------===//
722
723SDValue ARCTargetLowering::PerformDAGCombine(SDNode *N,
724 DAGCombinerInfo &DCI) const {
725 return {};
726}
727
728//===----------------------------------------------------------------------===//
729// Addressing mode description hooks
730//===----------------------------------------------------------------------===//
731
732/// Return true if the addressing mode represented by AM is legal for this
733/// target, for a load/store of the specified type.
735 const AddrMode &AM, Type *Ty,
736 unsigned AS,
737 Instruction *I) const {
738 return AM.Scale == 0;
739}
740
741// Don't emit tail calls for the time being.
742bool ARCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
743 return false;
744}
745
746SDValue ARCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
747 const ARCRegisterInfo &ARI = *Subtarget.getRegisterInfo();
749 MachineFrameInfo &MFI = MF.getFrameInfo();
750 MFI.setFrameAddressIsTaken(true);
751
752 EVT VT = Op.getValueType();
753 SDLoc dl(Op);
754 assert(cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0 &&
755 "Only support lowering frame addr of current frame.");
756 Register FrameReg = ARI.getFrameRegister(MF);
757 return DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
758}
759
760SDValue ARCTargetLowering::LowerGlobalAddress(SDValue Op,
761 SelectionDAG &DAG) const {
762 const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
763 const GlobalValue *GV = GN->getGlobal();
764 SDLoc dl(GN);
765 int64_t Offset = GN->getOffset();
766 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, Offset);
767 return DAG.getNode(ARCISD::GAWRAPPER, dl, MVT::i32, GA);
768}
769
772 auto *FuncInfo = MF.getInfo<ARCFunctionInfo>();
773
774 // vastart just stores the address of the VarArgsFrameIndex slot into the
775 // memory location argument.
776 SDLoc dl(Op);
778 SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
779 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
780 return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1),
782}
783
785 switch (Op.getOpcode()) {
787 return LowerGlobalAddress(Op, DAG);
788 case ISD::FRAMEADDR:
789 return LowerFRAMEADDR(Op, DAG);
790 case ISD::SELECT_CC:
791 return LowerSELECT_CC(Op, DAG);
792 case ISD::BR_CC:
793 return LowerBR_CC(Op, DAG);
795 return LowerSIGN_EXTEND_INREG(Op, DAG);
796 case ISD::JumpTable:
797 return LowerJumpTable(Op, DAG);
798 case ISD::VASTART:
799 return LowerVASTART(Op, DAG);
801 // As of LLVM 3.8, the lowering code insists that we customize it even
802 // though we've declared the i32 version as legal. This is because it only
803 // thinks i64 is the truly supported version. We've already converted the
804 // i64 version to a widened i32.
805 assert(Op.getSimpleValueType() == MVT::i32);
806 return Op;
807 default:
808 llvm_unreachable("unimplemented operand");
809 }
810}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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...
Function Alias Analysis Results
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#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
const char LLVMTargetMachineRef TM
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:110
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:225
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
Definition: SelectionDAG.h:720
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
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:478
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
Definition: SelectionDAG.h:730
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 getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, bool isTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), AAResults *AA=nullptr)
const DataLayout & getDataLayout() const
Definition: SelectionDAG.h:472
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:771
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:469
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
Definition: SelectionDAG.h:797
SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
SDValue getRegisterMask(const uint32_t *RegMask)
LLVMContext * getContext() const
Definition: SelectionDAG.h:485
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:554
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:577
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
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 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:78
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:119
@ 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:1121
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
Definition: ISDOpcodes.h:1117
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
Definition: ISDOpcodes.h:1150
@ ADDC
Carry-setting nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:269
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:239
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Definition: ISDOpcodes.h:1026
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition: ISDOpcodes.h:780
@ GlobalAddress
Definition: ISDOpcodes.h:78
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
Definition: ISDOpcodes.h:1380
@ SIGN_EXTEND
Conversion operators.
Definition: ISDOpcodes.h:774
@ BR_CC
BR_CC - Conditional branch.
Definition: ISDOpcodes.h:1072
@ BR_JT
BR_JT - Jumptable branch.
Definition: ISDOpcodes.h:1051
@ UNDEF
UNDEF - An undefined node.
Definition: ISDOpcodes.h:211
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
Definition: ISDOpcodes.h:1146
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:651
@ SHL
Shift and rotation operations.
Definition: ISDOpcodes.h:705
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition: ISDOpcodes.h:777
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition: ISDOpcodes.h:742
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition: ISDOpcodes.h:795
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition: ISDOpcodes.h:674
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
Definition: ISDOpcodes.h:94
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
Definition: ISDOpcodes.h:1177
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:680
@ ADDE
Carry-using nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:279
@ 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:1141
@ BRCOND
BRCOND - Conditional branch.
Definition: ISDOpcodes.h:1065
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
Definition: ISDOpcodes.h:1503
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:440
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:156
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:34
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition: ValueTypes.h:299
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 If BaseGV is null...
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