1326938Sdim//===- ARCISelLowering.cpp - ARC DAG Lowering Impl --------------*- C++ -*-===//
2326938Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6326938Sdim//
7326938Sdim//===----------------------------------------------------------------------===//
8326938Sdim//
9326938Sdim// This file implements the ARCTargetLowering class.
10326938Sdim//
11326938Sdim//===----------------------------------------------------------------------===//
12326938Sdim
13326938Sdim#include "ARCISelLowering.h"
14326938Sdim#include "ARC.h"
15326938Sdim#include "ARCMachineFunctionInfo.h"
16326938Sdim#include "ARCSubtarget.h"
17326938Sdim#include "ARCTargetMachine.h"
18326938Sdim#include "MCTargetDesc/ARCInfo.h"
19326938Sdim#include "llvm/CodeGen/CallingConvLower.h"
20326938Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
21326938Sdim#include "llvm/CodeGen/MachineFunction.h"
22326938Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
23326938Sdim#include "llvm/CodeGen/MachineJumpTableInfo.h"
24326938Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
25326938Sdim#include "llvm/CodeGen/SelectionDAGISel.h"
26326938Sdim#include "llvm/CodeGen/ValueTypes.h"
27326938Sdim#include "llvm/IR/CallingConv.h"
28326938Sdim#include "llvm/IR/Intrinsics.h"
29326938Sdim#include "llvm/Support/Debug.h"
30326938Sdim#include <algorithm>
31326938Sdim
32326938Sdim#define DEBUG_TYPE "arc-lower"
33326938Sdim
34326938Sdimusing namespace llvm;
35326938Sdim
36326938Sdimstatic SDValue lowerCallResult(SDValue Chain, SDValue InFlag,
37326938Sdim                               const SmallVectorImpl<CCValAssign> &RVLocs,
38326938Sdim                               SDLoc dl, SelectionDAG &DAG,
39326938Sdim                               SmallVectorImpl<SDValue> &InVals);
40326938Sdim
41326938Sdimstatic ARCCC::CondCode ISDCCtoARCCC(ISD::CondCode isdCC) {
42326938Sdim  switch (isdCC) {
43326938Sdim  case ISD::SETUEQ:
44326938Sdim    return ARCCC::EQ;
45326938Sdim  case ISD::SETUGT:
46326938Sdim    return ARCCC::HI;
47326938Sdim  case ISD::SETUGE:
48326938Sdim    return ARCCC::HS;
49326938Sdim  case ISD::SETULT:
50326938Sdim    return ARCCC::LO;
51326938Sdim  case ISD::SETULE:
52326938Sdim    return ARCCC::LS;
53326938Sdim  case ISD::SETUNE:
54326938Sdim    return ARCCC::NE;
55326938Sdim  case ISD::SETEQ:
56326938Sdim    return ARCCC::EQ;
57326938Sdim  case ISD::SETGT:
58326938Sdim    return ARCCC::GT;
59326938Sdim  case ISD::SETGE:
60326938Sdim    return ARCCC::GE;
61326938Sdim  case ISD::SETLT:
62326938Sdim    return ARCCC::LT;
63326938Sdim  case ISD::SETLE:
64326938Sdim    return ARCCC::LE;
65326938Sdim  case ISD::SETNE:
66326938Sdim    return ARCCC::NE;
67326938Sdim  default:
68326938Sdim    llvm_unreachable("Unhandled ISDCC code.");
69326938Sdim  }
70326938Sdim}
71326938Sdim
72326938SdimARCTargetLowering::ARCTargetLowering(const TargetMachine &TM,
73326938Sdim                                     const ARCSubtarget &Subtarget)
74341825Sdim    : TargetLowering(TM), Subtarget(Subtarget) {
75326938Sdim  // Set up the register classes.
76326938Sdim  addRegisterClass(MVT::i32, &ARC::GPR32RegClass);
77326938Sdim
78326938Sdim  // Compute derived properties from the register classes
79326938Sdim  computeRegisterProperties(Subtarget.getRegisterInfo());
80326938Sdim
81326938Sdim  setStackPointerRegisterToSaveRestore(ARC::SP);
82326938Sdim
83326938Sdim  setSchedulingPreference(Sched::Source);
84326938Sdim
85326938Sdim  // Use i32 for setcc operations results (slt, sgt, ...).
86326938Sdim  setBooleanContents(ZeroOrOneBooleanContent);
87326938Sdim  setBooleanVectorContents(ZeroOrOneBooleanContent);
88326938Sdim
89326938Sdim  for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
90326938Sdim    setOperationAction(Opc, MVT::i32, Expand);
91326938Sdim
92326938Sdim  // Operations to get us off of the ground.
93326938Sdim  // Basic.
94326938Sdim  setOperationAction(ISD::ADD, MVT::i32, Legal);
95326938Sdim  setOperationAction(ISD::SUB, MVT::i32, Legal);
96326938Sdim  setOperationAction(ISD::AND, MVT::i32, Legal);
97326938Sdim  setOperationAction(ISD::SMAX, MVT::i32, Legal);
98326938Sdim  setOperationAction(ISD::SMIN, MVT::i32, Legal);
99326938Sdim
100326938Sdim  // Need barrel shifter.
101326938Sdim  setOperationAction(ISD::SHL, MVT::i32, Legal);
102326938Sdim  setOperationAction(ISD::SRA, MVT::i32, Legal);
103326938Sdim  setOperationAction(ISD::SRL, MVT::i32, Legal);
104326938Sdim  setOperationAction(ISD::ROTR, MVT::i32, Legal);
105326938Sdim
106326938Sdim  setOperationAction(ISD::Constant, MVT::i32, Legal);
107326938Sdim  setOperationAction(ISD::UNDEF, MVT::i32, Legal);
108326938Sdim
109326938Sdim  // Need multiplier
110326938Sdim  setOperationAction(ISD::MUL, MVT::i32, Legal);
111326938Sdim  setOperationAction(ISD::MULHS, MVT::i32, Legal);
112326938Sdim  setOperationAction(ISD::MULHU, MVT::i32, Legal);
113326938Sdim  setOperationAction(ISD::LOAD, MVT::i32, Legal);
114326938Sdim  setOperationAction(ISD::STORE, MVT::i32, Legal);
115326938Sdim
116326938Sdim  setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
117326938Sdim  setOperationAction(ISD::BR_CC, MVT::i32, Custom);
118326938Sdim  setOperationAction(ISD::BRCOND, MVT::Other, Expand);
119326938Sdim  setOperationAction(ISD::BR_JT, MVT::Other, Expand);
120326938Sdim  setOperationAction(ISD::JumpTable, MVT::i32, Custom);
121326938Sdim
122360784Sdim  // Have pseudo instruction for frame addresses.
123326938Sdim  setOperationAction(ISD::FRAMEADDR, MVT::i32, Legal);
124326938Sdim  // Custom lower global addresses.
125326938Sdim  setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
126326938Sdim
127326938Sdim  // Expand var-args ops.
128326938Sdim  setOperationAction(ISD::VASTART, MVT::Other, Custom);
129326938Sdim  setOperationAction(ISD::VAEND, MVT::Other, Expand);
130326938Sdim  setOperationAction(ISD::VAARG, MVT::Other, Expand);
131326938Sdim  setOperationAction(ISD::VACOPY, MVT::Other, Expand);
132326938Sdim
133326938Sdim  // Other expansions
134326938Sdim  setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
135326938Sdim  setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
136326938Sdim
137326938Sdim  // Sign extend inreg
138326938Sdim  setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Custom);
139326938Sdim}
140326938Sdim
141326938Sdimconst char *ARCTargetLowering::getTargetNodeName(unsigned Opcode) const {
142326938Sdim  switch (Opcode) {
143326938Sdim  case ARCISD::BL:
144326938Sdim    return "ARCISD::BL";
145326938Sdim  case ARCISD::CMOV:
146326938Sdim    return "ARCISD::CMOV";
147326938Sdim  case ARCISD::CMP:
148326938Sdim    return "ARCISD::CMP";
149326938Sdim  case ARCISD::BRcc:
150326938Sdim    return "ARCISD::BRcc";
151326938Sdim  case ARCISD::RET:
152326938Sdim    return "ARCISD::RET";
153326938Sdim  case ARCISD::GAWRAPPER:
154326938Sdim    return "ARCISD::GAWRAPPER";
155326938Sdim  }
156326938Sdim  return nullptr;
157326938Sdim}
158326938Sdim
159326938Sdim//===----------------------------------------------------------------------===//
160326938Sdim//  Misc Lower Operation implementation
161326938Sdim//===----------------------------------------------------------------------===//
162326938Sdim
163326938SdimSDValue ARCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
164326938Sdim  SDValue LHS = Op.getOperand(0);
165326938Sdim  SDValue RHS = Op.getOperand(1);
166326938Sdim  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
167326938Sdim  SDValue TVal = Op.getOperand(2);
168326938Sdim  SDValue FVal = Op.getOperand(3);
169326938Sdim  SDLoc dl(Op);
170326938Sdim  ARCCC::CondCode ArcCC = ISDCCtoARCCC(CC);
171326938Sdim  assert(LHS.getValueType() == MVT::i32 && "Only know how to SELECT_CC i32");
172326938Sdim  SDValue Cmp = DAG.getNode(ARCISD::CMP, dl, MVT::Glue, LHS, RHS);
173326938Sdim  return DAG.getNode(ARCISD::CMOV, dl, TVal.getValueType(), TVal, FVal,
174326938Sdim                     DAG.getConstant(ArcCC, dl, MVT::i32), Cmp);
175326938Sdim}
176326938Sdim
177326938SdimSDValue ARCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
178326938Sdim                                                  SelectionDAG &DAG) const {
179326938Sdim  SDValue Op0 = Op.getOperand(0);
180326938Sdim  SDLoc dl(Op);
181326938Sdim  assert(Op.getValueType() == MVT::i32 &&
182326938Sdim         "Unhandled target sign_extend_inreg.");
183326938Sdim  // These are legal
184326938Sdim  unsigned Width = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits();
185326938Sdim  if (Width == 16 || Width == 8)
186326938Sdim    return Op;
187326938Sdim  if (Width >= 32) {
188326938Sdim    return {};
189326938Sdim  }
190326938Sdim  SDValue LS = DAG.getNode(ISD::SHL, dl, MVT::i32, Op0,
191326938Sdim                           DAG.getConstant(32 - Width, dl, MVT::i32));
192326938Sdim  SDValue SR = DAG.getNode(ISD::SRA, dl, MVT::i32, LS,
193326938Sdim                           DAG.getConstant(32 - Width, dl, MVT::i32));
194326938Sdim  return SR;
195326938Sdim}
196326938Sdim
197326938SdimSDValue ARCTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
198326938Sdim  SDValue Chain = Op.getOperand(0);
199326938Sdim  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
200326938Sdim  SDValue LHS = Op.getOperand(2);
201326938Sdim  SDValue RHS = Op.getOperand(3);
202326938Sdim  SDValue Dest = Op.getOperand(4);
203326938Sdim  SDLoc dl(Op);
204326938Sdim  ARCCC::CondCode arcCC = ISDCCtoARCCC(CC);
205326938Sdim  assert(LHS.getValueType() == MVT::i32 && "Only know how to BR_CC i32");
206326938Sdim  return DAG.getNode(ARCISD::BRcc, dl, MVT::Other, Chain, Dest, LHS, RHS,
207326938Sdim                     DAG.getConstant(arcCC, dl, MVT::i32));
208326938Sdim}
209326938Sdim
210326938SdimSDValue ARCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
211326938Sdim  auto *N = cast<JumpTableSDNode>(Op);
212326938Sdim  SDValue GA = DAG.getTargetJumpTable(N->getIndex(), MVT::i32);
213326938Sdim  return DAG.getNode(ARCISD::GAWRAPPER, SDLoc(N), MVT::i32, GA);
214326938Sdim}
215326938Sdim
216326938Sdim#include "ARCGenCallingConv.inc"
217326938Sdim
218326938Sdim//===----------------------------------------------------------------------===//
219326938Sdim//                  Call Calling Convention Implementation
220326938Sdim//===----------------------------------------------------------------------===//
221326938Sdim
222326938Sdim/// ARC call implementation
223326938SdimSDValue ARCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
224326938Sdim                                     SmallVectorImpl<SDValue> &InVals) const {
225326938Sdim  SelectionDAG &DAG = CLI.DAG;
226326938Sdim  SDLoc &dl = CLI.DL;
227326938Sdim  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
228326938Sdim  SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
229326938Sdim  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
230326938Sdim  SDValue Chain = CLI.Chain;
231326938Sdim  SDValue Callee = CLI.Callee;
232326938Sdim  CallingConv::ID CallConv = CLI.CallConv;
233326938Sdim  bool IsVarArg = CLI.IsVarArg;
234326938Sdim  bool &IsTailCall = CLI.IsTailCall;
235326938Sdim
236326938Sdim  IsTailCall = false; // Do not support tail calls yet.
237326938Sdim
238326938Sdim  SmallVector<CCValAssign, 16> ArgLocs;
239326938Sdim  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
240326938Sdim                 *DAG.getContext());
241326938Sdim
242326938Sdim  CCInfo.AnalyzeCallOperands(Outs, CC_ARC);
243326938Sdim
244326938Sdim  SmallVector<CCValAssign, 16> RVLocs;
245326938Sdim  // Analyze return values to determine the number of bytes of stack required.
246326938Sdim  CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
247326938Sdim                    *DAG.getContext());
248326938Sdim  RetCCInfo.AllocateStack(CCInfo.getNextStackOffset(), 4);
249326938Sdim  RetCCInfo.AnalyzeCallResult(Ins, RetCC_ARC);
250326938Sdim
251326938Sdim  // Get a count of how many bytes are to be pushed on the stack.
252326938Sdim  unsigned NumBytes = RetCCInfo.getNextStackOffset();
253326938Sdim  auto PtrVT = getPointerTy(DAG.getDataLayout());
254326938Sdim
255326938Sdim  Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
256326938Sdim
257326938Sdim  SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
258326938Sdim  SmallVector<SDValue, 12> MemOpChains;
259326938Sdim
260326938Sdim  SDValue StackPtr;
261326938Sdim  // Walk the register/memloc assignments, inserting copies/loads.
262326938Sdim  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
263326938Sdim    CCValAssign &VA = ArgLocs[i];
264326938Sdim    SDValue Arg = OutVals[i];
265326938Sdim
266326938Sdim    // Promote the value if needed.
267326938Sdim    switch (VA.getLocInfo()) {
268326938Sdim    default:
269326938Sdim      llvm_unreachable("Unknown loc info!");
270326938Sdim    case CCValAssign::Full:
271326938Sdim      break;
272326938Sdim    case CCValAssign::SExt:
273326938Sdim      Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
274326938Sdim      break;
275326938Sdim    case CCValAssign::ZExt:
276326938Sdim      Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
277326938Sdim      break;
278326938Sdim    case CCValAssign::AExt:
279326938Sdim      Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
280326938Sdim      break;
281326938Sdim    }
282326938Sdim
283326938Sdim    // Arguments that can be passed on register must be kept at
284326938Sdim    // RegsToPass vector
285326938Sdim    if (VA.isRegLoc()) {
286326938Sdim      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
287326938Sdim    } else {
288326938Sdim      assert(VA.isMemLoc() && "Must be register or memory argument.");
289326938Sdim      if (!StackPtr.getNode())
290326938Sdim        StackPtr = DAG.getCopyFromReg(Chain, dl, ARC::SP,
291326938Sdim                                      getPointerTy(DAG.getDataLayout()));
292326938Sdim      // Calculate the stack position.
293326938Sdim      SDValue SOffset = DAG.getIntPtrConstant(VA.getLocMemOffset(), dl);
294326938Sdim      SDValue PtrOff = DAG.getNode(
295326938Sdim          ISD::ADD, dl, getPointerTy(DAG.getDataLayout()), StackPtr, SOffset);
296326938Sdim
297326938Sdim      SDValue Store =
298326938Sdim          DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
299326938Sdim      MemOpChains.push_back(Store);
300326938Sdim      IsTailCall = false;
301326938Sdim    }
302326938Sdim  }
303326938Sdim
304326938Sdim  // Transform all store nodes into one single node because
305326938Sdim  // all store nodes are independent of each other.
306326938Sdim  if (!MemOpChains.empty())
307326938Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
308326938Sdim
309326938Sdim  // Build a sequence of copy-to-reg nodes chained together with token
310326938Sdim  // chain and flag operands which copy the outgoing args into registers.
311326938Sdim  // The InFlag in necessary since all emitted instructions must be
312326938Sdim  // stuck together.
313326938Sdim  SDValue Glue;
314326938Sdim  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
315326938Sdim    Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
316326938Sdim                             RegsToPass[i].second, Glue);
317326938Sdim    Glue = Chain.getValue(1);
318326938Sdim  }
319326938Sdim
320326938Sdim  // If the callee is a GlobalAddress node (quite common, every direct call is)
321326938Sdim  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
322326938Sdim  // Likewise ExternalSymbol -> TargetExternalSymbol.
323326938Sdim  bool IsDirect = true;
324326938Sdim  if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
325326938Sdim    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
326326938Sdim  else if (auto *E = dyn_cast<ExternalSymbolSDNode>(Callee))
327326938Sdim    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
328326938Sdim  else
329326938Sdim    IsDirect = false;
330326938Sdim  // Branch + Link = #chain, #target_address, #opt_in_flags...
331326938Sdim  //             = Chain, Callee, Reg#1, Reg#2, ...
332326938Sdim  //
333326938Sdim  // Returns a chain & a flag for retval copy to use.
334326938Sdim  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
335326938Sdim  SmallVector<SDValue, 8> Ops;
336326938Sdim  Ops.push_back(Chain);
337326938Sdim  Ops.push_back(Callee);
338326938Sdim
339326938Sdim  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
340326938Sdim    Ops.push_back(DAG.getRegister(RegsToPass[i].first,
341326938Sdim                                  RegsToPass[i].second.getValueType()));
342326938Sdim
343326938Sdim  // Add a register mask operand representing the call-preserved registers.
344326938Sdim  const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
345326938Sdim  const uint32_t *Mask =
346326938Sdim      TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
347326938Sdim  assert(Mask && "Missing call preserved mask for calling convention");
348326938Sdim  Ops.push_back(DAG.getRegisterMask(Mask));
349326938Sdim
350326938Sdim  if (Glue.getNode())
351326938Sdim    Ops.push_back(Glue);
352326938Sdim
353326938Sdim  Chain = DAG.getNode(IsDirect ? ARCISD::BL : ARCISD::JL, dl, NodeTys, Ops);
354326938Sdim  Glue = Chain.getValue(1);
355326938Sdim
356326938Sdim  // Create the CALLSEQ_END node.
357326938Sdim  Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, dl, PtrVT, true),
358326938Sdim                             DAG.getConstant(0, dl, PtrVT, true), Glue, dl);
359326938Sdim  Glue = Chain.getValue(1);
360326938Sdim
361326938Sdim  // Handle result values, copying them out of physregs into vregs that we
362326938Sdim  // return.
363326938Sdim  if (IsTailCall)
364326938Sdim    return Chain;
365326938Sdim  return lowerCallResult(Chain, Glue, RVLocs, dl, DAG, InVals);
366326938Sdim}
367326938Sdim
368326938Sdim/// Lower the result values of a call into the appropriate copies out of
369326938Sdim/// physical registers / memory locations.
370326938Sdimstatic SDValue lowerCallResult(SDValue Chain, SDValue Glue,
371326938Sdim                               const SmallVectorImpl<CCValAssign> &RVLocs,
372326938Sdim                               SDLoc dl, SelectionDAG &DAG,
373326938Sdim                               SmallVectorImpl<SDValue> &InVals) {
374326938Sdim  SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs;
375326938Sdim  // Copy results out of physical registers.
376326938Sdim  for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
377326938Sdim    const CCValAssign &VA = RVLocs[i];
378326938Sdim    if (VA.isRegLoc()) {
379326938Sdim      SDValue RetValue;
380326938Sdim      RetValue =
381326938Sdim          DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), Glue);
382326938Sdim      Chain = RetValue.getValue(1);
383326938Sdim      Glue = RetValue.getValue(2);
384326938Sdim      InVals.push_back(RetValue);
385326938Sdim    } else {
386326938Sdim      assert(VA.isMemLoc() && "Must be memory location.");
387326938Sdim      ResultMemLocs.push_back(
388326938Sdim          std::make_pair(VA.getLocMemOffset(), InVals.size()));
389326938Sdim
390326938Sdim      // Reserve space for this result.
391326938Sdim      InVals.push_back(SDValue());
392326938Sdim    }
393326938Sdim  }
394326938Sdim
395326938Sdim  // Copy results out of memory.
396326938Sdim  SmallVector<SDValue, 4> MemOpChains;
397326938Sdim  for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) {
398326938Sdim    int Offset = ResultMemLocs[i].first;
399326938Sdim    unsigned Index = ResultMemLocs[i].second;
400326938Sdim    SDValue StackPtr = DAG.getRegister(ARC::SP, MVT::i32);
401326938Sdim    SDValue SpLoc = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr,
402326938Sdim                                DAG.getConstant(Offset, dl, MVT::i32));
403326938Sdim    SDValue Load =
404326938Sdim        DAG.getLoad(MVT::i32, dl, Chain, SpLoc, MachinePointerInfo());
405326938Sdim    InVals[Index] = Load;
406326938Sdim    MemOpChains.push_back(Load.getValue(1));
407326938Sdim  }
408326938Sdim
409326938Sdim  // Transform all loads nodes into one single node because
410326938Sdim  // all load nodes are independent of each other.
411326938Sdim  if (!MemOpChains.empty())
412326938Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
413326938Sdim
414326938Sdim  return Chain;
415326938Sdim}
416326938Sdim
417326938Sdim//===----------------------------------------------------------------------===//
418326938Sdim//             Formal Arguments Calling Convention Implementation
419326938Sdim//===----------------------------------------------------------------------===//
420326938Sdim
421326938Sdimnamespace {
422326938Sdim
423326938Sdimstruct ArgDataPair {
424326938Sdim  SDValue SDV;
425326938Sdim  ISD::ArgFlagsTy Flags;
426326938Sdim};
427326938Sdim
428326938Sdim} // end anonymous namespace
429326938Sdim
430326938Sdim/// ARC formal arguments implementation
431326938SdimSDValue ARCTargetLowering::LowerFormalArguments(
432326938Sdim    SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
433326938Sdim    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
434326938Sdim    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
435326938Sdim  switch (CallConv) {
436326938Sdim  default:
437326938Sdim    llvm_unreachable("Unsupported calling convention");
438326938Sdim  case CallingConv::C:
439326938Sdim  case CallingConv::Fast:
440326938Sdim    return LowerCallArguments(Chain, CallConv, IsVarArg, Ins, dl, DAG, InVals);
441326938Sdim  }
442326938Sdim}
443326938Sdim
444326938Sdim/// Transform physical registers into virtual registers, and generate load
445326938Sdim/// operations for argument places on the stack.
446326938SdimSDValue ARCTargetLowering::LowerCallArguments(
447326938Sdim    SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
448326938Sdim    const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG,
449326938Sdim    SmallVectorImpl<SDValue> &InVals) const {
450326938Sdim  MachineFunction &MF = DAG.getMachineFunction();
451326938Sdim  MachineFrameInfo &MFI = MF.getFrameInfo();
452326938Sdim  MachineRegisterInfo &RegInfo = MF.getRegInfo();
453326938Sdim  auto *AFI = MF.getInfo<ARCFunctionInfo>();
454326938Sdim
455326938Sdim  // Assign locations to all of the incoming arguments.
456326938Sdim  SmallVector<CCValAssign, 16> ArgLocs;
457326938Sdim  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
458326938Sdim                 *DAG.getContext());
459326938Sdim
460326938Sdim  CCInfo.AnalyzeFormalArguments(Ins, CC_ARC);
461326938Sdim
462326938Sdim  unsigned StackSlotSize = 4;
463326938Sdim
464326938Sdim  if (!IsVarArg)
465326938Sdim    AFI->setReturnStackOffset(CCInfo.getNextStackOffset());
466326938Sdim
467326938Sdim  // All getCopyFromReg ops must precede any getMemcpys to prevent the
468326938Sdim  // scheduler clobbering a register before it has been copied.
469326938Sdim  // The stages are:
470326938Sdim  // 1. CopyFromReg (and load) arg & vararg registers.
471326938Sdim  // 2. Chain CopyFromReg nodes into a TokenFactor.
472326938Sdim  // 3. Memcpy 'byVal' args & push final InVals.
473326938Sdim  // 4. Chain mem ops nodes into a TokenFactor.
474326938Sdim  SmallVector<SDValue, 4> CFRegNode;
475326938Sdim  SmallVector<ArgDataPair, 4> ArgData;
476326938Sdim  SmallVector<SDValue, 4> MemOps;
477326938Sdim
478326938Sdim  // 1a. CopyFromReg (and load) arg registers.
479326938Sdim  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
480326938Sdim    CCValAssign &VA = ArgLocs[i];
481326938Sdim    SDValue ArgIn;
482326938Sdim
483326938Sdim    if (VA.isRegLoc()) {
484326938Sdim      // Arguments passed in registers
485326938Sdim      EVT RegVT = VA.getLocVT();
486326938Sdim      switch (RegVT.getSimpleVT().SimpleTy) {
487326938Sdim      default: {
488341825Sdim        LLVM_DEBUG(errs() << "LowerFormalArguments Unhandled argument type: "
489341825Sdim                          << (unsigned)RegVT.getSimpleVT().SimpleTy << "\n");
490326938Sdim        llvm_unreachable("Unhandled LowerFormalArguments type.");
491326938Sdim      }
492326938Sdim      case MVT::i32:
493326938Sdim        unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);
494326938Sdim        RegInfo.addLiveIn(VA.getLocReg(), VReg);
495326938Sdim        ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
496326938Sdim        CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1));
497326938Sdim      }
498326938Sdim    } else {
499326938Sdim      // sanity check
500326938Sdim      assert(VA.isMemLoc());
501326938Sdim      // Load the argument to a virtual register
502326938Sdim      unsigned ObjSize = VA.getLocVT().getStoreSize();
503326938Sdim      assert((ObjSize <= StackSlotSize) && "Unhandled argument");
504326938Sdim
505326938Sdim      // Create the frame index object for this incoming parameter...
506326938Sdim      int FI = MFI.CreateFixedObject(ObjSize, VA.getLocMemOffset(), true);
507326938Sdim
508326938Sdim      // Create the SelectionDAG nodes corresponding to a load
509326938Sdim      // from this parameter
510326938Sdim      SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
511326938Sdim      ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
512326938Sdim                          MachinePointerInfo::getFixedStack(MF, FI));
513326938Sdim    }
514326938Sdim    const ArgDataPair ADP = {ArgIn, Ins[i].Flags};
515326938Sdim    ArgData.push_back(ADP);
516326938Sdim  }
517326938Sdim
518326938Sdim  // 1b. CopyFromReg vararg registers.
519326938Sdim  if (IsVarArg) {
520326938Sdim    // Argument registers
521326938Sdim    static const MCPhysReg ArgRegs[] = {ARC::R0, ARC::R1, ARC::R2, ARC::R3,
522326938Sdim                                        ARC::R4, ARC::R5, ARC::R6, ARC::R7};
523326938Sdim    auto *AFI = MF.getInfo<ARCFunctionInfo>();
524326938Sdim    unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs);
525326938Sdim    if (FirstVAReg < array_lengthof(ArgRegs)) {
526326938Sdim      int Offset = 0;
527326938Sdim      // Save remaining registers, storing higher register numbers at a higher
528326938Sdim      // address
529326938Sdim      // There are (array_lengthof(ArgRegs) - FirstVAReg) registers which
530326938Sdim      // need to be saved.
531326938Sdim      int VarFI =
532326938Sdim          MFI.CreateFixedObject((array_lengthof(ArgRegs) - FirstVAReg) * 4,
533326938Sdim                                CCInfo.getNextStackOffset(), true);
534326938Sdim      AFI->setVarArgsFrameIndex(VarFI);
535326938Sdim      SDValue FIN = DAG.getFrameIndex(VarFI, MVT::i32);
536326938Sdim      for (unsigned i = FirstVAReg; i < array_lengthof(ArgRegs); i++) {
537326938Sdim        // Move argument from phys reg -> virt reg
538326938Sdim        unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);
539326938Sdim        RegInfo.addLiveIn(ArgRegs[i], VReg);
540326938Sdim        SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
541326938Sdim        CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1));
542326938Sdim        SDValue VAObj = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN,
543326938Sdim                                    DAG.getConstant(Offset, dl, MVT::i32));
544326938Sdim        // Move argument from virt reg -> stack
545326938Sdim        SDValue Store =
546326938Sdim            DAG.getStore(Val.getValue(1), dl, Val, VAObj, MachinePointerInfo());
547326938Sdim        MemOps.push_back(Store);
548326938Sdim        Offset += 4;
549326938Sdim      }
550326938Sdim    } else {
551326938Sdim      llvm_unreachable("Too many var args parameters.");
552326938Sdim    }
553326938Sdim  }
554326938Sdim
555326938Sdim  // 2. Chain CopyFromReg nodes into a TokenFactor.
556326938Sdim  if (!CFRegNode.empty())
557326938Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode);
558326938Sdim
559326938Sdim  // 3. Memcpy 'byVal' args & push final InVals.
560326938Sdim  // Aggregates passed "byVal" need to be copied by the callee.
561326938Sdim  // The callee will use a pointer to this copy, rather than the original
562326938Sdim  // pointer.
563326938Sdim  for (const auto &ArgDI : ArgData) {
564326938Sdim    if (ArgDI.Flags.isByVal() && ArgDI.Flags.getByValSize()) {
565326938Sdim      unsigned Size = ArgDI.Flags.getByValSize();
566326938Sdim      unsigned Align = std::max(StackSlotSize, ArgDI.Flags.getByValAlign());
567326938Sdim      // Create a new object on the stack and copy the pointee into it.
568326938Sdim      int FI = MFI.CreateStackObject(Size, Align, false);
569326938Sdim      SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
570326938Sdim      InVals.push_back(FIN);
571326938Sdim      MemOps.push_back(DAG.getMemcpy(
572326938Sdim          Chain, dl, FIN, ArgDI.SDV, DAG.getConstant(Size, dl, MVT::i32), Align,
573326938Sdim          false, false, false, MachinePointerInfo(), MachinePointerInfo()));
574326938Sdim    } else {
575326938Sdim      InVals.push_back(ArgDI.SDV);
576326938Sdim    }
577326938Sdim  }
578326938Sdim
579326938Sdim  // 4. Chain mem ops nodes into a TokenFactor.
580326938Sdim  if (!MemOps.empty()) {
581326938Sdim    MemOps.push_back(Chain);
582326938Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
583326938Sdim  }
584326938Sdim
585326938Sdim  return Chain;
586326938Sdim}
587326938Sdim
588326938Sdim//===----------------------------------------------------------------------===//
589326938Sdim//               Return Value Calling Convention Implementation
590326938Sdim//===----------------------------------------------------------------------===//
591326938Sdim
592326938Sdimbool ARCTargetLowering::CanLowerReturn(
593326938Sdim    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
594326938Sdim    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
595326938Sdim  SmallVector<CCValAssign, 16> RVLocs;
596326938Sdim  CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
597326938Sdim  if (!CCInfo.CheckReturn(Outs, RetCC_ARC))
598326938Sdim    return false;
599326938Sdim  if (CCInfo.getNextStackOffset() != 0 && IsVarArg)
600326938Sdim    return false;
601326938Sdim  return true;
602326938Sdim}
603326938Sdim
604326938SdimSDValue
605326938SdimARCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
606326938Sdim                               bool IsVarArg,
607326938Sdim                               const SmallVectorImpl<ISD::OutputArg> &Outs,
608326938Sdim                               const SmallVectorImpl<SDValue> &OutVals,
609326938Sdim                               const SDLoc &dl, SelectionDAG &DAG) const {
610326938Sdim  auto *AFI = DAG.getMachineFunction().getInfo<ARCFunctionInfo>();
611326938Sdim  MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
612326938Sdim
613326938Sdim  // CCValAssign - represent the assignment of
614326938Sdim  // the return value to a location
615326938Sdim  SmallVector<CCValAssign, 16> RVLocs;
616326938Sdim
617326938Sdim  // CCState - Info about the registers and stack slot.
618326938Sdim  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
619326938Sdim                 *DAG.getContext());
620326938Sdim
621326938Sdim  // Analyze return values.
622326938Sdim  if (!IsVarArg)
623326938Sdim    CCInfo.AllocateStack(AFI->getReturnStackOffset(), 4);
624326938Sdim
625326938Sdim  CCInfo.AnalyzeReturn(Outs, RetCC_ARC);
626326938Sdim
627326938Sdim  SDValue Flag;
628326938Sdim  SmallVector<SDValue, 4> RetOps(1, Chain);
629326938Sdim  SmallVector<SDValue, 4> MemOpChains;
630326938Sdim  // Handle return values that must be copied to memory.
631326938Sdim  for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
632326938Sdim    CCValAssign &VA = RVLocs[i];
633326938Sdim    if (VA.isRegLoc())
634326938Sdim      continue;
635326938Sdim    assert(VA.isMemLoc());
636326938Sdim    if (IsVarArg) {
637326938Sdim      report_fatal_error("Can't return value from vararg function in memory");
638326938Sdim    }
639326938Sdim
640326938Sdim    int Offset = VA.getLocMemOffset();
641326938Sdim    unsigned ObjSize = VA.getLocVT().getStoreSize();
642326938Sdim    // Create the frame index object for the memory location.
643326938Sdim    int FI = MFI.CreateFixedObject(ObjSize, Offset, false);
644326938Sdim
645326938Sdim    // Create a SelectionDAG node corresponding to a store
646326938Sdim    // to this memory location.
647326938Sdim    SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
648326938Sdim    MemOpChains.push_back(DAG.getStore(
649326938Sdim        Chain, dl, OutVals[i], FIN,
650326938Sdim        MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)));
651326938Sdim  }
652326938Sdim
653326938Sdim  // Transform all store nodes into one single node because
654326938Sdim  // all stores are independent of each other.
655326938Sdim  if (!MemOpChains.empty())
656326938Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
657326938Sdim
658326938Sdim  // Now handle return values copied to registers.
659326938Sdim  for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
660326938Sdim    CCValAssign &VA = RVLocs[i];
661326938Sdim    if (!VA.isRegLoc())
662326938Sdim      continue;
663326938Sdim    // Copy the result values into the output registers.
664326938Sdim    Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag);
665326938Sdim
666326938Sdim    // guarantee that all emitted copies are
667326938Sdim    // stuck together, avoiding something bad
668326938Sdim    Flag = Chain.getValue(1);
669326938Sdim    RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
670326938Sdim  }
671326938Sdim
672326938Sdim  RetOps[0] = Chain; // Update chain.
673326938Sdim
674326938Sdim  // Add the flag if we have it.
675326938Sdim  if (Flag.getNode())
676326938Sdim    RetOps.push_back(Flag);
677326938Sdim
678326938Sdim  // What to do with the RetOps?
679326938Sdim  return DAG.getNode(ARCISD::RET, dl, MVT::Other, RetOps);
680326938Sdim}
681326938Sdim
682326938Sdim//===----------------------------------------------------------------------===//
683326938Sdim// Target Optimization Hooks
684326938Sdim//===----------------------------------------------------------------------===//
685326938Sdim
686326938SdimSDValue ARCTargetLowering::PerformDAGCombine(SDNode *N,
687326938Sdim                                             DAGCombinerInfo &DCI) const {
688326938Sdim  return {};
689326938Sdim}
690326938Sdim
691326938Sdim//===----------------------------------------------------------------------===//
692326938Sdim//  Addressing mode description hooks
693326938Sdim//===----------------------------------------------------------------------===//
694326938Sdim
695326938Sdim/// Return true if the addressing mode represented by AM is legal for this
696326938Sdim/// target, for a load/store of the specified type.
697326938Sdimbool ARCTargetLowering::isLegalAddressingMode(const DataLayout &DL,
698326938Sdim                                              const AddrMode &AM, Type *Ty,
699326938Sdim                                              unsigned AS,
700326938Sdim                                              Instruction *I) const {
701326938Sdim  return AM.Scale == 0;
702326938Sdim}
703326938Sdim
704326938Sdim// Don't emit tail calls for the time being.
705326938Sdimbool ARCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
706326938Sdim  return false;
707326938Sdim}
708326938Sdim
709326938SdimSDValue ARCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
710326938Sdim  const ARCRegisterInfo &ARI = *Subtarget.getRegisterInfo();
711326938Sdim  MachineFunction &MF = DAG.getMachineFunction();
712326938Sdim  MachineFrameInfo &MFI = MF.getFrameInfo();
713326938Sdim  MFI.setFrameAddressIsTaken(true);
714326938Sdim
715326938Sdim  EVT VT = Op.getValueType();
716326938Sdim  SDLoc dl(Op);
717326938Sdim  assert(cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0 &&
718326938Sdim         "Only support lowering frame addr of current frame.");
719360784Sdim  Register FrameReg = ARI.getFrameRegister(MF);
720326938Sdim  return DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
721326938Sdim}
722326938Sdim
723326938SdimSDValue ARCTargetLowering::LowerGlobalAddress(SDValue Op,
724326938Sdim                                              SelectionDAG &DAG) const {
725326938Sdim  const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
726326938Sdim  const GlobalValue *GV = GN->getGlobal();
727326938Sdim  SDLoc dl(GN);
728326938Sdim  int64_t Offset = GN->getOffset();
729326938Sdim  SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, Offset);
730326938Sdim  return DAG.getNode(ARCISD::GAWRAPPER, dl, MVT::i32, GA);
731326938Sdim}
732326938Sdim
733326938Sdimstatic SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) {
734326938Sdim  MachineFunction &MF = DAG.getMachineFunction();
735326938Sdim  auto *FuncInfo = MF.getInfo<ARCFunctionInfo>();
736326938Sdim
737326938Sdim  // vastart just stores the address of the VarArgsFrameIndex slot into the
738326938Sdim  // memory location argument.
739326938Sdim  SDLoc dl(Op);
740326938Sdim  EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout());
741326938Sdim  SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
742326938Sdim  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
743326938Sdim  return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1),
744326938Sdim                      MachinePointerInfo(SV));
745326938Sdim}
746326938Sdim
747326938SdimSDValue ARCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
748326938Sdim  switch (Op.getOpcode()) {
749326938Sdim  case ISD::GlobalAddress:
750326938Sdim    return LowerGlobalAddress(Op, DAG);
751326938Sdim  case ISD::FRAMEADDR:
752326938Sdim    return LowerFRAMEADDR(Op, DAG);
753326938Sdim  case ISD::SELECT_CC:
754326938Sdim    return LowerSELECT_CC(Op, DAG);
755326938Sdim  case ISD::BR_CC:
756326938Sdim    return LowerBR_CC(Op, DAG);
757326938Sdim  case ISD::SIGN_EXTEND_INREG:
758326938Sdim    return LowerSIGN_EXTEND_INREG(Op, DAG);
759326938Sdim  case ISD::JumpTable:
760326938Sdim    return LowerJumpTable(Op, DAG);
761326938Sdim  case ISD::VASTART:
762326938Sdim    return LowerVASTART(Op, DAG);
763326938Sdim  default:
764326938Sdim    llvm_unreachable("unimplemented operand");
765326938Sdim  }
766326938Sdim}
767