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"
16249423Sdim#include "HexagonMachineFunctionInfo.h"
17249423Sdim#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"
28249423Sdim#include "llvm/IR/CallingConv.h"
29249423Sdim#include "llvm/IR/DerivedTypes.h"
30249423Sdim#include "llvm/IR/Function.h"
31249423Sdim#include "llvm/IR/GlobalAlias.h"
32249423Sdim#include "llvm/IR/GlobalVariable.h"
33249423Sdim#include "llvm/IR/InlineAsm.h"
34249423Sdim#include "llvm/IR/Intrinsics.h"
35234982Sdim#include "llvm/Support/CommandLine.h"
36234285Sdim#include "llvm/Support/Debug.h"
37234285Sdim#include "llvm/Support/ErrorHandling.h"
38234982Sdim#include "llvm/Support/raw_ostream.h"
39234982Sdim
40234285Sdimusing namespace llvm;
41234285Sdim
42234285Sdimconst unsigned Hexagon_MAX_RET_SIZE = 64;
43234285Sdim
44234285Sdimstatic cl::opt<bool>
45234285SdimEmitJumpTables("hexagon-emit-jump-tables", cl::init(true), cl::Hidden,
46234285Sdim               cl::desc("Control jump table emission on Hexagon target"));
47234285Sdim
48234285Sdimint NumNamedVarArgParams = -1;
49234285Sdim
50234285Sdim// Implement calling convention for Hexagon.
51234285Sdimstatic bool
52234285SdimCC_Hexagon(unsigned ValNo, MVT ValVT,
53234285Sdim           MVT LocVT, CCValAssign::LocInfo LocInfo,
54234285Sdim           ISD::ArgFlagsTy ArgFlags, CCState &State);
55234285Sdim
56234285Sdimstatic bool
57234285SdimCC_Hexagon32(unsigned ValNo, MVT ValVT,
58234285Sdim             MVT LocVT, CCValAssign::LocInfo LocInfo,
59234285Sdim             ISD::ArgFlagsTy ArgFlags, CCState &State);
60234285Sdim
61234285Sdimstatic bool
62234285SdimCC_Hexagon64(unsigned ValNo, MVT ValVT,
63234285Sdim             MVT LocVT, CCValAssign::LocInfo LocInfo,
64234285Sdim             ISD::ArgFlagsTy ArgFlags, CCState &State);
65234285Sdim
66234285Sdimstatic bool
67234285SdimRetCC_Hexagon(unsigned ValNo, MVT ValVT,
68234285Sdim              MVT LocVT, CCValAssign::LocInfo LocInfo,
69234285Sdim              ISD::ArgFlagsTy ArgFlags, CCState &State);
70234285Sdim
71234285Sdimstatic bool
72234285SdimRetCC_Hexagon32(unsigned ValNo, MVT ValVT,
73234285Sdim                MVT LocVT, CCValAssign::LocInfo LocInfo,
74234285Sdim                ISD::ArgFlagsTy ArgFlags, CCState &State);
75234285Sdim
76234285Sdimstatic bool
77234285SdimRetCC_Hexagon64(unsigned ValNo, MVT ValVT,
78234285Sdim                MVT LocVT, CCValAssign::LocInfo LocInfo,
79234285Sdim                ISD::ArgFlagsTy ArgFlags, CCState &State);
80234285Sdim
81234285Sdimstatic bool
82234285SdimCC_Hexagon_VarArg (unsigned ValNo, MVT ValVT,
83234285Sdim            MVT LocVT, CCValAssign::LocInfo LocInfo,
84234285Sdim            ISD::ArgFlagsTy ArgFlags, CCState &State) {
85234285Sdim
86234285Sdim  // NumNamedVarArgParams can not be zero for a VarArg function.
87234285Sdim  assert ( (NumNamedVarArgParams > 0) &&
88234285Sdim           "NumNamedVarArgParams is not bigger than zero.");
89234285Sdim
90234285Sdim  if ( (int)ValNo < NumNamedVarArgParams ) {
91234285Sdim    // Deal with named arguments.
92234285Sdim    return CC_Hexagon(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State);
93234285Sdim  }
94234285Sdim
95234285Sdim  // Deal with un-named arguments.
96234285Sdim  unsigned ofst;
97234285Sdim  if (ArgFlags.isByVal()) {
98234285Sdim    // If pass-by-value, the size allocated on stack is decided
99234285Sdim    // by ArgFlags.getByValSize(), not by the size of LocVT.
100234285Sdim    assert ((ArgFlags.getByValSize() > 8) &&
101234285Sdim            "ByValSize must be bigger than 8 bytes");
102234285Sdim    ofst = State.AllocateStack(ArgFlags.getByValSize(), 4);
103234285Sdim    State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
104234285Sdim    return false;
105234285Sdim  }
106249423Sdim  if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) {
107249423Sdim    LocVT = MVT::i32;
108249423Sdim    ValVT = MVT::i32;
109249423Sdim    if (ArgFlags.isSExt())
110249423Sdim      LocInfo = CCValAssign::SExt;
111249423Sdim    else if (ArgFlags.isZExt())
112249423Sdim      LocInfo = CCValAssign::ZExt;
113249423Sdim    else
114249423Sdim      LocInfo = CCValAssign::AExt;
115249423Sdim  }
116239462Sdim  if (LocVT == MVT::i32 || LocVT == MVT::f32) {
117234285Sdim    ofst = State.AllocateStack(4, 4);
118234285Sdim    State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
119234285Sdim    return false;
120234285Sdim  }
121239462Sdim  if (LocVT == MVT::i64 || LocVT == MVT::f64) {
122234285Sdim    ofst = State.AllocateStack(8, 8);
123234285Sdim    State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
124234285Sdim    return false;
125234285Sdim  }
126234285Sdim  llvm_unreachable(0);
127234285Sdim}
128234285Sdim
129234285Sdim
130234285Sdimstatic bool
131234285SdimCC_Hexagon (unsigned ValNo, MVT ValVT,
132234285Sdim            MVT LocVT, CCValAssign::LocInfo LocInfo,
133234285Sdim            ISD::ArgFlagsTy ArgFlags, CCState &State) {
134234285Sdim
135234285Sdim  if (ArgFlags.isByVal()) {
136234285Sdim    // Passed on stack.
137234285Sdim    assert ((ArgFlags.getByValSize() > 8) &&
138234285Sdim            "ByValSize must be bigger than 8 bytes");
139234285Sdim    unsigned Offset = State.AllocateStack(ArgFlags.getByValSize(), 4);
140234285Sdim    State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
141234285Sdim    return false;
142234285Sdim  }
143234285Sdim
144234285Sdim  if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) {
145234285Sdim    LocVT = MVT::i32;
146234285Sdim    ValVT = MVT::i32;
147234285Sdim    if (ArgFlags.isSExt())
148234285Sdim      LocInfo = CCValAssign::SExt;
149234285Sdim    else if (ArgFlags.isZExt())
150234285Sdim      LocInfo = CCValAssign::ZExt;
151234285Sdim    else
152234285Sdim      LocInfo = CCValAssign::AExt;
153234285Sdim  }
154234285Sdim
155239462Sdim  if (LocVT == MVT::i32 || LocVT == MVT::f32) {
156234285Sdim    if (!CC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
157234285Sdim      return false;
158234285Sdim  }
159234285Sdim
160239462Sdim  if (LocVT == MVT::i64 || LocVT == MVT::f64) {
161234285Sdim    if (!CC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
162234285Sdim      return false;
163234285Sdim  }
164234285Sdim
165234285Sdim  return true;  // CC didn't match.
166234285Sdim}
167234285Sdim
168234285Sdim
169234285Sdimstatic bool CC_Hexagon32(unsigned ValNo, MVT ValVT,
170234285Sdim                         MVT LocVT, CCValAssign::LocInfo LocInfo,
171234285Sdim                         ISD::ArgFlagsTy ArgFlags, CCState &State) {
172234285Sdim
173234285Sdim  static const uint16_t RegList[] = {
174234285Sdim    Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4,
175234285Sdim    Hexagon::R5
176234285Sdim  };
177234285Sdim  if (unsigned Reg = State.AllocateReg(RegList, 6)) {
178234285Sdim    State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
179234285Sdim    return false;
180234285Sdim  }
181234285Sdim
182234285Sdim  unsigned Offset = State.AllocateStack(4, 4);
183234285Sdim  State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
184234285Sdim  return false;
185234285Sdim}
186234285Sdim
187234285Sdimstatic bool CC_Hexagon64(unsigned ValNo, MVT ValVT,
188234285Sdim                         MVT LocVT, CCValAssign::LocInfo LocInfo,
189234285Sdim                         ISD::ArgFlagsTy ArgFlags, CCState &State) {
190234285Sdim
191234285Sdim  if (unsigned Reg = State.AllocateReg(Hexagon::D0)) {
192234285Sdim    State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
193234285Sdim    return false;
194234285Sdim  }
195234285Sdim
196234285Sdim  static const uint16_t RegList1[] = {
197234285Sdim    Hexagon::D1, Hexagon::D2
198234285Sdim  };
199234285Sdim  static const uint16_t RegList2[] = {
200234285Sdim    Hexagon::R1, Hexagon::R3
201234285Sdim  };
202234285Sdim  if (unsigned Reg = State.AllocateReg(RegList1, RegList2, 2)) {
203234285Sdim    State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
204234285Sdim    return false;
205234285Sdim  }
206234285Sdim
207234285Sdim  unsigned Offset = State.AllocateStack(8, 8, Hexagon::D2);
208234285Sdim  State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
209234285Sdim  return false;
210234285Sdim}
211234285Sdim
212234285Sdimstatic bool RetCC_Hexagon(unsigned ValNo, MVT ValVT,
213234285Sdim                          MVT LocVT, CCValAssign::LocInfo LocInfo,
214234285Sdim                          ISD::ArgFlagsTy ArgFlags, CCState &State) {
215234285Sdim
216234285Sdim
217234285Sdim  if (LocVT == MVT::i1 ||
218234285Sdim      LocVT == MVT::i8 ||
219234285Sdim      LocVT == MVT::i16) {
220234285Sdim    LocVT = MVT::i32;
221234285Sdim    ValVT = MVT::i32;
222234285Sdim    if (ArgFlags.isSExt())
223234285Sdim      LocInfo = CCValAssign::SExt;
224234285Sdim    else if (ArgFlags.isZExt())
225234285Sdim      LocInfo = CCValAssign::ZExt;
226234285Sdim    else
227234285Sdim      LocInfo = CCValAssign::AExt;
228234285Sdim  }
229234285Sdim
230239462Sdim  if (LocVT == MVT::i32 || LocVT == MVT::f32) {
231234285Sdim    if (!RetCC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
232234285Sdim    return false;
233234285Sdim  }
234234285Sdim
235239462Sdim  if (LocVT == MVT::i64 || LocVT == MVT::f64) {
236234285Sdim    if (!RetCC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
237234285Sdim    return false;
238234285Sdim  }
239234285Sdim
240234285Sdim  return true;  // CC didn't match.
241234285Sdim}
242234285Sdim
243234285Sdimstatic bool RetCC_Hexagon32(unsigned ValNo, MVT ValVT,
244234285Sdim                            MVT LocVT, CCValAssign::LocInfo LocInfo,
245234285Sdim                            ISD::ArgFlagsTy ArgFlags, CCState &State) {
246234285Sdim
247239462Sdim  if (LocVT == MVT::i32 || LocVT == MVT::f32) {
248234285Sdim    if (unsigned Reg = State.AllocateReg(Hexagon::R0)) {
249234285Sdim      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
250234285Sdim      return false;
251234285Sdim    }
252234285Sdim  }
253234285Sdim
254234285Sdim  unsigned Offset = State.AllocateStack(4, 4);
255234285Sdim  State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
256234285Sdim  return false;
257234285Sdim}
258234285Sdim
259234285Sdimstatic bool RetCC_Hexagon64(unsigned ValNo, MVT ValVT,
260234285Sdim                            MVT LocVT, CCValAssign::LocInfo LocInfo,
261234285Sdim                            ISD::ArgFlagsTy ArgFlags, CCState &State) {
262239462Sdim  if (LocVT == MVT::i64 || LocVT == MVT::f64) {
263234285Sdim    if (unsigned Reg = State.AllocateReg(Hexagon::D0)) {
264234285Sdim      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
265234285Sdim      return false;
266234285Sdim    }
267234285Sdim  }
268234285Sdim
269234285Sdim  unsigned Offset = State.AllocateStack(8, 8);
270234285Sdim  State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
271234285Sdim  return false;
272234285Sdim}
273234285Sdim
274234285SdimSDValue
275234285SdimHexagonTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG)
276234285Sdimconst {
277234285Sdim  return SDValue();
278234285Sdim}
279234285Sdim
280234285Sdim/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified
281234285Sdim/// by "Src" to address "Dst" of size "Size".  Alignment information is
282234285Sdim/// specified by the specific parameter attribute. The copy will be passed as
283234285Sdim/// a byval function parameter.  Sometimes what we are copying is the end of a
284234285Sdim/// larger object, the part that does not fit in registers.
285234285Sdimstatic SDValue
286234285SdimCreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain,
287234285Sdim                          ISD::ArgFlagsTy Flags, SelectionDAG &DAG,
288234285Sdim                          DebugLoc dl) {
289234285Sdim
290234285Sdim  SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32);
291234285Sdim  return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(),
292234285Sdim                       /*isVolatile=*/false, /*AlwaysInline=*/false,
293234285Sdim                       MachinePointerInfo(), MachinePointerInfo());
294234285Sdim}
295234285Sdim
296234285Sdim
297234285Sdim// LowerReturn - Lower ISD::RET. If a struct is larger than 8 bytes and is
298234285Sdim// passed by value, the function prototype is modified to return void and
299234285Sdim// the value is stored in memory pointed by a pointer passed by caller.
300234285SdimSDValue
301234285SdimHexagonTargetLowering::LowerReturn(SDValue Chain,
302234285Sdim                                   CallingConv::ID CallConv, bool isVarArg,
303234285Sdim                                   const SmallVectorImpl<ISD::OutputArg> &Outs,
304234285Sdim                                   const SmallVectorImpl<SDValue> &OutVals,
305234285Sdim                                   DebugLoc dl, SelectionDAG &DAG) const {
306234285Sdim
307234285Sdim  // CCValAssign - represent the assignment of the return value to locations.
308234285Sdim  SmallVector<CCValAssign, 16> RVLocs;
309234285Sdim
310234285Sdim  // CCState - Info about the registers and stack slot.
311234285Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
312239462Sdim                 getTargetMachine(), RVLocs, *DAG.getContext());
313234285Sdim
314234285Sdim  // Analyze return values of ISD::RET
315234285Sdim  CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon);
316234285Sdim
317249423Sdim  SDValue Flag;
318249423Sdim  SmallVector<SDValue, 4> RetOps(1, Chain);
319234285Sdim
320234285Sdim  // Copy the result values into the output registers.
321234285Sdim  for (unsigned i = 0; i != RVLocs.size(); ++i) {
322234285Sdim    CCValAssign &VA = RVLocs[i];
323234285Sdim
324234285Sdim    Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag);
325234285Sdim
326234285Sdim    // Guarantee that all emitted copies are stuck together with flags.
327234285Sdim    Flag = Chain.getValue(1);
328249423Sdim    RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
329234285Sdim  }
330234285Sdim
331249423Sdim  RetOps[0] = Chain;  // Update chain.
332249423Sdim
333249423Sdim  // Add the flag if we have it.
334234285Sdim  if (Flag.getNode())
335249423Sdim    RetOps.push_back(Flag);
336234285Sdim
337249423Sdim  return DAG.getNode(HexagonISD::RET_FLAG, dl, MVT::Other,
338249423Sdim                     &RetOps[0], RetOps.size());
339234285Sdim}
340234285Sdim
341234285Sdim
342234285Sdim
343234285Sdim
344234285Sdim/// LowerCallResult - Lower the result values of an ISD::CALL into the
345234285Sdim/// appropriate copies out of appropriate physical registers.  This assumes that
346234285Sdim/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
347234285Sdim/// being lowered. Returns a SDNode with the same number of values as the
348234285Sdim/// ISD::CALL.
349234285SdimSDValue
350234285SdimHexagonTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
351234285Sdim                                       CallingConv::ID CallConv, bool isVarArg,
352234285Sdim                                       const
353234285Sdim                                       SmallVectorImpl<ISD::InputArg> &Ins,
354234285Sdim                                       DebugLoc dl, SelectionDAG &DAG,
355234285Sdim                                       SmallVectorImpl<SDValue> &InVals,
356234285Sdim                                       const SmallVectorImpl<SDValue> &OutVals,
357234285Sdim                                       SDValue Callee) const {
358234285Sdim
359234285Sdim  // Assign locations to each value returned by this call.
360234285Sdim  SmallVector<CCValAssign, 16> RVLocs;
361234285Sdim
362234285Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
363239462Sdim                 getTargetMachine(), RVLocs, *DAG.getContext());
364234285Sdim
365234285Sdim  CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon);
366234285Sdim
367234285Sdim  // Copy all of the result registers out of their specified physreg.
368234285Sdim  for (unsigned i = 0; i != RVLocs.size(); ++i) {
369234285Sdim    Chain = DAG.getCopyFromReg(Chain, dl,
370234285Sdim                               RVLocs[i].getLocReg(),
371234285Sdim                               RVLocs[i].getValVT(), InFlag).getValue(1);
372234285Sdim    InFlag = Chain.getValue(2);
373234285Sdim    InVals.push_back(Chain.getValue(0));
374234285Sdim  }
375234285Sdim
376234285Sdim  return Chain;
377234285Sdim}
378234285Sdim
379234285Sdim/// LowerCall - Functions arguments are copied from virtual regs to
380234285Sdim/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
381234285SdimSDValue
382239462SdimHexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
383234285Sdim                                 SmallVectorImpl<SDValue> &InVals) const {
384239462Sdim  SelectionDAG &DAG                     = CLI.DAG;
385239462Sdim  DebugLoc &dl                          = CLI.DL;
386239462Sdim  SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs;
387239462Sdim  SmallVector<SDValue, 32> &OutVals     = CLI.OutVals;
388239462Sdim  SmallVector<ISD::InputArg, 32> &Ins   = CLI.Ins;
389239462Sdim  SDValue Chain                         = CLI.Chain;
390239462Sdim  SDValue Callee                        = CLI.Callee;
391239462Sdim  bool &isTailCall                      = CLI.IsTailCall;
392239462Sdim  CallingConv::ID CallConv              = CLI.CallConv;
393239462Sdim  bool isVarArg                         = CLI.IsVarArg;
394234285Sdim
395234285Sdim  bool IsStructRet    = (Outs.empty()) ? false : Outs[0].Flags.isSRet();
396234285Sdim
397234285Sdim  // Analyze operands of the call, assigning locations to each operand.
398234285Sdim  SmallVector<CCValAssign, 16> ArgLocs;
399234285Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
400239462Sdim                 getTargetMachine(), ArgLocs, *DAG.getContext());
401234285Sdim
402234285Sdim  // Check for varargs.
403234285Sdim  NumNamedVarArgParams = -1;
404234285Sdim  if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Callee))
405234285Sdim  {
406234285Sdim    const Function* CalleeFn = NULL;
407234285Sdim    Callee = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, MVT::i32);
408234285Sdim    if ((CalleeFn = dyn_cast<Function>(GA->getGlobal())))
409234285Sdim    {
410234285Sdim      // If a function has zero args and is a vararg function, that's
411234285Sdim      // disallowed so it must be an undeclared function.  Do not assume
412234285Sdim      // varargs if the callee is undefined.
413234285Sdim      if (CalleeFn->isVarArg() &&
414234285Sdim          CalleeFn->getFunctionType()->getNumParams() != 0) {
415234285Sdim        NumNamedVarArgParams = CalleeFn->getFunctionType()->getNumParams();
416234285Sdim      }
417234285Sdim    }
418234285Sdim  }
419234285Sdim
420234285Sdim  if (NumNamedVarArgParams > 0)
421234285Sdim    CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_VarArg);
422234285Sdim  else
423234285Sdim    CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon);
424234285Sdim
425234285Sdim
426234285Sdim  if(isTailCall) {
427234285Sdim    bool StructAttrFlag =
428234285Sdim      DAG.getMachineFunction().getFunction()->hasStructRetAttr();
429234285Sdim    isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv,
430234285Sdim                                                   isVarArg, IsStructRet,
431234285Sdim                                                   StructAttrFlag,
432234285Sdim                                                   Outs, OutVals, Ins, DAG);
433234285Sdim    for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i){
434234285Sdim      CCValAssign &VA = ArgLocs[i];
435234285Sdim      if (VA.isMemLoc()) {
436234285Sdim        isTailCall = false;
437234285Sdim        break;
438234285Sdim      }
439234285Sdim    }
440234285Sdim    if (isTailCall) {
441234285Sdim      DEBUG(dbgs () << "Eligible for Tail Call\n");
442234285Sdim    } else {
443234285Sdim      DEBUG(dbgs () <<
444234285Sdim            "Argument must be passed on stack. Not eligible for Tail Call\n");
445234285Sdim    }
446234285Sdim  }
447234285Sdim  // Get a count of how many bytes are to be pushed on the stack.
448234285Sdim  unsigned NumBytes = CCInfo.getNextStackOffset();
449234285Sdim  SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass;
450234285Sdim  SmallVector<SDValue, 8> MemOpChains;
451234285Sdim
452234285Sdim  SDValue StackPtr =
453234285Sdim    DAG.getCopyFromReg(Chain, dl, TM.getRegisterInfo()->getStackRegister(),
454234285Sdim                       getPointerTy());
455234285Sdim
456234285Sdim  // Walk the register/memloc assignments, inserting copies/loads.
457234285Sdim  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
458234285Sdim    CCValAssign &VA = ArgLocs[i];
459234285Sdim    SDValue Arg = OutVals[i];
460234285Sdim    ISD::ArgFlagsTy Flags = Outs[i].Flags;
461234285Sdim
462234285Sdim    // Promote the value if needed.
463234285Sdim    switch (VA.getLocInfo()) {
464234285Sdim      default:
465234285Sdim        // Loc info must be one of Full, SExt, ZExt, or AExt.
466234285Sdim        llvm_unreachable("Unknown loc info!");
467234285Sdim      case CCValAssign::Full:
468234285Sdim        break;
469234285Sdim      case CCValAssign::SExt:
470234285Sdim        Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
471234285Sdim        break;
472234285Sdim      case CCValAssign::ZExt:
473234285Sdim        Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
474234285Sdim        break;
475234285Sdim      case CCValAssign::AExt:
476234285Sdim        Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
477234285Sdim        break;
478234285Sdim    }
479234285Sdim
480234285Sdim    if (VA.isMemLoc()) {
481234285Sdim      unsigned LocMemOffset = VA.getLocMemOffset();
482234285Sdim      SDValue PtrOff = DAG.getConstant(LocMemOffset, StackPtr.getValueType());
483234285Sdim      PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
484234285Sdim
485234285Sdim      if (Flags.isByVal()) {
486234285Sdim        // The argument is a struct passed by value. According to LLVM, "Arg"
487234285Sdim        // is is pointer.
488234285Sdim        MemOpChains.push_back(CreateCopyOfByValArgument(Arg, PtrOff, Chain,
489234285Sdim                                                        Flags, DAG, dl));
490234285Sdim      } else {
491234285Sdim        // The argument is not passed by value. "Arg" is a buildin type. It is
492234285Sdim        // not a pointer.
493234285Sdim        MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
494234285Sdim                                           MachinePointerInfo(),false, false,
495234285Sdim                                           0));
496234285Sdim      }
497234285Sdim      continue;
498234285Sdim    }
499234285Sdim
500234285Sdim    // Arguments that can be passed on register must be kept at RegsToPass
501234285Sdim    // vector.
502234285Sdim    if (VA.isRegLoc()) {
503234285Sdim      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
504234285Sdim    }
505234285Sdim  }
506234285Sdim
507234285Sdim  // Transform all store nodes into one single node because all store
508234285Sdim  // nodes are independent of each other.
509234285Sdim  if (!MemOpChains.empty()) {
510234285Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOpChains[0],
511234285Sdim                        MemOpChains.size());
512234285Sdim  }
513234285Sdim
514234285Sdim  if (!isTailCall)
515234285Sdim    Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumBytes,
516234285Sdim                                                        getPointerTy(), true));
517234285Sdim
518234285Sdim  // Build a sequence of copy-to-reg nodes chained together with token
519234285Sdim  // chain and flag operands which copy the outgoing args into registers.
520239462Sdim  // The InFlag in necessary since all emitted instructions must be
521234285Sdim  // stuck together.
522234285Sdim  SDValue InFlag;
523234285Sdim  if (!isTailCall) {
524234285Sdim    for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
525234285Sdim      Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
526234285Sdim                               RegsToPass[i].second, InFlag);
527234285Sdim      InFlag = Chain.getValue(1);
528234285Sdim    }
529234285Sdim  }
530234285Sdim
531234285Sdim  // For tail calls lower the arguments to the 'real' stack slot.
532234285Sdim  if (isTailCall) {
533234285Sdim    // Force all the incoming stack arguments to be loaded from the stack
534234285Sdim    // before any new outgoing arguments are stored to the stack, because the
535234285Sdim    // outgoing stack slots may alias the incoming argument stack slots, and
536234285Sdim    // the alias isn't otherwise explicit. This is slightly more conservative
537234285Sdim    // than necessary, because it means that each store effectively depends
538234285Sdim    // on every argument instead of just those arguments it would clobber.
539234285Sdim    //
540239462Sdim    // Do not flag preceding copytoreg stuff together with the following stuff.
541234285Sdim    InFlag = SDValue();
542234285Sdim    for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
543234285Sdim      Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
544234285Sdim                               RegsToPass[i].second, InFlag);
545234285Sdim      InFlag = Chain.getValue(1);
546234285Sdim    }
547234285Sdim    InFlag =SDValue();
548234285Sdim  }
549234285Sdim
550234285Sdim  // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
551234285Sdim  // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
552234285Sdim  // node so that legalize doesn't hack it.
553234285Sdim  if (flag_aligned_memcpy) {
554234285Sdim    const char *MemcpyName =
555234285Sdim      "__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes";
556234285Sdim    Callee =
557234285Sdim      DAG.getTargetExternalSymbol(MemcpyName, getPointerTy());
558234285Sdim    flag_aligned_memcpy = false;
559234285Sdim  } else if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
560234285Sdim    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy());
561234285Sdim  } else if (ExternalSymbolSDNode *S =
562234285Sdim             dyn_cast<ExternalSymbolSDNode>(Callee)) {
563234285Sdim    Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
564234285Sdim  }
565234285Sdim
566234285Sdim  // Returns a chain & a flag for retval copy to use.
567234285Sdim  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
568234285Sdim  SmallVector<SDValue, 8> Ops;
569234285Sdim  Ops.push_back(Chain);
570234285Sdim  Ops.push_back(Callee);
571234285Sdim
572234285Sdim  // Add argument registers to the end of the list so that they are
573234285Sdim  // known live into the call.
574234285Sdim  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
575234285Sdim    Ops.push_back(DAG.getRegister(RegsToPass[i].first,
576234285Sdim                                  RegsToPass[i].second.getValueType()));
577234285Sdim  }
578234285Sdim
579234285Sdim  if (InFlag.getNode()) {
580234285Sdim    Ops.push_back(InFlag);
581234285Sdim  }
582234285Sdim
583234285Sdim  if (isTailCall)
584234285Sdim    return DAG.getNode(HexagonISD::TC_RETURN, dl, NodeTys, &Ops[0], Ops.size());
585234285Sdim
586234285Sdim  Chain = DAG.getNode(HexagonISD::CALL, dl, NodeTys, &Ops[0], Ops.size());
587234285Sdim  InFlag = Chain.getValue(1);
588234285Sdim
589234285Sdim  // Create the CALLSEQ_END node.
590234285Sdim  Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true),
591234285Sdim                             DAG.getIntPtrConstant(0, true), InFlag);
592234285Sdim  InFlag = Chain.getValue(1);
593234285Sdim
594234285Sdim  // Handle result values, copying them out of physregs into vregs that we
595234285Sdim  // return.
596234285Sdim  return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, DAG,
597234285Sdim                         InVals, OutVals, Callee);
598234285Sdim}
599234285Sdim
600234285Sdimstatic bool getIndexedAddressParts(SDNode *Ptr, EVT VT,
601234285Sdim                                   bool isSEXTLoad, SDValue &Base,
602234285Sdim                                   SDValue &Offset, bool &isInc,
603234285Sdim                                   SelectionDAG &DAG) {
604234285Sdim  if (Ptr->getOpcode() != ISD::ADD)
605234285Sdim  return false;
606234285Sdim
607234285Sdim  if (VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) {
608234285Sdim    isInc = (Ptr->getOpcode() == ISD::ADD);
609234285Sdim    Base = Ptr->getOperand(0);
610234285Sdim    Offset = Ptr->getOperand(1);
611234285Sdim    // Ensure that Offset is a constant.
612234285Sdim    return (isa<ConstantSDNode>(Offset));
613234285Sdim  }
614234285Sdim
615234285Sdim  return false;
616234285Sdim}
617234285Sdim
618234285Sdim// TODO: Put this function along with the other isS* functions in
619234285Sdim// HexagonISelDAGToDAG.cpp into a common file. Or better still, use the
620249423Sdim// functions defined in HexagonOperands.td.
621234285Sdimstatic bool Is_PostInc_S4_Offset(SDNode * S, int ShiftAmount) {
622234285Sdim  ConstantSDNode *N = cast<ConstantSDNode>(S);
623234285Sdim
624234285Sdim  // immS4 predicate - True if the immediate fits in a 4-bit sign extended.
625234285Sdim  // field.
626234285Sdim  int64_t v = (int64_t)N->getSExtValue();
627234285Sdim  int64_t m = 0;
628234285Sdim  if (ShiftAmount > 0) {
629234285Sdim    m = v % ShiftAmount;
630234285Sdim    v = v >> ShiftAmount;
631234285Sdim  }
632234285Sdim  return (v <= 7) && (v >= -8) && (m == 0);
633234285Sdim}
634234285Sdim
635234285Sdim/// getPostIndexedAddressParts - returns true by value, base pointer and
636234285Sdim/// offset pointer and addressing mode by reference if this node can be
637234285Sdim/// combined with a load / store to form a post-indexed load / store.
638234285Sdimbool HexagonTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
639234285Sdim                                                       SDValue &Base,
640234285Sdim                                                       SDValue &Offset,
641234285Sdim                                                       ISD::MemIndexedMode &AM,
642234285Sdim                                                       SelectionDAG &DAG) const
643234285Sdim{
644234285Sdim  EVT VT;
645234285Sdim  SDValue Ptr;
646234285Sdim  bool isSEXTLoad = false;
647234285Sdim
648234285Sdim  if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
649234285Sdim    VT  = LD->getMemoryVT();
650234285Sdim    isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD;
651234285Sdim  } else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
652234285Sdim    VT  = ST->getMemoryVT();
653234285Sdim    if (ST->getValue().getValueType() == MVT::i64 && ST->isTruncatingStore()) {
654234285Sdim      return false;
655234285Sdim    }
656234285Sdim  } else {
657234285Sdim    return false;
658234285Sdim  }
659234285Sdim
660234285Sdim  bool isInc = false;
661234285Sdim  bool isLegal = getIndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset,
662234285Sdim                                        isInc, DAG);
663234285Sdim  // ShiftAmount = number of left-shifted bits in the Hexagon instruction.
664234285Sdim  int ShiftAmount = VT.getSizeInBits() / 16;
665234285Sdim  if (isLegal && Is_PostInc_S4_Offset(Offset.getNode(), ShiftAmount)) {
666234285Sdim    AM = isInc ? ISD::POST_INC : ISD::POST_DEC;
667234285Sdim    return true;
668234285Sdim  }
669234285Sdim
670234285Sdim  return false;
671234285Sdim}
672234285Sdim
673234285SdimSDValue HexagonTargetLowering::LowerINLINEASM(SDValue Op,
674234285Sdim                                              SelectionDAG &DAG) const {
675234285Sdim  SDNode *Node = Op.getNode();
676234285Sdim  MachineFunction &MF = DAG.getMachineFunction();
677234285Sdim  HexagonMachineFunctionInfo *FuncInfo =
678234285Sdim    MF.getInfo<HexagonMachineFunctionInfo>();
679234285Sdim  switch (Node->getOpcode()) {
680234285Sdim    case ISD::INLINEASM: {
681234285Sdim      unsigned NumOps = Node->getNumOperands();
682234285Sdim      if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue)
683234285Sdim        --NumOps;  // Ignore the flag operand.
684234285Sdim
685234285Sdim      for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
686234285Sdim        if (FuncInfo->hasClobberLR())
687234285Sdim          break;
688234285Sdim        unsigned Flags =
689234285Sdim          cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
690234285Sdim        unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
691234285Sdim        ++i;  // Skip the ID value.
692234285Sdim
693234285Sdim        switch (InlineAsm::getKind(Flags)) {
694234285Sdim        default: llvm_unreachable("Bad flags!");
695234285Sdim          case InlineAsm::Kind_RegDef:
696234285Sdim          case InlineAsm::Kind_RegUse:
697234285Sdim          case InlineAsm::Kind_Imm:
698234285Sdim          case InlineAsm::Kind_Clobber:
699234285Sdim          case InlineAsm::Kind_Mem: {
700234285Sdim            for (; NumVals; --NumVals, ++i) {}
701234285Sdim            break;
702234285Sdim          }
703234285Sdim          case InlineAsm::Kind_RegDefEarlyClobber: {
704234285Sdim            for (; NumVals; --NumVals, ++i) {
705234285Sdim              unsigned Reg =
706234285Sdim                cast<RegisterSDNode>(Node->getOperand(i))->getReg();
707234285Sdim
708234285Sdim              // Check it to be lr
709234285Sdim              if (Reg == TM.getRegisterInfo()->getRARegister()) {
710234285Sdim                FuncInfo->setHasClobberLR(true);
711234285Sdim                break;
712234285Sdim              }
713234285Sdim            }
714234285Sdim            break;
715234285Sdim          }
716234285Sdim        }
717234285Sdim      }
718234285Sdim    }
719234285Sdim  } // Node->getOpcode
720234285Sdim  return Op;
721234285Sdim}
722234285Sdim
723234285Sdim
724234285Sdim//
725234285Sdim// Taken from the XCore backend.
726234285Sdim//
727234285SdimSDValue HexagonTargetLowering::
728234285SdimLowerBR_JT(SDValue Op, SelectionDAG &DAG) const
729234285Sdim{
730234285Sdim  SDValue Chain = Op.getOperand(0);
731234285Sdim  SDValue Table = Op.getOperand(1);
732234285Sdim  SDValue Index = Op.getOperand(2);
733234285Sdim  DebugLoc dl = Op.getDebugLoc();
734234285Sdim  JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
735234285Sdim  unsigned JTI = JT->getIndex();
736234285Sdim  MachineFunction &MF = DAG.getMachineFunction();
737234285Sdim  const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
738234285Sdim  SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
739234285Sdim
740234285Sdim  // Mark all jump table targets as address taken.
741234285Sdim  const std::vector<MachineJumpTableEntry> &JTE = MJTI->getJumpTables();
742234285Sdim  const std::vector<MachineBasicBlock*> &JTBBs = JTE[JTI].MBBs;
743234285Sdim  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
744234285Sdim    MachineBasicBlock *MBB = JTBBs[i];
745234285Sdim    MBB->setHasAddressTaken();
746234285Sdim    // This line is needed to set the hasAddressTaken flag on the BasicBlock
747234285Sdim    // object.
748234285Sdim    BlockAddress::get(const_cast<BasicBlock *>(MBB->getBasicBlock()));
749234285Sdim  }
750234285Sdim
751234285Sdim  SDValue JumpTableBase = DAG.getNode(HexagonISD::WrapperJT, dl,
752234285Sdim                                      getPointerTy(), TargetJT);
753234285Sdim  SDValue ShiftIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index,
754234285Sdim                                   DAG.getConstant(2, MVT::i32));
755234285Sdim  SDValue JTAddress = DAG.getNode(ISD::ADD, dl, MVT::i32, JumpTableBase,
756234285Sdim                                  ShiftIndex);
757234285Sdim  SDValue LoadTarget = DAG.getLoad(MVT::i32, dl, Chain, JTAddress,
758234285Sdim                                   MachinePointerInfo(), false, false, false,
759234285Sdim                                   0);
760234285Sdim  return DAG.getNode(HexagonISD::BR_JT, dl, MVT::Other, Chain, LoadTarget);
761234285Sdim}
762234285Sdim
763234285Sdim
764234285SdimSDValue
765234285SdimHexagonTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
766234285Sdim                                               SelectionDAG &DAG) const {
767234285Sdim  SDValue Chain = Op.getOperand(0);
768234285Sdim  SDValue Size = Op.getOperand(1);
769234285Sdim  DebugLoc dl = Op.getDebugLoc();
770234285Sdim
771234285Sdim  unsigned SPReg = getStackPointerRegisterToSaveRestore();
772234285Sdim
773234285Sdim  // Get a reference to the stack pointer.
774234285Sdim  SDValue StackPointer = DAG.getCopyFromReg(Chain, dl, SPReg, MVT::i32);
775234285Sdim
776234285Sdim  // Subtract the dynamic size from the actual stack size to
777234285Sdim  // obtain the new stack size.
778234285Sdim  SDValue Sub = DAG.getNode(ISD::SUB, dl, MVT::i32, StackPointer, Size);
779234285Sdim
780234285Sdim  //
781234285Sdim  // For Hexagon, the outgoing memory arguments area should be on top of the
782234285Sdim  // alloca area on the stack i.e., the outgoing memory arguments should be
783234285Sdim  // at a lower address than the alloca area. Move the alloca area down the
784234285Sdim  // stack by adding back the space reserved for outgoing arguments to SP
785234285Sdim  // here.
786234285Sdim  //
787234285Sdim  // We do not know what the size of the outgoing args is at this point.
788234285Sdim  // So, we add a pseudo instruction ADJDYNALLOC that will adjust the
789234285Sdim  // stack pointer. We patch this instruction with the correct, known
790234285Sdim  // offset in emitPrologue().
791234285Sdim  //
792234285Sdim  // Use a placeholder immediate (zero) for now. This will be patched up
793234285Sdim  // by emitPrologue().
794234285Sdim  SDValue ArgAdjust = DAG.getNode(HexagonISD::ADJDYNALLOC, dl,
795234285Sdim                                  MVT::i32,
796234285Sdim                                  Sub,
797234285Sdim                                  DAG.getConstant(0, MVT::i32));
798234285Sdim
799234285Sdim  // The Sub result contains the new stack start address, so it
800234285Sdim  // must be placed in the stack pointer register.
801234285Sdim  SDValue CopyChain = DAG.getCopyToReg(Chain, dl,
802234285Sdim                                       TM.getRegisterInfo()->getStackRegister(),
803234285Sdim                                       Sub);
804234285Sdim
805234285Sdim  SDValue Ops[2] = { ArgAdjust, CopyChain };
806234285Sdim  return DAG.getMergeValues(Ops, 2, dl);
807234285Sdim}
808234285Sdim
809234285SdimSDValue
810234285SdimHexagonTargetLowering::LowerFormalArguments(SDValue Chain,
811234285Sdim                                            CallingConv::ID CallConv,
812234285Sdim                                            bool isVarArg,
813234285Sdim                                            const
814234285Sdim                                            SmallVectorImpl<ISD::InputArg> &Ins,
815234285Sdim                                            DebugLoc dl, SelectionDAG &DAG,
816234285Sdim                                            SmallVectorImpl<SDValue> &InVals)
817234285Sdimconst {
818234285Sdim
819234285Sdim  MachineFunction &MF = DAG.getMachineFunction();
820234285Sdim  MachineFrameInfo *MFI = MF.getFrameInfo();
821234285Sdim  MachineRegisterInfo &RegInfo = MF.getRegInfo();
822234285Sdim  HexagonMachineFunctionInfo *FuncInfo =
823234285Sdim    MF.getInfo<HexagonMachineFunctionInfo>();
824234285Sdim
825234285Sdim
826234285Sdim  // Assign locations to all of the incoming arguments.
827234285Sdim  SmallVector<CCValAssign, 16> ArgLocs;
828234285Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
829239462Sdim                 getTargetMachine(), ArgLocs, *DAG.getContext());
830234285Sdim
831234285Sdim  CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon);
832234285Sdim
833234285Sdim  // For LLVM, in the case when returning a struct by value (>8byte),
834234285Sdim  // the first argument is a pointer that points to the location on caller's
835234285Sdim  // stack where the return value will be stored. For Hexagon, the location on
836234285Sdim  // caller's stack is passed only when the struct size is smaller than (and
837234285Sdim  // equal to) 8 bytes. If not, no address will be passed into callee and
838234285Sdim  // callee return the result direclty through R0/R1.
839234285Sdim
840234285Sdim  SmallVector<SDValue, 4> MemOps;
841234285Sdim
842234285Sdim  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
843234285Sdim    CCValAssign &VA = ArgLocs[i];
844234285Sdim    ISD::ArgFlagsTy Flags = Ins[i].Flags;
845234285Sdim    unsigned ObjSize;
846234285Sdim    unsigned StackLocation;
847234285Sdim    int FI;
848234285Sdim
849234285Sdim    if (   (VA.isRegLoc() && !Flags.isByVal())
850234285Sdim        || (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() > 8)) {
851234285Sdim      // Arguments passed in registers
852234285Sdim      // 1. int, long long, ptr args that get allocated in register.
853234285Sdim      // 2. Large struct that gets an register to put its address in.
854234285Sdim      EVT RegVT = VA.getLocVT();
855239462Sdim      if (RegVT == MVT::i8 || RegVT == MVT::i16 ||
856239462Sdim          RegVT == MVT::i32 || RegVT == MVT::f32) {
857234285Sdim        unsigned VReg =
858239462Sdim          RegInfo.createVirtualRegister(&Hexagon::IntRegsRegClass);
859234285Sdim        RegInfo.addLiveIn(VA.getLocReg(), VReg);
860234285Sdim        InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
861234285Sdim      } else if (RegVT == MVT::i64) {
862234285Sdim        unsigned VReg =
863239462Sdim          RegInfo.createVirtualRegister(&Hexagon::DoubleRegsRegClass);
864234285Sdim        RegInfo.addLiveIn(VA.getLocReg(), VReg);
865234285Sdim        InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
866234285Sdim      } else {
867234285Sdim        assert (0);
868234285Sdim      }
869234285Sdim    } else if (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() <= 8) {
870234285Sdim      assert (0 && "ByValSize must be bigger than 8 bytes");
871234285Sdim    } else {
872234285Sdim      // Sanity check.
873234285Sdim      assert(VA.isMemLoc());
874234285Sdim
875234285Sdim      if (Flags.isByVal()) {
876234285Sdim        // If it's a byval parameter, then we need to compute the
877234285Sdim        // "real" size, not the size of the pointer.
878234285Sdim        ObjSize = Flags.getByValSize();
879234285Sdim      } else {
880234285Sdim        ObjSize = VA.getLocVT().getStoreSizeInBits() >> 3;
881234285Sdim      }
882234285Sdim
883234285Sdim      StackLocation = HEXAGON_LRFP_SIZE + VA.getLocMemOffset();
884234285Sdim      // Create the frame index object for this incoming parameter...
885234285Sdim      FI = MFI->CreateFixedObject(ObjSize, StackLocation, true);
886234285Sdim
887234285Sdim      // Create the SelectionDAG nodes cordl, responding to a load
888234285Sdim      // from this parameter.
889234285Sdim      SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
890234285Sdim
891234285Sdim      if (Flags.isByVal()) {
892234285Sdim        // If it's a pass-by-value aggregate, then do not dereference the stack
893234285Sdim        // location. Instead, we should generate a reference to the stack
894234285Sdim        // location.
895234285Sdim        InVals.push_back(FIN);
896234285Sdim      } else {
897234285Sdim        InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
898234285Sdim                                     MachinePointerInfo(), false, false,
899234285Sdim                                     false, 0));
900234285Sdim      }
901234285Sdim    }
902234285Sdim  }
903234285Sdim
904234285Sdim  if (!MemOps.empty())
905234285Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOps[0],
906234285Sdim                        MemOps.size());
907234285Sdim
908234285Sdim  if (isVarArg) {
909234285Sdim    // This will point to the next argument passed via stack.
910234285Sdim    int FrameIndex = MFI->CreateFixedObject(Hexagon_PointerSize,
911234285Sdim                                            HEXAGON_LRFP_SIZE +
912234285Sdim                                            CCInfo.getNextStackOffset(),
913234285Sdim                                            true);
914234285Sdim    FuncInfo->setVarArgsFrameIndex(FrameIndex);
915234285Sdim  }
916234285Sdim
917234285Sdim  return Chain;
918234285Sdim}
919234285Sdim
920234285SdimSDValue
921234285SdimHexagonTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
922234285Sdim  // VASTART stores the address of the VarArgsFrameIndex slot into the
923234285Sdim  // memory location argument.
924234285Sdim  MachineFunction &MF = DAG.getMachineFunction();
925234285Sdim  HexagonMachineFunctionInfo *QFI = MF.getInfo<HexagonMachineFunctionInfo>();
926234285Sdim  SDValue Addr = DAG.getFrameIndex(QFI->getVarArgsFrameIndex(), MVT::i32);
927234285Sdim  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
928234285Sdim  return DAG.getStore(Op.getOperand(0), Op.getDebugLoc(), Addr,
929234285Sdim                      Op.getOperand(1), MachinePointerInfo(SV), false,
930234285Sdim                      false, 0);
931234285Sdim}
932234285Sdim
933234285SdimSDValue
934234285SdimHexagonTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
935239462Sdim  SDValue LHS = Op.getOperand(0);
936239462Sdim  SDValue RHS = Op.getOperand(1);
937239462Sdim  SDValue CC = Op.getOperand(4);
938239462Sdim  SDValue TrueVal = Op.getOperand(2);
939239462Sdim  SDValue FalseVal = Op.getOperand(3);
940239462Sdim  DebugLoc dl = Op.getDebugLoc();
941234285Sdim  SDNode* OpNode = Op.getNode();
942239462Sdim  EVT SVT = OpNode->getValueType(0);
943234285Sdim
944239462Sdim  SDValue Cond = DAG.getNode(ISD::SETCC, dl, MVT::i1, LHS, RHS, CC);
945239462Sdim  return DAG.getNode(ISD::SELECT, dl, SVT, Cond, TrueVal, FalseVal);
946234285Sdim}
947234285Sdim
948234285SdimSDValue
949239462SdimHexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const {
950239462Sdim  EVT ValTy = Op.getValueType();
951239462Sdim
952239462Sdim  DebugLoc dl = Op.getDebugLoc();
953239462Sdim  ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
954239462Sdim  SDValue Res;
955239462Sdim  if (CP->isMachineConstantPoolEntry())
956239462Sdim    Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), ValTy,
957239462Sdim                                    CP->getAlignment());
958239462Sdim  else
959239462Sdim    Res = DAG.getTargetConstantPool(CP->getConstVal(), ValTy,
960239462Sdim                                    CP->getAlignment());
961239462Sdim  return DAG.getNode(HexagonISD::CONST32, dl, ValTy, Res);
962239462Sdim}
963239462Sdim
964239462SdimSDValue
965234285SdimHexagonTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
966234285Sdim  const TargetRegisterInfo *TRI = TM.getRegisterInfo();
967234285Sdim  MachineFunction &MF = DAG.getMachineFunction();
968234285Sdim  MachineFrameInfo *MFI = MF.getFrameInfo();
969234285Sdim  MFI->setReturnAddressIsTaken(true);
970234285Sdim
971234285Sdim  EVT VT = Op.getValueType();
972234285Sdim  DebugLoc dl = Op.getDebugLoc();
973234285Sdim  unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
974234285Sdim  if (Depth) {
975234285Sdim    SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
976234285Sdim    SDValue Offset = DAG.getConstant(4, MVT::i32);
977234285Sdim    return DAG.getLoad(VT, dl, DAG.getEntryNode(),
978234285Sdim                       DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset),
979234285Sdim                       MachinePointerInfo(), false, false, false, 0);
980234285Sdim  }
981234285Sdim
982234285Sdim  // Return LR, which contains the return address. Mark it an implicit live-in.
983234285Sdim  unsigned Reg = MF.addLiveIn(TRI->getRARegister(), getRegClassFor(MVT::i32));
984234285Sdim  return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);
985234285Sdim}
986234285Sdim
987234285SdimSDValue
988234285SdimHexagonTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
989234285Sdim  const HexagonRegisterInfo  *TRI = TM.getRegisterInfo();
990234285Sdim  MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
991234285Sdim  MFI->setFrameAddressIsTaken(true);
992234285Sdim
993234285Sdim  EVT VT = Op.getValueType();
994234285Sdim  DebugLoc dl = Op.getDebugLoc();
995234285Sdim  unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
996234285Sdim  SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl,
997234285Sdim                                         TRI->getFrameRegister(), VT);
998234285Sdim  while (Depth--)
999234285Sdim    FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,
1000234285Sdim                            MachinePointerInfo(),
1001234285Sdim                            false, false, false, 0);
1002234285Sdim  return FrameAddr;
1003234285Sdim}
1004234285Sdim
1005234285SdimSDValue HexagonTargetLowering::LowerATOMIC_FENCE(SDValue Op,
1006234285Sdim                                                 SelectionDAG& DAG) const {
1007234285Sdim  DebugLoc dl = Op.getDebugLoc();
1008234285Sdim  return DAG.getNode(HexagonISD::BARRIER, dl, MVT::Other, Op.getOperand(0));
1009234285Sdim}
1010234285Sdim
1011234285Sdim
1012234285SdimSDValue HexagonTargetLowering::LowerGLOBALADDRESS(SDValue Op,
1013234285Sdim                                                  SelectionDAG &DAG) const {
1014234285Sdim  SDValue Result;
1015234285Sdim  const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
1016234285Sdim  int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();
1017234285Sdim  DebugLoc dl = Op.getDebugLoc();
1018234285Sdim  Result = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), Offset);
1019234285Sdim
1020249423Sdim  const HexagonTargetObjectFile &TLOF =
1021249423Sdim      static_cast<const HexagonTargetObjectFile &>(getObjFileLowering());
1022234285Sdim  if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) {
1023234285Sdim    return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), Result);
1024234285Sdim  }
1025234285Sdim
1026234285Sdim  return DAG.getNode(HexagonISD::CONST32, dl, getPointerTy(), Result);
1027234285Sdim}
1028234285Sdim
1029249423SdimSDValue
1030249423SdimHexagonTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const {
1031249423Sdim  const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
1032249423Sdim  SDValue BA_SD =  DAG.getTargetBlockAddress(BA, MVT::i32);
1033249423Sdim  DebugLoc dl = Op.getDebugLoc();
1034249423Sdim  return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), BA_SD);
1035249423Sdim}
1036249423Sdim
1037234285Sdim//===----------------------------------------------------------------------===//
1038234285Sdim// TargetLowering Implementation
1039234285Sdim//===----------------------------------------------------------------------===//
1040234285Sdim
1041234285SdimHexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine
1042234285Sdim                                             &targetmachine)
1043234285Sdim  : TargetLowering(targetmachine, new HexagonTargetObjectFile()),
1044234285Sdim    TM(targetmachine) {
1045234285Sdim
1046239462Sdim    const HexagonRegisterInfo* QRI = TM.getRegisterInfo();
1047239462Sdim
1048234285Sdim    // Set up the register classes.
1049239462Sdim    addRegisterClass(MVT::i32, &Hexagon::IntRegsRegClass);
1050239462Sdim    addRegisterClass(MVT::i64, &Hexagon::DoubleRegsRegClass);
1051234285Sdim
1052239462Sdim    if (QRI->Subtarget.hasV5TOps()) {
1053239462Sdim      addRegisterClass(MVT::f32, &Hexagon::IntRegsRegClass);
1054239462Sdim      addRegisterClass(MVT::f64, &Hexagon::DoubleRegsRegClass);
1055239462Sdim    }
1056234285Sdim
1057239462Sdim    addRegisterClass(MVT::i1, &Hexagon::PredRegsRegClass);
1058239462Sdim
1059234285Sdim    computeRegisterProperties();
1060234285Sdim
1061234285Sdim    // Align loop entry
1062234285Sdim    setPrefLoopAlignment(4);
1063234285Sdim
1064234285Sdim    // Limits for inline expansion of memcpy/memmove
1065249423Sdim    MaxStoresPerMemcpy = 6;
1066249423Sdim    MaxStoresPerMemmove = 6;
1067234285Sdim
1068234285Sdim    //
1069234285Sdim    // Library calls for unsupported operations
1070234285Sdim    //
1071234285Sdim
1072234285Sdim    setLibcallName(RTLIB::SINTTOFP_I128_F64, "__hexagon_floattidf");
1073234285Sdim    setLibcallName(RTLIB::SINTTOFP_I128_F32, "__hexagon_floattisf");
1074234285Sdim
1075234285Sdim    setLibcallName(RTLIB::FPTOUINT_F32_I128, "__hexagon_fixunssfti");
1076234285Sdim    setLibcallName(RTLIB::FPTOUINT_F64_I128, "__hexagon_fixunsdfti");
1077234285Sdim
1078234285Sdim    setLibcallName(RTLIB::FPTOSINT_F32_I128, "__hexagon_fixsfti");
1079234285Sdim    setLibcallName(RTLIB::FPTOSINT_F64_I128, "__hexagon_fixdfti");
1080234285Sdim
1081234285Sdim    setLibcallName(RTLIB::SDIV_I32, "__hexagon_divsi3");
1082234285Sdim    setOperationAction(ISD::SDIV,  MVT::i32, Expand);
1083234285Sdim    setLibcallName(RTLIB::SREM_I32, "__hexagon_umodsi3");
1084234285Sdim    setOperationAction(ISD::SREM,  MVT::i32, Expand);
1085234285Sdim
1086234285Sdim    setLibcallName(RTLIB::SDIV_I64, "__hexagon_divdi3");
1087234285Sdim    setOperationAction(ISD::SDIV,  MVT::i64, Expand);
1088234285Sdim    setLibcallName(RTLIB::SREM_I64, "__hexagon_moddi3");
1089234285Sdim    setOperationAction(ISD::SREM,  MVT::i64, Expand);
1090234285Sdim
1091234285Sdim    setLibcallName(RTLIB::UDIV_I32, "__hexagon_udivsi3");
1092234285Sdim    setOperationAction(ISD::UDIV,  MVT::i32, Expand);
1093234285Sdim
1094234285Sdim    setLibcallName(RTLIB::UDIV_I64, "__hexagon_udivdi3");
1095234285Sdim    setOperationAction(ISD::UDIV,  MVT::i64, Expand);
1096234285Sdim
1097234285Sdim    setLibcallName(RTLIB::UREM_I32, "__hexagon_umodsi3");
1098234285Sdim    setOperationAction(ISD::UREM,  MVT::i32, Expand);
1099234285Sdim
1100234285Sdim    setLibcallName(RTLIB::UREM_I64, "__hexagon_umoddi3");
1101234285Sdim    setOperationAction(ISD::UREM,  MVT::i64, Expand);
1102234285Sdim
1103234285Sdim    setLibcallName(RTLIB::DIV_F32, "__hexagon_divsf3");
1104234285Sdim    setOperationAction(ISD::FDIV,  MVT::f32, Expand);
1105234285Sdim
1106234285Sdim    setLibcallName(RTLIB::DIV_F64, "__hexagon_divdf3");
1107234285Sdim    setOperationAction(ISD::FDIV,  MVT::f64, Expand);
1108234285Sdim
1109239462Sdim    setOperationAction(ISD::FSQRT,  MVT::f32, Expand);
1110239462Sdim    setOperationAction(ISD::FSQRT,  MVT::f64, Expand);
1111239462Sdim    setOperationAction(ISD::FSIN,  MVT::f32, Expand);
1112239462Sdim    setOperationAction(ISD::FSIN,  MVT::f64, Expand);
1113234285Sdim
1114239462Sdim    if (QRI->Subtarget.hasV5TOps()) {
1115239462Sdim      // Hexagon V5 Support.
1116239462Sdim      setOperationAction(ISD::FADD,       MVT::f32, Legal);
1117239462Sdim      setOperationAction(ISD::FADD,       MVT::f64, Legal);
1118239462Sdim      setOperationAction(ISD::FP_EXTEND,  MVT::f32, Legal);
1119239462Sdim      setCondCodeAction(ISD::SETOEQ,      MVT::f32, Legal);
1120239462Sdim      setCondCodeAction(ISD::SETOEQ,      MVT::f64, Legal);
1121239462Sdim      setCondCodeAction(ISD::SETUEQ,      MVT::f32, Legal);
1122239462Sdim      setCondCodeAction(ISD::SETUEQ,      MVT::f64, Legal);
1123234285Sdim
1124239462Sdim      setCondCodeAction(ISD::SETOGE,      MVT::f32, Legal);
1125239462Sdim      setCondCodeAction(ISD::SETOGE,      MVT::f64, Legal);
1126239462Sdim      setCondCodeAction(ISD::SETUGE,      MVT::f32, Legal);
1127239462Sdim      setCondCodeAction(ISD::SETUGE,      MVT::f64, Legal);
1128234285Sdim
1129239462Sdim      setCondCodeAction(ISD::SETOGT,      MVT::f32, Legal);
1130239462Sdim      setCondCodeAction(ISD::SETOGT,      MVT::f64, Legal);
1131239462Sdim      setCondCodeAction(ISD::SETUGT,      MVT::f32, Legal);
1132239462Sdim      setCondCodeAction(ISD::SETUGT,      MVT::f64, Legal);
1133234285Sdim
1134239462Sdim      setCondCodeAction(ISD::SETOLE,      MVT::f32, Legal);
1135239462Sdim      setCondCodeAction(ISD::SETOLE,      MVT::f64, Legal);
1136239462Sdim      setCondCodeAction(ISD::SETOLT,      MVT::f32, Legal);
1137239462Sdim      setCondCodeAction(ISD::SETOLT,      MVT::f64, Legal);
1138234285Sdim
1139239462Sdim      setOperationAction(ISD::ConstantFP,  MVT::f32, Legal);
1140239462Sdim      setOperationAction(ISD::ConstantFP,  MVT::f64, Legal);
1141234285Sdim
1142239462Sdim      setOperationAction(ISD::FP_TO_UINT, MVT::i1, Promote);
1143239462Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::i1, Promote);
1144239462Sdim      setOperationAction(ISD::UINT_TO_FP, MVT::i1, Promote);
1145239462Sdim      setOperationAction(ISD::SINT_TO_FP, MVT::i1, Promote);
1146234285Sdim
1147239462Sdim      setOperationAction(ISD::FP_TO_UINT, MVT::i8, Promote);
1148239462Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::i8, Promote);
1149239462Sdim      setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
1150239462Sdim      setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
1151234285Sdim
1152239462Sdim      setOperationAction(ISD::FP_TO_UINT, MVT::i16, Promote);
1153239462Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::i16, Promote);
1154239462Sdim      setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
1155239462Sdim      setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
1156234285Sdim
1157239462Sdim      setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
1158239462Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
1159239462Sdim      setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
1160239462Sdim      setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
1161234285Sdim
1162239462Sdim      setOperationAction(ISD::FP_TO_UINT, MVT::i64, Legal);
1163239462Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::i64, Legal);
1164239462Sdim      setOperationAction(ISD::UINT_TO_FP, MVT::i64, Legal);
1165239462Sdim      setOperationAction(ISD::SINT_TO_FP, MVT::i64, Legal);
1166234285Sdim
1167239462Sdim      setOperationAction(ISD::FABS,  MVT::f32, Legal);
1168239462Sdim      setOperationAction(ISD::FABS,  MVT::f64, Expand);
1169234285Sdim
1170239462Sdim      setOperationAction(ISD::FNEG,  MVT::f32, Legal);
1171239462Sdim      setOperationAction(ISD::FNEG,  MVT::f64, Expand);
1172239462Sdim    } else {
1173234285Sdim
1174239462Sdim      // Expand fp<->uint.
1175239462Sdim      setOperationAction(ISD::FP_TO_SINT,  MVT::i32, Expand);
1176239462Sdim      setOperationAction(ISD::FP_TO_UINT,  MVT::i32, Expand);
1177234285Sdim
1178239462Sdim      setOperationAction(ISD::SINT_TO_FP,  MVT::i32, Expand);
1179239462Sdim      setOperationAction(ISD::UINT_TO_FP,  MVT::i32, Expand);
1180234285Sdim
1181239462Sdim      setLibcallName(RTLIB::SINTTOFP_I64_F32, "__hexagon_floatdisf");
1182239462Sdim      setLibcallName(RTLIB::UINTTOFP_I64_F32, "__hexagon_floatundisf");
1183234285Sdim
1184239462Sdim      setLibcallName(RTLIB::UINTTOFP_I32_F32, "__hexagon_floatunsisf");
1185239462Sdim      setLibcallName(RTLIB::SINTTOFP_I32_F32, "__hexagon_floatsisf");
1186234285Sdim
1187239462Sdim      setLibcallName(RTLIB::SINTTOFP_I64_F64, "__hexagon_floatdidf");
1188239462Sdim      setLibcallName(RTLIB::UINTTOFP_I64_F64, "__hexagon_floatundidf");
1189234285Sdim
1190239462Sdim      setLibcallName(RTLIB::UINTTOFP_I32_F64, "__hexagon_floatunsidf");
1191239462Sdim      setLibcallName(RTLIB::SINTTOFP_I32_F64, "__hexagon_floatsidf");
1192234285Sdim
1193239462Sdim      setLibcallName(RTLIB::FPTOUINT_F32_I32, "__hexagon_fixunssfsi");
1194239462Sdim      setLibcallName(RTLIB::FPTOUINT_F32_I64, "__hexagon_fixunssfdi");
1195234285Sdim
1196239462Sdim      setLibcallName(RTLIB::FPTOSINT_F64_I64, "__hexagon_fixdfdi");
1197239462Sdim      setLibcallName(RTLIB::FPTOSINT_F32_I64, "__hexagon_fixsfdi");
1198234285Sdim
1199239462Sdim      setLibcallName(RTLIB::FPTOUINT_F64_I32, "__hexagon_fixunsdfsi");
1200239462Sdim      setLibcallName(RTLIB::FPTOUINT_F64_I64, "__hexagon_fixunsdfdi");
1201234285Sdim
1202239462Sdim      setLibcallName(RTLIB::ADD_F64, "__hexagon_adddf3");
1203239462Sdim      setOperationAction(ISD::FADD,  MVT::f64, Expand);
1204234285Sdim
1205239462Sdim      setLibcallName(RTLIB::ADD_F32, "__hexagon_addsf3");
1206239462Sdim      setOperationAction(ISD::FADD,  MVT::f32, Expand);
1207234285Sdim
1208239462Sdim      setLibcallName(RTLIB::FPEXT_F32_F64, "__hexagon_extendsfdf2");
1209239462Sdim      setOperationAction(ISD::FP_EXTEND,  MVT::f32, Expand);
1210234285Sdim
1211239462Sdim      setLibcallName(RTLIB::OEQ_F32, "__hexagon_eqsf2");
1212239462Sdim      setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand);
1213234285Sdim
1214239462Sdim      setLibcallName(RTLIB::OEQ_F64, "__hexagon_eqdf2");
1215239462Sdim      setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand);
1216234285Sdim
1217239462Sdim      setLibcallName(RTLIB::OGE_F32, "__hexagon_gesf2");
1218239462Sdim      setCondCodeAction(ISD::SETOGE, MVT::f32, Expand);
1219234285Sdim
1220239462Sdim      setLibcallName(RTLIB::OGE_F64, "__hexagon_gedf2");
1221239462Sdim      setCondCodeAction(ISD::SETOGE, MVT::f64, Expand);
1222234285Sdim
1223239462Sdim      setLibcallName(RTLIB::OGT_F32, "__hexagon_gtsf2");
1224239462Sdim      setCondCodeAction(ISD::SETOGT, MVT::f32, Expand);
1225234285Sdim
1226239462Sdim      setLibcallName(RTLIB::OGT_F64, "__hexagon_gtdf2");
1227239462Sdim      setCondCodeAction(ISD::SETOGT, MVT::f64, Expand);
1228239462Sdim
1229239462Sdim      setLibcallName(RTLIB::FPTOSINT_F64_I32, "__hexagon_fixdfsi");
1230239462Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::f64, Expand);
1231239462Sdim
1232239462Sdim      setLibcallName(RTLIB::FPTOSINT_F32_I32, "__hexagon_fixsfsi");
1233239462Sdim      setOperationAction(ISD::FP_TO_SINT, MVT::f32, Expand);
1234239462Sdim
1235239462Sdim      setLibcallName(RTLIB::OLE_F64, "__hexagon_ledf2");
1236239462Sdim      setCondCodeAction(ISD::SETOLE, MVT::f64, Expand);
1237239462Sdim
1238239462Sdim      setLibcallName(RTLIB::OLE_F32, "__hexagon_lesf2");
1239239462Sdim      setCondCodeAction(ISD::SETOLE, MVT::f32, Expand);
1240239462Sdim
1241239462Sdim      setLibcallName(RTLIB::OLT_F64, "__hexagon_ltdf2");
1242239462Sdim      setCondCodeAction(ISD::SETOLT, MVT::f64, Expand);
1243239462Sdim
1244239462Sdim      setLibcallName(RTLIB::OLT_F32, "__hexagon_ltsf2");
1245239462Sdim      setCondCodeAction(ISD::SETOLT, MVT::f32, Expand);
1246239462Sdim
1247239462Sdim      setLibcallName(RTLIB::MUL_F64, "__hexagon_muldf3");
1248239462Sdim      setOperationAction(ISD::FMUL, MVT::f64, Expand);
1249239462Sdim
1250239462Sdim      setLibcallName(RTLIB::MUL_F32, "__hexagon_mulsf3");
1251239462Sdim      setOperationAction(ISD::MUL, MVT::f32, Expand);
1252239462Sdim
1253239462Sdim      setLibcallName(RTLIB::UNE_F64, "__hexagon_nedf2");
1254239462Sdim      setCondCodeAction(ISD::SETUNE, MVT::f64, Expand);
1255239462Sdim
1256239462Sdim      setLibcallName(RTLIB::UNE_F32, "__hexagon_nesf2");
1257239462Sdim
1258239462Sdim      setLibcallName(RTLIB::SUB_F64, "__hexagon_subdf3");
1259239462Sdim      setOperationAction(ISD::SUB, MVT::f64, Expand);
1260239462Sdim
1261239462Sdim      setLibcallName(RTLIB::SUB_F32, "__hexagon_subsf3");
1262239462Sdim      setOperationAction(ISD::SUB, MVT::f32, Expand);
1263239462Sdim
1264239462Sdim      setLibcallName(RTLIB::FPROUND_F64_F32, "__hexagon_truncdfsf2");
1265239462Sdim      setOperationAction(ISD::FP_ROUND, MVT::f64, Expand);
1266239462Sdim
1267239462Sdim      setLibcallName(RTLIB::UO_F64, "__hexagon_unorddf2");
1268239462Sdim      setCondCodeAction(ISD::SETUO, MVT::f64, Expand);
1269239462Sdim
1270239462Sdim      setLibcallName(RTLIB::O_F64, "__hexagon_unorddf2");
1271239462Sdim      setCondCodeAction(ISD::SETO, MVT::f64, Expand);
1272239462Sdim
1273239462Sdim      setLibcallName(RTLIB::O_F32, "__hexagon_unordsf2");
1274239462Sdim      setCondCodeAction(ISD::SETO, MVT::f32, Expand);
1275239462Sdim
1276239462Sdim      setLibcallName(RTLIB::UO_F32, "__hexagon_unordsf2");
1277239462Sdim      setCondCodeAction(ISD::SETUO, MVT::f32, Expand);
1278239462Sdim
1279239462Sdim      setOperationAction(ISD::FABS,  MVT::f32, Expand);
1280239462Sdim      setOperationAction(ISD::FABS,  MVT::f64, Expand);
1281239462Sdim      setOperationAction(ISD::FNEG,  MVT::f32, Expand);
1282239462Sdim      setOperationAction(ISD::FNEG,  MVT::f64, Expand);
1283239462Sdim    }
1284239462Sdim
1285239462Sdim    setLibcallName(RTLIB::SREM_I32, "__hexagon_modsi3");
1286239462Sdim    setOperationAction(ISD::SREM, MVT::i32, Expand);
1287239462Sdim
1288234285Sdim    setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal);
1289234285Sdim    setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal);
1290234285Sdim    setIndexedLoadAction(ISD::POST_INC, MVT::i32, Legal);
1291234285Sdim    setIndexedLoadAction(ISD::POST_INC, MVT::i64, Legal);
1292234285Sdim
1293234285Sdim    setIndexedStoreAction(ISD::POST_INC, MVT::i8, Legal);
1294234285Sdim    setIndexedStoreAction(ISD::POST_INC, MVT::i16, Legal);
1295234285Sdim    setIndexedStoreAction(ISD::POST_INC, MVT::i32, Legal);
1296234285Sdim    setIndexedStoreAction(ISD::POST_INC, MVT::i64, Legal);
1297234285Sdim
1298234285Sdim    setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
1299234285Sdim
1300234285Sdim    // Turn FP extload into load/fextend.
1301234285Sdim    setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
1302234285Sdim    // Hexagon has a i1 sign extending load.
1303234285Sdim    setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Expand);
1304234285Sdim    // Turn FP truncstore into trunc + store.
1305234285Sdim    setTruncStoreAction(MVT::f64, MVT::f32, Expand);
1306234285Sdim
1307234285Sdim    // Custom legalize GlobalAddress nodes into CONST32.
1308234285Sdim    setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
1309234285Sdim    setOperationAction(ISD::GlobalAddress, MVT::i8, Custom);
1310249423Sdim    setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
1311234285Sdim    // Truncate action?
1312234285Sdim    setOperationAction(ISD::TRUNCATE, MVT::i64, Expand);
1313234285Sdim
1314234285Sdim    // Hexagon doesn't have sext_inreg, replace them with shl/sra.
1315234285Sdim    setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand);
1316234285Sdim
1317234285Sdim    // Hexagon has no REM or DIVREM operations.
1318234285Sdim    setOperationAction(ISD::UREM, MVT::i32, Expand);
1319234285Sdim    setOperationAction(ISD::SREM, MVT::i32, Expand);
1320234285Sdim    setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
1321234285Sdim    setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
1322234285Sdim    setOperationAction(ISD::SREM, MVT::i64, Expand);
1323234285Sdim    setOperationAction(ISD::SDIVREM, MVT::i64, Expand);
1324234285Sdim    setOperationAction(ISD::UDIVREM, MVT::i64, Expand);
1325234285Sdim
1326234285Sdim    setOperationAction(ISD::BSWAP, MVT::i64, Expand);
1327234285Sdim
1328234285Sdim    // Lower SELECT_CC to SETCC and SELECT.
1329234285Sdim    setOperationAction(ISD::SELECT_CC, MVT::i32,   Custom);
1330234285Sdim    setOperationAction(ISD::SELECT_CC, MVT::i64,   Custom);
1331234285Sdim
1332239462Sdim    if (QRI->Subtarget.hasV5TOps()) {
1333239462Sdim
1334239462Sdim      // We need to make the operation type of SELECT node to be Custom,
1335239462Sdim      // such that we don't go into the infinite loop of
1336239462Sdim      // select ->  setcc -> select_cc -> select loop.
1337239462Sdim      setOperationAction(ISD::SELECT, MVT::f32, Custom);
1338239462Sdim      setOperationAction(ISD::SELECT, MVT::f64, Custom);
1339239462Sdim
1340239462Sdim      setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
1341239462Sdim      setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
1342239462Sdim      setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
1343239462Sdim
1344239462Sdim    } else {
1345239462Sdim
1346239462Sdim      // Hexagon has no select or setcc: expand to SELECT_CC.
1347239462Sdim      setOperationAction(ISD::SELECT, MVT::f32, Expand);
1348239462Sdim      setOperationAction(ISD::SELECT, MVT::f64, Expand);
1349239462Sdim
1350239462Sdim      // This is a workaround documented in DAGCombiner.cpp:2892 We don't
1351239462Sdim      // support SELECT_CC on every type.
1352239462Sdim      setOperationAction(ISD::SELECT_CC, MVT::Other,   Expand);
1353239462Sdim
1354239462Sdim    }
1355239462Sdim
1356234285Sdim    if (EmitJumpTables) {
1357234285Sdim      setOperationAction(ISD::BR_JT, MVT::Other, Custom);
1358234285Sdim    } else {
1359234285Sdim      setOperationAction(ISD::BR_JT, MVT::Other, Expand);
1360234285Sdim    }
1361243830Sdim    // Increase jump tables cutover to 5, was 4.
1362243830Sdim    setMinimumJumpTableEntries(5);
1363234285Sdim
1364249423Sdim    setOperationAction(ISD::BR_CC, MVT::Other, Expand);
1365249423Sdim    setOperationAction(ISD::BR_CC, MVT::f32, Expand);
1366249423Sdim    setOperationAction(ISD::BR_CC, MVT::f64, Expand);
1367249423Sdim    setOperationAction(ISD::BR_CC, MVT::i1,  Expand);
1368234285Sdim    setOperationAction(ISD::BR_CC, MVT::i32, Expand);
1369249423Sdim    setOperationAction(ISD::BR_CC, MVT::i64, Expand);
1370234285Sdim
1371234285Sdim    setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
1372234285Sdim
1373234285Sdim    setOperationAction(ISD::FSIN , MVT::f64, Expand);
1374234285Sdim    setOperationAction(ISD::FCOS , MVT::f64, Expand);
1375234285Sdim    setOperationAction(ISD::FREM , MVT::f64, Expand);
1376234285Sdim    setOperationAction(ISD::FSIN , MVT::f32, Expand);
1377234285Sdim    setOperationAction(ISD::FCOS , MVT::f32, Expand);
1378234285Sdim    setOperationAction(ISD::FREM , MVT::f32, Expand);
1379249423Sdim    setOperationAction(ISD::FSINCOS, MVT::f64, Expand);
1380249423Sdim    setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
1381249423Sdim
1382249423Sdim    // In V4, we have double word add/sub with carry. The problem with
1383249423Sdim    // modelling this instruction is that it produces 2 results - Rdd and Px.
1384249423Sdim    // To model update of Px, we will have to use Defs[p0..p3] which will
1385249423Sdim    // cause any predicate live range to spill. So, we pretend we dont't
1386249423Sdim    // have these instructions.
1387249423Sdim    setOperationAction(ISD::ADDE, MVT::i8, Expand);
1388249423Sdim    setOperationAction(ISD::ADDE, MVT::i16, Expand);
1389249423Sdim    setOperationAction(ISD::ADDE, MVT::i32, Expand);
1390249423Sdim    setOperationAction(ISD::ADDE, MVT::i64, Expand);
1391249423Sdim    setOperationAction(ISD::SUBE, MVT::i8, Expand);
1392249423Sdim    setOperationAction(ISD::SUBE, MVT::i16, Expand);
1393249423Sdim    setOperationAction(ISD::SUBE, MVT::i32, Expand);
1394249423Sdim    setOperationAction(ISD::SUBE, MVT::i64, Expand);
1395249423Sdim    setOperationAction(ISD::ADDC, MVT::i8, Expand);
1396249423Sdim    setOperationAction(ISD::ADDC, MVT::i16, Expand);
1397249423Sdim    setOperationAction(ISD::ADDC, MVT::i32, Expand);
1398249423Sdim    setOperationAction(ISD::ADDC, MVT::i64, Expand);
1399249423Sdim    setOperationAction(ISD::SUBC, MVT::i8, Expand);
1400249423Sdim    setOperationAction(ISD::SUBC, MVT::i16, Expand);
1401249423Sdim    setOperationAction(ISD::SUBC, MVT::i32, Expand);
1402249423Sdim    setOperationAction(ISD::SUBC, MVT::i64, Expand);
1403249423Sdim
1404234285Sdim    setOperationAction(ISD::CTPOP, MVT::i32, Expand);
1405249423Sdim    setOperationAction(ISD::CTPOP, MVT::i64, Expand);
1406234285Sdim    setOperationAction(ISD::CTTZ , MVT::i32, Expand);
1407249423Sdim    setOperationAction(ISD::CTTZ , MVT::i64, Expand);
1408234285Sdim    setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand);
1409249423Sdim    setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand);
1410234285Sdim    setOperationAction(ISD::CTLZ , MVT::i32, Expand);
1411249423Sdim    setOperationAction(ISD::CTLZ , MVT::i64, Expand);
1412234285Sdim    setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand);
1413249423Sdim    setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand);
1414234285Sdim    setOperationAction(ISD::ROTL , MVT::i32, Expand);
1415234285Sdim    setOperationAction(ISD::ROTR , MVT::i32, Expand);
1416234285Sdim    setOperationAction(ISD::BSWAP, MVT::i32, Expand);
1417234285Sdim    setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
1418234285Sdim    setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
1419234285Sdim    setOperationAction(ISD::FPOW , MVT::f64, Expand);
1420234285Sdim    setOperationAction(ISD::FPOW , MVT::f32, Expand);
1421234285Sdim
1422234285Sdim    setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
1423234285Sdim    setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
1424234285Sdim    setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
1425234285Sdim
1426234285Sdim    setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
1427234285Sdim    setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
1428234285Sdim
1429234285Sdim    setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
1430234285Sdim    setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
1431234285Sdim
1432234285Sdim    setOperationAction(ISD::EXCEPTIONADDR, MVT::i64, Expand);
1433234285Sdim    setOperationAction(ISD::EHSELECTION,   MVT::i64, Expand);
1434234285Sdim    setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand);
1435234285Sdim    setOperationAction(ISD::EHSELECTION,   MVT::i32, Expand);
1436234285Sdim
1437251662Sdim    setOperationAction(ISD::EH_RETURN,     MVT::Other, Custom);
1438234285Sdim
1439234285Sdim    if (TM.getSubtargetImpl()->isSubtargetV2()) {
1440234285Sdim      setExceptionPointerRegister(Hexagon::R20);
1441234285Sdim      setExceptionSelectorRegister(Hexagon::R21);
1442234285Sdim    } else {
1443234285Sdim      setExceptionPointerRegister(Hexagon::R0);
1444234285Sdim      setExceptionSelectorRegister(Hexagon::R1);
1445234285Sdim    }
1446234285Sdim
1447234285Sdim    // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
1448234285Sdim    setOperationAction(ISD::VASTART           , MVT::Other, Custom);
1449234285Sdim
1450234285Sdim    // Use the default implementation.
1451234285Sdim    setOperationAction(ISD::VAARG             , MVT::Other, Expand);
1452234285Sdim    setOperationAction(ISD::VACOPY            , MVT::Other, Expand);
1453234285Sdim    setOperationAction(ISD::VAEND             , MVT::Other, Expand);
1454234285Sdim    setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand);
1455234285Sdim    setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand);
1456234285Sdim
1457234285Sdim
1458234285Sdim    setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Custom);
1459234285Sdim    setOperationAction(ISD::INLINEASM         , MVT::Other, Custom);
1460234285Sdim
1461234285Sdim    setMinFunctionAlignment(2);
1462234285Sdim
1463234285Sdim    // Needed for DYNAMIC_STACKALLOC expansion.
1464234285Sdim    unsigned StackRegister = TM.getRegisterInfo()->getStackRegister();
1465234285Sdim    setStackPointerRegisterToSaveRestore(StackRegister);
1466234285Sdim    setSchedulingPreference(Sched::VLIW);
1467234285Sdim}
1468234285Sdim
1469234285Sdim
1470234285Sdimconst char*
1471234285SdimHexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {
1472234285Sdim  switch (Opcode) {
1473234285Sdim    default: return 0;
1474239462Sdim    case HexagonISD::CONST32:     return "HexagonISD::CONST32";
1475249423Sdim    case HexagonISD::CONST32_GP: return "HexagonISD::CONST32_GP";
1476249423Sdim    case HexagonISD::CONST32_Int_Real: return "HexagonISD::CONST32_Int_Real";
1477234285Sdim    case HexagonISD::ADJDYNALLOC: return "HexagonISD::ADJDYNALLOC";
1478239462Sdim    case HexagonISD::CMPICC:      return "HexagonISD::CMPICC";
1479239462Sdim    case HexagonISD::CMPFCC:      return "HexagonISD::CMPFCC";
1480239462Sdim    case HexagonISD::BRICC:       return "HexagonISD::BRICC";
1481239462Sdim    case HexagonISD::BRFCC:       return "HexagonISD::BRFCC";
1482239462Sdim    case HexagonISD::SELECT_ICC:  return "HexagonISD::SELECT_ICC";
1483239462Sdim    case HexagonISD::SELECT_FCC:  return "HexagonISD::SELECT_FCC";
1484239462Sdim    case HexagonISD::Hi:          return "HexagonISD::Hi";
1485239462Sdim    case HexagonISD::Lo:          return "HexagonISD::Lo";
1486239462Sdim    case HexagonISD::FTOI:        return "HexagonISD::FTOI";
1487239462Sdim    case HexagonISD::ITOF:        return "HexagonISD::ITOF";
1488239462Sdim    case HexagonISD::CALL:        return "HexagonISD::CALL";
1489239462Sdim    case HexagonISD::RET_FLAG:    return "HexagonISD::RET_FLAG";
1490239462Sdim    case HexagonISD::BR_JT:       return "HexagonISD::BR_JT";
1491239462Sdim    case HexagonISD::TC_RETURN:   return "HexagonISD::TC_RETURN";
1492251662Sdim  case HexagonISD::EH_RETURN: return "HexagonISD::EH_RETURN";
1493234285Sdim  }
1494234285Sdim}
1495234285Sdim
1496234285Sdimbool
1497234285SdimHexagonTargetLowering::isTruncateFree(Type *Ty1, Type *Ty2) const {
1498234285Sdim  EVT MTy1 = EVT::getEVT(Ty1);
1499234285Sdim  EVT MTy2 = EVT::getEVT(Ty2);
1500234285Sdim  if (!MTy1.isSimple() || !MTy2.isSimple()) {
1501234285Sdim    return false;
1502234285Sdim  }
1503234285Sdim  return ((MTy1.getSimpleVT() == MVT::i64) && (MTy2.getSimpleVT() == MVT::i32));
1504234285Sdim}
1505234285Sdim
1506234285Sdimbool HexagonTargetLowering::isTruncateFree(EVT VT1, EVT VT2) const {
1507234285Sdim  if (!VT1.isSimple() || !VT2.isSimple()) {
1508234285Sdim    return false;
1509234285Sdim  }
1510234285Sdim  return ((VT1.getSimpleVT() == MVT::i64) && (VT2.getSimpleVT() == MVT::i32));
1511234285Sdim}
1512234285Sdim
1513234285SdimSDValue
1514251662SdimHexagonTargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
1515251662Sdim  SDValue Chain     = Op.getOperand(0);
1516251662Sdim  SDValue Offset    = Op.getOperand(1);
1517251662Sdim  SDValue Handler   = Op.getOperand(2);
1518251662Sdim  DebugLoc dl       = Op.getDebugLoc();
1519251662Sdim
1520251662Sdim  // Mark function as containing a call to EH_RETURN.
1521251662Sdim  HexagonMachineFunctionInfo *FuncInfo =
1522251662Sdim    DAG.getMachineFunction().getInfo<HexagonMachineFunctionInfo>();
1523251662Sdim  FuncInfo->setHasEHReturn();
1524251662Sdim
1525251662Sdim  unsigned OffsetReg = Hexagon::R28;
1526251662Sdim
1527251662Sdim  SDValue StoreAddr = DAG.getNode(ISD::ADD, dl, getPointerTy(),
1528251662Sdim                                  DAG.getRegister(Hexagon::R30, getPointerTy()),
1529251662Sdim                                  DAG.getIntPtrConstant(4));
1530251662Sdim  Chain = DAG.getStore(Chain, dl, Handler, StoreAddr, MachinePointerInfo(),
1531251662Sdim                       false, false, 0);
1532251662Sdim  Chain = DAG.getCopyToReg(Chain, dl, OffsetReg, Offset);
1533251662Sdim
1534251662Sdim  // Not needed we already use it as explict input to EH_RETURN.
1535251662Sdim  // MF.getRegInfo().addLiveOut(OffsetReg);
1536251662Sdim
1537251662Sdim  return DAG.getNode(HexagonISD::EH_RETURN, dl, MVT::Other, Chain);
1538251662Sdim}
1539251662Sdim
1540251662SdimSDValue
1541234285SdimHexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
1542234285Sdim  switch (Op.getOpcode()) {
1543234285Sdim    default: llvm_unreachable("Should not custom lower this!");
1544239462Sdim    case ISD::ConstantPool:       return LowerConstantPool(Op, DAG);
1545251662Sdim    case ISD::EH_RETURN:          return LowerEH_RETURN(Op, DAG);
1546234285Sdim      // Frame & Return address.  Currently unimplemented.
1547239462Sdim    case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG);
1548239462Sdim    case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG);
1549234285Sdim    case ISD::GlobalTLSAddress:
1550234285Sdim                          llvm_unreachable("TLS not implemented for Hexagon.");
1551234285Sdim    case ISD::ATOMIC_FENCE:       return LowerATOMIC_FENCE(Op, DAG);
1552234285Sdim    case ISD::GlobalAddress:      return LowerGLOBALADDRESS(Op, DAG);
1553249423Sdim    case ISD::BlockAddress:       return LowerBlockAddress(Op, DAG);
1554234285Sdim    case ISD::VASTART:            return LowerVASTART(Op, DAG);
1555234285Sdim    case ISD::BR_JT:              return LowerBR_JT(Op, DAG);
1556234285Sdim
1557234285Sdim    case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
1558239462Sdim    case ISD::SELECT_CC:          return LowerSELECT_CC(Op, DAG);
1559239462Sdim    case ISD::SELECT:             return Op;
1560234285Sdim    case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
1561239462Sdim    case ISD::INLINEASM:          return LowerINLINEASM(Op, DAG);
1562234285Sdim
1563234285Sdim  }
1564234285Sdim}
1565234285Sdim
1566234285Sdim
1567234285Sdim
1568234285Sdim//===----------------------------------------------------------------------===//
1569234285Sdim//                           Hexagon Scheduler Hooks
1570234285Sdim//===----------------------------------------------------------------------===//
1571234285SdimMachineBasicBlock *
1572234285SdimHexagonTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
1573234285Sdim                                                   MachineBasicBlock *BB)
1574234285Sdimconst {
1575234285Sdim  switch (MI->getOpcode()) {
1576234285Sdim    case Hexagon::ADJDYNALLOC: {
1577234285Sdim      MachineFunction *MF = BB->getParent();
1578234285Sdim      HexagonMachineFunctionInfo *FuncInfo =
1579234285Sdim        MF->getInfo<HexagonMachineFunctionInfo>();
1580234285Sdim      FuncInfo->addAllocaAdjustInst(MI);
1581234285Sdim      return BB;
1582234285Sdim    }
1583234285Sdim    default: llvm_unreachable("Unexpected instr type to insert");
1584234285Sdim  } // switch
1585234285Sdim}
1586234285Sdim
1587234285Sdim//===----------------------------------------------------------------------===//
1588234285Sdim// Inline Assembly Support
1589234285Sdim//===----------------------------------------------------------------------===//
1590234285Sdim
1591234285Sdimstd::pair<unsigned, const TargetRegisterClass*>
1592234285SdimHexagonTargetLowering::getRegForInlineAsmConstraint(const
1593234285Sdim                                                    std::string &Constraint,
1594234285Sdim                                                    EVT VT) const {
1595234285Sdim  if (Constraint.size() == 1) {
1596234285Sdim    switch (Constraint[0]) {
1597234285Sdim    case 'r':   // R0-R31
1598234285Sdim       switch (VT.getSimpleVT().SimpleTy) {
1599234285Sdim       default:
1600234285Sdim         llvm_unreachable("getRegForInlineAsmConstraint Unhandled data type");
1601234285Sdim       case MVT::i32:
1602234285Sdim       case MVT::i16:
1603234285Sdim       case MVT::i8:
1604239462Sdim       case MVT::f32:
1605239462Sdim         return std::make_pair(0U, &Hexagon::IntRegsRegClass);
1606234285Sdim       case MVT::i64:
1607239462Sdim       case MVT::f64:
1608239462Sdim         return std::make_pair(0U, &Hexagon::DoubleRegsRegClass);
1609234285Sdim      }
1610234285Sdim    default:
1611234285Sdim      llvm_unreachable("Unknown asm register class");
1612234285Sdim    }
1613234285Sdim  }
1614234285Sdim
1615234285Sdim  return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
1616234285Sdim}
1617234285Sdim
1618239462Sdim/// isFPImmLegal - Returns true if the target can instruction select the
1619239462Sdim/// specified FP immediate natively. If false, the legalizer will
1620239462Sdim/// materialize the FP immediate as a load from a constant pool.
1621239462Sdimbool HexagonTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
1622239462Sdim  const HexagonRegisterInfo* QRI = TM.getRegisterInfo();
1623239462Sdim  return QRI->Subtarget.hasV5TOps();
1624239462Sdim}
1625239462Sdim
1626234285Sdim/// isLegalAddressingMode - Return true if the addressing mode represented by
1627234285Sdim/// AM is legal for this target, for a load/store of the specified type.
1628234285Sdimbool HexagonTargetLowering::isLegalAddressingMode(const AddrMode &AM,
1629234285Sdim                                                  Type *Ty) const {
1630234285Sdim  // Allows a signed-extended 11-bit immediate field.
1631234285Sdim  if (AM.BaseOffs <= -(1LL << 13) || AM.BaseOffs >= (1LL << 13)-1) {
1632234285Sdim    return false;
1633234285Sdim  }
1634234285Sdim
1635234285Sdim  // No global is ever allowed as a base.
1636234285Sdim  if (AM.BaseGV) {
1637234285Sdim    return false;
1638234285Sdim  }
1639234285Sdim
1640234285Sdim  int Scale = AM.Scale;
1641234285Sdim  if (Scale < 0) Scale = -Scale;
1642234285Sdim  switch (Scale) {
1643234285Sdim  case 0:  // No scale reg, "r+i", "r", or just "i".
1644234285Sdim    break;
1645234285Sdim  default: // No scaled addressing mode.
1646234285Sdim    return false;
1647234285Sdim  }
1648234285Sdim  return true;
1649234285Sdim}
1650234285Sdim
1651234285Sdim/// isLegalICmpImmediate - Return true if the specified immediate is legal
1652234285Sdim/// icmp immediate, that is the target has icmp instructions which can compare
1653234285Sdim/// a register against the immediate without having to materialize the
1654234285Sdim/// immediate into a register.
1655234285Sdimbool HexagonTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
1656234285Sdim  return Imm >= -512 && Imm <= 511;
1657234285Sdim}
1658234285Sdim
1659234285Sdim/// IsEligibleForTailCallOptimization - Check whether the call is eligible
1660234285Sdim/// for tail call optimization. Targets which want to do tail call
1661234285Sdim/// optimization should implement this function.
1662234285Sdimbool HexagonTargetLowering::IsEligibleForTailCallOptimization(
1663234285Sdim                                 SDValue Callee,
1664234285Sdim                                 CallingConv::ID CalleeCC,
1665234285Sdim                                 bool isVarArg,
1666234285Sdim                                 bool isCalleeStructRet,
1667234285Sdim                                 bool isCallerStructRet,
1668234285Sdim                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
1669234285Sdim                                 const SmallVectorImpl<SDValue> &OutVals,
1670234285Sdim                                 const SmallVectorImpl<ISD::InputArg> &Ins,
1671234285Sdim                                 SelectionDAG& DAG) const {
1672234285Sdim  const Function *CallerF = DAG.getMachineFunction().getFunction();
1673234285Sdim  CallingConv::ID CallerCC = CallerF->getCallingConv();
1674234285Sdim  bool CCMatch = CallerCC == CalleeCC;
1675234285Sdim
1676234285Sdim  // ***************************************************************************
1677234285Sdim  //  Look for obvious safe cases to perform tail call optimization that do not
1678234285Sdim  //  require ABI changes.
1679234285Sdim  // ***************************************************************************
1680234285Sdim
1681234285Sdim  // If this is a tail call via a function pointer, then don't do it!
1682234285Sdim  if (!(dyn_cast<GlobalAddressSDNode>(Callee))
1683234285Sdim      && !(dyn_cast<ExternalSymbolSDNode>(Callee))) {
1684234285Sdim    return false;
1685234285Sdim  }
1686234285Sdim
1687234285Sdim  // Do not optimize if the calling conventions do not match.
1688234285Sdim  if (!CCMatch)
1689234285Sdim    return false;
1690234285Sdim
1691234285Sdim  // Do not tail call optimize vararg calls.
1692234285Sdim  if (isVarArg)
1693234285Sdim    return false;
1694234285Sdim
1695234285Sdim  // Also avoid tail call optimization if either caller or callee uses struct
1696234285Sdim  // return semantics.
1697234285Sdim  if (isCalleeStructRet || isCallerStructRet)
1698234285Sdim    return false;
1699234285Sdim
1700234285Sdim  // In addition to the cases above, we also disable Tail Call Optimization if
1701234285Sdim  // the calling convention code that at least one outgoing argument needs to
1702234285Sdim  // go on the stack. We cannot check that here because at this point that
1703234285Sdim  // information is not available.
1704234285Sdim  return true;
1705234285Sdim}
1706