1234285Sdim//===-- HexagonISelLowering.cpp - Hexagon DAG Lowering Implementation -----===//
2234285Sdim//
3234285Sdim//                     The LLVM Compiler Infrastructure
4234285Sdim//
5234285Sdim// This file is distributed under the University of Illinois Open Source
6234285Sdim// License. See LICENSE.TXT for details.
7234285Sdim//
8234285Sdim//===----------------------------------------------------------------------===//
9234285Sdim//
10234285Sdim// This file implements the interfaces that Hexagon uses to lower LLVM code
11234285Sdim// into a selection DAG.
12234285Sdim//
13234285Sdim//===----------------------------------------------------------------------===//
14234285Sdim
15234285Sdim#include "HexagonISelLowering.h"
16252723Sdim#include "HexagonMachineFunctionInfo.h"
17252723Sdim#include "HexagonSubtarget.h"
18234285Sdim#include "HexagonTargetMachine.h"
19234285Sdim#include "HexagonTargetObjectFile.h"
20234285Sdim#include "llvm/CodeGen/CallingConvLower.h"
21234285Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
22234285Sdim#include "llvm/CodeGen/MachineFunction.h"
23234285Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
24234285Sdim#include "llvm/CodeGen/MachineJumpTableInfo.h"
25234285Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
26234285Sdim#include "llvm/CodeGen/SelectionDAGISel.h"
27234285Sdim#include "llvm/CodeGen/ValueTypes.h"
28252723Sdim#include "llvm/IR/CallingConv.h"
29252723Sdim#include "llvm/IR/DerivedTypes.h"
30252723Sdim#include "llvm/IR/Function.h"
31252723Sdim#include "llvm/IR/GlobalAlias.h"
32252723Sdim#include "llvm/IR/GlobalVariable.h"
33252723Sdim#include "llvm/IR/InlineAsm.h"
34252723Sdim#include "llvm/IR/Intrinsics.h"
35235633Sdim#include "llvm/Support/CommandLine.h"
36234285Sdim#include "llvm/Support/Debug.h"
37234285Sdim#include "llvm/Support/ErrorHandling.h"
38235633Sdim#include "llvm/Support/raw_ostream.h"
39235633Sdim
40234285Sdimusing namespace llvm;
41234285Sdim
42234285Sdimstatic cl::opt<bool>
43234285SdimEmitJumpTables("hexagon-emit-jump-tables", cl::init(true), cl::Hidden,
44234285Sdim               cl::desc("Control jump table emission on Hexagon target"));
45234285Sdim
46263509Sdimnamespace {
47263509Sdimclass HexagonCCState : public CCState {
48263509Sdim  int NumNamedVarArgParams;
49234285Sdim
50263509Sdimpublic:
51263509Sdim  HexagonCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
52263509Sdim                 const TargetMachine &TM, SmallVectorImpl<CCValAssign> &locs,
53263509Sdim                 LLVMContext &C, int NumNamedVarArgParams)
54263509Sdim      : CCState(CC, isVarArg, MF, TM, locs, C),
55263509Sdim        NumNamedVarArgParams(NumNamedVarArgParams) {}
56263509Sdim
57263509Sdim  int getNumNamedVarArgParams() const { return NumNamedVarArgParams; }
58263509Sdim};
59263509Sdim}
60263509Sdim
61234285Sdim// Implement calling convention for Hexagon.
62234285Sdimstatic bool
63234285SdimCC_Hexagon(unsigned ValNo, MVT ValVT,
64234285Sdim           MVT LocVT, CCValAssign::LocInfo LocInfo,
65234285Sdim           ISD::ArgFlagsTy ArgFlags, CCState &State);
66234285Sdim
67234285Sdimstatic bool
68234285SdimCC_Hexagon32(unsigned ValNo, MVT ValVT,
69234285Sdim             MVT LocVT, CCValAssign::LocInfo LocInfo,
70234285Sdim             ISD::ArgFlagsTy ArgFlags, CCState &State);
71234285Sdim
72234285Sdimstatic bool
73234285SdimCC_Hexagon64(unsigned ValNo, MVT ValVT,
74234285Sdim             MVT LocVT, CCValAssign::LocInfo LocInfo,
75234285Sdim             ISD::ArgFlagsTy ArgFlags, CCState &State);
76234285Sdim
77234285Sdimstatic bool
78234285SdimRetCC_Hexagon(unsigned ValNo, MVT ValVT,
79234285Sdim              MVT LocVT, CCValAssign::LocInfo LocInfo,
80234285Sdim              ISD::ArgFlagsTy ArgFlags, CCState &State);
81234285Sdim
82234285Sdimstatic bool
83234285SdimRetCC_Hexagon32(unsigned ValNo, MVT ValVT,
84234285Sdim                MVT LocVT, CCValAssign::LocInfo LocInfo,
85234285Sdim                ISD::ArgFlagsTy ArgFlags, CCState &State);
86234285Sdim
87234285Sdimstatic bool
88234285SdimRetCC_Hexagon64(unsigned ValNo, MVT ValVT,
89234285Sdim                MVT LocVT, CCValAssign::LocInfo LocInfo,
90234285Sdim                ISD::ArgFlagsTy ArgFlags, CCState &State);
91234285Sdim
92234285Sdimstatic bool
93234285SdimCC_Hexagon_VarArg (unsigned ValNo, MVT ValVT,
94234285Sdim            MVT LocVT, CCValAssign::LocInfo LocInfo,
95234285Sdim            ISD::ArgFlagsTy ArgFlags, CCState &State) {
96263509Sdim  HexagonCCState &HState = static_cast<HexagonCCState &>(State);
97234285Sdim
98234285Sdim  // NumNamedVarArgParams can not be zero for a VarArg function.
99263509Sdim  assert((HState.getNumNamedVarArgParams() > 0) &&
100263509Sdim         "NumNamedVarArgParams is not bigger than zero.");
101234285Sdim
102263509Sdim  if ((int)ValNo < HState.getNumNamedVarArgParams()) {
103234285Sdim    // Deal with named arguments.
104234285Sdim    return CC_Hexagon(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State);
105234285Sdim  }
106234285Sdim
107234285Sdim  // Deal with un-named arguments.
108234285Sdim  unsigned ofst;
109234285Sdim  if (ArgFlags.isByVal()) {
110234285Sdim    // If pass-by-value, the size allocated on stack is decided
111234285Sdim    // by ArgFlags.getByValSize(), not by the size of LocVT.
112234285Sdim    assert ((ArgFlags.getByValSize() > 8) &&
113234285Sdim            "ByValSize must be bigger than 8 bytes");
114234285Sdim    ofst = State.AllocateStack(ArgFlags.getByValSize(), 4);
115234285Sdim    State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
116234285Sdim    return false;
117234285Sdim  }
118252723Sdim  if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) {
119252723Sdim    LocVT = MVT::i32;
120252723Sdim    ValVT = MVT::i32;
121252723Sdim    if (ArgFlags.isSExt())
122252723Sdim      LocInfo = CCValAssign::SExt;
123252723Sdim    else if (ArgFlags.isZExt())
124252723Sdim      LocInfo = CCValAssign::ZExt;
125252723Sdim    else
126252723Sdim      LocInfo = CCValAssign::AExt;
127252723Sdim  }
128245431Sdim  if (LocVT == MVT::i32 || LocVT == MVT::f32) {
129234285Sdim    ofst = State.AllocateStack(4, 4);
130234285Sdim    State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
131234285Sdim    return false;
132234285Sdim  }
133245431Sdim  if (LocVT == MVT::i64 || LocVT == MVT::f64) {
134234285Sdim    ofst = State.AllocateStack(8, 8);
135234285Sdim    State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
136234285Sdim    return false;
137234285Sdim  }
138234285Sdim  llvm_unreachable(0);
139234285Sdim}
140234285Sdim
141234285Sdim
142234285Sdimstatic bool
143234285SdimCC_Hexagon (unsigned ValNo, MVT ValVT,
144234285Sdim            MVT LocVT, CCValAssign::LocInfo LocInfo,
145234285Sdim            ISD::ArgFlagsTy ArgFlags, CCState &State) {
146234285Sdim
147234285Sdim  if (ArgFlags.isByVal()) {
148234285Sdim    // Passed on stack.
149234285Sdim    assert ((ArgFlags.getByValSize() > 8) &&
150234285Sdim            "ByValSize must be bigger than 8 bytes");
151234285Sdim    unsigned Offset = State.AllocateStack(ArgFlags.getByValSize(), 4);
152234285Sdim    State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
153234285Sdim    return false;
154234285Sdim  }
155234285Sdim
156234285Sdim  if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) {
157234285Sdim    LocVT = MVT::i32;
158234285Sdim    ValVT = MVT::i32;
159234285Sdim    if (ArgFlags.isSExt())
160234285Sdim      LocInfo = CCValAssign::SExt;
161234285Sdim    else if (ArgFlags.isZExt())
162234285Sdim      LocInfo = CCValAssign::ZExt;
163234285Sdim    else
164234285Sdim      LocInfo = CCValAssign::AExt;
165234285Sdim  }
166234285Sdim
167245431Sdim  if (LocVT == MVT::i32 || LocVT == MVT::f32) {
168234285Sdim    if (!CC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
169234285Sdim      return false;
170234285Sdim  }
171234285Sdim
172245431Sdim  if (LocVT == MVT::i64 || LocVT == MVT::f64) {
173234285Sdim    if (!CC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
174234285Sdim      return false;
175234285Sdim  }
176234285Sdim
177234285Sdim  return true;  // CC didn't match.
178234285Sdim}
179234285Sdim
180234285Sdim
181234285Sdimstatic bool CC_Hexagon32(unsigned ValNo, MVT ValVT,
182234285Sdim                         MVT LocVT, CCValAssign::LocInfo LocInfo,
183234285Sdim                         ISD::ArgFlagsTy ArgFlags, CCState &State) {
184234285Sdim
185234285Sdim  static const uint16_t RegList[] = {
186234285Sdim    Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4,
187234285Sdim    Hexagon::R5
188234285Sdim  };
189234285Sdim  if (unsigned Reg = State.AllocateReg(RegList, 6)) {
190234285Sdim    State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
191234285Sdim    return false;
192234285Sdim  }
193234285Sdim
194234285Sdim  unsigned Offset = State.AllocateStack(4, 4);
195234285Sdim  State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
196234285Sdim  return false;
197234285Sdim}
198234285Sdim
199234285Sdimstatic bool CC_Hexagon64(unsigned ValNo, MVT ValVT,
200234285Sdim                         MVT LocVT, CCValAssign::LocInfo LocInfo,
201234285Sdim                         ISD::ArgFlagsTy ArgFlags, CCState &State) {
202234285Sdim
203234285Sdim  if (unsigned Reg = State.AllocateReg(Hexagon::D0)) {
204234285Sdim    State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
205234285Sdim    return false;
206234285Sdim  }
207234285Sdim
208234285Sdim  static const uint16_t RegList1[] = {
209234285Sdim    Hexagon::D1, Hexagon::D2
210234285Sdim  };
211234285Sdim  static const uint16_t RegList2[] = {
212234285Sdim    Hexagon::R1, Hexagon::R3
213234285Sdim  };
214234285Sdim  if (unsigned Reg = State.AllocateReg(RegList1, RegList2, 2)) {
215234285Sdim    State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
216234285Sdim    return false;
217234285Sdim  }
218234285Sdim
219234285Sdim  unsigned Offset = State.AllocateStack(8, 8, Hexagon::D2);
220234285Sdim  State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
221234285Sdim  return false;
222234285Sdim}
223234285Sdim
224234285Sdimstatic bool RetCC_Hexagon(unsigned ValNo, MVT ValVT,
225234285Sdim                          MVT LocVT, CCValAssign::LocInfo LocInfo,
226234285Sdim                          ISD::ArgFlagsTy ArgFlags, CCState &State) {
227234285Sdim
228234285Sdim
229234285Sdim  if (LocVT == MVT::i1 ||
230234285Sdim      LocVT == MVT::i8 ||
231234285Sdim      LocVT == MVT::i16) {
232234285Sdim    LocVT = MVT::i32;
233234285Sdim    ValVT = MVT::i32;
234234285Sdim    if (ArgFlags.isSExt())
235234285Sdim      LocInfo = CCValAssign::SExt;
236234285Sdim    else if (ArgFlags.isZExt())
237234285Sdim      LocInfo = CCValAssign::ZExt;
238234285Sdim    else
239234285Sdim      LocInfo = CCValAssign::AExt;
240234285Sdim  }
241234285Sdim
242245431Sdim  if (LocVT == MVT::i32 || LocVT == MVT::f32) {
243234285Sdim    if (!RetCC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
244234285Sdim    return false;
245234285Sdim  }
246234285Sdim
247245431Sdim  if (LocVT == MVT::i64 || LocVT == MVT::f64) {
248234285Sdim    if (!RetCC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
249234285Sdim    return false;
250234285Sdim  }
251234285Sdim
252234285Sdim  return true;  // CC didn't match.
253234285Sdim}
254234285Sdim
255234285Sdimstatic bool RetCC_Hexagon32(unsigned ValNo, MVT ValVT,
256234285Sdim                            MVT LocVT, CCValAssign::LocInfo LocInfo,
257234285Sdim                            ISD::ArgFlagsTy ArgFlags, CCState &State) {
258234285Sdim
259245431Sdim  if (LocVT == MVT::i32 || LocVT == MVT::f32) {
260234285Sdim    if (unsigned Reg = State.AllocateReg(Hexagon::R0)) {
261234285Sdim      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
262234285Sdim      return false;
263234285Sdim    }
264234285Sdim  }
265234285Sdim
266234285Sdim  unsigned Offset = State.AllocateStack(4, 4);
267234285Sdim  State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
268234285Sdim  return false;
269234285Sdim}
270234285Sdim
271234285Sdimstatic bool RetCC_Hexagon64(unsigned ValNo, MVT ValVT,
272234285Sdim                            MVT LocVT, CCValAssign::LocInfo LocInfo,
273234285Sdim                            ISD::ArgFlagsTy ArgFlags, CCState &State) {
274245431Sdim  if (LocVT == MVT::i64 || LocVT == MVT::f64) {
275234285Sdim    if (unsigned Reg = State.AllocateReg(Hexagon::D0)) {
276234285Sdim      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
277234285Sdim      return false;
278234285Sdim    }
279234285Sdim  }
280234285Sdim
281234285Sdim  unsigned Offset = State.AllocateStack(8, 8);
282234285Sdim  State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
283234285Sdim  return false;
284234285Sdim}
285234285Sdim
286234285SdimSDValue
287234285SdimHexagonTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG)
288234285Sdimconst {
289234285Sdim  return SDValue();
290234285Sdim}
291234285Sdim
292234285Sdim/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified
293234285Sdim/// by "Src" to address "Dst" of size "Size".  Alignment information is
294234285Sdim/// specified by the specific parameter attribute. The copy will be passed as
295234285Sdim/// a byval function parameter.  Sometimes what we are copying is the end of a
296234285Sdim/// larger object, the part that does not fit in registers.
297234285Sdimstatic SDValue
298234285SdimCreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain,
299234285Sdim                          ISD::ArgFlagsTy Flags, SelectionDAG &DAG,
300263509Sdim                          SDLoc dl) {
301234285Sdim
302234285Sdim  SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32);
303234285Sdim  return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(),
304234285Sdim                       /*isVolatile=*/false, /*AlwaysInline=*/false,
305234285Sdim                       MachinePointerInfo(), MachinePointerInfo());
306234285Sdim}
307234285Sdim
308234285Sdim
309234285Sdim// LowerReturn - Lower ISD::RET. If a struct is larger than 8 bytes and is
310234285Sdim// passed by value, the function prototype is modified to return void and
311234285Sdim// the value is stored in memory pointed by a pointer passed by caller.
312234285SdimSDValue
313234285SdimHexagonTargetLowering::LowerReturn(SDValue Chain,
314234285Sdim                                   CallingConv::ID CallConv, bool isVarArg,
315234285Sdim                                   const SmallVectorImpl<ISD::OutputArg> &Outs,
316234285Sdim                                   const SmallVectorImpl<SDValue> &OutVals,
317263509Sdim                                   SDLoc dl, SelectionDAG &DAG) const {
318234285Sdim
319234285Sdim  // CCValAssign - represent the assignment of the return value to locations.
320234285Sdim  SmallVector<CCValAssign, 16> RVLocs;
321234285Sdim
322234285Sdim  // CCState - Info about the registers and stack slot.
323234285Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
324245431Sdim                 getTargetMachine(), RVLocs, *DAG.getContext());
325234285Sdim
326234285Sdim  // Analyze return values of ISD::RET
327234285Sdim  CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon);
328234285Sdim
329252723Sdim  SDValue Flag;
330252723Sdim  SmallVector<SDValue, 4> RetOps(1, Chain);
331234285Sdim
332234285Sdim  // Copy the result values into the output registers.
333234285Sdim  for (unsigned i = 0; i != RVLocs.size(); ++i) {
334234285Sdim    CCValAssign &VA = RVLocs[i];
335234285Sdim
336234285Sdim    Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag);
337234285Sdim
338234285Sdim    // Guarantee that all emitted copies are stuck together with flags.
339234285Sdim    Flag = Chain.getValue(1);
340252723Sdim    RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
341234285Sdim  }
342234285Sdim
343252723Sdim  RetOps[0] = Chain;  // Update chain.
344252723Sdim
345252723Sdim  // Add the flag if we have it.
346234285Sdim  if (Flag.getNode())
347252723Sdim    RetOps.push_back(Flag);
348234285Sdim
349252723Sdim  return DAG.getNode(HexagonISD::RET_FLAG, dl, MVT::Other,
350252723Sdim                     &RetOps[0], RetOps.size());
351234285Sdim}
352234285Sdim
353234285Sdim
354234285Sdim
355234285Sdim
356234285Sdim/// LowerCallResult - Lower the result values of an ISD::CALL into the
357234285Sdim/// appropriate copies out of appropriate physical registers.  This assumes that
358234285Sdim/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
359234285Sdim/// being lowered. Returns a SDNode with the same number of values as the
360234285Sdim/// ISD::CALL.
361234285SdimSDValue
362234285SdimHexagonTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
363234285Sdim                                       CallingConv::ID CallConv, bool isVarArg,
364234285Sdim                                       const
365234285Sdim                                       SmallVectorImpl<ISD::InputArg> &Ins,
366263509Sdim                                       SDLoc dl, SelectionDAG &DAG,
367234285Sdim                                       SmallVectorImpl<SDValue> &InVals,
368234285Sdim                                       const SmallVectorImpl<SDValue> &OutVals,
369234285Sdim                                       SDValue Callee) const {
370234285Sdim
371234285Sdim  // Assign locations to each value returned by this call.
372234285Sdim  SmallVector<CCValAssign, 16> RVLocs;
373234285Sdim
374234285Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
375245431Sdim                 getTargetMachine(), RVLocs, *DAG.getContext());
376234285Sdim
377234285Sdim  CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon);
378234285Sdim
379234285Sdim  // Copy all of the result registers out of their specified physreg.
380234285Sdim  for (unsigned i = 0; i != RVLocs.size(); ++i) {
381234285Sdim    Chain = DAG.getCopyFromReg(Chain, dl,
382234285Sdim                               RVLocs[i].getLocReg(),
383234285Sdim                               RVLocs[i].getValVT(), InFlag).getValue(1);
384234285Sdim    InFlag = Chain.getValue(2);
385234285Sdim    InVals.push_back(Chain.getValue(0));
386234285Sdim  }
387234285Sdim
388234285Sdim  return Chain;
389234285Sdim}
390234285Sdim
391234285Sdim/// LowerCall - Functions arguments are copied from virtual regs to
392234285Sdim/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
393234285SdimSDValue
394245431SdimHexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
395234285Sdim                                 SmallVectorImpl<SDValue> &InVals) const {
396245431Sdim  SelectionDAG &DAG                     = CLI.DAG;
397263509Sdim  SDLoc &dl                             = CLI.DL;
398263509Sdim  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
399263509Sdim  SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
400263509Sdim  SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
401245431Sdim  SDValue Chain                         = CLI.Chain;
402245431Sdim  SDValue Callee                        = CLI.Callee;
403245431Sdim  bool &isTailCall                      = CLI.IsTailCall;
404245431Sdim  CallingConv::ID CallConv              = CLI.CallConv;
405245431Sdim  bool isVarArg                         = CLI.IsVarArg;
406234285Sdim
407234285Sdim  bool IsStructRet    = (Outs.empty()) ? false : Outs[0].Flags.isSRet();
408234285Sdim
409234285Sdim  // Check for varargs.
410263509Sdim  int NumNamedVarArgParams = -1;
411234285Sdim  if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Callee))
412234285Sdim  {
413234285Sdim    const Function* CalleeFn = NULL;
414234285Sdim    Callee = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, MVT::i32);
415234285Sdim    if ((CalleeFn = dyn_cast<Function>(GA->getGlobal())))
416234285Sdim    {
417234285Sdim      // If a function has zero args and is a vararg function, that's
418234285Sdim      // disallowed so it must be an undeclared function.  Do not assume
419234285Sdim      // varargs if the callee is undefined.
420234285Sdim      if (CalleeFn->isVarArg() &&
421234285Sdim          CalleeFn->getFunctionType()->getNumParams() != 0) {
422234285Sdim        NumNamedVarArgParams = CalleeFn->getFunctionType()->getNumParams();
423234285Sdim      }
424234285Sdim    }
425234285Sdim  }
426234285Sdim
427263509Sdim  // Analyze operands of the call, assigning locations to each operand.
428263509Sdim  SmallVector<CCValAssign, 16> ArgLocs;
429263509Sdim  HexagonCCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
430263509Sdim                        getTargetMachine(), ArgLocs, *DAG.getContext(),
431263509Sdim                        NumNamedVarArgParams);
432263509Sdim
433234285Sdim  if (NumNamedVarArgParams > 0)
434234285Sdim    CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_VarArg);
435234285Sdim  else
436234285Sdim    CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon);
437234285Sdim
438234285Sdim
439234285Sdim  if(isTailCall) {
440234285Sdim    bool StructAttrFlag =
441234285Sdim      DAG.getMachineFunction().getFunction()->hasStructRetAttr();
442234285Sdim    isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv,
443234285Sdim                                                   isVarArg, IsStructRet,
444234285Sdim                                                   StructAttrFlag,
445234285Sdim                                                   Outs, OutVals, Ins, DAG);
446234285Sdim    for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i){
447234285Sdim      CCValAssign &VA = ArgLocs[i];
448234285Sdim      if (VA.isMemLoc()) {
449234285Sdim        isTailCall = false;
450234285Sdim        break;
451234285Sdim      }
452234285Sdim    }
453234285Sdim    if (isTailCall) {
454234285Sdim      DEBUG(dbgs () << "Eligible for Tail Call\n");
455234285Sdim    } else {
456234285Sdim      DEBUG(dbgs () <<
457234285Sdim            "Argument must be passed on stack. Not eligible for Tail Call\n");
458234285Sdim    }
459234285Sdim  }
460234285Sdim  // Get a count of how many bytes are to be pushed on the stack.
461234285Sdim  unsigned NumBytes = CCInfo.getNextStackOffset();
462234285Sdim  SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass;
463234285Sdim  SmallVector<SDValue, 8> MemOpChains;
464234285Sdim
465234285Sdim  SDValue StackPtr =
466234285Sdim    DAG.getCopyFromReg(Chain, dl, TM.getRegisterInfo()->getStackRegister(),
467234285Sdim                       getPointerTy());
468234285Sdim
469234285Sdim  // Walk the register/memloc assignments, inserting copies/loads.
470234285Sdim  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
471234285Sdim    CCValAssign &VA = ArgLocs[i];
472234285Sdim    SDValue Arg = OutVals[i];
473234285Sdim    ISD::ArgFlagsTy Flags = Outs[i].Flags;
474234285Sdim
475234285Sdim    // Promote the value if needed.
476234285Sdim    switch (VA.getLocInfo()) {
477234285Sdim      default:
478234285Sdim        // Loc info must be one of Full, SExt, ZExt, or AExt.
479234285Sdim        llvm_unreachable("Unknown loc info!");
480234285Sdim      case CCValAssign::Full:
481234285Sdim        break;
482234285Sdim      case CCValAssign::SExt:
483234285Sdim        Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
484234285Sdim        break;
485234285Sdim      case CCValAssign::ZExt:
486234285Sdim        Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
487234285Sdim        break;
488234285Sdim      case CCValAssign::AExt:
489234285Sdim        Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
490234285Sdim        break;
491234285Sdim    }
492234285Sdim
493234285Sdim    if (VA.isMemLoc()) {
494234285Sdim      unsigned LocMemOffset = VA.getLocMemOffset();
495234285Sdim      SDValue PtrOff = DAG.getConstant(LocMemOffset, StackPtr.getValueType());
496234285Sdim      PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
497234285Sdim
498234285Sdim      if (Flags.isByVal()) {
499234285Sdim        // The argument is a struct passed by value. According to LLVM, "Arg"
500234285Sdim        // is is pointer.
501234285Sdim        MemOpChains.push_back(CreateCopyOfByValArgument(Arg, PtrOff, Chain,
502234285Sdim                                                        Flags, DAG, dl));
503234285Sdim      } else {
504234285Sdim        // The argument is not passed by value. "Arg" is a buildin type. It is
505234285Sdim        // not a pointer.
506234285Sdim        MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
507234285Sdim                                           MachinePointerInfo(),false, false,
508234285Sdim                                           0));
509234285Sdim      }
510234285Sdim      continue;
511234285Sdim    }
512234285Sdim
513234285Sdim    // Arguments that can be passed on register must be kept at RegsToPass
514234285Sdim    // vector.
515234285Sdim    if (VA.isRegLoc()) {
516234285Sdim      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
517234285Sdim    }
518234285Sdim  }
519234285Sdim
520234285Sdim  // Transform all store nodes into one single node because all store
521234285Sdim  // nodes are independent of each other.
522234285Sdim  if (!MemOpChains.empty()) {
523234285Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOpChains[0],
524234285Sdim                        MemOpChains.size());
525234285Sdim  }
526234285Sdim
527234285Sdim  if (!isTailCall)
528234285Sdim    Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumBytes,
529263509Sdim                                                        getPointerTy(), true),
530263509Sdim                                 dl);
531234285Sdim
532234285Sdim  // Build a sequence of copy-to-reg nodes chained together with token
533234285Sdim  // chain and flag operands which copy the outgoing args into registers.
534245431Sdim  // The InFlag in necessary since all emitted instructions must be
535234285Sdim  // stuck together.
536234285Sdim  SDValue InFlag;
537234285Sdim  if (!isTailCall) {
538234285Sdim    for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
539234285Sdim      Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
540234285Sdim                               RegsToPass[i].second, InFlag);
541234285Sdim      InFlag = Chain.getValue(1);
542234285Sdim    }
543234285Sdim  }
544234285Sdim
545234285Sdim  // For tail calls lower the arguments to the 'real' stack slot.
546234285Sdim  if (isTailCall) {
547234285Sdim    // Force all the incoming stack arguments to be loaded from the stack
548234285Sdim    // before any new outgoing arguments are stored to the stack, because the
549234285Sdim    // outgoing stack slots may alias the incoming argument stack slots, and
550234285Sdim    // the alias isn't otherwise explicit. This is slightly more conservative
551234285Sdim    // than necessary, because it means that each store effectively depends
552234285Sdim    // on every argument instead of just those arguments it would clobber.
553234285Sdim    //
554245431Sdim    // Do not flag preceding copytoreg stuff together with the following stuff.
555234285Sdim    InFlag = SDValue();
556234285Sdim    for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
557234285Sdim      Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
558234285Sdim                               RegsToPass[i].second, InFlag);
559234285Sdim      InFlag = Chain.getValue(1);
560234285Sdim    }
561234285Sdim    InFlag =SDValue();
562234285Sdim  }
563234285Sdim
564234285Sdim  // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
565234285Sdim  // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
566234285Sdim  // node so that legalize doesn't hack it.
567234285Sdim  if (flag_aligned_memcpy) {
568234285Sdim    const char *MemcpyName =
569234285Sdim      "__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes";
570234285Sdim    Callee =
571234285Sdim      DAG.getTargetExternalSymbol(MemcpyName, getPointerTy());
572234285Sdim    flag_aligned_memcpy = false;
573234285Sdim  } else if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
574234285Sdim    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy());
575234285Sdim  } else if (ExternalSymbolSDNode *S =
576234285Sdim             dyn_cast<ExternalSymbolSDNode>(Callee)) {
577234285Sdim    Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
578234285Sdim  }
579234285Sdim
580234285Sdim  // Returns a chain & a flag for retval copy to use.
581234285Sdim  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
582234285Sdim  SmallVector<SDValue, 8> Ops;
583234285Sdim  Ops.push_back(Chain);
584234285Sdim  Ops.push_back(Callee);
585234285Sdim
586234285Sdim  // Add argument registers to the end of the list so that they are
587234285Sdim  // known live into the call.
588234285Sdim  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
589234285Sdim    Ops.push_back(DAG.getRegister(RegsToPass[i].first,
590234285Sdim                                  RegsToPass[i].second.getValueType()));
591234285Sdim  }
592234285Sdim
593234285Sdim  if (InFlag.getNode()) {
594234285Sdim    Ops.push_back(InFlag);
595234285Sdim  }
596234285Sdim
597234285Sdim  if (isTailCall)
598234285Sdim    return DAG.getNode(HexagonISD::TC_RETURN, dl, NodeTys, &Ops[0], Ops.size());
599234285Sdim
600234285Sdim  Chain = DAG.getNode(HexagonISD::CALL, dl, NodeTys, &Ops[0], Ops.size());
601234285Sdim  InFlag = Chain.getValue(1);
602234285Sdim
603234285Sdim  // Create the CALLSEQ_END node.
604234285Sdim  Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true),
605263509Sdim                             DAG.getIntPtrConstant(0, true), InFlag, dl);
606234285Sdim  InFlag = Chain.getValue(1);
607234285Sdim
608234285Sdim  // Handle result values, copying them out of physregs into vregs that we
609234285Sdim  // return.
610234285Sdim  return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, DAG,
611234285Sdim                         InVals, OutVals, Callee);
612234285Sdim}
613234285Sdim
614234285Sdimstatic bool getIndexedAddressParts(SDNode *Ptr, EVT VT,
615234285Sdim                                   bool isSEXTLoad, SDValue &Base,
616234285Sdim                                   SDValue &Offset, bool &isInc,
617234285Sdim                                   SelectionDAG &DAG) {
618234285Sdim  if (Ptr->getOpcode() != ISD::ADD)
619234285Sdim  return false;
620234285Sdim
621234285Sdim  if (VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) {
622234285Sdim    isInc = (Ptr->getOpcode() == ISD::ADD);
623234285Sdim    Base = Ptr->getOperand(0);
624234285Sdim    Offset = Ptr->getOperand(1);
625234285Sdim    // Ensure that Offset is a constant.
626234285Sdim    return (isa<ConstantSDNode>(Offset));
627234285Sdim  }
628234285Sdim
629234285Sdim  return false;
630234285Sdim}
631234285Sdim
632234285Sdim// TODO: Put this function along with the other isS* functions in
633234285Sdim// HexagonISelDAGToDAG.cpp into a common file. Or better still, use the
634252723Sdim// functions defined in HexagonOperands.td.
635234285Sdimstatic bool Is_PostInc_S4_Offset(SDNode * S, int ShiftAmount) {
636234285Sdim  ConstantSDNode *N = cast<ConstantSDNode>(S);
637234285Sdim
638234285Sdim  // immS4 predicate - True if the immediate fits in a 4-bit sign extended.
639234285Sdim  // field.
640234285Sdim  int64_t v = (int64_t)N->getSExtValue();
641234285Sdim  int64_t m = 0;
642234285Sdim  if (ShiftAmount > 0) {
643234285Sdim    m = v % ShiftAmount;
644234285Sdim    v = v >> ShiftAmount;
645234285Sdim  }
646234285Sdim  return (v <= 7) && (v >= -8) && (m == 0);
647234285Sdim}
648234285Sdim
649234285Sdim/// getPostIndexedAddressParts - returns true by value, base pointer and
650234285Sdim/// offset pointer and addressing mode by reference if this node can be
651234285Sdim/// combined with a load / store to form a post-indexed load / store.
652234285Sdimbool HexagonTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
653234285Sdim                                                       SDValue &Base,
654234285Sdim                                                       SDValue &Offset,
655234285Sdim                                                       ISD::MemIndexedMode &AM,
656234285Sdim                                                       SelectionDAG &DAG) const
657234285Sdim{
658234285Sdim  EVT VT;
659234285Sdim  SDValue Ptr;
660234285Sdim  bool isSEXTLoad = false;
661234285Sdim
662234285Sdim  if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
663234285Sdim    VT  = LD->getMemoryVT();
664234285Sdim    isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD;
665234285Sdim  } else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
666234285Sdim    VT  = ST->getMemoryVT();
667234285Sdim    if (ST->getValue().getValueType() == MVT::i64 && ST->isTruncatingStore()) {
668234285Sdim      return false;
669234285Sdim    }
670234285Sdim  } else {
671234285Sdim    return false;
672234285Sdim  }
673234285Sdim
674234285Sdim  bool isInc = false;
675234285Sdim  bool isLegal = getIndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset,
676234285Sdim                                        isInc, DAG);
677234285Sdim  // ShiftAmount = number of left-shifted bits in the Hexagon instruction.
678234285Sdim  int ShiftAmount = VT.getSizeInBits() / 16;
679234285Sdim  if (isLegal && Is_PostInc_S4_Offset(Offset.getNode(), ShiftAmount)) {
680234285Sdim    AM = isInc ? ISD::POST_INC : ISD::POST_DEC;
681234285Sdim    return true;
682234285Sdim  }
683234285Sdim
684234285Sdim  return false;
685234285Sdim}
686234285Sdim
687234285SdimSDValue HexagonTargetLowering::LowerINLINEASM(SDValue Op,
688234285Sdim                                              SelectionDAG &DAG) const {
689234285Sdim  SDNode *Node = Op.getNode();
690234285Sdim  MachineFunction &MF = DAG.getMachineFunction();
691234285Sdim  HexagonMachineFunctionInfo *FuncInfo =
692234285Sdim    MF.getInfo<HexagonMachineFunctionInfo>();
693234285Sdim  switch (Node->getOpcode()) {
694234285Sdim    case ISD::INLINEASM: {
695234285Sdim      unsigned NumOps = Node->getNumOperands();
696234285Sdim      if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue)
697234285Sdim        --NumOps;  // Ignore the flag operand.
698234285Sdim
699234285Sdim      for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
700234285Sdim        if (FuncInfo->hasClobberLR())
701234285Sdim          break;
702234285Sdim        unsigned Flags =
703234285Sdim          cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
704234285Sdim        unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
705234285Sdim        ++i;  // Skip the ID value.
706234285Sdim
707234285Sdim        switch (InlineAsm::getKind(Flags)) {
708234285Sdim        default: llvm_unreachable("Bad flags!");
709234285Sdim          case InlineAsm::Kind_RegDef:
710234285Sdim          case InlineAsm::Kind_RegUse:
711234285Sdim          case InlineAsm::Kind_Imm:
712234285Sdim          case InlineAsm::Kind_Clobber:
713234285Sdim          case InlineAsm::Kind_Mem: {
714234285Sdim            for (; NumVals; --NumVals, ++i) {}
715234285Sdim            break;
716234285Sdim          }
717234285Sdim          case InlineAsm::Kind_RegDefEarlyClobber: {
718234285Sdim            for (; NumVals; --NumVals, ++i) {
719234285Sdim              unsigned Reg =
720234285Sdim                cast<RegisterSDNode>(Node->getOperand(i))->getReg();
721234285Sdim
722234285Sdim              // Check it to be lr
723234285Sdim              if (Reg == TM.getRegisterInfo()->getRARegister()) {
724234285Sdim                FuncInfo->setHasClobberLR(true);
725234285Sdim                break;
726234285Sdim              }
727234285Sdim            }
728234285Sdim            break;
729234285Sdim          }
730234285Sdim        }
731234285Sdim      }
732234285Sdim    }
733234285Sdim  } // Node->getOpcode
734234285Sdim  return Op;
735234285Sdim}
736234285Sdim
737234285Sdim
738234285Sdim//
739234285Sdim// Taken from the XCore backend.
740234285Sdim//
741234285SdimSDValue HexagonTargetLowering::
742234285SdimLowerBR_JT(SDValue Op, SelectionDAG &DAG) const
743234285Sdim{
744234285Sdim  SDValue Chain = Op.getOperand(0);
745234285Sdim  SDValue Table = Op.getOperand(1);
746234285Sdim  SDValue Index = Op.getOperand(2);
747263509Sdim  SDLoc dl(Op);
748234285Sdim  JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
749234285Sdim  unsigned JTI = JT->getIndex();
750234285Sdim  MachineFunction &MF = DAG.getMachineFunction();
751234285Sdim  const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
752234285Sdim  SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
753234285Sdim
754234285Sdim  // Mark all jump table targets as address taken.
755234285Sdim  const std::vector<MachineJumpTableEntry> &JTE = MJTI->getJumpTables();
756234285Sdim  const std::vector<MachineBasicBlock*> &JTBBs = JTE[JTI].MBBs;
757234285Sdim  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
758234285Sdim    MachineBasicBlock *MBB = JTBBs[i];
759234285Sdim    MBB->setHasAddressTaken();
760234285Sdim    // This line is needed to set the hasAddressTaken flag on the BasicBlock
761234285Sdim    // object.
762234285Sdim    BlockAddress::get(const_cast<BasicBlock *>(MBB->getBasicBlock()));
763234285Sdim  }
764234285Sdim
765234285Sdim  SDValue JumpTableBase = DAG.getNode(HexagonISD::WrapperJT, dl,
766234285Sdim                                      getPointerTy(), TargetJT);
767234285Sdim  SDValue ShiftIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index,
768234285Sdim                                   DAG.getConstant(2, MVT::i32));
769234285Sdim  SDValue JTAddress = DAG.getNode(ISD::ADD, dl, MVT::i32, JumpTableBase,
770234285Sdim                                  ShiftIndex);
771234285Sdim  SDValue LoadTarget = DAG.getLoad(MVT::i32, dl, Chain, JTAddress,
772234285Sdim                                   MachinePointerInfo(), false, false, false,
773234285Sdim                                   0);
774234285Sdim  return DAG.getNode(HexagonISD::BR_JT, dl, MVT::Other, Chain, LoadTarget);
775234285Sdim}
776234285Sdim
777234285Sdim
778234285SdimSDValue
779234285SdimHexagonTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
780234285Sdim                                               SelectionDAG &DAG) const {
781234285Sdim  SDValue Chain = Op.getOperand(0);
782234285Sdim  SDValue Size = Op.getOperand(1);
783263509Sdim  SDLoc dl(Op);
784234285Sdim
785234285Sdim  unsigned SPReg = getStackPointerRegisterToSaveRestore();
786234285Sdim
787234285Sdim  // Get a reference to the stack pointer.
788234285Sdim  SDValue StackPointer = DAG.getCopyFromReg(Chain, dl, SPReg, MVT::i32);
789234285Sdim
790234285Sdim  // Subtract the dynamic size from the actual stack size to
791234285Sdim  // obtain the new stack size.
792234285Sdim  SDValue Sub = DAG.getNode(ISD::SUB, dl, MVT::i32, StackPointer, Size);
793234285Sdim
794234285Sdim  //
795234285Sdim  // For Hexagon, the outgoing memory arguments area should be on top of the
796234285Sdim  // alloca area on the stack i.e., the outgoing memory arguments should be
797234285Sdim  // at a lower address than the alloca area. Move the alloca area down the
798234285Sdim  // stack by adding back the space reserved for outgoing arguments to SP
799234285Sdim  // here.
800234285Sdim  //
801234285Sdim  // We do not know what the size of the outgoing args is at this point.
802234285Sdim  // So, we add a pseudo instruction ADJDYNALLOC that will adjust the
803234285Sdim  // stack pointer. We patch this instruction with the correct, known
804234285Sdim  // offset in emitPrologue().
805234285Sdim  //
806234285Sdim  // Use a placeholder immediate (zero) for now. This will be patched up
807234285Sdim  // by emitPrologue().
808234285Sdim  SDValue ArgAdjust = DAG.getNode(HexagonISD::ADJDYNALLOC, dl,
809234285Sdim                                  MVT::i32,
810234285Sdim                                  Sub,
811234285Sdim                                  DAG.getConstant(0, MVT::i32));
812234285Sdim
813234285Sdim  // The Sub result contains the new stack start address, so it
814234285Sdim  // must be placed in the stack pointer register.
815234285Sdim  SDValue CopyChain = DAG.getCopyToReg(Chain, dl,
816234285Sdim                                       TM.getRegisterInfo()->getStackRegister(),
817234285Sdim                                       Sub);
818234285Sdim
819234285Sdim  SDValue Ops[2] = { ArgAdjust, CopyChain };
820234285Sdim  return DAG.getMergeValues(Ops, 2, dl);
821234285Sdim}
822234285Sdim
823234285SdimSDValue
824234285SdimHexagonTargetLowering::LowerFormalArguments(SDValue Chain,
825234285Sdim                                            CallingConv::ID CallConv,
826234285Sdim                                            bool isVarArg,
827234285Sdim                                            const
828234285Sdim                                            SmallVectorImpl<ISD::InputArg> &Ins,
829263509Sdim                                            SDLoc dl, SelectionDAG &DAG,
830234285Sdim                                            SmallVectorImpl<SDValue> &InVals)
831234285Sdimconst {
832234285Sdim
833234285Sdim  MachineFunction &MF = DAG.getMachineFunction();
834234285Sdim  MachineFrameInfo *MFI = MF.getFrameInfo();
835234285Sdim  MachineRegisterInfo &RegInfo = MF.getRegInfo();
836234285Sdim  HexagonMachineFunctionInfo *FuncInfo =
837234285Sdim    MF.getInfo<HexagonMachineFunctionInfo>();
838234285Sdim
839234285Sdim
840234285Sdim  // Assign locations to all of the incoming arguments.
841234285Sdim  SmallVector<CCValAssign, 16> ArgLocs;
842234285Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
843245431Sdim                 getTargetMachine(), ArgLocs, *DAG.getContext());
844234285Sdim
845234285Sdim  CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon);
846234285Sdim
847234285Sdim  // For LLVM, in the case when returning a struct by value (>8byte),
848234285Sdim  // the first argument is a pointer that points to the location on caller's
849234285Sdim  // stack where the return value will be stored. For Hexagon, the location on
850234285Sdim  // caller's stack is passed only when the struct size is smaller than (and
851234285Sdim  // equal to) 8 bytes. If not, no address will be passed into callee and
852234285Sdim  // callee return the result direclty through R0/R1.
853234285Sdim
854234285Sdim  SmallVector<SDValue, 4> MemOps;
855234285Sdim
856234285Sdim  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
857234285Sdim    CCValAssign &VA = ArgLocs[i];
858234285Sdim    ISD::ArgFlagsTy Flags = Ins[i].Flags;
859234285Sdim    unsigned ObjSize;
860234285Sdim    unsigned StackLocation;
861234285Sdim    int FI;
862234285Sdim
863234285Sdim    if (   (VA.isRegLoc() && !Flags.isByVal())
864234285Sdim        || (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() > 8)) {
865234285Sdim      // Arguments passed in registers
866234285Sdim      // 1. int, long long, ptr args that get allocated in register.
867234285Sdim      // 2. Large struct that gets an register to put its address in.
868234285Sdim      EVT RegVT = VA.getLocVT();
869245431Sdim      if (RegVT == MVT::i8 || RegVT == MVT::i16 ||
870245431Sdim          RegVT == MVT::i32 || RegVT == MVT::f32) {
871234285Sdim        unsigned VReg =
872245431Sdim          RegInfo.createVirtualRegister(&Hexagon::IntRegsRegClass);
873234285Sdim        RegInfo.addLiveIn(VA.getLocReg(), VReg);
874234285Sdim        InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
875234285Sdim      } else if (RegVT == MVT::i64) {
876234285Sdim        unsigned VReg =
877245431Sdim          RegInfo.createVirtualRegister(&Hexagon::DoubleRegsRegClass);
878234285Sdim        RegInfo.addLiveIn(VA.getLocReg(), VReg);
879234285Sdim        InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
880234285Sdim      } else {
881234285Sdim        assert (0);
882234285Sdim      }
883234285Sdim    } else if (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() <= 8) {
884234285Sdim      assert (0 && "ByValSize must be bigger than 8 bytes");
885234285Sdim    } else {
886234285Sdim      // Sanity check.
887234285Sdim      assert(VA.isMemLoc());
888234285Sdim
889234285Sdim      if (Flags.isByVal()) {
890234285Sdim        // If it's a byval parameter, then we need to compute the
891234285Sdim        // "real" size, not the size of the pointer.
892234285Sdim        ObjSize = Flags.getByValSize();
893234285Sdim      } else {
894234285Sdim        ObjSize = VA.getLocVT().getStoreSizeInBits() >> 3;
895234285Sdim      }
896234285Sdim
897234285Sdim      StackLocation = HEXAGON_LRFP_SIZE + VA.getLocMemOffset();
898234285Sdim      // Create the frame index object for this incoming parameter...
899234285Sdim      FI = MFI->CreateFixedObject(ObjSize, StackLocation, true);
900234285Sdim
901234285Sdim      // Create the SelectionDAG nodes cordl, responding to a load
902234285Sdim      // from this parameter.
903234285Sdim      SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
904234285Sdim
905234285Sdim      if (Flags.isByVal()) {
906234285Sdim        // If it's a pass-by-value aggregate, then do not dereference the stack
907234285Sdim        // location. Instead, we should generate a reference to the stack
908234285Sdim        // location.
909234285Sdim        InVals.push_back(FIN);
910234285Sdim      } else {
911234285Sdim        InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
912234285Sdim                                     MachinePointerInfo(), false, false,
913234285Sdim                                     false, 0));
914234285Sdim      }
915234285Sdim    }
916234285Sdim  }
917234285Sdim
918234285Sdim  if (!MemOps.empty())
919234285Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOps[0],
920234285Sdim                        MemOps.size());
921234285Sdim
922234285Sdim  if (isVarArg) {
923234285Sdim    // This will point to the next argument passed via stack.
924234285Sdim    int FrameIndex = MFI->CreateFixedObject(Hexagon_PointerSize,
925234285Sdim                                            HEXAGON_LRFP_SIZE +
926234285Sdim                                            CCInfo.getNextStackOffset(),
927234285Sdim                                            true);
928234285Sdim    FuncInfo->setVarArgsFrameIndex(FrameIndex);
929234285Sdim  }
930234285Sdim
931234285Sdim  return Chain;
932234285Sdim}
933234285Sdim
934234285SdimSDValue
935234285SdimHexagonTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
936234285Sdim  // VASTART stores the address of the VarArgsFrameIndex slot into the
937234285Sdim  // memory location argument.
938234285Sdim  MachineFunction &MF = DAG.getMachineFunction();
939234285Sdim  HexagonMachineFunctionInfo *QFI = MF.getInfo<HexagonMachineFunctionInfo>();
940234285Sdim  SDValue Addr = DAG.getFrameIndex(QFI->getVarArgsFrameIndex(), MVT::i32);
941234285Sdim  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
942263509Sdim  return DAG.getStore(Op.getOperand(0), SDLoc(Op), Addr,
943234285Sdim                      Op.getOperand(1), MachinePointerInfo(SV), false,
944234285Sdim                      false, 0);
945234285Sdim}
946234285Sdim
947234285SdimSDValue
948234285SdimHexagonTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
949245431Sdim  SDValue LHS = Op.getOperand(0);
950245431Sdim  SDValue RHS = Op.getOperand(1);
951245431Sdim  SDValue CC = Op.getOperand(4);
952245431Sdim  SDValue TrueVal = Op.getOperand(2);
953245431Sdim  SDValue FalseVal = Op.getOperand(3);
954263509Sdim  SDLoc dl(Op);
955234285Sdim  SDNode* OpNode = Op.getNode();
956245431Sdim  EVT SVT = OpNode->getValueType(0);
957234285Sdim
958245431Sdim  SDValue Cond = DAG.getNode(ISD::SETCC, dl, MVT::i1, LHS, RHS, CC);
959245431Sdim  return DAG.getNode(ISD::SELECT, dl, SVT, Cond, TrueVal, FalseVal);
960234285Sdim}
961234285Sdim
962234285SdimSDValue
963245431SdimHexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const {
964245431Sdim  EVT ValTy = Op.getValueType();
965263509Sdim  SDLoc dl(Op);
966245431Sdim  ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
967245431Sdim  SDValue Res;
968245431Sdim  if (CP->isMachineConstantPoolEntry())
969245431Sdim    Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), ValTy,
970245431Sdim                                    CP->getAlignment());
971245431Sdim  else
972245431Sdim    Res = DAG.getTargetConstantPool(CP->getConstVal(), ValTy,
973245431Sdim                                    CP->getAlignment());
974245431Sdim  return DAG.getNode(HexagonISD::CONST32, dl, ValTy, Res);
975245431Sdim}
976245431Sdim
977245431SdimSDValue
978234285SdimHexagonTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
979234285Sdim  const TargetRegisterInfo *TRI = TM.getRegisterInfo();
980234285Sdim  MachineFunction &MF = DAG.getMachineFunction();
981234285Sdim  MachineFrameInfo *MFI = MF.getFrameInfo();
982234285Sdim  MFI->setReturnAddressIsTaken(true);
983234285Sdim
984234285Sdim  EVT VT = Op.getValueType();
985263509Sdim  SDLoc dl(Op);
986234285Sdim  unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
987234285Sdim  if (Depth) {
988234285Sdim    SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
989234285Sdim    SDValue Offset = DAG.getConstant(4, MVT::i32);
990234285Sdim    return DAG.getLoad(VT, dl, DAG.getEntryNode(),
991234285Sdim                       DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset),
992234285Sdim                       MachinePointerInfo(), false, false, false, 0);
993234285Sdim  }
994234285Sdim
995234285Sdim  // Return LR, which contains the return address. Mark it an implicit live-in.
996234285Sdim  unsigned Reg = MF.addLiveIn(TRI->getRARegister(), getRegClassFor(MVT::i32));
997234285Sdim  return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);
998234285Sdim}
999234285Sdim
1000234285SdimSDValue
1001234285SdimHexagonTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
1002234285Sdim  const HexagonRegisterInfo  *TRI = TM.getRegisterInfo();
1003234285Sdim  MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
1004234285Sdim  MFI->setFrameAddressIsTaken(true);
1005234285Sdim
1006234285Sdim  EVT VT = Op.getValueType();
1007263509Sdim  SDLoc dl(Op);
1008234285Sdim  unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1009234285Sdim  SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl,
1010234285Sdim                                         TRI->getFrameRegister(), VT);
1011234285Sdim  while (Depth--)
1012234285Sdim    FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,
1013234285Sdim                            MachinePointerInfo(),
1014234285Sdim                            false, false, false, 0);
1015234285Sdim  return FrameAddr;
1016234285Sdim}
1017234285Sdim
1018234285SdimSDValue HexagonTargetLowering::LowerATOMIC_FENCE(SDValue Op,
1019234285Sdim                                                 SelectionDAG& DAG) const {
1020263509Sdim  SDLoc dl(Op);
1021234285Sdim  return DAG.getNode(HexagonISD::BARRIER, dl, MVT::Other, Op.getOperand(0));
1022234285Sdim}
1023234285Sdim
1024234285Sdim
1025234285SdimSDValue HexagonTargetLowering::LowerGLOBALADDRESS(SDValue Op,
1026234285Sdim                                                  SelectionDAG &DAG) const {
1027234285Sdim  SDValue Result;
1028234285Sdim  const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
1029234285Sdim  int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();
1030263509Sdim  SDLoc dl(Op);
1031234285Sdim  Result = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), Offset);
1032234285Sdim
1033252723Sdim  const HexagonTargetObjectFile &TLOF =
1034252723Sdim      static_cast<const HexagonTargetObjectFile &>(getObjFileLowering());
1035234285Sdim  if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) {
1036234285Sdim    return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), Result);
1037234285Sdim  }
1038234285Sdim
1039234285Sdim  return DAG.getNode(HexagonISD::CONST32, dl, getPointerTy(), Result);
1040234285Sdim}
1041234285Sdim
1042252723SdimSDValue
1043252723SdimHexagonTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const {
1044252723Sdim  const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
1045252723Sdim  SDValue BA_SD =  DAG.getTargetBlockAddress(BA, MVT::i32);
1046263509Sdim  SDLoc dl(Op);
1047252723Sdim  return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), BA_SD);
1048252723Sdim}
1049252723Sdim
1050234285Sdim//===----------------------------------------------------------------------===//
1051234285Sdim// TargetLowering Implementation
1052234285Sdim//===----------------------------------------------------------------------===//
1053234285Sdim
1054234285SdimHexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine
1055234285Sdim                                             &targetmachine)
1056234285Sdim  : TargetLowering(targetmachine, new HexagonTargetObjectFile()),
1057234285Sdim    TM(targetmachine) {
1058234285Sdim
1059245431Sdim    const HexagonRegisterInfo* QRI = TM.getRegisterInfo();
1060245431Sdim
1061234285Sdim    // Set up the register classes.
1062245431Sdim    addRegisterClass(MVT::i32, &Hexagon::IntRegsRegClass);
1063245431Sdim    addRegisterClass(MVT::i64, &Hexagon::DoubleRegsRegClass);
1064234285Sdim
1065245431Sdim    if (QRI->Subtarget.hasV5TOps()) {
1066245431Sdim      addRegisterClass(MVT::f32, &Hexagon::IntRegsRegClass);
1067245431Sdim      addRegisterClass(MVT::f64, &Hexagon::DoubleRegsRegClass);
1068245431Sdim    }
1069234285Sdim
1070245431Sdim    addRegisterClass(MVT::i1, &Hexagon::PredRegsRegClass);
1071245431Sdim
1072234285Sdim    computeRegisterProperties();
1073234285Sdim
1074234285Sdim    // Align loop entry
1075234285Sdim    setPrefLoopAlignment(4);
1076234285Sdim
1077234285Sdim    // Limits for inline expansion of memcpy/memmove
1078252723Sdim    MaxStoresPerMemcpy = 6;
1079252723Sdim    MaxStoresPerMemmove = 6;
1080234285Sdim
1081234285Sdim    //
1082234285Sdim    // Library calls for unsupported operations
1083234285Sdim    //
1084234285Sdim
1085234285Sdim    setLibcallName(RTLIB::SINTTOFP_I128_F64, "__hexagon_floattidf");
1086234285Sdim    setLibcallName(RTLIB::SINTTOFP_I128_F32, "__hexagon_floattisf");
1087234285Sdim
1088234285Sdim    setLibcallName(RTLIB::FPTOUINT_F32_I128, "__hexagon_fixunssfti");
1089234285Sdim    setLibcallName(RTLIB::FPTOUINT_F64_I128, "__hexagon_fixunsdfti");
1090234285Sdim
1091234285Sdim    setLibcallName(RTLIB::FPTOSINT_F32_I128, "__hexagon_fixsfti");
1092234285Sdim    setLibcallName(RTLIB::FPTOSINT_F64_I128, "__hexagon_fixdfti");
1093234285Sdim
1094234285Sdim    setLibcallName(RTLIB::SDIV_I32, "__hexagon_divsi3");
1095234285Sdim    setOperationAction(ISD::SDIV,  MVT::i32, Expand);
1096234285Sdim    setLibcallName(RTLIB::SREM_I32, "__hexagon_umodsi3");
1097234285Sdim    setOperationAction(ISD::SREM,  MVT::i32, Expand);
1098234285Sdim
1099234285Sdim    setLibcallName(RTLIB::SDIV_I64, "__hexagon_divdi3");
1100234285Sdim    setOperationAction(ISD::SDIV,  MVT::i64, Expand);
1101234285Sdim    setLibcallName(RTLIB::SREM_I64, "__hexagon_moddi3");
1102234285Sdim    setOperationAction(ISD::SREM,  MVT::i64, Expand);
1103234285Sdim
1104234285Sdim    setLibcallName(RTLIB::UDIV_I32, "__hexagon_udivsi3");
1105234285Sdim    setOperationAction(ISD::UDIV,  MVT::i32, Expand);
1106234285Sdim
1107234285Sdim    setLibcallName(RTLIB::UDIV_I64, "__hexagon_udivdi3");
1108234285Sdim    setOperationAction(ISD::UDIV,  MVT::i64, Expand);
1109234285Sdim
1110234285Sdim    setLibcallName(RTLIB::UREM_I32, "__hexagon_umodsi3");
1111234285Sdim    setOperationAction(ISD::UREM,  MVT::i32, Expand);
1112234285Sdim
1113234285Sdim    setLibcallName(RTLIB::UREM_I64, "__hexagon_umoddi3");
1114234285Sdim    setOperationAction(ISD::UREM,  MVT::i64, Expand);
1115234285Sdim
1116234285Sdim    setLibcallName(RTLIB::DIV_F32, "__hexagon_divsf3");
1117234285Sdim    setOperationAction(ISD::FDIV,  MVT::f32, Expand);
1118234285Sdim
1119234285Sdim    setLibcallName(RTLIB::DIV_F64, "__hexagon_divdf3");
1120234285Sdim    setOperationAction(ISD::FDIV,  MVT::f64, Expand);
1121234285Sdim
1122245431Sdim    setOperationAction(ISD::FSQRT,  MVT::f32, Expand);
1123245431Sdim    setOperationAction(ISD::FSQRT,  MVT::f64, Expand);
1124245431Sdim    setOperationAction(ISD::FSIN,  MVT::f32, Expand);
1125245431Sdim    setOperationAction(ISD::FSIN,  MVT::f64, Expand);
1126234285Sdim
1127245431Sdim    if (QRI->Subtarget.hasV5TOps()) {
1128245431Sdim      // Hexagon V5 Support.
1129245431Sdim      setOperationAction(ISD::FADD,       MVT::f32, Legal);
1130245431Sdim      setOperationAction(ISD::FADD,       MVT::f64, Legal);
1131245431Sdim      setOperationAction(ISD::FP_EXTEND,  MVT::f32, Legal);
1132245431Sdim      setCondCodeAction(ISD::SETOEQ,      MVT::f32, Legal);
1133245431Sdim      setCondCodeAction(ISD::SETOEQ,      MVT::f64, Legal);
1134245431Sdim      setCondCodeAction(ISD::SETUEQ,      MVT::f32, Legal);
1135245431Sdim      setCondCodeAction(ISD::SETUEQ,      MVT::f64, Legal);
1136234285Sdim
1137245431Sdim      setCondCodeAction(ISD::SETOGE,      MVT::f32, Legal);
1138245431Sdim      setCondCodeAction(ISD::SETOGE,      MVT::f64, Legal);
1139245431Sdim      setCondCodeAction(ISD::SETUGE,      MVT::f32, Legal);
1140245431Sdim      setCondCodeAction(ISD::SETUGE,      MVT::f64, Legal);
1141234285Sdim
1142245431Sdim      setCondCodeAction(ISD::SETOGT,      MVT::f32, Legal);
1143245431Sdim      setCondCodeAction(ISD::SETOGT,      MVT::f64, Legal);
1144245431Sdim      setCondCodeAction(ISD::SETUGT,      MVT::f32, Legal);
1145245431Sdim      setCondCodeAction(ISD::SETUGT,      MVT::f64, Legal);
1146234285Sdim
1147245431Sdim      setCondCodeAction(ISD::SETOLE,      MVT::f32, Legal);
1148245431Sdim      setCondCodeAction(ISD::SETOLE,      MVT::f64, Legal);
1149245431Sdim      setCondCodeAction(ISD::SETOLT,      MVT::f32, Legal);
1150245431Sdim      setCondCodeAction(ISD::SETOLT,      MVT::f64, Legal);
1151234285Sdim
1152245431Sdim      setOperationAction(ISD::ConstantFP,  MVT::f32, Legal);
1153245431Sdim      setOperationAction(ISD::ConstantFP,  MVT::f64, Legal);
1154234285Sdim
1155245431Sdim      setOperationAction(ISD::FP_TO_UINT, MVT::i1, Promote);
1156245431Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::i1, Promote);
1157245431Sdim      setOperationAction(ISD::UINT_TO_FP, MVT::i1, Promote);
1158245431Sdim      setOperationAction(ISD::SINT_TO_FP, MVT::i1, Promote);
1159234285Sdim
1160245431Sdim      setOperationAction(ISD::FP_TO_UINT, MVT::i8, Promote);
1161245431Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::i8, Promote);
1162245431Sdim      setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
1163245431Sdim      setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
1164234285Sdim
1165245431Sdim      setOperationAction(ISD::FP_TO_UINT, MVT::i16, Promote);
1166245431Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::i16, Promote);
1167245431Sdim      setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
1168245431Sdim      setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
1169234285Sdim
1170245431Sdim      setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
1171245431Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
1172245431Sdim      setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
1173245431Sdim      setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
1174234285Sdim
1175245431Sdim      setOperationAction(ISD::FP_TO_UINT, MVT::i64, Legal);
1176245431Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::i64, Legal);
1177245431Sdim      setOperationAction(ISD::UINT_TO_FP, MVT::i64, Legal);
1178245431Sdim      setOperationAction(ISD::SINT_TO_FP, MVT::i64, Legal);
1179234285Sdim
1180245431Sdim      setOperationAction(ISD::FABS,  MVT::f32, Legal);
1181245431Sdim      setOperationAction(ISD::FABS,  MVT::f64, Expand);
1182234285Sdim
1183245431Sdim      setOperationAction(ISD::FNEG,  MVT::f32, Legal);
1184245431Sdim      setOperationAction(ISD::FNEG,  MVT::f64, Expand);
1185245431Sdim    } else {
1186234285Sdim
1187245431Sdim      // Expand fp<->uint.
1188245431Sdim      setOperationAction(ISD::FP_TO_SINT,  MVT::i32, Expand);
1189245431Sdim      setOperationAction(ISD::FP_TO_UINT,  MVT::i32, Expand);
1190234285Sdim
1191245431Sdim      setOperationAction(ISD::SINT_TO_FP,  MVT::i32, Expand);
1192245431Sdim      setOperationAction(ISD::UINT_TO_FP,  MVT::i32, Expand);
1193234285Sdim
1194245431Sdim      setLibcallName(RTLIB::SINTTOFP_I64_F32, "__hexagon_floatdisf");
1195245431Sdim      setLibcallName(RTLIB::UINTTOFP_I64_F32, "__hexagon_floatundisf");
1196234285Sdim
1197245431Sdim      setLibcallName(RTLIB::UINTTOFP_I32_F32, "__hexagon_floatunsisf");
1198245431Sdim      setLibcallName(RTLIB::SINTTOFP_I32_F32, "__hexagon_floatsisf");
1199234285Sdim
1200245431Sdim      setLibcallName(RTLIB::SINTTOFP_I64_F64, "__hexagon_floatdidf");
1201245431Sdim      setLibcallName(RTLIB::UINTTOFP_I64_F64, "__hexagon_floatundidf");
1202234285Sdim
1203245431Sdim      setLibcallName(RTLIB::UINTTOFP_I32_F64, "__hexagon_floatunsidf");
1204245431Sdim      setLibcallName(RTLIB::SINTTOFP_I32_F64, "__hexagon_floatsidf");
1205234285Sdim
1206245431Sdim      setLibcallName(RTLIB::FPTOUINT_F32_I32, "__hexagon_fixunssfsi");
1207245431Sdim      setLibcallName(RTLIB::FPTOUINT_F32_I64, "__hexagon_fixunssfdi");
1208234285Sdim
1209245431Sdim      setLibcallName(RTLIB::FPTOSINT_F64_I64, "__hexagon_fixdfdi");
1210245431Sdim      setLibcallName(RTLIB::FPTOSINT_F32_I64, "__hexagon_fixsfdi");
1211234285Sdim
1212245431Sdim      setLibcallName(RTLIB::FPTOUINT_F64_I32, "__hexagon_fixunsdfsi");
1213245431Sdim      setLibcallName(RTLIB::FPTOUINT_F64_I64, "__hexagon_fixunsdfdi");
1214234285Sdim
1215245431Sdim      setLibcallName(RTLIB::ADD_F64, "__hexagon_adddf3");
1216245431Sdim      setOperationAction(ISD::FADD,  MVT::f64, Expand);
1217234285Sdim
1218245431Sdim      setLibcallName(RTLIB::ADD_F32, "__hexagon_addsf3");
1219245431Sdim      setOperationAction(ISD::FADD,  MVT::f32, Expand);
1220234285Sdim
1221245431Sdim      setLibcallName(RTLIB::FPEXT_F32_F64, "__hexagon_extendsfdf2");
1222245431Sdim      setOperationAction(ISD::FP_EXTEND,  MVT::f32, Expand);
1223234285Sdim
1224245431Sdim      setLibcallName(RTLIB::OEQ_F32, "__hexagon_eqsf2");
1225245431Sdim      setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand);
1226234285Sdim
1227245431Sdim      setLibcallName(RTLIB::OEQ_F64, "__hexagon_eqdf2");
1228245431Sdim      setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand);
1229234285Sdim
1230245431Sdim      setLibcallName(RTLIB::OGE_F32, "__hexagon_gesf2");
1231245431Sdim      setCondCodeAction(ISD::SETOGE, MVT::f32, Expand);
1232234285Sdim
1233245431Sdim      setLibcallName(RTLIB::OGE_F64, "__hexagon_gedf2");
1234245431Sdim      setCondCodeAction(ISD::SETOGE, MVT::f64, Expand);
1235234285Sdim
1236245431Sdim      setLibcallName(RTLIB::OGT_F32, "__hexagon_gtsf2");
1237245431Sdim      setCondCodeAction(ISD::SETOGT, MVT::f32, Expand);
1238234285Sdim
1239245431Sdim      setLibcallName(RTLIB::OGT_F64, "__hexagon_gtdf2");
1240245431Sdim      setCondCodeAction(ISD::SETOGT, MVT::f64, Expand);
1241245431Sdim
1242245431Sdim      setLibcallName(RTLIB::FPTOSINT_F64_I32, "__hexagon_fixdfsi");
1243245431Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::f64, Expand);
1244245431Sdim
1245245431Sdim      setLibcallName(RTLIB::FPTOSINT_F32_I32, "__hexagon_fixsfsi");
1246245431Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::f32, Expand);
1247245431Sdim
1248245431Sdim      setLibcallName(RTLIB::OLE_F64, "__hexagon_ledf2");
1249245431Sdim      setCondCodeAction(ISD::SETOLE, MVT::f64, Expand);
1250245431Sdim
1251245431Sdim      setLibcallName(RTLIB::OLE_F32, "__hexagon_lesf2");
1252245431Sdim      setCondCodeAction(ISD::SETOLE, MVT::f32, Expand);
1253245431Sdim
1254245431Sdim      setLibcallName(RTLIB::OLT_F64, "__hexagon_ltdf2");
1255245431Sdim      setCondCodeAction(ISD::SETOLT, MVT::f64, Expand);
1256245431Sdim
1257245431Sdim      setLibcallName(RTLIB::OLT_F32, "__hexagon_ltsf2");
1258245431Sdim      setCondCodeAction(ISD::SETOLT, MVT::f32, Expand);
1259245431Sdim
1260245431Sdim      setLibcallName(RTLIB::MUL_F64, "__hexagon_muldf3");
1261245431Sdim      setOperationAction(ISD::FMUL, MVT::f64, Expand);
1262245431Sdim
1263245431Sdim      setLibcallName(RTLIB::MUL_F32, "__hexagon_mulsf3");
1264245431Sdim      setOperationAction(ISD::MUL, MVT::f32, Expand);
1265245431Sdim
1266245431Sdim      setLibcallName(RTLIB::UNE_F64, "__hexagon_nedf2");
1267245431Sdim      setCondCodeAction(ISD::SETUNE, MVT::f64, Expand);
1268245431Sdim
1269245431Sdim      setLibcallName(RTLIB::UNE_F32, "__hexagon_nesf2");
1270245431Sdim
1271245431Sdim      setLibcallName(RTLIB::SUB_F64, "__hexagon_subdf3");
1272245431Sdim      setOperationAction(ISD::SUB, MVT::f64, Expand);
1273245431Sdim
1274245431Sdim      setLibcallName(RTLIB::SUB_F32, "__hexagon_subsf3");
1275245431Sdim      setOperationAction(ISD::SUB, MVT::f32, Expand);
1276245431Sdim
1277245431Sdim      setLibcallName(RTLIB::FPROUND_F64_F32, "__hexagon_truncdfsf2");
1278245431Sdim      setOperationAction(ISD::FP_ROUND, MVT::f64, Expand);
1279245431Sdim
1280245431Sdim      setLibcallName(RTLIB::UO_F64, "__hexagon_unorddf2");
1281245431Sdim      setCondCodeAction(ISD::SETUO, MVT::f64, Expand);
1282245431Sdim
1283245431Sdim      setLibcallName(RTLIB::O_F64, "__hexagon_unorddf2");
1284245431Sdim      setCondCodeAction(ISD::SETO, MVT::f64, Expand);
1285245431Sdim
1286245431Sdim      setLibcallName(RTLIB::O_F32, "__hexagon_unordsf2");
1287245431Sdim      setCondCodeAction(ISD::SETO, MVT::f32, Expand);
1288245431Sdim
1289245431Sdim      setLibcallName(RTLIB::UO_F32, "__hexagon_unordsf2");
1290245431Sdim      setCondCodeAction(ISD::SETUO, MVT::f32, Expand);
1291245431Sdim
1292245431Sdim      setOperationAction(ISD::FABS,  MVT::f32, Expand);
1293245431Sdim      setOperationAction(ISD::FABS,  MVT::f64, Expand);
1294245431Sdim      setOperationAction(ISD::FNEG,  MVT::f32, Expand);
1295245431Sdim      setOperationAction(ISD::FNEG,  MVT::f64, Expand);
1296245431Sdim    }
1297245431Sdim
1298245431Sdim    setLibcallName(RTLIB::SREM_I32, "__hexagon_modsi3");
1299245431Sdim    setOperationAction(ISD::SREM, MVT::i32, Expand);
1300245431Sdim
1301234285Sdim    setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal);
1302234285Sdim    setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal);
1303234285Sdim    setIndexedLoadAction(ISD::POST_INC, MVT::i32, Legal);
1304234285Sdim    setIndexedLoadAction(ISD::POST_INC, MVT::i64, Legal);
1305234285Sdim
1306234285Sdim    setIndexedStoreAction(ISD::POST_INC, MVT::i8, Legal);
1307234285Sdim    setIndexedStoreAction(ISD::POST_INC, MVT::i16, Legal);
1308234285Sdim    setIndexedStoreAction(ISD::POST_INC, MVT::i32, Legal);
1309234285Sdim    setIndexedStoreAction(ISD::POST_INC, MVT::i64, Legal);
1310234285Sdim
1311234285Sdim    setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
1312234285Sdim
1313234285Sdim    // Turn FP extload into load/fextend.
1314234285Sdim    setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
1315234285Sdim    // Hexagon has a i1 sign extending load.
1316234285Sdim    setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Expand);
1317234285Sdim    // Turn FP truncstore into trunc + store.
1318234285Sdim    setTruncStoreAction(MVT::f64, MVT::f32, Expand);
1319234285Sdim
1320234285Sdim    // Custom legalize GlobalAddress nodes into CONST32.
1321234285Sdim    setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
1322234285Sdim    setOperationAction(ISD::GlobalAddress, MVT::i8, Custom);
1323252723Sdim    setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
1324234285Sdim    // Truncate action?
1325234285Sdim    setOperationAction(ISD::TRUNCATE, MVT::i64, Expand);
1326234285Sdim
1327234285Sdim    // Hexagon doesn't have sext_inreg, replace them with shl/sra.
1328234285Sdim    setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand);
1329234285Sdim
1330234285Sdim    // Hexagon has no REM or DIVREM operations.
1331234285Sdim    setOperationAction(ISD::UREM, MVT::i32, Expand);
1332234285Sdim    setOperationAction(ISD::SREM, MVT::i32, Expand);
1333234285Sdim    setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
1334234285Sdim    setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
1335234285Sdim    setOperationAction(ISD::SREM, MVT::i64, Expand);
1336234285Sdim    setOperationAction(ISD::SDIVREM, MVT::i64, Expand);
1337234285Sdim    setOperationAction(ISD::UDIVREM, MVT::i64, Expand);
1338234285Sdim
1339234285Sdim    setOperationAction(ISD::BSWAP, MVT::i64, Expand);
1340234285Sdim
1341234285Sdim    // Lower SELECT_CC to SETCC and SELECT.
1342234285Sdim    setOperationAction(ISD::SELECT_CC, MVT::i32,   Custom);
1343234285Sdim    setOperationAction(ISD::SELECT_CC, MVT::i64,   Custom);
1344234285Sdim
1345245431Sdim    if (QRI->Subtarget.hasV5TOps()) {
1346245431Sdim
1347245431Sdim      // We need to make the operation type of SELECT node to be Custom,
1348245431Sdim      // such that we don't go into the infinite loop of
1349245431Sdim      // select ->  setcc -> select_cc -> select loop.
1350245431Sdim      setOperationAction(ISD::SELECT, MVT::f32, Custom);
1351245431Sdim      setOperationAction(ISD::SELECT, MVT::f64, Custom);
1352245431Sdim
1353245431Sdim      setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
1354245431Sdim      setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
1355245431Sdim      setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
1356245431Sdim
1357245431Sdim    } else {
1358245431Sdim
1359245431Sdim      // Hexagon has no select or setcc: expand to SELECT_CC.
1360245431Sdim      setOperationAction(ISD::SELECT, MVT::f32, Expand);
1361245431Sdim      setOperationAction(ISD::SELECT, MVT::f64, Expand);
1362245431Sdim
1363245431Sdim      // This is a workaround documented in DAGCombiner.cpp:2892 We don't
1364245431Sdim      // support SELECT_CC on every type.
1365245431Sdim      setOperationAction(ISD::SELECT_CC, MVT::Other,   Expand);
1366245431Sdim
1367245431Sdim    }
1368245431Sdim
1369234285Sdim    if (EmitJumpTables) {
1370234285Sdim      setOperationAction(ISD::BR_JT, MVT::Other, Custom);
1371234285Sdim    } else {
1372234285Sdim      setOperationAction(ISD::BR_JT, MVT::Other, Expand);
1373234285Sdim    }
1374245431Sdim    // Increase jump tables cutover to 5, was 4.
1375245431Sdim    setMinimumJumpTableEntries(5);
1376234285Sdim
1377252723Sdim    setOperationAction(ISD::BR_CC, MVT::f32, Expand);
1378252723Sdim    setOperationAction(ISD::BR_CC, MVT::f64, Expand);
1379252723Sdim    setOperationAction(ISD::BR_CC, MVT::i1,  Expand);
1380234285Sdim    setOperationAction(ISD::BR_CC, MVT::i32, Expand);
1381252723Sdim    setOperationAction(ISD::BR_CC, MVT::i64, Expand);
1382234285Sdim
1383234285Sdim    setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
1384234285Sdim
1385234285Sdim    setOperationAction(ISD::FSIN , MVT::f64, Expand);
1386234285Sdim    setOperationAction(ISD::FCOS , MVT::f64, Expand);
1387234285Sdim    setOperationAction(ISD::FREM , MVT::f64, Expand);
1388234285Sdim    setOperationAction(ISD::FSIN , MVT::f32, Expand);
1389234285Sdim    setOperationAction(ISD::FCOS , MVT::f32, Expand);
1390234285Sdim    setOperationAction(ISD::FREM , MVT::f32, Expand);
1391252723Sdim    setOperationAction(ISD::FSINCOS, MVT::f64, Expand);
1392252723Sdim    setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
1393252723Sdim
1394252723Sdim    // In V4, we have double word add/sub with carry. The problem with
1395252723Sdim    // modelling this instruction is that it produces 2 results - Rdd and Px.
1396252723Sdim    // To model update of Px, we will have to use Defs[p0..p3] which will
1397252723Sdim    // cause any predicate live range to spill. So, we pretend we dont't
1398252723Sdim    // have these instructions.
1399252723Sdim    setOperationAction(ISD::ADDE, MVT::i8, Expand);
1400252723Sdim    setOperationAction(ISD::ADDE, MVT::i16, Expand);
1401252723Sdim    setOperationAction(ISD::ADDE, MVT::i32, Expand);
1402252723Sdim    setOperationAction(ISD::ADDE, MVT::i64, Expand);
1403252723Sdim    setOperationAction(ISD::SUBE, MVT::i8, Expand);
1404252723Sdim    setOperationAction(ISD::SUBE, MVT::i16, Expand);
1405252723Sdim    setOperationAction(ISD::SUBE, MVT::i32, Expand);
1406252723Sdim    setOperationAction(ISD::SUBE, MVT::i64, Expand);
1407252723Sdim    setOperationAction(ISD::ADDC, MVT::i8, Expand);
1408252723Sdim    setOperationAction(ISD::ADDC, MVT::i16, Expand);
1409252723Sdim    setOperationAction(ISD::ADDC, MVT::i32, Expand);
1410252723Sdim    setOperationAction(ISD::ADDC, MVT::i64, Expand);
1411252723Sdim    setOperationAction(ISD::SUBC, MVT::i8, Expand);
1412252723Sdim    setOperationAction(ISD::SUBC, MVT::i16, Expand);
1413252723Sdim    setOperationAction(ISD::SUBC, MVT::i32, Expand);
1414252723Sdim    setOperationAction(ISD::SUBC, MVT::i64, Expand);
1415252723Sdim
1416234285Sdim    setOperationAction(ISD::CTPOP, MVT::i32, Expand);
1417252723Sdim    setOperationAction(ISD::CTPOP, MVT::i64, Expand);
1418234285Sdim    setOperationAction(ISD::CTTZ , MVT::i32, Expand);
1419252723Sdim    setOperationAction(ISD::CTTZ , MVT::i64, Expand);
1420234285Sdim    setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand);
1421252723Sdim    setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand);
1422234285Sdim    setOperationAction(ISD::CTLZ , MVT::i32, Expand);
1423252723Sdim    setOperationAction(ISD::CTLZ , MVT::i64, Expand);
1424234285Sdim    setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand);
1425252723Sdim    setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand);
1426234285Sdim    setOperationAction(ISD::ROTL , MVT::i32, Expand);
1427234285Sdim    setOperationAction(ISD::ROTR , MVT::i32, Expand);
1428234285Sdim    setOperationAction(ISD::BSWAP, MVT::i32, Expand);
1429234285Sdim    setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
1430234285Sdim    setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
1431234285Sdim    setOperationAction(ISD::FPOW , MVT::f64, Expand);
1432234285Sdim    setOperationAction(ISD::FPOW , MVT::f32, Expand);
1433234285Sdim
1434234285Sdim    setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
1435234285Sdim    setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
1436234285Sdim    setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
1437234285Sdim
1438234285Sdim    setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
1439234285Sdim    setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
1440234285Sdim
1441234285Sdim    setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
1442234285Sdim    setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
1443234285Sdim
1444252723Sdim    setOperationAction(ISD::EH_RETURN,     MVT::Other, Custom);
1445234285Sdim
1446234285Sdim    if (TM.getSubtargetImpl()->isSubtargetV2()) {
1447234285Sdim      setExceptionPointerRegister(Hexagon::R20);
1448234285Sdim      setExceptionSelectorRegister(Hexagon::R21);
1449234285Sdim    } else {
1450234285Sdim      setExceptionPointerRegister(Hexagon::R0);
1451234285Sdim      setExceptionSelectorRegister(Hexagon::R1);
1452234285Sdim    }
1453234285Sdim
1454234285Sdim    // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
1455234285Sdim    setOperationAction(ISD::VASTART           , MVT::Other, Custom);
1456234285Sdim
1457234285Sdim    // Use the default implementation.
1458234285Sdim    setOperationAction(ISD::VAARG             , MVT::Other, Expand);
1459234285Sdim    setOperationAction(ISD::VACOPY            , MVT::Other, Expand);
1460234285Sdim    setOperationAction(ISD::VAEND             , MVT::Other, Expand);
1461234285Sdim    setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand);
1462234285Sdim    setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand);
1463234285Sdim
1464234285Sdim
1465234285Sdim    setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Custom);
1466234285Sdim    setOperationAction(ISD::INLINEASM         , MVT::Other, Custom);
1467234285Sdim
1468234285Sdim    setMinFunctionAlignment(2);
1469234285Sdim
1470234285Sdim    // Needed for DYNAMIC_STACKALLOC expansion.
1471234285Sdim    unsigned StackRegister = TM.getRegisterInfo()->getStackRegister();
1472234285Sdim    setStackPointerRegisterToSaveRestore(StackRegister);
1473234285Sdim    setSchedulingPreference(Sched::VLIW);
1474234285Sdim}
1475234285Sdim
1476234285Sdim
1477234285Sdimconst char*
1478234285SdimHexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {
1479234285Sdim  switch (Opcode) {
1480234285Sdim    default: return 0;
1481245431Sdim    case HexagonISD::CONST32:     return "HexagonISD::CONST32";
1482252723Sdim    case HexagonISD::CONST32_GP: return "HexagonISD::CONST32_GP";
1483252723Sdim    case HexagonISD::CONST32_Int_Real: return "HexagonISD::CONST32_Int_Real";
1484234285Sdim    case HexagonISD::ADJDYNALLOC: return "HexagonISD::ADJDYNALLOC";
1485245431Sdim    case HexagonISD::CMPICC:      return "HexagonISD::CMPICC";
1486245431Sdim    case HexagonISD::CMPFCC:      return "HexagonISD::CMPFCC";
1487245431Sdim    case HexagonISD::BRICC:       return "HexagonISD::BRICC";
1488245431Sdim    case HexagonISD::BRFCC:       return "HexagonISD::BRFCC";
1489245431Sdim    case HexagonISD::SELECT_ICC:  return "HexagonISD::SELECT_ICC";
1490245431Sdim    case HexagonISD::SELECT_FCC:  return "HexagonISD::SELECT_FCC";
1491245431Sdim    case HexagonISD::Hi:          return "HexagonISD::Hi";
1492245431Sdim    case HexagonISD::Lo:          return "HexagonISD::Lo";
1493245431Sdim    case HexagonISD::FTOI:        return "HexagonISD::FTOI";
1494245431Sdim    case HexagonISD::ITOF:        return "HexagonISD::ITOF";
1495245431Sdim    case HexagonISD::CALL:        return "HexagonISD::CALL";
1496245431Sdim    case HexagonISD::RET_FLAG:    return "HexagonISD::RET_FLAG";
1497245431Sdim    case HexagonISD::BR_JT:       return "HexagonISD::BR_JT";
1498245431Sdim    case HexagonISD::TC_RETURN:   return "HexagonISD::TC_RETURN";
1499252723Sdim  case HexagonISD::EH_RETURN: return "HexagonISD::EH_RETURN";
1500234285Sdim  }
1501234285Sdim}
1502234285Sdim
1503234285Sdimbool
1504234285SdimHexagonTargetLowering::isTruncateFree(Type *Ty1, Type *Ty2) const {
1505234285Sdim  EVT MTy1 = EVT::getEVT(Ty1);
1506234285Sdim  EVT MTy2 = EVT::getEVT(Ty2);
1507234285Sdim  if (!MTy1.isSimple() || !MTy2.isSimple()) {
1508234285Sdim    return false;
1509234285Sdim  }
1510234285Sdim  return ((MTy1.getSimpleVT() == MVT::i64) && (MTy2.getSimpleVT() == MVT::i32));
1511234285Sdim}
1512234285Sdim
1513234285Sdimbool HexagonTargetLowering::isTruncateFree(EVT VT1, EVT VT2) const {
1514234285Sdim  if (!VT1.isSimple() || !VT2.isSimple()) {
1515234285Sdim    return false;
1516234285Sdim  }
1517234285Sdim  return ((VT1.getSimpleVT() == MVT::i64) && (VT2.getSimpleVT() == MVT::i32));
1518234285Sdim}
1519234285Sdim
1520263509Sdimbool
1521263509SdimHexagonTargetLowering::allowTruncateForTailCall(Type *Ty1, Type *Ty2) const {
1522263509Sdim  // Assuming the caller does not have either a signext or zeroext modifier, and
1523263509Sdim  // only one value is accepted, any reasonable truncation is allowed.
1524263509Sdim  if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())
1525263509Sdim    return false;
1526263509Sdim
1527263509Sdim  // FIXME: in principle up to 64-bit could be made safe, but it would be very
1528263509Sdim  // fragile at the moment: any support for multiple value returns would be
1529263509Sdim  // liable to disallow tail calls involving i64 -> iN truncation in many cases.
1530263509Sdim  return Ty1->getPrimitiveSizeInBits() <= 32;
1531263509Sdim}
1532263509Sdim
1533234285SdimSDValue
1534252723SdimHexagonTargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
1535252723Sdim  SDValue Chain     = Op.getOperand(0);
1536252723Sdim  SDValue Offset    = Op.getOperand(1);
1537252723Sdim  SDValue Handler   = Op.getOperand(2);
1538263509Sdim  SDLoc dl(Op);
1539252723Sdim
1540252723Sdim  // Mark function as containing a call to EH_RETURN.
1541252723Sdim  HexagonMachineFunctionInfo *FuncInfo =
1542252723Sdim    DAG.getMachineFunction().getInfo<HexagonMachineFunctionInfo>();
1543252723Sdim  FuncInfo->setHasEHReturn();
1544252723Sdim
1545252723Sdim  unsigned OffsetReg = Hexagon::R28;
1546252723Sdim
1547252723Sdim  SDValue StoreAddr = DAG.getNode(ISD::ADD, dl, getPointerTy(),
1548252723Sdim                                  DAG.getRegister(Hexagon::R30, getPointerTy()),
1549252723Sdim                                  DAG.getIntPtrConstant(4));
1550252723Sdim  Chain = DAG.getStore(Chain, dl, Handler, StoreAddr, MachinePointerInfo(),
1551252723Sdim                       false, false, 0);
1552252723Sdim  Chain = DAG.getCopyToReg(Chain, dl, OffsetReg, Offset);
1553252723Sdim
1554252723Sdim  // Not needed we already use it as explict input to EH_RETURN.
1555252723Sdim  // MF.getRegInfo().addLiveOut(OffsetReg);
1556252723Sdim
1557252723Sdim  return DAG.getNode(HexagonISD::EH_RETURN, dl, MVT::Other, Chain);
1558252723Sdim}
1559252723Sdim
1560252723SdimSDValue
1561234285SdimHexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
1562234285Sdim  switch (Op.getOpcode()) {
1563234285Sdim    default: llvm_unreachable("Should not custom lower this!");
1564245431Sdim    case ISD::ConstantPool:       return LowerConstantPool(Op, DAG);
1565252723Sdim    case ISD::EH_RETURN:          return LowerEH_RETURN(Op, DAG);
1566234285Sdim      // Frame & Return address.  Currently unimplemented.
1567245431Sdim    case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG);
1568245431Sdim    case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG);
1569234285Sdim    case ISD::GlobalTLSAddress:
1570234285Sdim                          llvm_unreachable("TLS not implemented for Hexagon.");
1571234285Sdim    case ISD::ATOMIC_FENCE:       return LowerATOMIC_FENCE(Op, DAG);
1572234285Sdim    case ISD::GlobalAddress:      return LowerGLOBALADDRESS(Op, DAG);
1573252723Sdim    case ISD::BlockAddress:       return LowerBlockAddress(Op, DAG);
1574234285Sdim    case ISD::VASTART:            return LowerVASTART(Op, DAG);
1575234285Sdim    case ISD::BR_JT:              return LowerBR_JT(Op, DAG);
1576234285Sdim
1577234285Sdim    case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
1578245431Sdim    case ISD::SELECT_CC:          return LowerSELECT_CC(Op, DAG);
1579245431Sdim    case ISD::SELECT:             return Op;
1580234285Sdim    case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
1581245431Sdim    case ISD::INLINEASM:          return LowerINLINEASM(Op, DAG);
1582234285Sdim
1583234285Sdim  }
1584234285Sdim}
1585234285Sdim
1586234285Sdim
1587234285Sdim
1588234285Sdim//===----------------------------------------------------------------------===//
1589234285Sdim//                           Hexagon Scheduler Hooks
1590234285Sdim//===----------------------------------------------------------------------===//
1591234285SdimMachineBasicBlock *
1592234285SdimHexagonTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
1593234285Sdim                                                   MachineBasicBlock *BB)
1594234285Sdimconst {
1595234285Sdim  switch (MI->getOpcode()) {
1596234285Sdim    case Hexagon::ADJDYNALLOC: {
1597234285Sdim      MachineFunction *MF = BB->getParent();
1598234285Sdim      HexagonMachineFunctionInfo *FuncInfo =
1599234285Sdim        MF->getInfo<HexagonMachineFunctionInfo>();
1600234285Sdim      FuncInfo->addAllocaAdjustInst(MI);
1601234285Sdim      return BB;
1602234285Sdim    }
1603234285Sdim    default: llvm_unreachable("Unexpected instr type to insert");
1604234285Sdim  } // switch
1605234285Sdim}
1606234285Sdim
1607234285Sdim//===----------------------------------------------------------------------===//
1608234285Sdim// Inline Assembly Support
1609234285Sdim//===----------------------------------------------------------------------===//
1610234285Sdim
1611234285Sdimstd::pair<unsigned, const TargetRegisterClass*>
1612234285SdimHexagonTargetLowering::getRegForInlineAsmConstraint(const
1613234285Sdim                                                    std::string &Constraint,
1614263509Sdim                                                    MVT VT) const {
1615234285Sdim  if (Constraint.size() == 1) {
1616234285Sdim    switch (Constraint[0]) {
1617234285Sdim    case 'r':   // R0-R31
1618263509Sdim       switch (VT.SimpleTy) {
1619234285Sdim       default:
1620234285Sdim         llvm_unreachable("getRegForInlineAsmConstraint Unhandled data type");
1621234285Sdim       case MVT::i32:
1622234285Sdim       case MVT::i16:
1623234285Sdim       case MVT::i8:
1624245431Sdim       case MVT::f32:
1625245431Sdim         return std::make_pair(0U, &Hexagon::IntRegsRegClass);
1626234285Sdim       case MVT::i64:
1627245431Sdim       case MVT::f64:
1628245431Sdim         return std::make_pair(0U, &Hexagon::DoubleRegsRegClass);
1629234285Sdim      }
1630234285Sdim    default:
1631234285Sdim      llvm_unreachable("Unknown asm register class");
1632234285Sdim    }
1633234285Sdim  }
1634234285Sdim
1635234285Sdim  return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
1636234285Sdim}
1637234285Sdim
1638245431Sdim/// isFPImmLegal - Returns true if the target can instruction select the
1639245431Sdim/// specified FP immediate natively. If false, the legalizer will
1640245431Sdim/// materialize the FP immediate as a load from a constant pool.
1641245431Sdimbool HexagonTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
1642245431Sdim  const HexagonRegisterInfo* QRI = TM.getRegisterInfo();
1643245431Sdim  return QRI->Subtarget.hasV5TOps();
1644245431Sdim}
1645245431Sdim
1646234285Sdim/// isLegalAddressingMode - Return true if the addressing mode represented by
1647234285Sdim/// AM is legal for this target, for a load/store of the specified type.
1648234285Sdimbool HexagonTargetLowering::isLegalAddressingMode(const AddrMode &AM,
1649234285Sdim                                                  Type *Ty) const {
1650234285Sdim  // Allows a signed-extended 11-bit immediate field.
1651234285Sdim  if (AM.BaseOffs <= -(1LL << 13) || AM.BaseOffs >= (1LL << 13)-1) {
1652234285Sdim    return false;
1653234285Sdim  }
1654234285Sdim
1655234285Sdim  // No global is ever allowed as a base.
1656234285Sdim  if (AM.BaseGV) {
1657234285Sdim    return false;
1658234285Sdim  }
1659234285Sdim
1660234285Sdim  int Scale = AM.Scale;
1661234285Sdim  if (Scale < 0) Scale = -Scale;
1662234285Sdim  switch (Scale) {
1663234285Sdim  case 0:  // No scale reg, "r+i", "r", or just "i".
1664234285Sdim    break;
1665234285Sdim  default: // No scaled addressing mode.
1666234285Sdim    return false;
1667234285Sdim  }
1668234285Sdim  return true;
1669234285Sdim}
1670234285Sdim
1671234285Sdim/// isLegalICmpImmediate - Return true if the specified immediate is legal
1672234285Sdim/// icmp immediate, that is the target has icmp instructions which can compare
1673234285Sdim/// a register against the immediate without having to materialize the
1674234285Sdim/// immediate into a register.
1675234285Sdimbool HexagonTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
1676234285Sdim  return Imm >= -512 && Imm <= 511;
1677234285Sdim}
1678234285Sdim
1679234285Sdim/// IsEligibleForTailCallOptimization - Check whether the call is eligible
1680234285Sdim/// for tail call optimization. Targets which want to do tail call
1681234285Sdim/// optimization should implement this function.
1682234285Sdimbool HexagonTargetLowering::IsEligibleForTailCallOptimization(
1683234285Sdim                                 SDValue Callee,
1684234285Sdim                                 CallingConv::ID CalleeCC,
1685234285Sdim                                 bool isVarArg,
1686234285Sdim                                 bool isCalleeStructRet,
1687234285Sdim                                 bool isCallerStructRet,
1688234285Sdim                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
1689234285Sdim                                 const SmallVectorImpl<SDValue> &OutVals,
1690234285Sdim                                 const SmallVectorImpl<ISD::InputArg> &Ins,
1691234285Sdim                                 SelectionDAG& DAG) const {
1692234285Sdim  const Function *CallerF = DAG.getMachineFunction().getFunction();
1693234285Sdim  CallingConv::ID CallerCC = CallerF->getCallingConv();
1694234285Sdim  bool CCMatch = CallerCC == CalleeCC;
1695234285Sdim
1696234285Sdim  // ***************************************************************************
1697234285Sdim  //  Look for obvious safe cases to perform tail call optimization that do not
1698234285Sdim  //  require ABI changes.
1699234285Sdim  // ***************************************************************************
1700234285Sdim
1701234285Sdim  // If this is a tail call via a function pointer, then don't do it!
1702234285Sdim  if (!(dyn_cast<GlobalAddressSDNode>(Callee))
1703234285Sdim      && !(dyn_cast<ExternalSymbolSDNode>(Callee))) {
1704234285Sdim    return false;
1705234285Sdim  }
1706234285Sdim
1707234285Sdim  // Do not optimize if the calling conventions do not match.
1708234285Sdim  if (!CCMatch)
1709234285Sdim    return false;
1710234285Sdim
1711234285Sdim  // Do not tail call optimize vararg calls.
1712234285Sdim  if (isVarArg)
1713234285Sdim    return false;
1714234285Sdim
1715234285Sdim  // Also avoid tail call optimization if either caller or callee uses struct
1716234285Sdim  // return semantics.
1717234285Sdim  if (isCalleeStructRet || isCallerStructRet)
1718234285Sdim    return false;
1719234285Sdim
1720234285Sdim  // In addition to the cases above, we also disable Tail Call Optimization if
1721234285Sdim  // the calling convention code that at least one outgoing argument needs to
1722234285Sdim  // go on the stack. We cannot check that here because at this point that
1723234285Sdim  // information is not available.
1724234285Sdim  return true;
1725234285Sdim}
1726