xref: /minix3/external/bsd/llvm/dist/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===-- HexagonISelLowering.cpp - Hexagon DAG Lowering Implementation -----===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file implements the interfaces that Hexagon uses to lower LLVM code
11f4a2713aSLionel Sambuc // into a selection DAG.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc 
15f4a2713aSLionel Sambuc #include "HexagonISelLowering.h"
16f4a2713aSLionel Sambuc #include "HexagonMachineFunctionInfo.h"
17f4a2713aSLionel Sambuc #include "HexagonSubtarget.h"
18f4a2713aSLionel Sambuc #include "HexagonTargetMachine.h"
19f4a2713aSLionel Sambuc #include "HexagonTargetObjectFile.h"
20f4a2713aSLionel Sambuc #include "llvm/CodeGen/CallingConvLower.h"
21f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineFrameInfo.h"
22f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineFunction.h"
23f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineInstrBuilder.h"
24f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineJumpTableInfo.h"
25f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineRegisterInfo.h"
26f4a2713aSLionel Sambuc #include "llvm/CodeGen/SelectionDAGISel.h"
27f4a2713aSLionel Sambuc #include "llvm/CodeGen/ValueTypes.h"
28f4a2713aSLionel Sambuc #include "llvm/IR/CallingConv.h"
29f4a2713aSLionel Sambuc #include "llvm/IR/DerivedTypes.h"
30f4a2713aSLionel Sambuc #include "llvm/IR/Function.h"
31f4a2713aSLionel Sambuc #include "llvm/IR/GlobalAlias.h"
32f4a2713aSLionel Sambuc #include "llvm/IR/GlobalVariable.h"
33f4a2713aSLionel Sambuc #include "llvm/IR/InlineAsm.h"
34f4a2713aSLionel Sambuc #include "llvm/IR/Intrinsics.h"
35f4a2713aSLionel Sambuc #include "llvm/Support/CommandLine.h"
36f4a2713aSLionel Sambuc #include "llvm/Support/Debug.h"
37f4a2713aSLionel Sambuc #include "llvm/Support/ErrorHandling.h"
38f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
39f4a2713aSLionel Sambuc 
40f4a2713aSLionel Sambuc using namespace llvm;
41f4a2713aSLionel Sambuc 
42*0a6a1f1dSLionel Sambuc #define DEBUG_TYPE "hexagon-lowering"
43*0a6a1f1dSLionel Sambuc 
44f4a2713aSLionel Sambuc static cl::opt<bool>
45f4a2713aSLionel Sambuc EmitJumpTables("hexagon-emit-jump-tables", cl::init(true), cl::Hidden,
46f4a2713aSLionel Sambuc                cl::desc("Control jump table emission on Hexagon target"));
47f4a2713aSLionel Sambuc 
48f4a2713aSLionel Sambuc namespace {
49f4a2713aSLionel Sambuc class HexagonCCState : public CCState {
50f4a2713aSLionel Sambuc   int NumNamedVarArgParams;
51f4a2713aSLionel Sambuc 
52f4a2713aSLionel Sambuc public:
HexagonCCState(CallingConv::ID CC,bool isVarArg,MachineFunction & MF,SmallVectorImpl<CCValAssign> & locs,LLVMContext & C,int NumNamedVarArgParams)53f4a2713aSLionel Sambuc   HexagonCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
54*0a6a1f1dSLionel Sambuc                  SmallVectorImpl<CCValAssign> &locs, LLVMContext &C,
55*0a6a1f1dSLionel Sambuc                  int NumNamedVarArgParams)
56*0a6a1f1dSLionel Sambuc       : CCState(CC, isVarArg, MF, locs, C),
57f4a2713aSLionel Sambuc         NumNamedVarArgParams(NumNamedVarArgParams) {}
58f4a2713aSLionel Sambuc 
getNumNamedVarArgParams() const59f4a2713aSLionel Sambuc   int getNumNamedVarArgParams() const { return NumNamedVarArgParams; }
60f4a2713aSLionel Sambuc };
61f4a2713aSLionel Sambuc }
62f4a2713aSLionel Sambuc 
63f4a2713aSLionel Sambuc // Implement calling convention for Hexagon.
64f4a2713aSLionel Sambuc static bool
65f4a2713aSLionel Sambuc CC_Hexagon(unsigned ValNo, MVT ValVT,
66f4a2713aSLionel Sambuc            MVT LocVT, CCValAssign::LocInfo LocInfo,
67f4a2713aSLionel Sambuc            ISD::ArgFlagsTy ArgFlags, CCState &State);
68f4a2713aSLionel Sambuc 
69f4a2713aSLionel Sambuc static bool
70f4a2713aSLionel Sambuc CC_Hexagon32(unsigned ValNo, MVT ValVT,
71f4a2713aSLionel Sambuc              MVT LocVT, CCValAssign::LocInfo LocInfo,
72f4a2713aSLionel Sambuc              ISD::ArgFlagsTy ArgFlags, CCState &State);
73f4a2713aSLionel Sambuc 
74f4a2713aSLionel Sambuc static bool
75f4a2713aSLionel Sambuc CC_Hexagon64(unsigned ValNo, MVT ValVT,
76f4a2713aSLionel Sambuc              MVT LocVT, CCValAssign::LocInfo LocInfo,
77f4a2713aSLionel Sambuc              ISD::ArgFlagsTy ArgFlags, CCState &State);
78f4a2713aSLionel Sambuc 
79f4a2713aSLionel Sambuc static bool
80f4a2713aSLionel Sambuc RetCC_Hexagon(unsigned ValNo, MVT ValVT,
81f4a2713aSLionel Sambuc               MVT LocVT, CCValAssign::LocInfo LocInfo,
82f4a2713aSLionel Sambuc               ISD::ArgFlagsTy ArgFlags, CCState &State);
83f4a2713aSLionel Sambuc 
84f4a2713aSLionel Sambuc static bool
85f4a2713aSLionel Sambuc RetCC_Hexagon32(unsigned ValNo, MVT ValVT,
86f4a2713aSLionel Sambuc                 MVT LocVT, CCValAssign::LocInfo LocInfo,
87f4a2713aSLionel Sambuc                 ISD::ArgFlagsTy ArgFlags, CCState &State);
88f4a2713aSLionel Sambuc 
89f4a2713aSLionel Sambuc static bool
90f4a2713aSLionel Sambuc RetCC_Hexagon64(unsigned ValNo, MVT ValVT,
91f4a2713aSLionel Sambuc                 MVT LocVT, CCValAssign::LocInfo LocInfo,
92f4a2713aSLionel Sambuc                 ISD::ArgFlagsTy ArgFlags, CCState &State);
93f4a2713aSLionel Sambuc 
94f4a2713aSLionel Sambuc static bool
CC_Hexagon_VarArg(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)95f4a2713aSLionel Sambuc CC_Hexagon_VarArg (unsigned ValNo, MVT ValVT,
96f4a2713aSLionel Sambuc             MVT LocVT, CCValAssign::LocInfo LocInfo,
97f4a2713aSLionel Sambuc             ISD::ArgFlagsTy ArgFlags, CCState &State) {
98f4a2713aSLionel Sambuc   HexagonCCState &HState = static_cast<HexagonCCState &>(State);
99f4a2713aSLionel Sambuc 
100f4a2713aSLionel Sambuc   // NumNamedVarArgParams can not be zero for a VarArg function.
101f4a2713aSLionel Sambuc   assert((HState.getNumNamedVarArgParams() > 0) &&
102f4a2713aSLionel Sambuc          "NumNamedVarArgParams is not bigger than zero.");
103f4a2713aSLionel Sambuc 
104f4a2713aSLionel Sambuc   if ((int)ValNo < HState.getNumNamedVarArgParams()) {
105f4a2713aSLionel Sambuc     // Deal with named arguments.
106f4a2713aSLionel Sambuc     return CC_Hexagon(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State);
107f4a2713aSLionel Sambuc   }
108f4a2713aSLionel Sambuc 
109f4a2713aSLionel Sambuc   // Deal with un-named arguments.
110f4a2713aSLionel Sambuc   unsigned ofst;
111f4a2713aSLionel Sambuc   if (ArgFlags.isByVal()) {
112f4a2713aSLionel Sambuc     // If pass-by-value, the size allocated on stack is decided
113f4a2713aSLionel Sambuc     // by ArgFlags.getByValSize(), not by the size of LocVT.
114f4a2713aSLionel Sambuc     assert ((ArgFlags.getByValSize() > 8) &&
115f4a2713aSLionel Sambuc             "ByValSize must be bigger than 8 bytes");
116f4a2713aSLionel Sambuc     ofst = State.AllocateStack(ArgFlags.getByValSize(), 4);
117f4a2713aSLionel Sambuc     State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
118f4a2713aSLionel Sambuc     return false;
119f4a2713aSLionel Sambuc   }
120f4a2713aSLionel Sambuc   if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) {
121f4a2713aSLionel Sambuc     LocVT = MVT::i32;
122f4a2713aSLionel Sambuc     ValVT = MVT::i32;
123f4a2713aSLionel Sambuc     if (ArgFlags.isSExt())
124f4a2713aSLionel Sambuc       LocInfo = CCValAssign::SExt;
125f4a2713aSLionel Sambuc     else if (ArgFlags.isZExt())
126f4a2713aSLionel Sambuc       LocInfo = CCValAssign::ZExt;
127f4a2713aSLionel Sambuc     else
128f4a2713aSLionel Sambuc       LocInfo = CCValAssign::AExt;
129f4a2713aSLionel Sambuc   }
130f4a2713aSLionel Sambuc   if (LocVT == MVT::i32 || LocVT == MVT::f32) {
131f4a2713aSLionel Sambuc     ofst = State.AllocateStack(4, 4);
132f4a2713aSLionel Sambuc     State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
133f4a2713aSLionel Sambuc     return false;
134f4a2713aSLionel Sambuc   }
135f4a2713aSLionel Sambuc   if (LocVT == MVT::i64 || LocVT == MVT::f64) {
136f4a2713aSLionel Sambuc     ofst = State.AllocateStack(8, 8);
137f4a2713aSLionel Sambuc     State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
138f4a2713aSLionel Sambuc     return false;
139f4a2713aSLionel Sambuc   }
140*0a6a1f1dSLionel Sambuc   llvm_unreachable(nullptr);
141f4a2713aSLionel Sambuc }
142f4a2713aSLionel Sambuc 
143f4a2713aSLionel Sambuc 
144f4a2713aSLionel Sambuc static bool
CC_Hexagon(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)145f4a2713aSLionel Sambuc CC_Hexagon (unsigned ValNo, MVT ValVT,
146f4a2713aSLionel Sambuc             MVT LocVT, CCValAssign::LocInfo LocInfo,
147f4a2713aSLionel Sambuc             ISD::ArgFlagsTy ArgFlags, CCState &State) {
148f4a2713aSLionel Sambuc 
149f4a2713aSLionel Sambuc   if (ArgFlags.isByVal()) {
150f4a2713aSLionel Sambuc     // Passed on stack.
151f4a2713aSLionel Sambuc     assert ((ArgFlags.getByValSize() > 8) &&
152f4a2713aSLionel Sambuc             "ByValSize must be bigger than 8 bytes");
153f4a2713aSLionel Sambuc     unsigned Offset = State.AllocateStack(ArgFlags.getByValSize(), 4);
154f4a2713aSLionel Sambuc     State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
155f4a2713aSLionel Sambuc     return false;
156f4a2713aSLionel Sambuc   }
157f4a2713aSLionel Sambuc 
158f4a2713aSLionel Sambuc   if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) {
159f4a2713aSLionel Sambuc     LocVT = MVT::i32;
160f4a2713aSLionel Sambuc     ValVT = MVT::i32;
161f4a2713aSLionel Sambuc     if (ArgFlags.isSExt())
162f4a2713aSLionel Sambuc       LocInfo = CCValAssign::SExt;
163f4a2713aSLionel Sambuc     else if (ArgFlags.isZExt())
164f4a2713aSLionel Sambuc       LocInfo = CCValAssign::ZExt;
165f4a2713aSLionel Sambuc     else
166f4a2713aSLionel Sambuc       LocInfo = CCValAssign::AExt;
167f4a2713aSLionel Sambuc   }
168f4a2713aSLionel Sambuc 
169f4a2713aSLionel Sambuc   if (LocVT == MVT::i32 || LocVT == MVT::f32) {
170f4a2713aSLionel Sambuc     if (!CC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
171f4a2713aSLionel Sambuc       return false;
172f4a2713aSLionel Sambuc   }
173f4a2713aSLionel Sambuc 
174f4a2713aSLionel Sambuc   if (LocVT == MVT::i64 || LocVT == MVT::f64) {
175f4a2713aSLionel Sambuc     if (!CC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
176f4a2713aSLionel Sambuc       return false;
177f4a2713aSLionel Sambuc   }
178f4a2713aSLionel Sambuc 
179f4a2713aSLionel Sambuc   return true;  // CC didn't match.
180f4a2713aSLionel Sambuc }
181f4a2713aSLionel Sambuc 
182f4a2713aSLionel Sambuc 
CC_Hexagon32(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)183f4a2713aSLionel Sambuc static bool CC_Hexagon32(unsigned ValNo, MVT ValVT,
184f4a2713aSLionel Sambuc                          MVT LocVT, CCValAssign::LocInfo LocInfo,
185f4a2713aSLionel Sambuc                          ISD::ArgFlagsTy ArgFlags, CCState &State) {
186f4a2713aSLionel Sambuc 
187*0a6a1f1dSLionel Sambuc   static const MCPhysReg RegList[] = {
188f4a2713aSLionel Sambuc     Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4,
189f4a2713aSLionel Sambuc     Hexagon::R5
190f4a2713aSLionel Sambuc   };
191f4a2713aSLionel Sambuc   if (unsigned Reg = State.AllocateReg(RegList, 6)) {
192f4a2713aSLionel Sambuc     State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
193f4a2713aSLionel Sambuc     return false;
194f4a2713aSLionel Sambuc   }
195f4a2713aSLionel Sambuc 
196f4a2713aSLionel Sambuc   unsigned Offset = State.AllocateStack(4, 4);
197f4a2713aSLionel Sambuc   State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
198f4a2713aSLionel Sambuc   return false;
199f4a2713aSLionel Sambuc }
200f4a2713aSLionel Sambuc 
CC_Hexagon64(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)201f4a2713aSLionel Sambuc static bool CC_Hexagon64(unsigned ValNo, MVT ValVT,
202f4a2713aSLionel Sambuc                          MVT LocVT, CCValAssign::LocInfo LocInfo,
203f4a2713aSLionel Sambuc                          ISD::ArgFlagsTy ArgFlags, CCState &State) {
204f4a2713aSLionel Sambuc 
205f4a2713aSLionel Sambuc   if (unsigned Reg = State.AllocateReg(Hexagon::D0)) {
206f4a2713aSLionel Sambuc     State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
207f4a2713aSLionel Sambuc     return false;
208f4a2713aSLionel Sambuc   }
209f4a2713aSLionel Sambuc 
210*0a6a1f1dSLionel Sambuc   static const MCPhysReg RegList1[] = {
211f4a2713aSLionel Sambuc     Hexagon::D1, Hexagon::D2
212f4a2713aSLionel Sambuc   };
213*0a6a1f1dSLionel Sambuc   static const MCPhysReg RegList2[] = {
214f4a2713aSLionel Sambuc     Hexagon::R1, Hexagon::R3
215f4a2713aSLionel Sambuc   };
216f4a2713aSLionel Sambuc   if (unsigned Reg = State.AllocateReg(RegList1, RegList2, 2)) {
217f4a2713aSLionel Sambuc     State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
218f4a2713aSLionel Sambuc     return false;
219f4a2713aSLionel Sambuc   }
220f4a2713aSLionel Sambuc 
221f4a2713aSLionel Sambuc   unsigned Offset = State.AllocateStack(8, 8, Hexagon::D2);
222f4a2713aSLionel Sambuc   State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
223f4a2713aSLionel Sambuc   return false;
224f4a2713aSLionel Sambuc }
225f4a2713aSLionel Sambuc 
RetCC_Hexagon(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)226f4a2713aSLionel Sambuc static bool RetCC_Hexagon(unsigned ValNo, MVT ValVT,
227f4a2713aSLionel Sambuc                           MVT LocVT, CCValAssign::LocInfo LocInfo,
228f4a2713aSLionel Sambuc                           ISD::ArgFlagsTy ArgFlags, CCState &State) {
229f4a2713aSLionel Sambuc 
230f4a2713aSLionel Sambuc 
231f4a2713aSLionel Sambuc   if (LocVT == MVT::i1 ||
232f4a2713aSLionel Sambuc       LocVT == MVT::i8 ||
233f4a2713aSLionel Sambuc       LocVT == MVT::i16) {
234f4a2713aSLionel Sambuc     LocVT = MVT::i32;
235f4a2713aSLionel Sambuc     ValVT = MVT::i32;
236f4a2713aSLionel Sambuc     if (ArgFlags.isSExt())
237f4a2713aSLionel Sambuc       LocInfo = CCValAssign::SExt;
238f4a2713aSLionel Sambuc     else if (ArgFlags.isZExt())
239f4a2713aSLionel Sambuc       LocInfo = CCValAssign::ZExt;
240f4a2713aSLionel Sambuc     else
241f4a2713aSLionel Sambuc       LocInfo = CCValAssign::AExt;
242f4a2713aSLionel Sambuc   }
243f4a2713aSLionel Sambuc 
244f4a2713aSLionel Sambuc   if (LocVT == MVT::i32 || LocVT == MVT::f32) {
245f4a2713aSLionel Sambuc     if (!RetCC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
246f4a2713aSLionel Sambuc     return false;
247f4a2713aSLionel Sambuc   }
248f4a2713aSLionel Sambuc 
249f4a2713aSLionel Sambuc   if (LocVT == MVT::i64 || LocVT == MVT::f64) {
250f4a2713aSLionel Sambuc     if (!RetCC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
251f4a2713aSLionel Sambuc     return false;
252f4a2713aSLionel Sambuc   }
253f4a2713aSLionel Sambuc 
254f4a2713aSLionel Sambuc   return true;  // CC didn't match.
255f4a2713aSLionel Sambuc }
256f4a2713aSLionel Sambuc 
RetCC_Hexagon32(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)257f4a2713aSLionel Sambuc static bool RetCC_Hexagon32(unsigned ValNo, MVT ValVT,
258f4a2713aSLionel Sambuc                             MVT LocVT, CCValAssign::LocInfo LocInfo,
259f4a2713aSLionel Sambuc                             ISD::ArgFlagsTy ArgFlags, CCState &State) {
260f4a2713aSLionel Sambuc 
261f4a2713aSLionel Sambuc   if (LocVT == MVT::i32 || LocVT == MVT::f32) {
262f4a2713aSLionel Sambuc     if (unsigned Reg = State.AllocateReg(Hexagon::R0)) {
263f4a2713aSLionel Sambuc       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
264f4a2713aSLionel Sambuc       return false;
265f4a2713aSLionel Sambuc     }
266f4a2713aSLionel Sambuc   }
267f4a2713aSLionel Sambuc 
268f4a2713aSLionel Sambuc   unsigned Offset = State.AllocateStack(4, 4);
269f4a2713aSLionel Sambuc   State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
270f4a2713aSLionel Sambuc   return false;
271f4a2713aSLionel Sambuc }
272f4a2713aSLionel Sambuc 
RetCC_Hexagon64(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)273f4a2713aSLionel Sambuc static bool RetCC_Hexagon64(unsigned ValNo, MVT ValVT,
274f4a2713aSLionel Sambuc                             MVT LocVT, CCValAssign::LocInfo LocInfo,
275f4a2713aSLionel Sambuc                             ISD::ArgFlagsTy ArgFlags, CCState &State) {
276f4a2713aSLionel Sambuc   if (LocVT == MVT::i64 || LocVT == MVT::f64) {
277f4a2713aSLionel Sambuc     if (unsigned Reg = State.AllocateReg(Hexagon::D0)) {
278f4a2713aSLionel Sambuc       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
279f4a2713aSLionel Sambuc       return false;
280f4a2713aSLionel Sambuc     }
281f4a2713aSLionel Sambuc   }
282f4a2713aSLionel Sambuc 
283f4a2713aSLionel Sambuc   unsigned Offset = State.AllocateStack(8, 8);
284f4a2713aSLionel Sambuc   State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
285f4a2713aSLionel Sambuc   return false;
286f4a2713aSLionel Sambuc }
287f4a2713aSLionel Sambuc 
288f4a2713aSLionel Sambuc SDValue
LowerINTRINSIC_WO_CHAIN(SDValue Op,SelectionDAG & DAG) const289f4a2713aSLionel Sambuc HexagonTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG)
290f4a2713aSLionel Sambuc const {
291f4a2713aSLionel Sambuc   return SDValue();
292f4a2713aSLionel Sambuc }
293f4a2713aSLionel Sambuc 
294f4a2713aSLionel Sambuc /// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified
295f4a2713aSLionel Sambuc /// by "Src" to address "Dst" of size "Size".  Alignment information is
296f4a2713aSLionel Sambuc /// specified by the specific parameter attribute. The copy will be passed as
297f4a2713aSLionel Sambuc /// a byval function parameter.  Sometimes what we are copying is the end of a
298f4a2713aSLionel Sambuc /// larger object, the part that does not fit in registers.
299f4a2713aSLionel Sambuc static SDValue
CreateCopyOfByValArgument(SDValue Src,SDValue Dst,SDValue Chain,ISD::ArgFlagsTy Flags,SelectionDAG & DAG,SDLoc dl)300f4a2713aSLionel Sambuc CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain,
301f4a2713aSLionel Sambuc                           ISD::ArgFlagsTy Flags, SelectionDAG &DAG,
302f4a2713aSLionel Sambuc                           SDLoc dl) {
303f4a2713aSLionel Sambuc 
304f4a2713aSLionel Sambuc   SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32);
305f4a2713aSLionel Sambuc   return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(),
306f4a2713aSLionel Sambuc                        /*isVolatile=*/false, /*AlwaysInline=*/false,
307f4a2713aSLionel Sambuc                        MachinePointerInfo(), MachinePointerInfo());
308f4a2713aSLionel Sambuc }
309f4a2713aSLionel Sambuc 
310f4a2713aSLionel Sambuc 
311f4a2713aSLionel Sambuc // LowerReturn - Lower ISD::RET. If a struct is larger than 8 bytes and is
312f4a2713aSLionel Sambuc // passed by value, the function prototype is modified to return void and
313f4a2713aSLionel Sambuc // the value is stored in memory pointed by a pointer passed by caller.
314f4a2713aSLionel Sambuc SDValue
LowerReturn(SDValue Chain,CallingConv::ID CallConv,bool isVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,SDLoc dl,SelectionDAG & DAG) const315f4a2713aSLionel Sambuc HexagonTargetLowering::LowerReturn(SDValue Chain,
316f4a2713aSLionel Sambuc                                    CallingConv::ID CallConv, bool isVarArg,
317f4a2713aSLionel Sambuc                                    const SmallVectorImpl<ISD::OutputArg> &Outs,
318f4a2713aSLionel Sambuc                                    const SmallVectorImpl<SDValue> &OutVals,
319f4a2713aSLionel Sambuc                                    SDLoc dl, SelectionDAG &DAG) const {
320f4a2713aSLionel Sambuc 
321f4a2713aSLionel Sambuc   // CCValAssign - represent the assignment of the return value to locations.
322f4a2713aSLionel Sambuc   SmallVector<CCValAssign, 16> RVLocs;
323f4a2713aSLionel Sambuc 
324f4a2713aSLionel Sambuc   // CCState - Info about the registers and stack slot.
325*0a6a1f1dSLionel Sambuc   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
326*0a6a1f1dSLionel Sambuc                  *DAG.getContext());
327f4a2713aSLionel Sambuc 
328f4a2713aSLionel Sambuc   // Analyze return values of ISD::RET
329f4a2713aSLionel Sambuc   CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon);
330f4a2713aSLionel Sambuc 
331f4a2713aSLionel Sambuc   SDValue Flag;
332f4a2713aSLionel Sambuc   SmallVector<SDValue, 4> RetOps(1, Chain);
333f4a2713aSLionel Sambuc 
334f4a2713aSLionel Sambuc   // Copy the result values into the output registers.
335f4a2713aSLionel Sambuc   for (unsigned i = 0; i != RVLocs.size(); ++i) {
336f4a2713aSLionel Sambuc     CCValAssign &VA = RVLocs[i];
337f4a2713aSLionel Sambuc 
338f4a2713aSLionel Sambuc     Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag);
339f4a2713aSLionel Sambuc 
340f4a2713aSLionel Sambuc     // Guarantee that all emitted copies are stuck together with flags.
341f4a2713aSLionel Sambuc     Flag = Chain.getValue(1);
342f4a2713aSLionel Sambuc     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
343f4a2713aSLionel Sambuc   }
344f4a2713aSLionel Sambuc 
345f4a2713aSLionel Sambuc   RetOps[0] = Chain;  // Update chain.
346f4a2713aSLionel Sambuc 
347f4a2713aSLionel Sambuc   // Add the flag if we have it.
348f4a2713aSLionel Sambuc   if (Flag.getNode())
349f4a2713aSLionel Sambuc     RetOps.push_back(Flag);
350f4a2713aSLionel Sambuc 
351*0a6a1f1dSLionel Sambuc   return DAG.getNode(HexagonISD::RET_FLAG, dl, MVT::Other, RetOps);
352f4a2713aSLionel Sambuc }
353f4a2713aSLionel Sambuc 
354f4a2713aSLionel Sambuc 
355f4a2713aSLionel Sambuc 
356f4a2713aSLionel Sambuc 
357f4a2713aSLionel Sambuc /// LowerCallResult - Lower the result values of an ISD::CALL into the
358f4a2713aSLionel Sambuc /// appropriate copies out of appropriate physical registers.  This assumes that
359f4a2713aSLionel Sambuc /// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
360f4a2713aSLionel Sambuc /// being lowered. Returns a SDNode with the same number of values as the
361f4a2713aSLionel Sambuc /// ISD::CALL.
362f4a2713aSLionel Sambuc SDValue
LowerCallResult(SDValue Chain,SDValue InFlag,CallingConv::ID CallConv,bool isVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,SDLoc dl,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals,const SmallVectorImpl<SDValue> & OutVals,SDValue Callee) const363f4a2713aSLionel Sambuc HexagonTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
364f4a2713aSLionel Sambuc                                        CallingConv::ID CallConv, bool isVarArg,
365f4a2713aSLionel Sambuc                                        const
366f4a2713aSLionel Sambuc                                        SmallVectorImpl<ISD::InputArg> &Ins,
367f4a2713aSLionel Sambuc                                        SDLoc dl, SelectionDAG &DAG,
368f4a2713aSLionel Sambuc                                        SmallVectorImpl<SDValue> &InVals,
369f4a2713aSLionel Sambuc                                        const SmallVectorImpl<SDValue> &OutVals,
370f4a2713aSLionel Sambuc                                        SDValue Callee) const {
371f4a2713aSLionel Sambuc 
372f4a2713aSLionel Sambuc   // Assign locations to each value returned by this call.
373f4a2713aSLionel Sambuc   SmallVector<CCValAssign, 16> RVLocs;
374f4a2713aSLionel Sambuc 
375*0a6a1f1dSLionel Sambuc   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
376*0a6a1f1dSLionel Sambuc                  *DAG.getContext());
377f4a2713aSLionel Sambuc 
378f4a2713aSLionel Sambuc   CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon);
379f4a2713aSLionel Sambuc 
380f4a2713aSLionel Sambuc   // Copy all of the result registers out of their specified physreg.
381f4a2713aSLionel Sambuc   for (unsigned i = 0; i != RVLocs.size(); ++i) {
382f4a2713aSLionel Sambuc     Chain = DAG.getCopyFromReg(Chain, dl,
383f4a2713aSLionel Sambuc                                RVLocs[i].getLocReg(),
384f4a2713aSLionel Sambuc                                RVLocs[i].getValVT(), InFlag).getValue(1);
385f4a2713aSLionel Sambuc     InFlag = Chain.getValue(2);
386f4a2713aSLionel Sambuc     InVals.push_back(Chain.getValue(0));
387f4a2713aSLionel Sambuc   }
388f4a2713aSLionel Sambuc 
389f4a2713aSLionel Sambuc   return Chain;
390f4a2713aSLionel Sambuc }
391f4a2713aSLionel Sambuc 
392f4a2713aSLionel Sambuc /// LowerCall - Functions arguments are copied from virtual regs to
393f4a2713aSLionel Sambuc /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
394f4a2713aSLionel Sambuc SDValue
LowerCall(TargetLowering::CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const395f4a2713aSLionel Sambuc HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
396f4a2713aSLionel Sambuc                                  SmallVectorImpl<SDValue> &InVals) const {
397f4a2713aSLionel Sambuc   SelectionDAG &DAG                     = CLI.DAG;
398f4a2713aSLionel Sambuc   SDLoc &dl                             = CLI.DL;
399f4a2713aSLionel Sambuc   SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
400f4a2713aSLionel Sambuc   SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
401f4a2713aSLionel Sambuc   SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
402f4a2713aSLionel Sambuc   SDValue Chain                         = CLI.Chain;
403f4a2713aSLionel Sambuc   SDValue Callee                        = CLI.Callee;
404f4a2713aSLionel Sambuc   bool &isTailCall                      = CLI.IsTailCall;
405f4a2713aSLionel Sambuc   CallingConv::ID CallConv              = CLI.CallConv;
406f4a2713aSLionel Sambuc   bool isVarArg                         = CLI.IsVarArg;
407f4a2713aSLionel Sambuc 
408f4a2713aSLionel Sambuc   bool IsStructRet    = (Outs.empty()) ? false : Outs[0].Flags.isSRet();
409f4a2713aSLionel Sambuc 
410f4a2713aSLionel Sambuc   // Check for varargs.
411f4a2713aSLionel Sambuc   int NumNamedVarArgParams = -1;
412f4a2713aSLionel Sambuc   if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Callee))
413f4a2713aSLionel Sambuc   {
414*0a6a1f1dSLionel Sambuc     const Function* CalleeFn = nullptr;
415f4a2713aSLionel Sambuc     Callee = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, MVT::i32);
416f4a2713aSLionel Sambuc     if ((CalleeFn = dyn_cast<Function>(GA->getGlobal())))
417f4a2713aSLionel Sambuc     {
418f4a2713aSLionel Sambuc       // If a function has zero args and is a vararg function, that's
419f4a2713aSLionel Sambuc       // disallowed so it must be an undeclared function.  Do not assume
420f4a2713aSLionel Sambuc       // varargs if the callee is undefined.
421f4a2713aSLionel Sambuc       if (CalleeFn->isVarArg() &&
422f4a2713aSLionel Sambuc           CalleeFn->getFunctionType()->getNumParams() != 0) {
423f4a2713aSLionel Sambuc         NumNamedVarArgParams = CalleeFn->getFunctionType()->getNumParams();
424f4a2713aSLionel Sambuc       }
425f4a2713aSLionel Sambuc     }
426f4a2713aSLionel Sambuc   }
427f4a2713aSLionel Sambuc 
428f4a2713aSLionel Sambuc   // Analyze operands of the call, assigning locations to each operand.
429f4a2713aSLionel Sambuc   SmallVector<CCValAssign, 16> ArgLocs;
430*0a6a1f1dSLionel Sambuc   HexagonCCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
431*0a6a1f1dSLionel Sambuc                         *DAG.getContext(), NumNamedVarArgParams);
432f4a2713aSLionel Sambuc 
433f4a2713aSLionel Sambuc   if (NumNamedVarArgParams > 0)
434f4a2713aSLionel Sambuc     CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_VarArg);
435f4a2713aSLionel Sambuc   else
436f4a2713aSLionel Sambuc     CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon);
437f4a2713aSLionel Sambuc 
438f4a2713aSLionel Sambuc 
439f4a2713aSLionel Sambuc   if(isTailCall) {
440f4a2713aSLionel Sambuc     bool StructAttrFlag =
441f4a2713aSLionel Sambuc       DAG.getMachineFunction().getFunction()->hasStructRetAttr();
442f4a2713aSLionel Sambuc     isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv,
443f4a2713aSLionel Sambuc                                                    isVarArg, IsStructRet,
444f4a2713aSLionel Sambuc                                                    StructAttrFlag,
445f4a2713aSLionel Sambuc                                                    Outs, OutVals, Ins, DAG);
446f4a2713aSLionel Sambuc     for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i){
447f4a2713aSLionel Sambuc       CCValAssign &VA = ArgLocs[i];
448f4a2713aSLionel Sambuc       if (VA.isMemLoc()) {
449f4a2713aSLionel Sambuc         isTailCall = false;
450f4a2713aSLionel Sambuc         break;
451f4a2713aSLionel Sambuc       }
452f4a2713aSLionel Sambuc     }
453f4a2713aSLionel Sambuc     if (isTailCall) {
454f4a2713aSLionel Sambuc       DEBUG(dbgs () << "Eligible for Tail Call\n");
455f4a2713aSLionel Sambuc     } else {
456f4a2713aSLionel Sambuc       DEBUG(dbgs () <<
457f4a2713aSLionel Sambuc             "Argument must be passed on stack. Not eligible for Tail Call\n");
458f4a2713aSLionel Sambuc     }
459f4a2713aSLionel Sambuc   }
460f4a2713aSLionel Sambuc   // Get a count of how many bytes are to be pushed on the stack.
461f4a2713aSLionel Sambuc   unsigned NumBytes = CCInfo.getNextStackOffset();
462f4a2713aSLionel Sambuc   SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass;
463f4a2713aSLionel Sambuc   SmallVector<SDValue, 8> MemOpChains;
464f4a2713aSLionel Sambuc 
465*0a6a1f1dSLionel Sambuc   const HexagonRegisterInfo *QRI = static_cast<const HexagonRegisterInfo *>(
466*0a6a1f1dSLionel Sambuc       DAG.getSubtarget().getRegisterInfo());
467f4a2713aSLionel Sambuc   SDValue StackPtr =
468*0a6a1f1dSLionel Sambuc       DAG.getCopyFromReg(Chain, dl, QRI->getStackRegister(), getPointerTy());
469f4a2713aSLionel Sambuc 
470f4a2713aSLionel Sambuc   // Walk the register/memloc assignments, inserting copies/loads.
471f4a2713aSLionel Sambuc   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
472f4a2713aSLionel Sambuc     CCValAssign &VA = ArgLocs[i];
473f4a2713aSLionel Sambuc     SDValue Arg = OutVals[i];
474f4a2713aSLionel Sambuc     ISD::ArgFlagsTy Flags = Outs[i].Flags;
475f4a2713aSLionel Sambuc 
476f4a2713aSLionel Sambuc     // Promote the value if needed.
477f4a2713aSLionel Sambuc     switch (VA.getLocInfo()) {
478f4a2713aSLionel Sambuc       default:
479f4a2713aSLionel Sambuc         // Loc info must be one of Full, SExt, ZExt, or AExt.
480f4a2713aSLionel Sambuc         llvm_unreachable("Unknown loc info!");
481f4a2713aSLionel Sambuc       case CCValAssign::Full:
482f4a2713aSLionel Sambuc         break;
483f4a2713aSLionel Sambuc       case CCValAssign::SExt:
484f4a2713aSLionel Sambuc         Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
485f4a2713aSLionel Sambuc         break;
486f4a2713aSLionel Sambuc       case CCValAssign::ZExt:
487f4a2713aSLionel Sambuc         Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
488f4a2713aSLionel Sambuc         break;
489f4a2713aSLionel Sambuc       case CCValAssign::AExt:
490f4a2713aSLionel Sambuc         Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
491f4a2713aSLionel Sambuc         break;
492f4a2713aSLionel Sambuc     }
493f4a2713aSLionel Sambuc 
494f4a2713aSLionel Sambuc     if (VA.isMemLoc()) {
495f4a2713aSLionel Sambuc       unsigned LocMemOffset = VA.getLocMemOffset();
496f4a2713aSLionel Sambuc       SDValue PtrOff = DAG.getConstant(LocMemOffset, StackPtr.getValueType());
497f4a2713aSLionel Sambuc       PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
498f4a2713aSLionel Sambuc 
499f4a2713aSLionel Sambuc       if (Flags.isByVal()) {
500f4a2713aSLionel Sambuc         // The argument is a struct passed by value. According to LLVM, "Arg"
501f4a2713aSLionel Sambuc         // is is pointer.
502f4a2713aSLionel Sambuc         MemOpChains.push_back(CreateCopyOfByValArgument(Arg, PtrOff, Chain,
503f4a2713aSLionel Sambuc                                                         Flags, DAG, dl));
504f4a2713aSLionel Sambuc       } else {
505f4a2713aSLionel Sambuc         // The argument is not passed by value. "Arg" is a buildin type. It is
506f4a2713aSLionel Sambuc         // not a pointer.
507f4a2713aSLionel Sambuc         MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
508f4a2713aSLionel Sambuc                                            MachinePointerInfo(),false, false,
509f4a2713aSLionel Sambuc                                            0));
510f4a2713aSLionel Sambuc       }
511f4a2713aSLionel Sambuc       continue;
512f4a2713aSLionel Sambuc     }
513f4a2713aSLionel Sambuc 
514f4a2713aSLionel Sambuc     // Arguments that can be passed on register must be kept at RegsToPass
515f4a2713aSLionel Sambuc     // vector.
516f4a2713aSLionel Sambuc     if (VA.isRegLoc()) {
517f4a2713aSLionel Sambuc       RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
518f4a2713aSLionel Sambuc     }
519f4a2713aSLionel Sambuc   }
520f4a2713aSLionel Sambuc 
521f4a2713aSLionel Sambuc   // Transform all store nodes into one single node because all store
522f4a2713aSLionel Sambuc   // nodes are independent of each other.
523f4a2713aSLionel Sambuc   if (!MemOpChains.empty()) {
524*0a6a1f1dSLionel Sambuc     Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
525f4a2713aSLionel Sambuc   }
526f4a2713aSLionel Sambuc 
527f4a2713aSLionel Sambuc   if (!isTailCall)
528f4a2713aSLionel Sambuc     Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumBytes,
529f4a2713aSLionel Sambuc                                                         getPointerTy(), true),
530f4a2713aSLionel Sambuc                                  dl);
531f4a2713aSLionel Sambuc 
532f4a2713aSLionel Sambuc   // Build a sequence of copy-to-reg nodes chained together with token
533f4a2713aSLionel Sambuc   // chain and flag operands which copy the outgoing args into registers.
534f4a2713aSLionel Sambuc   // The InFlag in necessary since all emitted instructions must be
535f4a2713aSLionel Sambuc   // stuck together.
536f4a2713aSLionel Sambuc   SDValue InFlag;
537f4a2713aSLionel Sambuc   if (!isTailCall) {
538f4a2713aSLionel Sambuc     for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
539f4a2713aSLionel Sambuc       Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
540f4a2713aSLionel Sambuc                                RegsToPass[i].second, InFlag);
541f4a2713aSLionel Sambuc       InFlag = Chain.getValue(1);
542f4a2713aSLionel Sambuc     }
543f4a2713aSLionel Sambuc   }
544f4a2713aSLionel Sambuc 
545f4a2713aSLionel Sambuc   // For tail calls lower the arguments to the 'real' stack slot.
546f4a2713aSLionel Sambuc   if (isTailCall) {
547f4a2713aSLionel Sambuc     // Force all the incoming stack arguments to be loaded from the stack
548f4a2713aSLionel Sambuc     // before any new outgoing arguments are stored to the stack, because the
549f4a2713aSLionel Sambuc     // outgoing stack slots may alias the incoming argument stack slots, and
550f4a2713aSLionel Sambuc     // the alias isn't otherwise explicit. This is slightly more conservative
551f4a2713aSLionel Sambuc     // than necessary, because it means that each store effectively depends
552f4a2713aSLionel Sambuc     // on every argument instead of just those arguments it would clobber.
553f4a2713aSLionel Sambuc     //
554f4a2713aSLionel Sambuc     // Do not flag preceding copytoreg stuff together with the following stuff.
555f4a2713aSLionel Sambuc     InFlag = SDValue();
556f4a2713aSLionel Sambuc     for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
557f4a2713aSLionel Sambuc       Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
558f4a2713aSLionel Sambuc                                RegsToPass[i].second, InFlag);
559f4a2713aSLionel Sambuc       InFlag = Chain.getValue(1);
560f4a2713aSLionel Sambuc     }
561f4a2713aSLionel Sambuc     InFlag =SDValue();
562f4a2713aSLionel Sambuc   }
563f4a2713aSLionel Sambuc 
564f4a2713aSLionel Sambuc   // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
565f4a2713aSLionel Sambuc   // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
566f4a2713aSLionel Sambuc   // node so that legalize doesn't hack it.
567f4a2713aSLionel Sambuc   if (flag_aligned_memcpy) {
568f4a2713aSLionel Sambuc     const char *MemcpyName =
569f4a2713aSLionel Sambuc       "__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes";
570f4a2713aSLionel Sambuc     Callee =
571f4a2713aSLionel Sambuc       DAG.getTargetExternalSymbol(MemcpyName, getPointerTy());
572f4a2713aSLionel Sambuc     flag_aligned_memcpy = false;
573f4a2713aSLionel Sambuc   } else if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
574f4a2713aSLionel Sambuc     Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy());
575f4a2713aSLionel Sambuc   } else if (ExternalSymbolSDNode *S =
576f4a2713aSLionel Sambuc              dyn_cast<ExternalSymbolSDNode>(Callee)) {
577f4a2713aSLionel Sambuc     Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
578f4a2713aSLionel Sambuc   }
579f4a2713aSLionel Sambuc 
580f4a2713aSLionel Sambuc   // Returns a chain & a flag for retval copy to use.
581f4a2713aSLionel Sambuc   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
582f4a2713aSLionel Sambuc   SmallVector<SDValue, 8> Ops;
583f4a2713aSLionel Sambuc   Ops.push_back(Chain);
584f4a2713aSLionel Sambuc   Ops.push_back(Callee);
585f4a2713aSLionel Sambuc 
586f4a2713aSLionel Sambuc   // Add argument registers to the end of the list so that they are
587f4a2713aSLionel Sambuc   // known live into the call.
588f4a2713aSLionel Sambuc   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
589f4a2713aSLionel Sambuc     Ops.push_back(DAG.getRegister(RegsToPass[i].first,
590f4a2713aSLionel Sambuc                                   RegsToPass[i].second.getValueType()));
591f4a2713aSLionel Sambuc   }
592f4a2713aSLionel Sambuc 
593f4a2713aSLionel Sambuc   if (InFlag.getNode()) {
594f4a2713aSLionel Sambuc     Ops.push_back(InFlag);
595f4a2713aSLionel Sambuc   }
596f4a2713aSLionel Sambuc 
597f4a2713aSLionel Sambuc   if (isTailCall)
598*0a6a1f1dSLionel Sambuc     return DAG.getNode(HexagonISD::TC_RETURN, dl, NodeTys, Ops);
599f4a2713aSLionel Sambuc 
600*0a6a1f1dSLionel Sambuc   Chain = DAG.getNode(HexagonISD::CALL, dl, NodeTys, Ops);
601f4a2713aSLionel Sambuc   InFlag = Chain.getValue(1);
602f4a2713aSLionel Sambuc 
603f4a2713aSLionel Sambuc   // Create the CALLSEQ_END node.
604f4a2713aSLionel Sambuc   Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true),
605f4a2713aSLionel Sambuc                              DAG.getIntPtrConstant(0, true), InFlag, dl);
606f4a2713aSLionel Sambuc   InFlag = Chain.getValue(1);
607f4a2713aSLionel Sambuc 
608f4a2713aSLionel Sambuc   // Handle result values, copying them out of physregs into vregs that we
609f4a2713aSLionel Sambuc   // return.
610f4a2713aSLionel Sambuc   return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, DAG,
611f4a2713aSLionel Sambuc                          InVals, OutVals, Callee);
612f4a2713aSLionel Sambuc }
613f4a2713aSLionel Sambuc 
getIndexedAddressParts(SDNode * Ptr,EVT VT,bool isSEXTLoad,SDValue & Base,SDValue & Offset,bool & isInc,SelectionDAG & DAG)614f4a2713aSLionel Sambuc static bool getIndexedAddressParts(SDNode *Ptr, EVT VT,
615f4a2713aSLionel Sambuc                                    bool isSEXTLoad, SDValue &Base,
616f4a2713aSLionel Sambuc                                    SDValue &Offset, bool &isInc,
617f4a2713aSLionel Sambuc                                    SelectionDAG &DAG) {
618f4a2713aSLionel Sambuc   if (Ptr->getOpcode() != ISD::ADD)
619f4a2713aSLionel Sambuc   return false;
620f4a2713aSLionel Sambuc 
621f4a2713aSLionel Sambuc   if (VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) {
622f4a2713aSLionel Sambuc     isInc = (Ptr->getOpcode() == ISD::ADD);
623f4a2713aSLionel Sambuc     Base = Ptr->getOperand(0);
624f4a2713aSLionel Sambuc     Offset = Ptr->getOperand(1);
625f4a2713aSLionel Sambuc     // Ensure that Offset is a constant.
626f4a2713aSLionel Sambuc     return (isa<ConstantSDNode>(Offset));
627f4a2713aSLionel Sambuc   }
628f4a2713aSLionel Sambuc 
629f4a2713aSLionel Sambuc   return false;
630f4a2713aSLionel Sambuc }
631f4a2713aSLionel Sambuc 
632f4a2713aSLionel Sambuc // TODO: Put this function along with the other isS* functions in
633f4a2713aSLionel Sambuc // HexagonISelDAGToDAG.cpp into a common file. Or better still, use the
634f4a2713aSLionel Sambuc // functions defined in HexagonOperands.td.
Is_PostInc_S4_Offset(SDNode * S,int ShiftAmount)635f4a2713aSLionel Sambuc static bool Is_PostInc_S4_Offset(SDNode * S, int ShiftAmount) {
636f4a2713aSLionel Sambuc   ConstantSDNode *N = cast<ConstantSDNode>(S);
637f4a2713aSLionel Sambuc 
638f4a2713aSLionel Sambuc   // immS4 predicate - True if the immediate fits in a 4-bit sign extended.
639f4a2713aSLionel Sambuc   // field.
640f4a2713aSLionel Sambuc   int64_t v = (int64_t)N->getSExtValue();
641f4a2713aSLionel Sambuc   int64_t m = 0;
642f4a2713aSLionel Sambuc   if (ShiftAmount > 0) {
643f4a2713aSLionel Sambuc     m = v % ShiftAmount;
644f4a2713aSLionel Sambuc     v = v >> ShiftAmount;
645f4a2713aSLionel Sambuc   }
646f4a2713aSLionel Sambuc   return (v <= 7) && (v >= -8) && (m == 0);
647f4a2713aSLionel Sambuc }
648f4a2713aSLionel Sambuc 
649f4a2713aSLionel Sambuc /// getPostIndexedAddressParts - returns true by value, base pointer and
650f4a2713aSLionel Sambuc /// offset pointer and addressing mode by reference if this node can be
651f4a2713aSLionel Sambuc /// combined with a load / store to form a post-indexed load / store.
getPostIndexedAddressParts(SDNode * N,SDNode * Op,SDValue & Base,SDValue & Offset,ISD::MemIndexedMode & AM,SelectionDAG & DAG) const652f4a2713aSLionel Sambuc bool HexagonTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
653f4a2713aSLionel Sambuc                                                        SDValue &Base,
654f4a2713aSLionel Sambuc                                                        SDValue &Offset,
655f4a2713aSLionel Sambuc                                                        ISD::MemIndexedMode &AM,
656f4a2713aSLionel Sambuc                                                        SelectionDAG &DAG) const
657f4a2713aSLionel Sambuc {
658f4a2713aSLionel Sambuc   EVT VT;
659f4a2713aSLionel Sambuc   SDValue Ptr;
660f4a2713aSLionel Sambuc   bool isSEXTLoad = false;
661f4a2713aSLionel Sambuc 
662f4a2713aSLionel Sambuc   if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
663f4a2713aSLionel Sambuc     VT  = LD->getMemoryVT();
664f4a2713aSLionel Sambuc     isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD;
665f4a2713aSLionel Sambuc   } else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
666f4a2713aSLionel Sambuc     VT  = ST->getMemoryVT();
667f4a2713aSLionel Sambuc     if (ST->getValue().getValueType() == MVT::i64 && ST->isTruncatingStore()) {
668f4a2713aSLionel Sambuc       return false;
669f4a2713aSLionel Sambuc     }
670f4a2713aSLionel Sambuc   } else {
671f4a2713aSLionel Sambuc     return false;
672f4a2713aSLionel Sambuc   }
673f4a2713aSLionel Sambuc 
674f4a2713aSLionel Sambuc   bool isInc = false;
675f4a2713aSLionel Sambuc   bool isLegal = getIndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset,
676f4a2713aSLionel Sambuc                                         isInc, DAG);
677f4a2713aSLionel Sambuc   // ShiftAmount = number of left-shifted bits in the Hexagon instruction.
678f4a2713aSLionel Sambuc   int ShiftAmount = VT.getSizeInBits() / 16;
679f4a2713aSLionel Sambuc   if (isLegal && Is_PostInc_S4_Offset(Offset.getNode(), ShiftAmount)) {
680f4a2713aSLionel Sambuc     AM = isInc ? ISD::POST_INC : ISD::POST_DEC;
681f4a2713aSLionel Sambuc     return true;
682f4a2713aSLionel Sambuc   }
683f4a2713aSLionel Sambuc 
684f4a2713aSLionel Sambuc   return false;
685f4a2713aSLionel Sambuc }
686f4a2713aSLionel Sambuc 
LowerINLINEASM(SDValue Op,SelectionDAG & DAG) const687f4a2713aSLionel Sambuc SDValue HexagonTargetLowering::LowerINLINEASM(SDValue Op,
688f4a2713aSLionel Sambuc                                               SelectionDAG &DAG) const {
689f4a2713aSLionel Sambuc   SDNode *Node = Op.getNode();
690f4a2713aSLionel Sambuc   MachineFunction &MF = DAG.getMachineFunction();
691f4a2713aSLionel Sambuc   HexagonMachineFunctionInfo *FuncInfo =
692f4a2713aSLionel Sambuc     MF.getInfo<HexagonMachineFunctionInfo>();
693f4a2713aSLionel Sambuc   switch (Node->getOpcode()) {
694f4a2713aSLionel Sambuc     case ISD::INLINEASM: {
695f4a2713aSLionel Sambuc       unsigned NumOps = Node->getNumOperands();
696f4a2713aSLionel Sambuc       if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue)
697f4a2713aSLionel Sambuc         --NumOps;  // Ignore the flag operand.
698f4a2713aSLionel Sambuc 
699f4a2713aSLionel Sambuc       for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
700f4a2713aSLionel Sambuc         if (FuncInfo->hasClobberLR())
701f4a2713aSLionel Sambuc           break;
702f4a2713aSLionel Sambuc         unsigned Flags =
703f4a2713aSLionel Sambuc           cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
704f4a2713aSLionel Sambuc         unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
705f4a2713aSLionel Sambuc         ++i;  // Skip the ID value.
706f4a2713aSLionel Sambuc 
707f4a2713aSLionel Sambuc         switch (InlineAsm::getKind(Flags)) {
708f4a2713aSLionel Sambuc         default: llvm_unreachable("Bad flags!");
709f4a2713aSLionel Sambuc           case InlineAsm::Kind_RegDef:
710f4a2713aSLionel Sambuc           case InlineAsm::Kind_RegUse:
711f4a2713aSLionel Sambuc           case InlineAsm::Kind_Imm:
712f4a2713aSLionel Sambuc           case InlineAsm::Kind_Clobber:
713f4a2713aSLionel Sambuc           case InlineAsm::Kind_Mem: {
714f4a2713aSLionel Sambuc             for (; NumVals; --NumVals, ++i) {}
715f4a2713aSLionel Sambuc             break;
716f4a2713aSLionel Sambuc           }
717f4a2713aSLionel Sambuc           case InlineAsm::Kind_RegDefEarlyClobber: {
718f4a2713aSLionel Sambuc             for (; NumVals; --NumVals, ++i) {
719f4a2713aSLionel Sambuc               unsigned Reg =
720f4a2713aSLionel Sambuc                 cast<RegisterSDNode>(Node->getOperand(i))->getReg();
721f4a2713aSLionel Sambuc 
722f4a2713aSLionel Sambuc               // Check it to be lr
723*0a6a1f1dSLionel Sambuc               const HexagonRegisterInfo *QRI =
724*0a6a1f1dSLionel Sambuc                   static_cast<const HexagonRegisterInfo *>(
725*0a6a1f1dSLionel Sambuc                       DAG.getSubtarget().getRegisterInfo());
726*0a6a1f1dSLionel Sambuc               if (Reg == QRI->getRARegister()) {
727f4a2713aSLionel Sambuc                 FuncInfo->setHasClobberLR(true);
728f4a2713aSLionel Sambuc                 break;
729f4a2713aSLionel Sambuc               }
730f4a2713aSLionel Sambuc             }
731f4a2713aSLionel Sambuc             break;
732f4a2713aSLionel Sambuc           }
733f4a2713aSLionel Sambuc         }
734f4a2713aSLionel Sambuc       }
735f4a2713aSLionel Sambuc     }
736f4a2713aSLionel Sambuc   } // Node->getOpcode
737f4a2713aSLionel Sambuc   return Op;
738f4a2713aSLionel Sambuc }
739f4a2713aSLionel Sambuc 
740f4a2713aSLionel Sambuc 
741f4a2713aSLionel Sambuc //
742f4a2713aSLionel Sambuc // Taken from the XCore backend.
743f4a2713aSLionel Sambuc //
744f4a2713aSLionel Sambuc SDValue HexagonTargetLowering::
LowerBR_JT(SDValue Op,SelectionDAG & DAG) const745f4a2713aSLionel Sambuc LowerBR_JT(SDValue Op, SelectionDAG &DAG) const
746f4a2713aSLionel Sambuc {
747f4a2713aSLionel Sambuc   SDValue Chain = Op.getOperand(0);
748f4a2713aSLionel Sambuc   SDValue Table = Op.getOperand(1);
749f4a2713aSLionel Sambuc   SDValue Index = Op.getOperand(2);
750f4a2713aSLionel Sambuc   SDLoc dl(Op);
751f4a2713aSLionel Sambuc   JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
752f4a2713aSLionel Sambuc   unsigned JTI = JT->getIndex();
753f4a2713aSLionel Sambuc   MachineFunction &MF = DAG.getMachineFunction();
754f4a2713aSLionel Sambuc   const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
755f4a2713aSLionel Sambuc   SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
756f4a2713aSLionel Sambuc 
757f4a2713aSLionel Sambuc   // Mark all jump table targets as address taken.
758f4a2713aSLionel Sambuc   const std::vector<MachineJumpTableEntry> &JTE = MJTI->getJumpTables();
759f4a2713aSLionel Sambuc   const std::vector<MachineBasicBlock*> &JTBBs = JTE[JTI].MBBs;
760f4a2713aSLionel Sambuc   for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
761f4a2713aSLionel Sambuc     MachineBasicBlock *MBB = JTBBs[i];
762f4a2713aSLionel Sambuc     MBB->setHasAddressTaken();
763f4a2713aSLionel Sambuc     // This line is needed to set the hasAddressTaken flag on the BasicBlock
764f4a2713aSLionel Sambuc     // object.
765f4a2713aSLionel Sambuc     BlockAddress::get(const_cast<BasicBlock *>(MBB->getBasicBlock()));
766f4a2713aSLionel Sambuc   }
767f4a2713aSLionel Sambuc 
768f4a2713aSLionel Sambuc   SDValue JumpTableBase = DAG.getNode(HexagonISD::WrapperJT, dl,
769f4a2713aSLionel Sambuc                                       getPointerTy(), TargetJT);
770f4a2713aSLionel Sambuc   SDValue ShiftIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index,
771f4a2713aSLionel Sambuc                                    DAG.getConstant(2, MVT::i32));
772f4a2713aSLionel Sambuc   SDValue JTAddress = DAG.getNode(ISD::ADD, dl, MVT::i32, JumpTableBase,
773f4a2713aSLionel Sambuc                                   ShiftIndex);
774f4a2713aSLionel Sambuc   SDValue LoadTarget = DAG.getLoad(MVT::i32, dl, Chain, JTAddress,
775f4a2713aSLionel Sambuc                                    MachinePointerInfo(), false, false, false,
776f4a2713aSLionel Sambuc                                    0);
777f4a2713aSLionel Sambuc   return DAG.getNode(HexagonISD::BR_JT, dl, MVT::Other, Chain, LoadTarget);
778f4a2713aSLionel Sambuc }
779f4a2713aSLionel Sambuc 
780f4a2713aSLionel Sambuc 
781f4a2713aSLionel Sambuc SDValue
LowerDYNAMIC_STACKALLOC(SDValue Op,SelectionDAG & DAG) const782f4a2713aSLionel Sambuc HexagonTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
783f4a2713aSLionel Sambuc                                                SelectionDAG &DAG) const {
784f4a2713aSLionel Sambuc   SDValue Chain = Op.getOperand(0);
785f4a2713aSLionel Sambuc   SDValue Size = Op.getOperand(1);
786f4a2713aSLionel Sambuc   SDLoc dl(Op);
787f4a2713aSLionel Sambuc 
788f4a2713aSLionel Sambuc   unsigned SPReg = getStackPointerRegisterToSaveRestore();
789f4a2713aSLionel Sambuc 
790f4a2713aSLionel Sambuc   // Get a reference to the stack pointer.
791f4a2713aSLionel Sambuc   SDValue StackPointer = DAG.getCopyFromReg(Chain, dl, SPReg, MVT::i32);
792f4a2713aSLionel Sambuc 
793f4a2713aSLionel Sambuc   // Subtract the dynamic size from the actual stack size to
794f4a2713aSLionel Sambuc   // obtain the new stack size.
795f4a2713aSLionel Sambuc   SDValue Sub = DAG.getNode(ISD::SUB, dl, MVT::i32, StackPointer, Size);
796f4a2713aSLionel Sambuc 
797f4a2713aSLionel Sambuc   //
798f4a2713aSLionel Sambuc   // For Hexagon, the outgoing memory arguments area should be on top of the
799f4a2713aSLionel Sambuc   // alloca area on the stack i.e., the outgoing memory arguments should be
800f4a2713aSLionel Sambuc   // at a lower address than the alloca area. Move the alloca area down the
801f4a2713aSLionel Sambuc   // stack by adding back the space reserved for outgoing arguments to SP
802f4a2713aSLionel Sambuc   // here.
803f4a2713aSLionel Sambuc   //
804f4a2713aSLionel Sambuc   // We do not know what the size of the outgoing args is at this point.
805f4a2713aSLionel Sambuc   // So, we add a pseudo instruction ADJDYNALLOC that will adjust the
806f4a2713aSLionel Sambuc   // stack pointer. We patch this instruction with the correct, known
807f4a2713aSLionel Sambuc   // offset in emitPrologue().
808f4a2713aSLionel Sambuc   //
809f4a2713aSLionel Sambuc   // Use a placeholder immediate (zero) for now. This will be patched up
810f4a2713aSLionel Sambuc   // by emitPrologue().
811f4a2713aSLionel Sambuc   SDValue ArgAdjust = DAG.getNode(HexagonISD::ADJDYNALLOC, dl,
812f4a2713aSLionel Sambuc                                   MVT::i32,
813f4a2713aSLionel Sambuc                                   Sub,
814f4a2713aSLionel Sambuc                                   DAG.getConstant(0, MVT::i32));
815f4a2713aSLionel Sambuc 
816f4a2713aSLionel Sambuc   // The Sub result contains the new stack start address, so it
817f4a2713aSLionel Sambuc   // must be placed in the stack pointer register.
818*0a6a1f1dSLionel Sambuc   const HexagonRegisterInfo *QRI = static_cast<const HexagonRegisterInfo *>(
819*0a6a1f1dSLionel Sambuc       DAG.getSubtarget().getRegisterInfo());
820*0a6a1f1dSLionel Sambuc   SDValue CopyChain = DAG.getCopyToReg(Chain, dl, QRI->getStackRegister(), Sub);
821f4a2713aSLionel Sambuc 
822f4a2713aSLionel Sambuc   SDValue Ops[2] = { ArgAdjust, CopyChain };
823*0a6a1f1dSLionel Sambuc   return DAG.getMergeValues(Ops, dl);
824f4a2713aSLionel Sambuc }
825f4a2713aSLionel Sambuc 
826f4a2713aSLionel Sambuc SDValue
LowerFormalArguments(SDValue Chain,CallingConv::ID CallConv,bool isVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,SDLoc dl,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const827f4a2713aSLionel Sambuc HexagonTargetLowering::LowerFormalArguments(SDValue Chain,
828f4a2713aSLionel Sambuc                                             CallingConv::ID CallConv,
829f4a2713aSLionel Sambuc                                             bool isVarArg,
830f4a2713aSLionel Sambuc                                             const
831f4a2713aSLionel Sambuc                                             SmallVectorImpl<ISD::InputArg> &Ins,
832f4a2713aSLionel Sambuc                                             SDLoc dl, SelectionDAG &DAG,
833f4a2713aSLionel Sambuc                                             SmallVectorImpl<SDValue> &InVals)
834f4a2713aSLionel Sambuc const {
835f4a2713aSLionel Sambuc 
836f4a2713aSLionel Sambuc   MachineFunction &MF = DAG.getMachineFunction();
837f4a2713aSLionel Sambuc   MachineFrameInfo *MFI = MF.getFrameInfo();
838f4a2713aSLionel Sambuc   MachineRegisterInfo &RegInfo = MF.getRegInfo();
839f4a2713aSLionel Sambuc   HexagonMachineFunctionInfo *FuncInfo =
840f4a2713aSLionel Sambuc     MF.getInfo<HexagonMachineFunctionInfo>();
841f4a2713aSLionel Sambuc 
842f4a2713aSLionel Sambuc 
843f4a2713aSLionel Sambuc   // Assign locations to all of the incoming arguments.
844f4a2713aSLionel Sambuc   SmallVector<CCValAssign, 16> ArgLocs;
845*0a6a1f1dSLionel Sambuc   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
846*0a6a1f1dSLionel Sambuc                  *DAG.getContext());
847f4a2713aSLionel Sambuc 
848f4a2713aSLionel Sambuc   CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon);
849f4a2713aSLionel Sambuc 
850f4a2713aSLionel Sambuc   // For LLVM, in the case when returning a struct by value (>8byte),
851f4a2713aSLionel Sambuc   // the first argument is a pointer that points to the location on caller's
852f4a2713aSLionel Sambuc   // stack where the return value will be stored. For Hexagon, the location on
853f4a2713aSLionel Sambuc   // caller's stack is passed only when the struct size is smaller than (and
854f4a2713aSLionel Sambuc   // equal to) 8 bytes. If not, no address will be passed into callee and
855f4a2713aSLionel Sambuc   // callee return the result direclty through R0/R1.
856f4a2713aSLionel Sambuc 
857f4a2713aSLionel Sambuc   SmallVector<SDValue, 4> MemOps;
858f4a2713aSLionel Sambuc 
859f4a2713aSLionel Sambuc   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
860f4a2713aSLionel Sambuc     CCValAssign &VA = ArgLocs[i];
861f4a2713aSLionel Sambuc     ISD::ArgFlagsTy Flags = Ins[i].Flags;
862f4a2713aSLionel Sambuc     unsigned ObjSize;
863f4a2713aSLionel Sambuc     unsigned StackLocation;
864f4a2713aSLionel Sambuc     int FI;
865f4a2713aSLionel Sambuc 
866f4a2713aSLionel Sambuc     if (   (VA.isRegLoc() && !Flags.isByVal())
867f4a2713aSLionel Sambuc         || (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() > 8)) {
868f4a2713aSLionel Sambuc       // Arguments passed in registers
869f4a2713aSLionel Sambuc       // 1. int, long long, ptr args that get allocated in register.
870f4a2713aSLionel Sambuc       // 2. Large struct that gets an register to put its address in.
871f4a2713aSLionel Sambuc       EVT RegVT = VA.getLocVT();
872f4a2713aSLionel Sambuc       if (RegVT == MVT::i8 || RegVT == MVT::i16 ||
873f4a2713aSLionel Sambuc           RegVT == MVT::i32 || RegVT == MVT::f32) {
874f4a2713aSLionel Sambuc         unsigned VReg =
875f4a2713aSLionel Sambuc           RegInfo.createVirtualRegister(&Hexagon::IntRegsRegClass);
876f4a2713aSLionel Sambuc         RegInfo.addLiveIn(VA.getLocReg(), VReg);
877f4a2713aSLionel Sambuc         InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
878f4a2713aSLionel Sambuc       } else if (RegVT == MVT::i64) {
879f4a2713aSLionel Sambuc         unsigned VReg =
880f4a2713aSLionel Sambuc           RegInfo.createVirtualRegister(&Hexagon::DoubleRegsRegClass);
881f4a2713aSLionel Sambuc         RegInfo.addLiveIn(VA.getLocReg(), VReg);
882f4a2713aSLionel Sambuc         InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
883f4a2713aSLionel Sambuc       } else {
884f4a2713aSLionel Sambuc         assert (0);
885f4a2713aSLionel Sambuc       }
886f4a2713aSLionel Sambuc     } else if (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() <= 8) {
887f4a2713aSLionel Sambuc       assert (0 && "ByValSize must be bigger than 8 bytes");
888f4a2713aSLionel Sambuc     } else {
889f4a2713aSLionel Sambuc       // Sanity check.
890f4a2713aSLionel Sambuc       assert(VA.isMemLoc());
891f4a2713aSLionel Sambuc 
892f4a2713aSLionel Sambuc       if (Flags.isByVal()) {
893f4a2713aSLionel Sambuc         // If it's a byval parameter, then we need to compute the
894f4a2713aSLionel Sambuc         // "real" size, not the size of the pointer.
895f4a2713aSLionel Sambuc         ObjSize = Flags.getByValSize();
896f4a2713aSLionel Sambuc       } else {
897f4a2713aSLionel Sambuc         ObjSize = VA.getLocVT().getStoreSizeInBits() >> 3;
898f4a2713aSLionel Sambuc       }
899f4a2713aSLionel Sambuc 
900f4a2713aSLionel Sambuc       StackLocation = HEXAGON_LRFP_SIZE + VA.getLocMemOffset();
901f4a2713aSLionel Sambuc       // Create the frame index object for this incoming parameter...
902f4a2713aSLionel Sambuc       FI = MFI->CreateFixedObject(ObjSize, StackLocation, true);
903f4a2713aSLionel Sambuc 
904f4a2713aSLionel Sambuc       // Create the SelectionDAG nodes cordl, responding to a load
905f4a2713aSLionel Sambuc       // from this parameter.
906f4a2713aSLionel Sambuc       SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
907f4a2713aSLionel Sambuc 
908f4a2713aSLionel Sambuc       if (Flags.isByVal()) {
909f4a2713aSLionel Sambuc         // If it's a pass-by-value aggregate, then do not dereference the stack
910f4a2713aSLionel Sambuc         // location. Instead, we should generate a reference to the stack
911f4a2713aSLionel Sambuc         // location.
912f4a2713aSLionel Sambuc         InVals.push_back(FIN);
913f4a2713aSLionel Sambuc       } else {
914f4a2713aSLionel Sambuc         InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
915f4a2713aSLionel Sambuc                                      MachinePointerInfo(), false, false,
916f4a2713aSLionel Sambuc                                      false, 0));
917f4a2713aSLionel Sambuc       }
918f4a2713aSLionel Sambuc     }
919f4a2713aSLionel Sambuc   }
920f4a2713aSLionel Sambuc 
921f4a2713aSLionel Sambuc   if (!MemOps.empty())
922*0a6a1f1dSLionel Sambuc     Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
923f4a2713aSLionel Sambuc 
924f4a2713aSLionel Sambuc   if (isVarArg) {
925f4a2713aSLionel Sambuc     // This will point to the next argument passed via stack.
926f4a2713aSLionel Sambuc     int FrameIndex = MFI->CreateFixedObject(Hexagon_PointerSize,
927f4a2713aSLionel Sambuc                                             HEXAGON_LRFP_SIZE +
928f4a2713aSLionel Sambuc                                             CCInfo.getNextStackOffset(),
929f4a2713aSLionel Sambuc                                             true);
930f4a2713aSLionel Sambuc     FuncInfo->setVarArgsFrameIndex(FrameIndex);
931f4a2713aSLionel Sambuc   }
932f4a2713aSLionel Sambuc 
933f4a2713aSLionel Sambuc   return Chain;
934f4a2713aSLionel Sambuc }
935f4a2713aSLionel Sambuc 
936f4a2713aSLionel Sambuc SDValue
LowerVASTART(SDValue Op,SelectionDAG & DAG) const937f4a2713aSLionel Sambuc HexagonTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
938f4a2713aSLionel Sambuc   // VASTART stores the address of the VarArgsFrameIndex slot into the
939f4a2713aSLionel Sambuc   // memory location argument.
940f4a2713aSLionel Sambuc   MachineFunction &MF = DAG.getMachineFunction();
941f4a2713aSLionel Sambuc   HexagonMachineFunctionInfo *QFI = MF.getInfo<HexagonMachineFunctionInfo>();
942f4a2713aSLionel Sambuc   SDValue Addr = DAG.getFrameIndex(QFI->getVarArgsFrameIndex(), MVT::i32);
943f4a2713aSLionel Sambuc   const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
944f4a2713aSLionel Sambuc   return DAG.getStore(Op.getOperand(0), SDLoc(Op), Addr,
945f4a2713aSLionel Sambuc                       Op.getOperand(1), MachinePointerInfo(SV), false,
946f4a2713aSLionel Sambuc                       false, 0);
947f4a2713aSLionel Sambuc }
948f4a2713aSLionel Sambuc 
949f4a2713aSLionel Sambuc SDValue
LowerConstantPool(SDValue Op,SelectionDAG & DAG) const950f4a2713aSLionel Sambuc HexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const {
951f4a2713aSLionel Sambuc   EVT ValTy = Op.getValueType();
952f4a2713aSLionel Sambuc   SDLoc dl(Op);
953f4a2713aSLionel Sambuc   ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
954f4a2713aSLionel Sambuc   SDValue Res;
955f4a2713aSLionel Sambuc   if (CP->isMachineConstantPoolEntry())
956f4a2713aSLionel Sambuc     Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), ValTy,
957f4a2713aSLionel Sambuc                                     CP->getAlignment());
958f4a2713aSLionel Sambuc   else
959f4a2713aSLionel Sambuc     Res = DAG.getTargetConstantPool(CP->getConstVal(), ValTy,
960f4a2713aSLionel Sambuc                                     CP->getAlignment());
961f4a2713aSLionel Sambuc   return DAG.getNode(HexagonISD::CONST32, dl, ValTy, Res);
962f4a2713aSLionel Sambuc }
963f4a2713aSLionel Sambuc 
964f4a2713aSLionel Sambuc SDValue
LowerRETURNADDR(SDValue Op,SelectionDAG & DAG) const965f4a2713aSLionel Sambuc HexagonTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
966*0a6a1f1dSLionel Sambuc   const TargetRegisterInfo *TRI = DAG.getSubtarget().getRegisterInfo();
967f4a2713aSLionel Sambuc   MachineFunction &MF = DAG.getMachineFunction();
968f4a2713aSLionel Sambuc   MachineFrameInfo *MFI = MF.getFrameInfo();
969f4a2713aSLionel Sambuc   MFI->setReturnAddressIsTaken(true);
970f4a2713aSLionel Sambuc 
971*0a6a1f1dSLionel Sambuc   if (verifyReturnAddressArgumentIsConstant(Op, DAG))
972*0a6a1f1dSLionel Sambuc     return SDValue();
973*0a6a1f1dSLionel Sambuc 
974f4a2713aSLionel Sambuc   EVT VT = Op.getValueType();
975f4a2713aSLionel Sambuc   SDLoc dl(Op);
976f4a2713aSLionel Sambuc   unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
977f4a2713aSLionel Sambuc   if (Depth) {
978f4a2713aSLionel Sambuc     SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
979f4a2713aSLionel Sambuc     SDValue Offset = DAG.getConstant(4, MVT::i32);
980f4a2713aSLionel Sambuc     return DAG.getLoad(VT, dl, DAG.getEntryNode(),
981f4a2713aSLionel Sambuc                        DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset),
982f4a2713aSLionel Sambuc                        MachinePointerInfo(), false, false, false, 0);
983f4a2713aSLionel Sambuc   }
984f4a2713aSLionel Sambuc 
985f4a2713aSLionel Sambuc   // Return LR, which contains the return address. Mark it an implicit live-in.
986f4a2713aSLionel Sambuc   unsigned Reg = MF.addLiveIn(TRI->getRARegister(), getRegClassFor(MVT::i32));
987f4a2713aSLionel Sambuc   return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);
988f4a2713aSLionel Sambuc }
989f4a2713aSLionel Sambuc 
990f4a2713aSLionel Sambuc SDValue
LowerFRAMEADDR(SDValue Op,SelectionDAG & DAG) const991f4a2713aSLionel Sambuc HexagonTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
992*0a6a1f1dSLionel Sambuc   const HexagonRegisterInfo *TRI = static_cast<const HexagonRegisterInfo *>(
993*0a6a1f1dSLionel Sambuc       DAG.getSubtarget().getRegisterInfo());
994f4a2713aSLionel Sambuc   MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
995f4a2713aSLionel Sambuc   MFI->setFrameAddressIsTaken(true);
996f4a2713aSLionel Sambuc 
997f4a2713aSLionel Sambuc   EVT VT = Op.getValueType();
998f4a2713aSLionel Sambuc   SDLoc dl(Op);
999f4a2713aSLionel Sambuc   unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1000f4a2713aSLionel Sambuc   SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl,
1001f4a2713aSLionel Sambuc                                          TRI->getFrameRegister(), VT);
1002f4a2713aSLionel Sambuc   while (Depth--)
1003f4a2713aSLionel Sambuc     FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,
1004f4a2713aSLionel Sambuc                             MachinePointerInfo(),
1005f4a2713aSLionel Sambuc                             false, false, false, 0);
1006f4a2713aSLionel Sambuc   return FrameAddr;
1007f4a2713aSLionel Sambuc }
1008f4a2713aSLionel Sambuc 
LowerATOMIC_FENCE(SDValue Op,SelectionDAG & DAG) const1009f4a2713aSLionel Sambuc SDValue HexagonTargetLowering::LowerATOMIC_FENCE(SDValue Op,
1010f4a2713aSLionel Sambuc                                                  SelectionDAG& DAG) const {
1011f4a2713aSLionel Sambuc   SDLoc dl(Op);
1012f4a2713aSLionel Sambuc   return DAG.getNode(HexagonISD::BARRIER, dl, MVT::Other, Op.getOperand(0));
1013f4a2713aSLionel Sambuc }
1014f4a2713aSLionel Sambuc 
1015f4a2713aSLionel Sambuc 
LowerGLOBALADDRESS(SDValue Op,SelectionDAG & DAG) const1016f4a2713aSLionel Sambuc SDValue HexagonTargetLowering::LowerGLOBALADDRESS(SDValue Op,
1017f4a2713aSLionel Sambuc                                                   SelectionDAG &DAG) const {
1018f4a2713aSLionel Sambuc   SDValue Result;
1019f4a2713aSLionel Sambuc   const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
1020f4a2713aSLionel Sambuc   int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();
1021f4a2713aSLionel Sambuc   SDLoc dl(Op);
1022f4a2713aSLionel Sambuc   Result = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), Offset);
1023f4a2713aSLionel Sambuc 
1024f4a2713aSLionel Sambuc   const HexagonTargetObjectFile &TLOF =
1025f4a2713aSLionel Sambuc       static_cast<const HexagonTargetObjectFile &>(getObjFileLowering());
1026f4a2713aSLionel Sambuc   if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) {
1027f4a2713aSLionel Sambuc     return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), Result);
1028f4a2713aSLionel Sambuc   }
1029f4a2713aSLionel Sambuc 
1030f4a2713aSLionel Sambuc   return DAG.getNode(HexagonISD::CONST32, dl, getPointerTy(), Result);
1031f4a2713aSLionel Sambuc }
1032f4a2713aSLionel Sambuc 
1033f4a2713aSLionel Sambuc SDValue
LowerBlockAddress(SDValue Op,SelectionDAG & DAG) const1034f4a2713aSLionel Sambuc HexagonTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const {
1035f4a2713aSLionel Sambuc   const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
1036f4a2713aSLionel Sambuc   SDValue BA_SD =  DAG.getTargetBlockAddress(BA, MVT::i32);
1037f4a2713aSLionel Sambuc   SDLoc dl(Op);
1038f4a2713aSLionel Sambuc   return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), BA_SD);
1039f4a2713aSLionel Sambuc }
1040f4a2713aSLionel Sambuc 
1041f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
1042f4a2713aSLionel Sambuc // TargetLowering Implementation
1043f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
1044f4a2713aSLionel Sambuc 
HexagonTargetLowering(const TargetMachine & targetmachine)1045*0a6a1f1dSLionel Sambuc HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &targetmachine)
1046*0a6a1f1dSLionel Sambuc     : TargetLowering(targetmachine),
1047f4a2713aSLionel Sambuc       TM(targetmachine) {
1048f4a2713aSLionel Sambuc 
1049*0a6a1f1dSLionel Sambuc   const HexagonSubtarget &Subtarget = TM.getSubtarget<HexagonSubtarget>();
1050f4a2713aSLionel Sambuc 
1051f4a2713aSLionel Sambuc   // Set up the register classes.
1052f4a2713aSLionel Sambuc   addRegisterClass(MVT::i32, &Hexagon::IntRegsRegClass);
1053f4a2713aSLionel Sambuc   addRegisterClass(MVT::i64, &Hexagon::DoubleRegsRegClass);
1054f4a2713aSLionel Sambuc 
1055*0a6a1f1dSLionel Sambuc   if (Subtarget.hasV5TOps()) {
1056f4a2713aSLionel Sambuc     addRegisterClass(MVT::f32, &Hexagon::IntRegsRegClass);
1057f4a2713aSLionel Sambuc     addRegisterClass(MVT::f64, &Hexagon::DoubleRegsRegClass);
1058f4a2713aSLionel Sambuc   }
1059f4a2713aSLionel Sambuc 
1060f4a2713aSLionel Sambuc   addRegisterClass(MVT::i1, &Hexagon::PredRegsRegClass);
1061f4a2713aSLionel Sambuc 
1062f4a2713aSLionel Sambuc   computeRegisterProperties();
1063f4a2713aSLionel Sambuc 
1064f4a2713aSLionel Sambuc   // Align loop entry
1065f4a2713aSLionel Sambuc   setPrefLoopAlignment(4);
1066f4a2713aSLionel Sambuc 
1067f4a2713aSLionel Sambuc   // Limits for inline expansion of memcpy/memmove
1068f4a2713aSLionel Sambuc   MaxStoresPerMemcpy = 6;
1069f4a2713aSLionel Sambuc   MaxStoresPerMemmove = 6;
1070f4a2713aSLionel Sambuc 
1071f4a2713aSLionel Sambuc   //
1072f4a2713aSLionel Sambuc   // Library calls for unsupported operations
1073f4a2713aSLionel Sambuc   //
1074f4a2713aSLionel Sambuc 
1075f4a2713aSLionel Sambuc   setLibcallName(RTLIB::SINTTOFP_I128_F64, "__hexagon_floattidf");
1076f4a2713aSLionel Sambuc   setLibcallName(RTLIB::SINTTOFP_I128_F32, "__hexagon_floattisf");
1077f4a2713aSLionel Sambuc 
1078f4a2713aSLionel Sambuc   setLibcallName(RTLIB::FPTOUINT_F32_I128, "__hexagon_fixunssfti");
1079f4a2713aSLionel Sambuc   setLibcallName(RTLIB::FPTOUINT_F64_I128, "__hexagon_fixunsdfti");
1080f4a2713aSLionel Sambuc 
1081f4a2713aSLionel Sambuc   setLibcallName(RTLIB::FPTOSINT_F32_I128, "__hexagon_fixsfti");
1082f4a2713aSLionel Sambuc   setLibcallName(RTLIB::FPTOSINT_F64_I128, "__hexagon_fixdfti");
1083f4a2713aSLionel Sambuc 
1084f4a2713aSLionel Sambuc   setLibcallName(RTLIB::SDIV_I32, "__hexagon_divsi3");
1085f4a2713aSLionel Sambuc   setOperationAction(ISD::SDIV, MVT::i32, Expand);
1086f4a2713aSLionel Sambuc   setLibcallName(RTLIB::SREM_I32, "__hexagon_umodsi3");
1087f4a2713aSLionel Sambuc   setOperationAction(ISD::SREM, MVT::i32, Expand);
1088f4a2713aSLionel Sambuc 
1089f4a2713aSLionel Sambuc   setLibcallName(RTLIB::SDIV_I64, "__hexagon_divdi3");
1090f4a2713aSLionel Sambuc   setOperationAction(ISD::SDIV, MVT::i64, Expand);
1091f4a2713aSLionel Sambuc   setLibcallName(RTLIB::SREM_I64, "__hexagon_moddi3");
1092f4a2713aSLionel Sambuc   setOperationAction(ISD::SREM, MVT::i64, Expand);
1093f4a2713aSLionel Sambuc 
1094f4a2713aSLionel Sambuc   setLibcallName(RTLIB::UDIV_I32, "__hexagon_udivsi3");
1095f4a2713aSLionel Sambuc   setOperationAction(ISD::UDIV, MVT::i32, Expand);
1096f4a2713aSLionel Sambuc 
1097f4a2713aSLionel Sambuc   setLibcallName(RTLIB::UDIV_I64, "__hexagon_udivdi3");
1098f4a2713aSLionel Sambuc   setOperationAction(ISD::UDIV, MVT::i64, Expand);
1099f4a2713aSLionel Sambuc 
1100f4a2713aSLionel Sambuc   setLibcallName(RTLIB::UREM_I32, "__hexagon_umodsi3");
1101f4a2713aSLionel Sambuc   setOperationAction(ISD::UREM, MVT::i32, Expand);
1102f4a2713aSLionel Sambuc 
1103f4a2713aSLionel Sambuc   setLibcallName(RTLIB::UREM_I64, "__hexagon_umoddi3");
1104f4a2713aSLionel Sambuc   setOperationAction(ISD::UREM, MVT::i64, Expand);
1105f4a2713aSLionel Sambuc 
1106f4a2713aSLionel Sambuc   setLibcallName(RTLIB::DIV_F32, "__hexagon_divsf3");
1107f4a2713aSLionel Sambuc   setOperationAction(ISD::FDIV, MVT::f32, Expand);
1108f4a2713aSLionel Sambuc 
1109f4a2713aSLionel Sambuc   setLibcallName(RTLIB::DIV_F64, "__hexagon_divdf3");
1110f4a2713aSLionel Sambuc   setOperationAction(ISD::FDIV, MVT::f64, Expand);
1111f4a2713aSLionel Sambuc 
1112f4a2713aSLionel Sambuc   setOperationAction(ISD::FSQRT, MVT::f32, Expand);
1113f4a2713aSLionel Sambuc   setOperationAction(ISD::FSQRT, MVT::f64, Expand);
1114f4a2713aSLionel Sambuc   setOperationAction(ISD::FSIN, MVT::f32, Expand);
1115f4a2713aSLionel Sambuc   setOperationAction(ISD::FSIN, MVT::f64, Expand);
1116f4a2713aSLionel Sambuc 
1117*0a6a1f1dSLionel Sambuc   if (Subtarget.hasV5TOps()) {
1118f4a2713aSLionel Sambuc     // Hexagon V5 Support.
1119f4a2713aSLionel Sambuc     setOperationAction(ISD::FADD, MVT::f32, Legal);
1120f4a2713aSLionel Sambuc     setOperationAction(ISD::FADD, MVT::f64, Legal);
1121f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_EXTEND, MVT::f32, Legal);
1122f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOEQ, MVT::f32, Legal);
1123f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOEQ, MVT::f64, Legal);
1124f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETUEQ, MVT::f32, Legal);
1125f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETUEQ, MVT::f64, Legal);
1126f4a2713aSLionel Sambuc 
1127f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOGE, MVT::f32, Legal);
1128f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOGE, MVT::f64, Legal);
1129f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETUGE, MVT::f32, Legal);
1130f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETUGE, MVT::f64, Legal);
1131f4a2713aSLionel Sambuc 
1132f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOGT, MVT::f32, Legal);
1133f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOGT, MVT::f64, Legal);
1134f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETUGT, MVT::f32, Legal);
1135f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETUGT, MVT::f64, Legal);
1136f4a2713aSLionel Sambuc 
1137f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOLE, MVT::f32, Legal);
1138f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOLE, MVT::f64, Legal);
1139f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOLT, MVT::f32, Legal);
1140f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOLT, MVT::f64, Legal);
1141f4a2713aSLionel Sambuc 
1142f4a2713aSLionel Sambuc     setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
1143f4a2713aSLionel Sambuc     setOperationAction(ISD::ConstantFP, MVT::f64, Legal);
1144f4a2713aSLionel Sambuc 
1145f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_UINT, MVT::i1, Promote);
1146f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_SINT, MVT::i1, Promote);
1147f4a2713aSLionel Sambuc     setOperationAction(ISD::UINT_TO_FP, MVT::i1, Promote);
1148f4a2713aSLionel Sambuc     setOperationAction(ISD::SINT_TO_FP, MVT::i1, Promote);
1149f4a2713aSLionel Sambuc 
1150f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_UINT, MVT::i8, Promote);
1151f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_SINT, MVT::i8, Promote);
1152f4a2713aSLionel Sambuc     setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
1153f4a2713aSLionel Sambuc     setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
1154f4a2713aSLionel Sambuc 
1155f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_UINT, MVT::i16, Promote);
1156f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_SINT, MVT::i16, Promote);
1157f4a2713aSLionel Sambuc     setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
1158f4a2713aSLionel Sambuc     setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
1159f4a2713aSLionel Sambuc 
1160f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
1161f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
1162f4a2713aSLionel Sambuc     setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
1163f4a2713aSLionel Sambuc     setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
1164f4a2713aSLionel Sambuc 
1165f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_UINT, MVT::i64, Legal);
1166f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_SINT, MVT::i64, Legal);
1167f4a2713aSLionel Sambuc     setOperationAction(ISD::UINT_TO_FP, MVT::i64, Legal);
1168f4a2713aSLionel Sambuc     setOperationAction(ISD::SINT_TO_FP, MVT::i64, Legal);
1169f4a2713aSLionel Sambuc 
1170f4a2713aSLionel Sambuc     setOperationAction(ISD::FABS, MVT::f32, Legal);
1171f4a2713aSLionel Sambuc     setOperationAction(ISD::FABS, MVT::f64, Expand);
1172f4a2713aSLionel Sambuc 
1173f4a2713aSLionel Sambuc     setOperationAction(ISD::FNEG, MVT::f32, Legal);
1174f4a2713aSLionel Sambuc     setOperationAction(ISD::FNEG, MVT::f64, Expand);
1175f4a2713aSLionel Sambuc   } else {
1176f4a2713aSLionel Sambuc 
1177f4a2713aSLionel Sambuc     // Expand fp<->uint.
1178f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_SINT, MVT::i32, Expand);
1179f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
1180f4a2713aSLionel Sambuc 
1181f4a2713aSLionel Sambuc     setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand);
1182f4a2713aSLionel Sambuc     setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand);
1183f4a2713aSLionel Sambuc 
1184f4a2713aSLionel Sambuc     setLibcallName(RTLIB::SINTTOFP_I64_F32, "__hexagon_floatdisf");
1185f4a2713aSLionel Sambuc     setLibcallName(RTLIB::UINTTOFP_I64_F32, "__hexagon_floatundisf");
1186f4a2713aSLionel Sambuc 
1187f4a2713aSLionel Sambuc     setLibcallName(RTLIB::UINTTOFP_I32_F32, "__hexagon_floatunsisf");
1188f4a2713aSLionel Sambuc     setLibcallName(RTLIB::SINTTOFP_I32_F32, "__hexagon_floatsisf");
1189f4a2713aSLionel Sambuc 
1190f4a2713aSLionel Sambuc     setLibcallName(RTLIB::SINTTOFP_I64_F64, "__hexagon_floatdidf");
1191f4a2713aSLionel Sambuc     setLibcallName(RTLIB::UINTTOFP_I64_F64, "__hexagon_floatundidf");
1192f4a2713aSLionel Sambuc 
1193f4a2713aSLionel Sambuc     setLibcallName(RTLIB::UINTTOFP_I32_F64, "__hexagon_floatunsidf");
1194f4a2713aSLionel Sambuc     setLibcallName(RTLIB::SINTTOFP_I32_F64, "__hexagon_floatsidf");
1195f4a2713aSLionel Sambuc 
1196f4a2713aSLionel Sambuc     setLibcallName(RTLIB::FPTOUINT_F32_I32, "__hexagon_fixunssfsi");
1197f4a2713aSLionel Sambuc     setLibcallName(RTLIB::FPTOUINT_F32_I64, "__hexagon_fixunssfdi");
1198f4a2713aSLionel Sambuc 
1199f4a2713aSLionel Sambuc     setLibcallName(RTLIB::FPTOSINT_F64_I64, "__hexagon_fixdfdi");
1200f4a2713aSLionel Sambuc     setLibcallName(RTLIB::FPTOSINT_F32_I64, "__hexagon_fixsfdi");
1201f4a2713aSLionel Sambuc 
1202f4a2713aSLionel Sambuc     setLibcallName(RTLIB::FPTOUINT_F64_I32, "__hexagon_fixunsdfsi");
1203f4a2713aSLionel Sambuc     setLibcallName(RTLIB::FPTOUINT_F64_I64, "__hexagon_fixunsdfdi");
1204f4a2713aSLionel Sambuc 
1205f4a2713aSLionel Sambuc     setLibcallName(RTLIB::ADD_F64, "__hexagon_adddf3");
1206f4a2713aSLionel Sambuc     setOperationAction(ISD::FADD, MVT::f64, Expand);
1207f4a2713aSLionel Sambuc 
1208f4a2713aSLionel Sambuc     setLibcallName(RTLIB::ADD_F32, "__hexagon_addsf3");
1209f4a2713aSLionel Sambuc     setOperationAction(ISD::FADD, MVT::f32, Expand);
1210f4a2713aSLionel Sambuc 
1211f4a2713aSLionel Sambuc     setLibcallName(RTLIB::FPEXT_F32_F64, "__hexagon_extendsfdf2");
1212f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_EXTEND, MVT::f32, Expand);
1213f4a2713aSLionel Sambuc 
1214f4a2713aSLionel Sambuc     setLibcallName(RTLIB::OEQ_F32, "__hexagon_eqsf2");
1215f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand);
1216f4a2713aSLionel Sambuc 
1217f4a2713aSLionel Sambuc     setLibcallName(RTLIB::OEQ_F64, "__hexagon_eqdf2");
1218f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand);
1219f4a2713aSLionel Sambuc 
1220f4a2713aSLionel Sambuc     setLibcallName(RTLIB::OGE_F32, "__hexagon_gesf2");
1221f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOGE, MVT::f32, Expand);
1222f4a2713aSLionel Sambuc 
1223f4a2713aSLionel Sambuc     setLibcallName(RTLIB::OGE_F64, "__hexagon_gedf2");
1224f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOGE, MVT::f64, Expand);
1225f4a2713aSLionel Sambuc 
1226f4a2713aSLionel Sambuc     setLibcallName(RTLIB::OGT_F32, "__hexagon_gtsf2");
1227f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOGT, MVT::f32, Expand);
1228f4a2713aSLionel Sambuc 
1229f4a2713aSLionel Sambuc     setLibcallName(RTLIB::OGT_F64, "__hexagon_gtdf2");
1230f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOGT, MVT::f64, Expand);
1231f4a2713aSLionel Sambuc 
1232f4a2713aSLionel Sambuc     setLibcallName(RTLIB::FPTOSINT_F64_I32, "__hexagon_fixdfsi");
1233f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_SINT, MVT::f64, Expand);
1234f4a2713aSLionel Sambuc 
1235f4a2713aSLionel Sambuc     setLibcallName(RTLIB::FPTOSINT_F32_I32, "__hexagon_fixsfsi");
1236f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_TO_SINT, MVT::f32, Expand);
1237f4a2713aSLionel Sambuc 
1238f4a2713aSLionel Sambuc     setLibcallName(RTLIB::OLE_F64, "__hexagon_ledf2");
1239f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOLE, MVT::f64, Expand);
1240f4a2713aSLionel Sambuc 
1241f4a2713aSLionel Sambuc     setLibcallName(RTLIB::OLE_F32, "__hexagon_lesf2");
1242f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOLE, MVT::f32, Expand);
1243f4a2713aSLionel Sambuc 
1244f4a2713aSLionel Sambuc     setLibcallName(RTLIB::OLT_F64, "__hexagon_ltdf2");
1245f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOLT, MVT::f64, Expand);
1246f4a2713aSLionel Sambuc 
1247f4a2713aSLionel Sambuc     setLibcallName(RTLIB::OLT_F32, "__hexagon_ltsf2");
1248f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETOLT, MVT::f32, Expand);
1249f4a2713aSLionel Sambuc 
1250f4a2713aSLionel Sambuc     setLibcallName(RTLIB::MUL_F64, "__hexagon_muldf3");
1251f4a2713aSLionel Sambuc     setOperationAction(ISD::FMUL, MVT::f64, Expand);
1252f4a2713aSLionel Sambuc 
1253f4a2713aSLionel Sambuc     setLibcallName(RTLIB::MUL_F32, "__hexagon_mulsf3");
1254f4a2713aSLionel Sambuc     setOperationAction(ISD::MUL, MVT::f32, Expand);
1255f4a2713aSLionel Sambuc 
1256f4a2713aSLionel Sambuc     setLibcallName(RTLIB::UNE_F64, "__hexagon_nedf2");
1257f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETUNE, MVT::f64, Expand);
1258f4a2713aSLionel Sambuc 
1259f4a2713aSLionel Sambuc     setLibcallName(RTLIB::UNE_F32, "__hexagon_nesf2");
1260f4a2713aSLionel Sambuc 
1261f4a2713aSLionel Sambuc     setLibcallName(RTLIB::SUB_F64, "__hexagon_subdf3");
1262f4a2713aSLionel Sambuc     setOperationAction(ISD::SUB, MVT::f64, Expand);
1263f4a2713aSLionel Sambuc 
1264f4a2713aSLionel Sambuc     setLibcallName(RTLIB::SUB_F32, "__hexagon_subsf3");
1265f4a2713aSLionel Sambuc     setOperationAction(ISD::SUB, MVT::f32, Expand);
1266f4a2713aSLionel Sambuc 
1267f4a2713aSLionel Sambuc     setLibcallName(RTLIB::FPROUND_F64_F32, "__hexagon_truncdfsf2");
1268f4a2713aSLionel Sambuc     setOperationAction(ISD::FP_ROUND, MVT::f64, Expand);
1269f4a2713aSLionel Sambuc 
1270f4a2713aSLionel Sambuc     setLibcallName(RTLIB::UO_F64, "__hexagon_unorddf2");
1271f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETUO, MVT::f64, Expand);
1272f4a2713aSLionel Sambuc 
1273f4a2713aSLionel Sambuc     setLibcallName(RTLIB::O_F64, "__hexagon_unorddf2");
1274f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETO, MVT::f64, Expand);
1275f4a2713aSLionel Sambuc 
1276f4a2713aSLionel Sambuc     setLibcallName(RTLIB::O_F32, "__hexagon_unordsf2");
1277f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETO, MVT::f32, Expand);
1278f4a2713aSLionel Sambuc 
1279f4a2713aSLionel Sambuc     setLibcallName(RTLIB::UO_F32, "__hexagon_unordsf2");
1280f4a2713aSLionel Sambuc     setCondCodeAction(ISD::SETUO, MVT::f32, Expand);
1281f4a2713aSLionel Sambuc 
1282f4a2713aSLionel Sambuc     setOperationAction(ISD::FABS, MVT::f32, Expand);
1283f4a2713aSLionel Sambuc     setOperationAction(ISD::FABS, MVT::f64, Expand);
1284f4a2713aSLionel Sambuc     setOperationAction(ISD::FNEG, MVT::f32, Expand);
1285f4a2713aSLionel Sambuc     setOperationAction(ISD::FNEG, MVT::f64, Expand);
1286f4a2713aSLionel Sambuc   }
1287f4a2713aSLionel Sambuc 
1288f4a2713aSLionel Sambuc   setLibcallName(RTLIB::SREM_I32, "__hexagon_modsi3");
1289f4a2713aSLionel Sambuc   setOperationAction(ISD::SREM, MVT::i32, Expand);
1290f4a2713aSLionel Sambuc 
1291f4a2713aSLionel Sambuc   setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal);
1292f4a2713aSLionel Sambuc   setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal);
1293f4a2713aSLionel Sambuc   setIndexedLoadAction(ISD::POST_INC, MVT::i32, Legal);
1294f4a2713aSLionel Sambuc   setIndexedLoadAction(ISD::POST_INC, MVT::i64, Legal);
1295f4a2713aSLionel Sambuc 
1296f4a2713aSLionel Sambuc   setIndexedStoreAction(ISD::POST_INC, MVT::i8, Legal);
1297f4a2713aSLionel Sambuc   setIndexedStoreAction(ISD::POST_INC, MVT::i16, Legal);
1298f4a2713aSLionel Sambuc   setIndexedStoreAction(ISD::POST_INC, MVT::i32, Legal);
1299f4a2713aSLionel Sambuc   setIndexedStoreAction(ISD::POST_INC, MVT::i64, Legal);
1300f4a2713aSLionel Sambuc 
1301f4a2713aSLionel Sambuc   setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
1302f4a2713aSLionel Sambuc 
1303f4a2713aSLionel Sambuc   // Turn FP extload into load/fextend.
1304*0a6a1f1dSLionel Sambuc   for (MVT VT : MVT::fp_valuetypes())
1305*0a6a1f1dSLionel Sambuc     setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand);
1306f4a2713aSLionel Sambuc   // Hexagon has a i1 sign extending load.
1307*0a6a1f1dSLionel Sambuc   for (MVT VT : MVT::integer_valuetypes())
1308*0a6a1f1dSLionel Sambuc     setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Expand);
1309f4a2713aSLionel Sambuc   // Turn FP truncstore into trunc + store.
1310f4a2713aSLionel Sambuc   setTruncStoreAction(MVT::f64, MVT::f32, Expand);
1311f4a2713aSLionel Sambuc 
1312f4a2713aSLionel Sambuc   // Custom legalize GlobalAddress nodes into CONST32.
1313f4a2713aSLionel Sambuc   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
1314f4a2713aSLionel Sambuc   setOperationAction(ISD::GlobalAddress, MVT::i8, Custom);
1315f4a2713aSLionel Sambuc   setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
1316f4a2713aSLionel Sambuc   // Truncate action?
1317f4a2713aSLionel Sambuc   setOperationAction(ISD::TRUNCATE, MVT::i64, Expand);
1318f4a2713aSLionel Sambuc 
1319f4a2713aSLionel Sambuc   // Hexagon doesn't have sext_inreg, replace them with shl/sra.
1320f4a2713aSLionel Sambuc   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
1321f4a2713aSLionel Sambuc 
1322f4a2713aSLionel Sambuc   // Hexagon has no REM or DIVREM operations.
1323f4a2713aSLionel Sambuc   setOperationAction(ISD::UREM, MVT::i32, Expand);
1324f4a2713aSLionel Sambuc   setOperationAction(ISD::SREM, MVT::i32, Expand);
1325f4a2713aSLionel Sambuc   setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
1326f4a2713aSLionel Sambuc   setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
1327f4a2713aSLionel Sambuc   setOperationAction(ISD::SREM, MVT::i64, Expand);
1328f4a2713aSLionel Sambuc   setOperationAction(ISD::SDIVREM, MVT::i64, Expand);
1329f4a2713aSLionel Sambuc   setOperationAction(ISD::UDIVREM, MVT::i64, Expand);
1330f4a2713aSLionel Sambuc 
1331f4a2713aSLionel Sambuc   setOperationAction(ISD::BSWAP, MVT::i64, Expand);
1332f4a2713aSLionel Sambuc 
1333f4a2713aSLionel Sambuc   // Lower SELECT_CC to SETCC and SELECT.
1334*0a6a1f1dSLionel Sambuc   setOperationAction(ISD::SELECT_CC, MVT::i1, Expand);
1335*0a6a1f1dSLionel Sambuc   setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);
1336*0a6a1f1dSLionel Sambuc   setOperationAction(ISD::SELECT_CC, MVT::i64, Expand);
1337f4a2713aSLionel Sambuc 
1338*0a6a1f1dSLionel Sambuc   if (Subtarget.hasV5TOps()) {
1339f4a2713aSLionel Sambuc 
1340f4a2713aSLionel Sambuc     // We need to make the operation type of SELECT node to be Custom,
1341f4a2713aSLionel Sambuc     // such that we don't go into the infinite loop of
1342f4a2713aSLionel Sambuc     // select ->  setcc -> select_cc -> select loop.
1343f4a2713aSLionel Sambuc     setOperationAction(ISD::SELECT, MVT::f32, Custom);
1344f4a2713aSLionel Sambuc     setOperationAction(ISD::SELECT, MVT::f64, Custom);
1345f4a2713aSLionel Sambuc 
1346f4a2713aSLionel Sambuc     setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
1347f4a2713aSLionel Sambuc     setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
1348f4a2713aSLionel Sambuc 
1349f4a2713aSLionel Sambuc   } else {
1350f4a2713aSLionel Sambuc 
1351f4a2713aSLionel Sambuc     // Hexagon has no select or setcc: expand to SELECT_CC.
1352f4a2713aSLionel Sambuc     setOperationAction(ISD::SELECT, MVT::f32, Expand);
1353f4a2713aSLionel Sambuc     setOperationAction(ISD::SELECT, MVT::f64, Expand);
1354f4a2713aSLionel Sambuc   }
1355f4a2713aSLionel Sambuc 
1356f4a2713aSLionel Sambuc   if (EmitJumpTables) {
1357f4a2713aSLionel Sambuc     setOperationAction(ISD::BR_JT, MVT::Other, Custom);
1358f4a2713aSLionel Sambuc   } else {
1359f4a2713aSLionel Sambuc     setOperationAction(ISD::BR_JT, MVT::Other, Expand);
1360f4a2713aSLionel Sambuc   }
1361f4a2713aSLionel Sambuc   // Increase jump tables cutover to 5, was 4.
1362f4a2713aSLionel Sambuc   setMinimumJumpTableEntries(5);
1363f4a2713aSLionel Sambuc 
1364f4a2713aSLionel Sambuc   setOperationAction(ISD::BR_CC, MVT::f32, Expand);
1365f4a2713aSLionel Sambuc   setOperationAction(ISD::BR_CC, MVT::f64, Expand);
1366f4a2713aSLionel Sambuc   setOperationAction(ISD::BR_CC, MVT::i1, Expand);
1367f4a2713aSLionel Sambuc   setOperationAction(ISD::BR_CC, MVT::i32, Expand);
1368f4a2713aSLionel Sambuc   setOperationAction(ISD::BR_CC, MVT::i64, Expand);
1369f4a2713aSLionel Sambuc 
1370f4a2713aSLionel Sambuc   setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
1371f4a2713aSLionel Sambuc 
1372f4a2713aSLionel Sambuc   setOperationAction(ISD::FSIN, MVT::f64, Expand);
1373f4a2713aSLionel Sambuc   setOperationAction(ISD::FCOS, MVT::f64, Expand);
1374f4a2713aSLionel Sambuc   setOperationAction(ISD::FREM, MVT::f64, Expand);
1375f4a2713aSLionel Sambuc   setOperationAction(ISD::FSIN, MVT::f32, Expand);
1376f4a2713aSLionel Sambuc   setOperationAction(ISD::FCOS, MVT::f32, Expand);
1377f4a2713aSLionel Sambuc   setOperationAction(ISD::FREM, MVT::f32, Expand);
1378f4a2713aSLionel Sambuc   setOperationAction(ISD::FSINCOS, MVT::f64, Expand);
1379f4a2713aSLionel Sambuc   setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
1380f4a2713aSLionel Sambuc 
1381f4a2713aSLionel Sambuc   // In V4, we have double word add/sub with carry. The problem with
1382f4a2713aSLionel Sambuc   // modelling this instruction is that it produces 2 results - Rdd and Px.
1383f4a2713aSLionel Sambuc   // To model update of Px, we will have to use Defs[p0..p3] which will
1384f4a2713aSLionel Sambuc   // cause any predicate live range to spill. So, we pretend we dont't
1385f4a2713aSLionel Sambuc   // have these instructions.
1386f4a2713aSLionel Sambuc   setOperationAction(ISD::ADDE, MVT::i8, Expand);
1387f4a2713aSLionel Sambuc   setOperationAction(ISD::ADDE, MVT::i16, Expand);
1388f4a2713aSLionel Sambuc   setOperationAction(ISD::ADDE, MVT::i32, Expand);
1389f4a2713aSLionel Sambuc   setOperationAction(ISD::ADDE, MVT::i64, Expand);
1390f4a2713aSLionel Sambuc   setOperationAction(ISD::SUBE, MVT::i8, Expand);
1391f4a2713aSLionel Sambuc   setOperationAction(ISD::SUBE, MVT::i16, Expand);
1392f4a2713aSLionel Sambuc   setOperationAction(ISD::SUBE, MVT::i32, Expand);
1393f4a2713aSLionel Sambuc   setOperationAction(ISD::SUBE, MVT::i64, Expand);
1394f4a2713aSLionel Sambuc   setOperationAction(ISD::ADDC, MVT::i8, Expand);
1395f4a2713aSLionel Sambuc   setOperationAction(ISD::ADDC, MVT::i16, Expand);
1396f4a2713aSLionel Sambuc   setOperationAction(ISD::ADDC, MVT::i32, Expand);
1397f4a2713aSLionel Sambuc   setOperationAction(ISD::ADDC, MVT::i64, Expand);
1398f4a2713aSLionel Sambuc   setOperationAction(ISD::SUBC, MVT::i8, Expand);
1399f4a2713aSLionel Sambuc   setOperationAction(ISD::SUBC, MVT::i16, Expand);
1400f4a2713aSLionel Sambuc   setOperationAction(ISD::SUBC, MVT::i32, Expand);
1401f4a2713aSLionel Sambuc   setOperationAction(ISD::SUBC, MVT::i64, Expand);
1402f4a2713aSLionel Sambuc 
1403f4a2713aSLionel Sambuc   setOperationAction(ISD::CTPOP, MVT::i32, Expand);
1404f4a2713aSLionel Sambuc   setOperationAction(ISD::CTPOP, MVT::i64, Expand);
1405f4a2713aSLionel Sambuc   setOperationAction(ISD::CTTZ, MVT::i32, Expand);
1406f4a2713aSLionel Sambuc   setOperationAction(ISD::CTTZ, MVT::i64, Expand);
1407f4a2713aSLionel Sambuc   setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand);
1408f4a2713aSLionel Sambuc   setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand);
1409f4a2713aSLionel Sambuc   setOperationAction(ISD::CTLZ, MVT::i32, Expand);
1410f4a2713aSLionel Sambuc   setOperationAction(ISD::CTLZ, MVT::i64, Expand);
1411f4a2713aSLionel Sambuc   setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand);
1412f4a2713aSLionel Sambuc   setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand);
1413f4a2713aSLionel Sambuc   setOperationAction(ISD::ROTL, MVT::i32, Expand);
1414f4a2713aSLionel Sambuc   setOperationAction(ISD::ROTR, MVT::i32, Expand);
1415f4a2713aSLionel Sambuc   setOperationAction(ISD::BSWAP, MVT::i32, Expand);
1416f4a2713aSLionel Sambuc   setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
1417f4a2713aSLionel Sambuc   setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
1418f4a2713aSLionel Sambuc   setOperationAction(ISD::FPOW, MVT::f64, Expand);
1419f4a2713aSLionel Sambuc   setOperationAction(ISD::FPOW, MVT::f32, Expand);
1420f4a2713aSLionel Sambuc 
1421f4a2713aSLionel Sambuc   setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
1422f4a2713aSLionel Sambuc   setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
1423f4a2713aSLionel Sambuc   setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
1424f4a2713aSLionel Sambuc 
1425f4a2713aSLionel Sambuc   setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
1426f4a2713aSLionel Sambuc   setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
1427f4a2713aSLionel Sambuc 
1428f4a2713aSLionel Sambuc   setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
1429f4a2713aSLionel Sambuc   setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
1430f4a2713aSLionel Sambuc 
1431f4a2713aSLionel Sambuc   setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);
1432f4a2713aSLionel Sambuc 
1433*0a6a1f1dSLionel Sambuc   if (Subtarget.isSubtargetV2()) {
1434f4a2713aSLionel Sambuc     setExceptionPointerRegister(Hexagon::R20);
1435f4a2713aSLionel Sambuc     setExceptionSelectorRegister(Hexagon::R21);
1436f4a2713aSLionel Sambuc   } else {
1437f4a2713aSLionel Sambuc     setExceptionPointerRegister(Hexagon::R0);
1438f4a2713aSLionel Sambuc     setExceptionSelectorRegister(Hexagon::R1);
1439f4a2713aSLionel Sambuc   }
1440f4a2713aSLionel Sambuc 
1441f4a2713aSLionel Sambuc   // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
1442f4a2713aSLionel Sambuc   setOperationAction(ISD::VASTART, MVT::Other, Custom);
1443f4a2713aSLionel Sambuc 
1444f4a2713aSLionel Sambuc   // Use the default implementation.
1445f4a2713aSLionel Sambuc   setOperationAction(ISD::VAARG, MVT::Other, Expand);
1446f4a2713aSLionel Sambuc   setOperationAction(ISD::VACOPY, MVT::Other, Expand);
1447f4a2713aSLionel Sambuc   setOperationAction(ISD::VAEND, MVT::Other, Expand);
1448f4a2713aSLionel Sambuc   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
1449f4a2713aSLionel Sambuc   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
1450f4a2713aSLionel Sambuc 
1451f4a2713aSLionel Sambuc   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
1452f4a2713aSLionel Sambuc   setOperationAction(ISD::INLINEASM, MVT::Other, Custom);
1453f4a2713aSLionel Sambuc 
1454f4a2713aSLionel Sambuc   setMinFunctionAlignment(2);
1455f4a2713aSLionel Sambuc 
1456f4a2713aSLionel Sambuc   // Needed for DYNAMIC_STACKALLOC expansion.
1457*0a6a1f1dSLionel Sambuc   const HexagonRegisterInfo *QRI = static_cast<const HexagonRegisterInfo *>(
1458*0a6a1f1dSLionel Sambuc       TM.getSubtargetImpl()->getRegisterInfo());
1459*0a6a1f1dSLionel Sambuc   setStackPointerRegisterToSaveRestore(QRI->getStackRegister());
1460f4a2713aSLionel Sambuc   setSchedulingPreference(Sched::VLIW);
1461f4a2713aSLionel Sambuc }
1462f4a2713aSLionel Sambuc 
1463f4a2713aSLionel Sambuc const char*
getTargetNodeName(unsigned Opcode) const1464f4a2713aSLionel Sambuc HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {
1465f4a2713aSLionel Sambuc   switch (Opcode) {
1466*0a6a1f1dSLionel Sambuc     default: return nullptr;
1467f4a2713aSLionel Sambuc     case HexagonISD::CONST32:     return "HexagonISD::CONST32";
1468f4a2713aSLionel Sambuc     case HexagonISD::CONST32_GP: return "HexagonISD::CONST32_GP";
1469f4a2713aSLionel Sambuc     case HexagonISD::CONST32_Int_Real: return "HexagonISD::CONST32_Int_Real";
1470f4a2713aSLionel Sambuc     case HexagonISD::ADJDYNALLOC: return "HexagonISD::ADJDYNALLOC";
1471f4a2713aSLionel Sambuc     case HexagonISD::CMPICC:      return "HexagonISD::CMPICC";
1472f4a2713aSLionel Sambuc     case HexagonISD::CMPFCC:      return "HexagonISD::CMPFCC";
1473f4a2713aSLionel Sambuc     case HexagonISD::BRICC:       return "HexagonISD::BRICC";
1474f4a2713aSLionel Sambuc     case HexagonISD::BRFCC:       return "HexagonISD::BRFCC";
1475f4a2713aSLionel Sambuc     case HexagonISD::SELECT_ICC:  return "HexagonISD::SELECT_ICC";
1476f4a2713aSLionel Sambuc     case HexagonISD::SELECT_FCC:  return "HexagonISD::SELECT_FCC";
1477f4a2713aSLionel Sambuc     case HexagonISD::Hi:          return "HexagonISD::Hi";
1478f4a2713aSLionel Sambuc     case HexagonISD::Lo:          return "HexagonISD::Lo";
1479f4a2713aSLionel Sambuc     case HexagonISD::FTOI:        return "HexagonISD::FTOI";
1480f4a2713aSLionel Sambuc     case HexagonISD::ITOF:        return "HexagonISD::ITOF";
1481f4a2713aSLionel Sambuc     case HexagonISD::CALL:        return "HexagonISD::CALL";
1482f4a2713aSLionel Sambuc     case HexagonISD::RET_FLAG:    return "HexagonISD::RET_FLAG";
1483f4a2713aSLionel Sambuc     case HexagonISD::BR_JT:       return "HexagonISD::BR_JT";
1484f4a2713aSLionel Sambuc     case HexagonISD::TC_RETURN:   return "HexagonISD::TC_RETURN";
1485f4a2713aSLionel Sambuc   case HexagonISD::EH_RETURN: return "HexagonISD::EH_RETURN";
1486f4a2713aSLionel Sambuc   }
1487f4a2713aSLionel Sambuc }
1488f4a2713aSLionel Sambuc 
1489f4a2713aSLionel Sambuc bool
isTruncateFree(Type * Ty1,Type * Ty2) const1490f4a2713aSLionel Sambuc HexagonTargetLowering::isTruncateFree(Type *Ty1, Type *Ty2) const {
1491f4a2713aSLionel Sambuc   EVT MTy1 = EVT::getEVT(Ty1);
1492f4a2713aSLionel Sambuc   EVT MTy2 = EVT::getEVT(Ty2);
1493f4a2713aSLionel Sambuc   if (!MTy1.isSimple() || !MTy2.isSimple()) {
1494f4a2713aSLionel Sambuc     return false;
1495f4a2713aSLionel Sambuc   }
1496f4a2713aSLionel Sambuc   return ((MTy1.getSimpleVT() == MVT::i64) && (MTy2.getSimpleVT() == MVT::i32));
1497f4a2713aSLionel Sambuc }
1498f4a2713aSLionel Sambuc 
isTruncateFree(EVT VT1,EVT VT2) const1499f4a2713aSLionel Sambuc bool HexagonTargetLowering::isTruncateFree(EVT VT1, EVT VT2) const {
1500f4a2713aSLionel Sambuc   if (!VT1.isSimple() || !VT2.isSimple()) {
1501f4a2713aSLionel Sambuc     return false;
1502f4a2713aSLionel Sambuc   }
1503f4a2713aSLionel Sambuc   return ((VT1.getSimpleVT() == MVT::i64) && (VT2.getSimpleVT() == MVT::i32));
1504f4a2713aSLionel Sambuc }
1505f4a2713aSLionel Sambuc 
1506f4a2713aSLionel Sambuc bool
allowTruncateForTailCall(Type * Ty1,Type * Ty2) const1507f4a2713aSLionel Sambuc HexagonTargetLowering::allowTruncateForTailCall(Type *Ty1, Type *Ty2) const {
1508f4a2713aSLionel Sambuc   // Assuming the caller does not have either a signext or zeroext modifier, and
1509f4a2713aSLionel Sambuc   // only one value is accepted, any reasonable truncation is allowed.
1510f4a2713aSLionel Sambuc   if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())
1511f4a2713aSLionel Sambuc     return false;
1512f4a2713aSLionel Sambuc 
1513f4a2713aSLionel Sambuc   // FIXME: in principle up to 64-bit could be made safe, but it would be very
1514f4a2713aSLionel Sambuc   // fragile at the moment: any support for multiple value returns would be
1515f4a2713aSLionel Sambuc   // liable to disallow tail calls involving i64 -> iN truncation in many cases.
1516f4a2713aSLionel Sambuc   return Ty1->getPrimitiveSizeInBits() <= 32;
1517f4a2713aSLionel Sambuc }
1518f4a2713aSLionel Sambuc 
1519f4a2713aSLionel Sambuc SDValue
LowerEH_RETURN(SDValue Op,SelectionDAG & DAG) const1520f4a2713aSLionel Sambuc HexagonTargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
1521f4a2713aSLionel Sambuc   SDValue Chain     = Op.getOperand(0);
1522f4a2713aSLionel Sambuc   SDValue Offset    = Op.getOperand(1);
1523f4a2713aSLionel Sambuc   SDValue Handler   = Op.getOperand(2);
1524f4a2713aSLionel Sambuc   SDLoc dl(Op);
1525f4a2713aSLionel Sambuc 
1526f4a2713aSLionel Sambuc   // Mark function as containing a call to EH_RETURN.
1527f4a2713aSLionel Sambuc   HexagonMachineFunctionInfo *FuncInfo =
1528f4a2713aSLionel Sambuc     DAG.getMachineFunction().getInfo<HexagonMachineFunctionInfo>();
1529f4a2713aSLionel Sambuc   FuncInfo->setHasEHReturn();
1530f4a2713aSLionel Sambuc 
1531f4a2713aSLionel Sambuc   unsigned OffsetReg = Hexagon::R28;
1532f4a2713aSLionel Sambuc 
1533f4a2713aSLionel Sambuc   SDValue StoreAddr = DAG.getNode(ISD::ADD, dl, getPointerTy(),
1534f4a2713aSLionel Sambuc                                   DAG.getRegister(Hexagon::R30, getPointerTy()),
1535f4a2713aSLionel Sambuc                                   DAG.getIntPtrConstant(4));
1536f4a2713aSLionel Sambuc   Chain = DAG.getStore(Chain, dl, Handler, StoreAddr, MachinePointerInfo(),
1537f4a2713aSLionel Sambuc                        false, false, 0);
1538f4a2713aSLionel Sambuc   Chain = DAG.getCopyToReg(Chain, dl, OffsetReg, Offset);
1539f4a2713aSLionel Sambuc 
1540f4a2713aSLionel Sambuc   // Not needed we already use it as explict input to EH_RETURN.
1541f4a2713aSLionel Sambuc   // MF.getRegInfo().addLiveOut(OffsetReg);
1542f4a2713aSLionel Sambuc 
1543f4a2713aSLionel Sambuc   return DAG.getNode(HexagonISD::EH_RETURN, dl, MVT::Other, Chain);
1544f4a2713aSLionel Sambuc }
1545f4a2713aSLionel Sambuc 
1546f4a2713aSLionel Sambuc SDValue
LowerOperation(SDValue Op,SelectionDAG & DAG) const1547f4a2713aSLionel Sambuc HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
1548f4a2713aSLionel Sambuc   switch (Op.getOpcode()) {
1549f4a2713aSLionel Sambuc     default: llvm_unreachable("Should not custom lower this!");
1550f4a2713aSLionel Sambuc     case ISD::ConstantPool:       return LowerConstantPool(Op, DAG);
1551f4a2713aSLionel Sambuc     case ISD::EH_RETURN:          return LowerEH_RETURN(Op, DAG);
1552f4a2713aSLionel Sambuc       // Frame & Return address.  Currently unimplemented.
1553f4a2713aSLionel Sambuc     case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG);
1554f4a2713aSLionel Sambuc     case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG);
1555f4a2713aSLionel Sambuc     case ISD::GlobalTLSAddress:
1556f4a2713aSLionel Sambuc                           llvm_unreachable("TLS not implemented for Hexagon.");
1557f4a2713aSLionel Sambuc     case ISD::ATOMIC_FENCE:       return LowerATOMIC_FENCE(Op, DAG);
1558f4a2713aSLionel Sambuc     case ISD::GlobalAddress:      return LowerGLOBALADDRESS(Op, DAG);
1559f4a2713aSLionel Sambuc     case ISD::BlockAddress:       return LowerBlockAddress(Op, DAG);
1560f4a2713aSLionel Sambuc     case ISD::VASTART:            return LowerVASTART(Op, DAG);
1561f4a2713aSLionel Sambuc     case ISD::BR_JT:              return LowerBR_JT(Op, DAG);
1562f4a2713aSLionel Sambuc 
1563f4a2713aSLionel Sambuc     case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
1564f4a2713aSLionel Sambuc     case ISD::SELECT:             return Op;
1565f4a2713aSLionel Sambuc     case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
1566f4a2713aSLionel Sambuc     case ISD::INLINEASM:          return LowerINLINEASM(Op, DAG);
1567f4a2713aSLionel Sambuc 
1568f4a2713aSLionel Sambuc   }
1569f4a2713aSLionel Sambuc }
1570f4a2713aSLionel Sambuc 
1571f4a2713aSLionel Sambuc 
1572f4a2713aSLionel Sambuc 
1573f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
1574f4a2713aSLionel Sambuc //                           Hexagon Scheduler Hooks
1575f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
1576f4a2713aSLionel Sambuc MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr * MI,MachineBasicBlock * BB) const1577f4a2713aSLionel Sambuc HexagonTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
1578f4a2713aSLionel Sambuc                                                    MachineBasicBlock *BB)
1579f4a2713aSLionel Sambuc const {
1580f4a2713aSLionel Sambuc   switch (MI->getOpcode()) {
1581f4a2713aSLionel Sambuc     case Hexagon::ADJDYNALLOC: {
1582f4a2713aSLionel Sambuc       MachineFunction *MF = BB->getParent();
1583f4a2713aSLionel Sambuc       HexagonMachineFunctionInfo *FuncInfo =
1584f4a2713aSLionel Sambuc         MF->getInfo<HexagonMachineFunctionInfo>();
1585f4a2713aSLionel Sambuc       FuncInfo->addAllocaAdjustInst(MI);
1586f4a2713aSLionel Sambuc       return BB;
1587f4a2713aSLionel Sambuc     }
1588f4a2713aSLionel Sambuc     default: llvm_unreachable("Unexpected instr type to insert");
1589f4a2713aSLionel Sambuc   } // switch
1590f4a2713aSLionel Sambuc }
1591f4a2713aSLionel Sambuc 
1592f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
1593f4a2713aSLionel Sambuc // Inline Assembly Support
1594f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
1595f4a2713aSLionel Sambuc 
1596f4a2713aSLionel Sambuc std::pair<unsigned, const TargetRegisterClass*>
getRegForInlineAsmConstraint(const std::string & Constraint,MVT VT) const1597f4a2713aSLionel Sambuc HexagonTargetLowering::getRegForInlineAsmConstraint(const
1598f4a2713aSLionel Sambuc                                                     std::string &Constraint,
1599f4a2713aSLionel Sambuc                                                     MVT VT) const {
1600f4a2713aSLionel Sambuc   if (Constraint.size() == 1) {
1601f4a2713aSLionel Sambuc     switch (Constraint[0]) {
1602f4a2713aSLionel Sambuc     case 'r':   // R0-R31
1603f4a2713aSLionel Sambuc        switch (VT.SimpleTy) {
1604f4a2713aSLionel Sambuc        default:
1605f4a2713aSLionel Sambuc          llvm_unreachable("getRegForInlineAsmConstraint Unhandled data type");
1606f4a2713aSLionel Sambuc        case MVT::i32:
1607f4a2713aSLionel Sambuc        case MVT::i16:
1608f4a2713aSLionel Sambuc        case MVT::i8:
1609f4a2713aSLionel Sambuc        case MVT::f32:
1610f4a2713aSLionel Sambuc          return std::make_pair(0U, &Hexagon::IntRegsRegClass);
1611f4a2713aSLionel Sambuc        case MVT::i64:
1612f4a2713aSLionel Sambuc        case MVT::f64:
1613f4a2713aSLionel Sambuc          return std::make_pair(0U, &Hexagon::DoubleRegsRegClass);
1614f4a2713aSLionel Sambuc       }
1615f4a2713aSLionel Sambuc     default:
1616f4a2713aSLionel Sambuc       llvm_unreachable("Unknown asm register class");
1617f4a2713aSLionel Sambuc     }
1618f4a2713aSLionel Sambuc   }
1619f4a2713aSLionel Sambuc 
1620f4a2713aSLionel Sambuc   return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
1621f4a2713aSLionel Sambuc }
1622f4a2713aSLionel Sambuc 
1623f4a2713aSLionel Sambuc /// isFPImmLegal - Returns true if the target can instruction select the
1624f4a2713aSLionel Sambuc /// specified FP immediate natively. If false, the legalizer will
1625f4a2713aSLionel Sambuc /// materialize the FP immediate as a load from a constant pool.
isFPImmLegal(const APFloat & Imm,EVT VT) const1626f4a2713aSLionel Sambuc bool HexagonTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
1627*0a6a1f1dSLionel Sambuc   return TM.getSubtarget<HexagonSubtarget>().hasV5TOps();
1628f4a2713aSLionel Sambuc }
1629f4a2713aSLionel Sambuc 
1630f4a2713aSLionel Sambuc /// isLegalAddressingMode - Return true if the addressing mode represented by
1631f4a2713aSLionel Sambuc /// AM is legal for this target, for a load/store of the specified type.
isLegalAddressingMode(const AddrMode & AM,Type * Ty) const1632f4a2713aSLionel Sambuc bool HexagonTargetLowering::isLegalAddressingMode(const AddrMode &AM,
1633f4a2713aSLionel Sambuc                                                   Type *Ty) const {
1634f4a2713aSLionel Sambuc   // Allows a signed-extended 11-bit immediate field.
1635f4a2713aSLionel Sambuc   if (AM.BaseOffs <= -(1LL << 13) || AM.BaseOffs >= (1LL << 13)-1) {
1636f4a2713aSLionel Sambuc     return false;
1637f4a2713aSLionel Sambuc   }
1638f4a2713aSLionel Sambuc 
1639f4a2713aSLionel Sambuc   // No global is ever allowed as a base.
1640f4a2713aSLionel Sambuc   if (AM.BaseGV) {
1641f4a2713aSLionel Sambuc     return false;
1642f4a2713aSLionel Sambuc   }
1643f4a2713aSLionel Sambuc 
1644f4a2713aSLionel Sambuc   int Scale = AM.Scale;
1645f4a2713aSLionel Sambuc   if (Scale < 0) Scale = -Scale;
1646f4a2713aSLionel Sambuc   switch (Scale) {
1647f4a2713aSLionel Sambuc   case 0:  // No scale reg, "r+i", "r", or just "i".
1648f4a2713aSLionel Sambuc     break;
1649f4a2713aSLionel Sambuc   default: // No scaled addressing mode.
1650f4a2713aSLionel Sambuc     return false;
1651f4a2713aSLionel Sambuc   }
1652f4a2713aSLionel Sambuc   return true;
1653f4a2713aSLionel Sambuc }
1654f4a2713aSLionel Sambuc 
1655f4a2713aSLionel Sambuc /// isLegalICmpImmediate - Return true if the specified immediate is legal
1656f4a2713aSLionel Sambuc /// icmp immediate, that is the target has icmp instructions which can compare
1657f4a2713aSLionel Sambuc /// a register against the immediate without having to materialize the
1658f4a2713aSLionel Sambuc /// immediate into a register.
isLegalICmpImmediate(int64_t Imm) const1659f4a2713aSLionel Sambuc bool HexagonTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
1660f4a2713aSLionel Sambuc   return Imm >= -512 && Imm <= 511;
1661f4a2713aSLionel Sambuc }
1662f4a2713aSLionel Sambuc 
1663f4a2713aSLionel Sambuc /// IsEligibleForTailCallOptimization - Check whether the call is eligible
1664f4a2713aSLionel Sambuc /// for tail call optimization. Targets which want to do tail call
1665f4a2713aSLionel Sambuc /// optimization should implement this function.
IsEligibleForTailCallOptimization(SDValue Callee,CallingConv::ID CalleeCC,bool isVarArg,bool isCalleeStructRet,bool isCallerStructRet,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SmallVectorImpl<ISD::InputArg> & Ins,SelectionDAG & DAG) const1666f4a2713aSLionel Sambuc bool HexagonTargetLowering::IsEligibleForTailCallOptimization(
1667f4a2713aSLionel Sambuc                                  SDValue Callee,
1668f4a2713aSLionel Sambuc                                  CallingConv::ID CalleeCC,
1669f4a2713aSLionel Sambuc                                  bool isVarArg,
1670f4a2713aSLionel Sambuc                                  bool isCalleeStructRet,
1671f4a2713aSLionel Sambuc                                  bool isCallerStructRet,
1672f4a2713aSLionel Sambuc                                  const SmallVectorImpl<ISD::OutputArg> &Outs,
1673f4a2713aSLionel Sambuc                                  const SmallVectorImpl<SDValue> &OutVals,
1674f4a2713aSLionel Sambuc                                  const SmallVectorImpl<ISD::InputArg> &Ins,
1675f4a2713aSLionel Sambuc                                  SelectionDAG& DAG) const {
1676f4a2713aSLionel Sambuc   const Function *CallerF = DAG.getMachineFunction().getFunction();
1677f4a2713aSLionel Sambuc   CallingConv::ID CallerCC = CallerF->getCallingConv();
1678f4a2713aSLionel Sambuc   bool CCMatch = CallerCC == CalleeCC;
1679f4a2713aSLionel Sambuc 
1680f4a2713aSLionel Sambuc   // ***************************************************************************
1681f4a2713aSLionel Sambuc   //  Look for obvious safe cases to perform tail call optimization that do not
1682f4a2713aSLionel Sambuc   //  require ABI changes.
1683f4a2713aSLionel Sambuc   // ***************************************************************************
1684f4a2713aSLionel Sambuc 
1685f4a2713aSLionel Sambuc   // If this is a tail call via a function pointer, then don't do it!
1686f4a2713aSLionel Sambuc   if (!(dyn_cast<GlobalAddressSDNode>(Callee))
1687f4a2713aSLionel Sambuc       && !(dyn_cast<ExternalSymbolSDNode>(Callee))) {
1688f4a2713aSLionel Sambuc     return false;
1689f4a2713aSLionel Sambuc   }
1690f4a2713aSLionel Sambuc 
1691f4a2713aSLionel Sambuc   // Do not optimize if the calling conventions do not match.
1692f4a2713aSLionel Sambuc   if (!CCMatch)
1693f4a2713aSLionel Sambuc     return false;
1694f4a2713aSLionel Sambuc 
1695f4a2713aSLionel Sambuc   // Do not tail call optimize vararg calls.
1696f4a2713aSLionel Sambuc   if (isVarArg)
1697f4a2713aSLionel Sambuc     return false;
1698f4a2713aSLionel Sambuc 
1699f4a2713aSLionel Sambuc   // Also avoid tail call optimization if either caller or callee uses struct
1700f4a2713aSLionel Sambuc   // return semantics.
1701f4a2713aSLionel Sambuc   if (isCalleeStructRet || isCallerStructRet)
1702f4a2713aSLionel Sambuc     return false;
1703f4a2713aSLionel Sambuc 
1704f4a2713aSLionel Sambuc   // In addition to the cases above, we also disable Tail Call Optimization if
1705f4a2713aSLionel Sambuc   // the calling convention code that at least one outgoing argument needs to
1706f4a2713aSLionel Sambuc   // go on the stack. We cannot check that here because at this point that
1707f4a2713aSLionel Sambuc   // information is not available.
1708f4a2713aSLionel Sambuc   return true;
1709f4a2713aSLionel Sambuc }
1710*0a6a1f1dSLionel Sambuc 
1711*0a6a1f1dSLionel Sambuc // Return true when the given node fits in a positive half word.
isPositiveHalfWord(SDNode * N)1712*0a6a1f1dSLionel Sambuc bool llvm::isPositiveHalfWord(SDNode *N) {
1713*0a6a1f1dSLionel Sambuc   ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N);
1714*0a6a1f1dSLionel Sambuc   if (CN && CN->getSExtValue() > 0 && isInt<16>(CN->getSExtValue()))
1715*0a6a1f1dSLionel Sambuc     return true;
1716*0a6a1f1dSLionel Sambuc 
1717*0a6a1f1dSLionel Sambuc   switch (N->getOpcode()) {
1718*0a6a1f1dSLionel Sambuc   default:
1719*0a6a1f1dSLionel Sambuc     return false;
1720*0a6a1f1dSLionel Sambuc   case ISD::SIGN_EXTEND_INREG:
1721*0a6a1f1dSLionel Sambuc     return true;
1722*0a6a1f1dSLionel Sambuc   }
1723*0a6a1f1dSLionel Sambuc }
1724