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,
634 const Type *RetTy) const {
636 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
637 if (!CCInfo.CheckReturn(Outs, RetCC_ARC))
638 return false;
639 if (CCInfo.getStackSize() != 0 && IsVarArg)
640 return false;
641 return true;
642}
643
645ARCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
646 bool IsVarArg,
648 const SmallVectorImpl<SDValue> &OutVals,
649 const SDLoc &dl, SelectionDAG &DAG) const {
650 auto *AFI = DAG.getMachineFunction().getInfo<ARCFunctionInfo>();
652
653 // CCValAssign - represent the assignment of
654 // the return value to a location
656
657 // CCState - Info about the registers and stack slot.
658 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
659 *DAG.getContext());
660
661 // Analyze return values.
662 if (!IsVarArg)
663 CCInfo.AllocateStack(AFI->getReturnStackOffset(), Align(4));
664
665 CCInfo.AnalyzeReturn(Outs, RetCC_ARC);
666
667 SDValue Glue;
668 SmallVector<SDValue, 4> RetOps(1, Chain);
669 SmallVector<SDValue, 4> MemOpChains;
670 // Handle return values that must be copied to memory.
671 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
672 CCValAssign &VA = RVLocs[i];
673 if (VA.isRegLoc())
674 continue;
675 assert(VA.isMemLoc());
676 if (IsVarArg) {
677 report_fatal_error("Can't return value from vararg function in memory");
678 }
679
680 int Offset = VA.getLocMemOffset();
681 unsigned ObjSize = VA.getLocVT().getStoreSize();
682 // Create the frame index object for the memory location.
683 int FI = MFI.CreateFixedObject(ObjSize, Offset, false);
684
685 // Create a SelectionDAG node corresponding to a store
686 // to this memory location.
687 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
688 MemOpChains.push_back(DAG.getStore(
689 Chain, dl, OutVals[i], FIN,
691 }
692
693 // Transform all store nodes into one single node because
694 // all stores are independent of each other.
695 if (!MemOpChains.empty())
696 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
697
698 // Now handle return values copied to registers.
699 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
700 CCValAssign &VA = RVLocs[i];
701 if (!VA.isRegLoc())
702 continue;
703 // Copy the result values into the output registers.
704 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);
705
706 // guarantee that all emitted copies are
707 // stuck together, avoiding something bad
708 Glue = Chain.getValue(1);
709 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
710 }
711
712 RetOps[0] = Chain; // Update chain.
713
714 // Add the glue if we have it.
715 if (Glue.getNode())
716 RetOps.push_back(Glue);
717
718 // What to do with the RetOps?
719 return DAG.getNode(ARCISD::RET, dl, MVT::Other, RetOps);
720}
721
722//===----------------------------------------------------------------------===//
723// Target Optimization Hooks
724//===----------------------------------------------------------------------===//
725
726SDValue ARCTargetLowering::PerformDAGCombine(SDNode *N,
727 DAGCombinerInfo &DCI) const {
728 return {};
729}
730
731//===----------------------------------------------------------------------===//
732// Addressing mode description hooks
733//===----------------------------------------------------------------------===//
734
735/// Return true if the addressing mode represented by AM is legal for this
736/// target, for a load/store of the specified type.
738 const AddrMode &AM, Type *Ty,
739 unsigned AS,
740 Instruction *I) const {
741 return AM.Scale == 0;
742}
743
744// Don't emit tail calls for the time being.
745bool ARCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
746 return false;
747}
748
749SDValue ARCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
750 const ARCRegisterInfo &ARI = *Subtarget.getRegisterInfo();
752 MachineFrameInfo &MFI = MF.getFrameInfo();
753 MFI.setFrameAddressIsTaken(true);
754
755 EVT VT = Op.getValueType();
756 SDLoc dl(Op);
757 assert(Op.getConstantOperandVal(0) == 0 &&
758 "Only support lowering frame addr of current frame.");
759 Register FrameReg = ARI.getFrameRegister(MF);
760 return DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
761}
762
763SDValue ARCTargetLowering::LowerGlobalAddress(SDValue Op,
764 SelectionDAG &DAG) const {
765 const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
766 const GlobalValue *GV = GN->getGlobal();
767 SDLoc dl(GN);
768 int64_t Offset = GN->getOffset();
769 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, Offset);
770 return DAG.getNode(ARCISD::GAWRAPPER, dl, MVT::i32, GA);
771}
772
775 auto *FuncInfo = MF.getInfo<ARCFunctionInfo>();
776
777 // vastart just stores the address of the VarArgsFrameIndex slot into the
778 // memory location argument.
779 SDLoc dl(Op);
781 SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
782 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
783 return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1),
785}
786
788 switch (Op.getOpcode()) {
790 return LowerGlobalAddress(Op, DAG);
791 case ISD::FRAMEADDR:
792 return LowerFRAMEADDR(Op, DAG);
793 case ISD::SELECT_CC:
794 return LowerSELECT_CC(Op, DAG);
795 case ISD::BR_CC:
796 return LowerBR_CC(Op, DAG);
798 return LowerSIGN_EXTEND_INREG(Op, DAG);
799 case ISD::JumpTable:
800 return LowerJumpTable(Op, DAG);
801 case ISD::VASTART:
802 return LowerVASTART(Op, DAG);
804 // As of LLVM 3.8, the lowering code insists that we customize it even
805 // though we've declared the i32 version as legal. This is because it only
806 // thinks i64 is the truly supported version. We've already converted the
807 // i64 version to a widened i32.
808 assert(Op.getSimpleValueType() == MVT::i32);
809 return Op;
810 default:
811 llvm_unreachable("unimplemented operand");
812 }
813}
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
return RetTy
#define LLVM_DEBUG(...)
Definition: Debug.h:106
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:228
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
Definition: SelectionDAG.h:750
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
Definition: SelectionDAG.h:801
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 getRegister(Register Reg, EVT VT)
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:503
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
Definition: SelectionDAG.h:760
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)
Definition: SelectionDAG.h:827
const DataLayout & getDataLayout() const
Definition: SelectionDAG.h:497
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 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:492
SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
SDValue getRegisterMask(const uint32_t *RegMask)
LLVMContext * getContext() const
Definition: SelectionDAG.h:510
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:580
bool empty() const
Definition: SmallVector.h:81
size_t size() const
Definition: SmallVector.h:78
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
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:125
@ 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:1197
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
Definition: ISDOpcodes.h:1193
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
Definition: ISDOpcodes.h:1226
@ 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:1102
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition: ISDOpcodes.h:814
@ GlobalAddress
Definition: ISDOpcodes.h:78
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
Definition: ISDOpcodes.h:1494
@ SIGN_EXTEND
Conversion operators.
Definition: ISDOpcodes.h:805
@ BR_CC
BR_CC - Conditional branch.
Definition: ISDOpcodes.h:1148
@ BR_JT
BR_JT - Jumptable branch.
Definition: ISDOpcodes.h:1127
@ 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:1222
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:674
@ SHL
Shift and rotation operations.
Definition: ISDOpcodes.h:735
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition: ISDOpcodes.h:811
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition: ISDOpcodes.h:772
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition: ISDOpcodes.h:849
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition: ISDOpcodes.h:697
@ 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:1253
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:709
@ 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:1217
@ BRCOND
BRCOND - Conditional branch.
Definition: ISDOpcodes.h:1141
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
Definition: ISDOpcodes.h:1610
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:311
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