xref: /aosp_15_r20/external/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- HexagonISelLowering.cpp - Hexagon DAG Lowering Implementation -----===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the interfaces that Hexagon uses to lower LLVM code
11*9880d681SAndroid Build Coastguard Worker // into a selection DAG.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #include "HexagonISelLowering.h"
16*9880d681SAndroid Build Coastguard Worker #include "HexagonMachineFunctionInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "HexagonSubtarget.h"
18*9880d681SAndroid Build Coastguard Worker #include "HexagonTargetMachine.h"
19*9880d681SAndroid Build Coastguard Worker #include "HexagonTargetObjectFile.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/CallingConvLower.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineJumpTableInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/SelectionDAGISel.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ValueTypes.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/CallingConv.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GlobalAlias.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GlobalVariable.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/InlineAsm.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Intrinsics.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
39*9880d681SAndroid Build Coastguard Worker 
40*9880d681SAndroid Build Coastguard Worker using namespace llvm;
41*9880d681SAndroid Build Coastguard Worker 
42*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "hexagon-lowering"
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> EmitJumpTables("hexagon-emit-jump-tables",
45*9880d681SAndroid Build Coastguard Worker   cl::init(true), cl::Hidden,
46*9880d681SAndroid Build Coastguard Worker   cl::desc("Control jump table emission on Hexagon target"));
47*9880d681SAndroid Build Coastguard Worker 
48*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> EnableHexSDNodeSched("enable-hexagon-sdnode-sched",
49*9880d681SAndroid Build Coastguard Worker   cl::Hidden, cl::ZeroOrMore, cl::init(false),
50*9880d681SAndroid Build Coastguard Worker   cl::desc("Enable Hexagon SDNode scheduling"));
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> EnableFastMath("ffast-math",
53*9880d681SAndroid Build Coastguard Worker   cl::Hidden, cl::ZeroOrMore, cl::init(false),
54*9880d681SAndroid Build Coastguard Worker   cl::desc("Enable Fast Math processing"));
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker static cl::opt<int> MinimumJumpTables("minimum-jump-tables",
57*9880d681SAndroid Build Coastguard Worker   cl::Hidden, cl::ZeroOrMore, cl::init(5),
58*9880d681SAndroid Build Coastguard Worker   cl::desc("Set minimum jump tables"));
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker static cl::opt<int> MaxStoresPerMemcpyCL("max-store-memcpy",
61*9880d681SAndroid Build Coastguard Worker   cl::Hidden, cl::ZeroOrMore, cl::init(6),
62*9880d681SAndroid Build Coastguard Worker   cl::desc("Max #stores to inline memcpy"));
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker static cl::opt<int> MaxStoresPerMemcpyOptSizeCL("max-store-memcpy-Os",
65*9880d681SAndroid Build Coastguard Worker   cl::Hidden, cl::ZeroOrMore, cl::init(4),
66*9880d681SAndroid Build Coastguard Worker   cl::desc("Max #stores to inline memcpy"));
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker static cl::opt<int> MaxStoresPerMemmoveCL("max-store-memmove",
69*9880d681SAndroid Build Coastguard Worker   cl::Hidden, cl::ZeroOrMore, cl::init(6),
70*9880d681SAndroid Build Coastguard Worker   cl::desc("Max #stores to inline memmove"));
71*9880d681SAndroid Build Coastguard Worker 
72*9880d681SAndroid Build Coastguard Worker static cl::opt<int> MaxStoresPerMemmoveOptSizeCL("max-store-memmove-Os",
73*9880d681SAndroid Build Coastguard Worker   cl::Hidden, cl::ZeroOrMore, cl::init(4),
74*9880d681SAndroid Build Coastguard Worker   cl::desc("Max #stores to inline memmove"));
75*9880d681SAndroid Build Coastguard Worker 
76*9880d681SAndroid Build Coastguard Worker static cl::opt<int> MaxStoresPerMemsetCL("max-store-memset",
77*9880d681SAndroid Build Coastguard Worker   cl::Hidden, cl::ZeroOrMore, cl::init(8),
78*9880d681SAndroid Build Coastguard Worker   cl::desc("Max #stores to inline memset"));
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker static cl::opt<int> MaxStoresPerMemsetOptSizeCL("max-store-memset-Os",
81*9880d681SAndroid Build Coastguard Worker   cl::Hidden, cl::ZeroOrMore, cl::init(4),
82*9880d681SAndroid Build Coastguard Worker   cl::desc("Max #stores to inline memset"));
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker 
85*9880d681SAndroid Build Coastguard Worker namespace {
86*9880d681SAndroid Build Coastguard Worker class HexagonCCState : public CCState {
87*9880d681SAndroid Build Coastguard Worker   unsigned NumNamedVarArgParams;
88*9880d681SAndroid Build Coastguard Worker 
89*9880d681SAndroid Build Coastguard Worker public:
HexagonCCState(CallingConv::ID CC,bool isVarArg,MachineFunction & MF,SmallVectorImpl<CCValAssign> & locs,LLVMContext & C,int NumNamedVarArgParams)90*9880d681SAndroid Build Coastguard Worker   HexagonCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
91*9880d681SAndroid Build Coastguard Worker                  SmallVectorImpl<CCValAssign> &locs, LLVMContext &C,
92*9880d681SAndroid Build Coastguard Worker                  int NumNamedVarArgParams)
93*9880d681SAndroid Build Coastguard Worker       : CCState(CC, isVarArg, MF, locs, C),
94*9880d681SAndroid Build Coastguard Worker         NumNamedVarArgParams(NumNamedVarArgParams) {}
95*9880d681SAndroid Build Coastguard Worker 
getNumNamedVarArgParams() const96*9880d681SAndroid Build Coastguard Worker   unsigned getNumNamedVarArgParams() const { return NumNamedVarArgParams; }
97*9880d681SAndroid Build Coastguard Worker };
98*9880d681SAndroid Build Coastguard Worker }
99*9880d681SAndroid Build Coastguard Worker 
100*9880d681SAndroid Build Coastguard Worker // Implement calling convention for Hexagon.
101*9880d681SAndroid Build Coastguard Worker 
102*9880d681SAndroid Build Coastguard Worker static bool IsHvxVectorType(MVT ty);
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker static bool
105*9880d681SAndroid Build Coastguard Worker CC_Hexagon(unsigned ValNo, MVT ValVT,
106*9880d681SAndroid Build Coastguard Worker            MVT LocVT, CCValAssign::LocInfo LocInfo,
107*9880d681SAndroid Build Coastguard Worker            ISD::ArgFlagsTy ArgFlags, CCState &State);
108*9880d681SAndroid Build Coastguard Worker 
109*9880d681SAndroid Build Coastguard Worker static bool
110*9880d681SAndroid Build Coastguard Worker CC_Hexagon32(unsigned ValNo, MVT ValVT,
111*9880d681SAndroid Build Coastguard Worker              MVT LocVT, CCValAssign::LocInfo LocInfo,
112*9880d681SAndroid Build Coastguard Worker              ISD::ArgFlagsTy ArgFlags, CCState &State);
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker static bool
115*9880d681SAndroid Build Coastguard Worker CC_Hexagon64(unsigned ValNo, MVT ValVT,
116*9880d681SAndroid Build Coastguard Worker              MVT LocVT, CCValAssign::LocInfo LocInfo,
117*9880d681SAndroid Build Coastguard Worker              ISD::ArgFlagsTy ArgFlags, CCState &State);
118*9880d681SAndroid Build Coastguard Worker 
119*9880d681SAndroid Build Coastguard Worker static bool
120*9880d681SAndroid Build Coastguard Worker CC_HexagonVector(unsigned ValNo, MVT ValVT,
121*9880d681SAndroid Build Coastguard Worker                  MVT LocVT, CCValAssign::LocInfo LocInfo,
122*9880d681SAndroid Build Coastguard Worker                  ISD::ArgFlagsTy ArgFlags, CCState &State);
123*9880d681SAndroid Build Coastguard Worker 
124*9880d681SAndroid Build Coastguard Worker static bool
125*9880d681SAndroid Build Coastguard Worker RetCC_Hexagon(unsigned ValNo, MVT ValVT,
126*9880d681SAndroid Build Coastguard Worker               MVT LocVT, CCValAssign::LocInfo LocInfo,
127*9880d681SAndroid Build Coastguard Worker               ISD::ArgFlagsTy ArgFlags, CCState &State);
128*9880d681SAndroid Build Coastguard Worker 
129*9880d681SAndroid Build Coastguard Worker static bool
130*9880d681SAndroid Build Coastguard Worker RetCC_Hexagon32(unsigned ValNo, MVT ValVT,
131*9880d681SAndroid Build Coastguard Worker                 MVT LocVT, CCValAssign::LocInfo LocInfo,
132*9880d681SAndroid Build Coastguard Worker                 ISD::ArgFlagsTy ArgFlags, CCState &State);
133*9880d681SAndroid Build Coastguard Worker 
134*9880d681SAndroid Build Coastguard Worker static bool
135*9880d681SAndroid Build Coastguard Worker RetCC_Hexagon64(unsigned ValNo, MVT ValVT,
136*9880d681SAndroid Build Coastguard Worker                 MVT LocVT, CCValAssign::LocInfo LocInfo,
137*9880d681SAndroid Build Coastguard Worker                 ISD::ArgFlagsTy ArgFlags, CCState &State);
138*9880d681SAndroid Build Coastguard Worker 
139*9880d681SAndroid Build Coastguard Worker static bool
140*9880d681SAndroid Build Coastguard Worker RetCC_HexagonVector(unsigned ValNo, MVT ValVT,
141*9880d681SAndroid Build Coastguard Worker                     MVT LocVT, CCValAssign::LocInfo LocInfo,
142*9880d681SAndroid Build Coastguard Worker                     ISD::ArgFlagsTy ArgFlags, CCState &State);
143*9880d681SAndroid Build Coastguard Worker 
144*9880d681SAndroid Build Coastguard Worker static bool
CC_Hexagon_VarArg(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)145*9880d681SAndroid Build Coastguard Worker CC_Hexagon_VarArg (unsigned ValNo, MVT ValVT,
146*9880d681SAndroid Build Coastguard Worker             MVT LocVT, CCValAssign::LocInfo LocInfo,
147*9880d681SAndroid Build Coastguard Worker             ISD::ArgFlagsTy ArgFlags, CCState &State) {
148*9880d681SAndroid Build Coastguard Worker   HexagonCCState &HState = static_cast<HexagonCCState &>(State);
149*9880d681SAndroid Build Coastguard Worker 
150*9880d681SAndroid Build Coastguard Worker   if (ValNo < HState.getNumNamedVarArgParams()) {
151*9880d681SAndroid Build Coastguard Worker     // Deal with named arguments.
152*9880d681SAndroid Build Coastguard Worker     return CC_Hexagon(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State);
153*9880d681SAndroid Build Coastguard Worker   }
154*9880d681SAndroid Build Coastguard Worker 
155*9880d681SAndroid Build Coastguard Worker   // Deal with un-named arguments.
156*9880d681SAndroid Build Coastguard Worker   unsigned ofst;
157*9880d681SAndroid Build Coastguard Worker   if (ArgFlags.isByVal()) {
158*9880d681SAndroid Build Coastguard Worker     // If pass-by-value, the size allocated on stack is decided
159*9880d681SAndroid Build Coastguard Worker     // by ArgFlags.getByValSize(), not by the size of LocVT.
160*9880d681SAndroid Build Coastguard Worker     ofst = State.AllocateStack(ArgFlags.getByValSize(),
161*9880d681SAndroid Build Coastguard Worker                                ArgFlags.getByValAlign());
162*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
163*9880d681SAndroid Build Coastguard Worker     return false;
164*9880d681SAndroid Build Coastguard Worker   }
165*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) {
166*9880d681SAndroid Build Coastguard Worker     LocVT = MVT::i32;
167*9880d681SAndroid Build Coastguard Worker     ValVT = MVT::i32;
168*9880d681SAndroid Build Coastguard Worker     if (ArgFlags.isSExt())
169*9880d681SAndroid Build Coastguard Worker       LocInfo = CCValAssign::SExt;
170*9880d681SAndroid Build Coastguard Worker     else if (ArgFlags.isZExt())
171*9880d681SAndroid Build Coastguard Worker       LocInfo = CCValAssign::ZExt;
172*9880d681SAndroid Build Coastguard Worker     else
173*9880d681SAndroid Build Coastguard Worker       LocInfo = CCValAssign::AExt;
174*9880d681SAndroid Build Coastguard Worker   }
175*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::i32 || LocVT == MVT::f32) {
176*9880d681SAndroid Build Coastguard Worker     ofst = State.AllocateStack(4, 4);
177*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
178*9880d681SAndroid Build Coastguard Worker     return false;
179*9880d681SAndroid Build Coastguard Worker   }
180*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::i64 || LocVT == MVT::f64) {
181*9880d681SAndroid Build Coastguard Worker     ofst = State.AllocateStack(8, 8);
182*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
183*9880d681SAndroid Build Coastguard Worker     return false;
184*9880d681SAndroid Build Coastguard Worker   }
185*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::v2i64 || LocVT == MVT::v4i32 || LocVT == MVT::v8i16 ||
186*9880d681SAndroid Build Coastguard Worker       LocVT == MVT::v16i8) {
187*9880d681SAndroid Build Coastguard Worker     ofst = State.AllocateStack(16, 16);
188*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
189*9880d681SAndroid Build Coastguard Worker     return false;
190*9880d681SAndroid Build Coastguard Worker   }
191*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::v4i64 || LocVT == MVT::v8i32 || LocVT == MVT::v16i16 ||
192*9880d681SAndroid Build Coastguard Worker       LocVT == MVT::v32i8) {
193*9880d681SAndroid Build Coastguard Worker     ofst = State.AllocateStack(32, 32);
194*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
195*9880d681SAndroid Build Coastguard Worker     return false;
196*9880d681SAndroid Build Coastguard Worker   }
197*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::v8i64 || LocVT == MVT::v16i32 || LocVT == MVT::v32i16 ||
198*9880d681SAndroid Build Coastguard Worker       LocVT == MVT::v64i8 || LocVT == MVT::v512i1) {
199*9880d681SAndroid Build Coastguard Worker     ofst = State.AllocateStack(64, 64);
200*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
201*9880d681SAndroid Build Coastguard Worker     return false;
202*9880d681SAndroid Build Coastguard Worker   }
203*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::v16i64 || LocVT == MVT::v32i32 || LocVT == MVT::v64i16 ||
204*9880d681SAndroid Build Coastguard Worker       LocVT == MVT::v128i8 || LocVT == MVT::v1024i1) {
205*9880d681SAndroid Build Coastguard Worker     ofst = State.AllocateStack(128, 128);
206*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
207*9880d681SAndroid Build Coastguard Worker     return false;
208*9880d681SAndroid Build Coastguard Worker   }
209*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::v32i64 || LocVT == MVT::v64i32 || LocVT == MVT::v128i16 ||
210*9880d681SAndroid Build Coastguard Worker       LocVT == MVT::v256i8) {
211*9880d681SAndroid Build Coastguard Worker     ofst = State.AllocateStack(256, 256);
212*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
213*9880d681SAndroid Build Coastguard Worker     return false;
214*9880d681SAndroid Build Coastguard Worker   }
215*9880d681SAndroid Build Coastguard Worker 
216*9880d681SAndroid Build Coastguard Worker   llvm_unreachable(nullptr);
217*9880d681SAndroid Build Coastguard Worker }
218*9880d681SAndroid Build Coastguard Worker 
219*9880d681SAndroid Build Coastguard Worker 
CC_Hexagon(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)220*9880d681SAndroid Build Coastguard Worker static bool CC_Hexagon (unsigned ValNo, MVT ValVT, MVT LocVT,
221*9880d681SAndroid Build Coastguard Worker       CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State) {
222*9880d681SAndroid Build Coastguard Worker   if (ArgFlags.isByVal()) {
223*9880d681SAndroid Build Coastguard Worker     // Passed on stack.
224*9880d681SAndroid Build Coastguard Worker     unsigned Offset = State.AllocateStack(ArgFlags.getByValSize(),
225*9880d681SAndroid Build Coastguard Worker                                           ArgFlags.getByValAlign());
226*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
227*9880d681SAndroid Build Coastguard Worker     return false;
228*9880d681SAndroid Build Coastguard Worker   }
229*9880d681SAndroid Build Coastguard Worker 
230*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) {
231*9880d681SAndroid Build Coastguard Worker     LocVT = MVT::i32;
232*9880d681SAndroid Build Coastguard Worker     ValVT = MVT::i32;
233*9880d681SAndroid Build Coastguard Worker     if (ArgFlags.isSExt())
234*9880d681SAndroid Build Coastguard Worker       LocInfo = CCValAssign::SExt;
235*9880d681SAndroid Build Coastguard Worker     else if (ArgFlags.isZExt())
236*9880d681SAndroid Build Coastguard Worker       LocInfo = CCValAssign::ZExt;
237*9880d681SAndroid Build Coastguard Worker     else
238*9880d681SAndroid Build Coastguard Worker       LocInfo = CCValAssign::AExt;
239*9880d681SAndroid Build Coastguard Worker   } else if (LocVT == MVT::v4i8 || LocVT == MVT::v2i16) {
240*9880d681SAndroid Build Coastguard Worker     LocVT = MVT::i32;
241*9880d681SAndroid Build Coastguard Worker     LocInfo = CCValAssign::BCvt;
242*9880d681SAndroid Build Coastguard Worker   } else if (LocVT == MVT::v8i8 || LocVT == MVT::v4i16 || LocVT == MVT::v2i32) {
243*9880d681SAndroid Build Coastguard Worker     LocVT = MVT::i64;
244*9880d681SAndroid Build Coastguard Worker     LocInfo = CCValAssign::BCvt;
245*9880d681SAndroid Build Coastguard Worker   }
246*9880d681SAndroid Build Coastguard Worker 
247*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::i32 || LocVT == MVT::f32) {
248*9880d681SAndroid Build Coastguard Worker     if (!CC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
249*9880d681SAndroid Build Coastguard Worker       return false;
250*9880d681SAndroid Build Coastguard Worker   }
251*9880d681SAndroid Build Coastguard Worker 
252*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::i64 || LocVT == MVT::f64) {
253*9880d681SAndroid Build Coastguard Worker     if (!CC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
254*9880d681SAndroid Build Coastguard Worker       return false;
255*9880d681SAndroid Build Coastguard Worker   }
256*9880d681SAndroid Build Coastguard Worker 
257*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::v8i32 || LocVT == MVT::v16i16 || LocVT == MVT::v32i8) {
258*9880d681SAndroid Build Coastguard Worker     unsigned Offset = State.AllocateStack(ArgFlags.getByValSize(), 32);
259*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
260*9880d681SAndroid Build Coastguard Worker     return false;
261*9880d681SAndroid Build Coastguard Worker   }
262*9880d681SAndroid Build Coastguard Worker 
263*9880d681SAndroid Build Coastguard Worker   if (IsHvxVectorType(LocVT)) {
264*9880d681SAndroid Build Coastguard Worker     if (!CC_HexagonVector(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
265*9880d681SAndroid Build Coastguard Worker       return false;
266*9880d681SAndroid Build Coastguard Worker   }
267*9880d681SAndroid Build Coastguard Worker 
268*9880d681SAndroid Build Coastguard Worker   return true;  // CC didn't match.
269*9880d681SAndroid Build Coastguard Worker }
270*9880d681SAndroid Build Coastguard Worker 
271*9880d681SAndroid Build Coastguard Worker 
CC_Hexagon32(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)272*9880d681SAndroid Build Coastguard Worker static bool CC_Hexagon32(unsigned ValNo, MVT ValVT,
273*9880d681SAndroid Build Coastguard Worker                          MVT LocVT, CCValAssign::LocInfo LocInfo,
274*9880d681SAndroid Build Coastguard Worker                          ISD::ArgFlagsTy ArgFlags, CCState &State) {
275*9880d681SAndroid Build Coastguard Worker 
276*9880d681SAndroid Build Coastguard Worker   static const MCPhysReg RegList[] = {
277*9880d681SAndroid Build Coastguard Worker     Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4,
278*9880d681SAndroid Build Coastguard Worker     Hexagon::R5
279*9880d681SAndroid Build Coastguard Worker   };
280*9880d681SAndroid Build Coastguard Worker   if (unsigned Reg = State.AllocateReg(RegList)) {
281*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
282*9880d681SAndroid Build Coastguard Worker     return false;
283*9880d681SAndroid Build Coastguard Worker   }
284*9880d681SAndroid Build Coastguard Worker 
285*9880d681SAndroid Build Coastguard Worker   unsigned Offset = State.AllocateStack(4, 4);
286*9880d681SAndroid Build Coastguard Worker   State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
287*9880d681SAndroid Build Coastguard Worker   return false;
288*9880d681SAndroid Build Coastguard Worker }
289*9880d681SAndroid Build Coastguard Worker 
CC_Hexagon64(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)290*9880d681SAndroid Build Coastguard Worker static bool CC_Hexagon64(unsigned ValNo, MVT ValVT,
291*9880d681SAndroid Build Coastguard Worker                          MVT LocVT, CCValAssign::LocInfo LocInfo,
292*9880d681SAndroid Build Coastguard Worker                          ISD::ArgFlagsTy ArgFlags, CCState &State) {
293*9880d681SAndroid Build Coastguard Worker 
294*9880d681SAndroid Build Coastguard Worker   if (unsigned Reg = State.AllocateReg(Hexagon::D0)) {
295*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
296*9880d681SAndroid Build Coastguard Worker     return false;
297*9880d681SAndroid Build Coastguard Worker   }
298*9880d681SAndroid Build Coastguard Worker 
299*9880d681SAndroid Build Coastguard Worker   static const MCPhysReg RegList1[] = {
300*9880d681SAndroid Build Coastguard Worker     Hexagon::D1, Hexagon::D2
301*9880d681SAndroid Build Coastguard Worker   };
302*9880d681SAndroid Build Coastguard Worker   static const MCPhysReg RegList2[] = {
303*9880d681SAndroid Build Coastguard Worker     Hexagon::R1, Hexagon::R3
304*9880d681SAndroid Build Coastguard Worker   };
305*9880d681SAndroid Build Coastguard Worker   if (unsigned Reg = State.AllocateReg(RegList1, RegList2)) {
306*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
307*9880d681SAndroid Build Coastguard Worker     return false;
308*9880d681SAndroid Build Coastguard Worker   }
309*9880d681SAndroid Build Coastguard Worker 
310*9880d681SAndroid Build Coastguard Worker   unsigned Offset = State.AllocateStack(8, 8, Hexagon::D2);
311*9880d681SAndroid Build Coastguard Worker   State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
312*9880d681SAndroid Build Coastguard Worker   return false;
313*9880d681SAndroid Build Coastguard Worker }
314*9880d681SAndroid Build Coastguard Worker 
CC_HexagonVector(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)315*9880d681SAndroid Build Coastguard Worker static bool CC_HexagonVector(unsigned ValNo, MVT ValVT,
316*9880d681SAndroid Build Coastguard Worker                              MVT LocVT, CCValAssign::LocInfo LocInfo,
317*9880d681SAndroid Build Coastguard Worker                              ISD::ArgFlagsTy ArgFlags, CCState &State) {
318*9880d681SAndroid Build Coastguard Worker 
319*9880d681SAndroid Build Coastguard Worker     static const MCPhysReg VecLstS[] = { Hexagon::V0, Hexagon::V1,
320*9880d681SAndroid Build Coastguard Worker                                          Hexagon::V2, Hexagon::V3,
321*9880d681SAndroid Build Coastguard Worker                                          Hexagon::V4, Hexagon::V5,
322*9880d681SAndroid Build Coastguard Worker                                          Hexagon::V6, Hexagon::V7,
323*9880d681SAndroid Build Coastguard Worker                                          Hexagon::V8, Hexagon::V9,
324*9880d681SAndroid Build Coastguard Worker                                          Hexagon::V10, Hexagon::V11,
325*9880d681SAndroid Build Coastguard Worker                                          Hexagon::V12, Hexagon::V13,
326*9880d681SAndroid Build Coastguard Worker                                          Hexagon::V14, Hexagon::V15};
327*9880d681SAndroid Build Coastguard Worker     static const MCPhysReg VecLstD[] = { Hexagon::W0, Hexagon::W1,
328*9880d681SAndroid Build Coastguard Worker                                          Hexagon::W2, Hexagon::W3,
329*9880d681SAndroid Build Coastguard Worker                                          Hexagon::W4, Hexagon::W5,
330*9880d681SAndroid Build Coastguard Worker                                          Hexagon::W6, Hexagon::W7};
331*9880d681SAndroid Build Coastguard Worker   auto &MF = State.getMachineFunction();
332*9880d681SAndroid Build Coastguard Worker   auto &HST = MF.getSubtarget<HexagonSubtarget>();
333*9880d681SAndroid Build Coastguard Worker   bool UseHVX = HST.useHVXOps();
334*9880d681SAndroid Build Coastguard Worker   bool UseHVXDbl = HST.useHVXDblOps();
335*9880d681SAndroid Build Coastguard Worker 
336*9880d681SAndroid Build Coastguard Worker   if ((UseHVX && !UseHVXDbl) &&
337*9880d681SAndroid Build Coastguard Worker       (LocVT == MVT::v8i64 || LocVT == MVT::v16i32 || LocVT == MVT::v32i16 ||
338*9880d681SAndroid Build Coastguard Worker        LocVT == MVT::v64i8 || LocVT == MVT::v512i1)) {
339*9880d681SAndroid Build Coastguard Worker     if (unsigned Reg = State.AllocateReg(VecLstS)) {
340*9880d681SAndroid Build Coastguard Worker       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
341*9880d681SAndroid Build Coastguard Worker       return false;
342*9880d681SAndroid Build Coastguard Worker     }
343*9880d681SAndroid Build Coastguard Worker     unsigned Offset = State.AllocateStack(64, 64);
344*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
345*9880d681SAndroid Build Coastguard Worker     return false;
346*9880d681SAndroid Build Coastguard Worker   }
347*9880d681SAndroid Build Coastguard Worker   if ((UseHVX && !UseHVXDbl) &&
348*9880d681SAndroid Build Coastguard Worker       (LocVT == MVT::v16i64 || LocVT == MVT::v32i32 || LocVT == MVT::v64i16 ||
349*9880d681SAndroid Build Coastguard Worker        LocVT == MVT::v128i8)) {
350*9880d681SAndroid Build Coastguard Worker     if (unsigned Reg = State.AllocateReg(VecLstD)) {
351*9880d681SAndroid Build Coastguard Worker       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
352*9880d681SAndroid Build Coastguard Worker       return false;
353*9880d681SAndroid Build Coastguard Worker     }
354*9880d681SAndroid Build Coastguard Worker     unsigned Offset = State.AllocateStack(128, 128);
355*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
356*9880d681SAndroid Build Coastguard Worker     return false;
357*9880d681SAndroid Build Coastguard Worker   }
358*9880d681SAndroid Build Coastguard Worker   // 128B Mode
359*9880d681SAndroid Build Coastguard Worker   if ((UseHVX && UseHVXDbl) &&
360*9880d681SAndroid Build Coastguard Worker       (LocVT == MVT::v32i64 || LocVT == MVT::v64i32 || LocVT == MVT::v128i16 ||
361*9880d681SAndroid Build Coastguard Worker        LocVT == MVT::v256i8)) {
362*9880d681SAndroid Build Coastguard Worker     if (unsigned Reg = State.AllocateReg(VecLstD)) {
363*9880d681SAndroid Build Coastguard Worker       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
364*9880d681SAndroid Build Coastguard Worker       return false;
365*9880d681SAndroid Build Coastguard Worker     }
366*9880d681SAndroid Build Coastguard Worker     unsigned Offset = State.AllocateStack(256, 256);
367*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
368*9880d681SAndroid Build Coastguard Worker     return false;
369*9880d681SAndroid Build Coastguard Worker   }
370*9880d681SAndroid Build Coastguard Worker   if ((UseHVX && UseHVXDbl) &&
371*9880d681SAndroid Build Coastguard Worker       (LocVT == MVT::v16i64 || LocVT == MVT::v32i32 || LocVT == MVT::v64i16 ||
372*9880d681SAndroid Build Coastguard Worker        LocVT == MVT::v128i8 || LocVT == MVT::v1024i1)) {
373*9880d681SAndroid Build Coastguard Worker     if (unsigned Reg = State.AllocateReg(VecLstS)) {
374*9880d681SAndroid Build Coastguard Worker       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
375*9880d681SAndroid Build Coastguard Worker       return false;
376*9880d681SAndroid Build Coastguard Worker     }
377*9880d681SAndroid Build Coastguard Worker     unsigned Offset = State.AllocateStack(128, 128);
378*9880d681SAndroid Build Coastguard Worker     State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
379*9880d681SAndroid Build Coastguard Worker     return false;
380*9880d681SAndroid Build Coastguard Worker   }
381*9880d681SAndroid Build Coastguard Worker   return true;
382*9880d681SAndroid Build Coastguard Worker }
383*9880d681SAndroid Build Coastguard Worker 
RetCC_Hexagon(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)384*9880d681SAndroid Build Coastguard Worker static bool RetCC_Hexagon(unsigned ValNo, MVT ValVT,
385*9880d681SAndroid Build Coastguard Worker                           MVT LocVT, CCValAssign::LocInfo LocInfo,
386*9880d681SAndroid Build Coastguard Worker                           ISD::ArgFlagsTy ArgFlags, CCState &State) {
387*9880d681SAndroid Build Coastguard Worker   auto &MF = State.getMachineFunction();
388*9880d681SAndroid Build Coastguard Worker   auto &HST = MF.getSubtarget<HexagonSubtarget>();
389*9880d681SAndroid Build Coastguard Worker   bool UseHVX = HST.useHVXOps();
390*9880d681SAndroid Build Coastguard Worker   bool UseHVXDbl = HST.useHVXDblOps();
391*9880d681SAndroid Build Coastguard Worker 
392*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::i1) {
393*9880d681SAndroid Build Coastguard Worker     // Return values of type MVT::i1 still need to be assigned to R0, but
394*9880d681SAndroid Build Coastguard Worker     // the value type needs to remain i1. LowerCallResult will deal with it,
395*9880d681SAndroid Build Coastguard Worker     // but it needs to recognize i1 as the value type.
396*9880d681SAndroid Build Coastguard Worker     LocVT = MVT::i32;
397*9880d681SAndroid Build Coastguard Worker   } else if (LocVT == MVT::i8 || LocVT == MVT::i16) {
398*9880d681SAndroid Build Coastguard Worker     LocVT = MVT::i32;
399*9880d681SAndroid Build Coastguard Worker     ValVT = MVT::i32;
400*9880d681SAndroid Build Coastguard Worker     if (ArgFlags.isSExt())
401*9880d681SAndroid Build Coastguard Worker       LocInfo = CCValAssign::SExt;
402*9880d681SAndroid Build Coastguard Worker     else if (ArgFlags.isZExt())
403*9880d681SAndroid Build Coastguard Worker       LocInfo = CCValAssign::ZExt;
404*9880d681SAndroid Build Coastguard Worker     else
405*9880d681SAndroid Build Coastguard Worker       LocInfo = CCValAssign::AExt;
406*9880d681SAndroid Build Coastguard Worker   } else if (LocVT == MVT::v4i8 || LocVT == MVT::v2i16) {
407*9880d681SAndroid Build Coastguard Worker     LocVT = MVT::i32;
408*9880d681SAndroid Build Coastguard Worker     LocInfo = CCValAssign::BCvt;
409*9880d681SAndroid Build Coastguard Worker   } else if (LocVT == MVT::v8i8 || LocVT == MVT::v4i16 || LocVT == MVT::v2i32) {
410*9880d681SAndroid Build Coastguard Worker     LocVT = MVT::i64;
411*9880d681SAndroid Build Coastguard Worker     LocInfo = CCValAssign::BCvt;
412*9880d681SAndroid Build Coastguard Worker   } else if (LocVT == MVT::v64i8 || LocVT == MVT::v32i16 ||
413*9880d681SAndroid Build Coastguard Worker              LocVT == MVT::v16i32 || LocVT == MVT::v8i64 ||
414*9880d681SAndroid Build Coastguard Worker              LocVT == MVT::v512i1) {
415*9880d681SAndroid Build Coastguard Worker     LocVT = MVT::v16i32;
416*9880d681SAndroid Build Coastguard Worker     ValVT = MVT::v16i32;
417*9880d681SAndroid Build Coastguard Worker     LocInfo = CCValAssign::Full;
418*9880d681SAndroid Build Coastguard Worker   } else if (LocVT == MVT::v128i8 || LocVT == MVT::v64i16 ||
419*9880d681SAndroid Build Coastguard Worker              LocVT == MVT::v32i32 || LocVT == MVT::v16i64 ||
420*9880d681SAndroid Build Coastguard Worker              (LocVT == MVT::v1024i1 && UseHVX && UseHVXDbl)) {
421*9880d681SAndroid Build Coastguard Worker     LocVT = MVT::v32i32;
422*9880d681SAndroid Build Coastguard Worker     ValVT = MVT::v32i32;
423*9880d681SAndroid Build Coastguard Worker     LocInfo = CCValAssign::Full;
424*9880d681SAndroid Build Coastguard Worker   } else if (LocVT == MVT::v256i8 || LocVT == MVT::v128i16 ||
425*9880d681SAndroid Build Coastguard Worker              LocVT == MVT::v64i32 || LocVT == MVT::v32i64) {
426*9880d681SAndroid Build Coastguard Worker     LocVT = MVT::v64i32;
427*9880d681SAndroid Build Coastguard Worker     ValVT = MVT::v64i32;
428*9880d681SAndroid Build Coastguard Worker     LocInfo = CCValAssign::Full;
429*9880d681SAndroid Build Coastguard Worker   }
430*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::i32 || LocVT == MVT::f32) {
431*9880d681SAndroid Build Coastguard Worker     if (!RetCC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
432*9880d681SAndroid Build Coastguard Worker     return false;
433*9880d681SAndroid Build Coastguard Worker   }
434*9880d681SAndroid Build Coastguard Worker 
435*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::i64 || LocVT == MVT::f64) {
436*9880d681SAndroid Build Coastguard Worker     if (!RetCC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
437*9880d681SAndroid Build Coastguard Worker     return false;
438*9880d681SAndroid Build Coastguard Worker   }
439*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::v16i32 || LocVT == MVT::v32i32 || LocVT == MVT::v64i32) {
440*9880d681SAndroid Build Coastguard Worker     if (!RetCC_HexagonVector(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
441*9880d681SAndroid Build Coastguard Worker     return false;
442*9880d681SAndroid Build Coastguard Worker   }
443*9880d681SAndroid Build Coastguard Worker   return true;  // CC didn't match.
444*9880d681SAndroid Build Coastguard Worker }
445*9880d681SAndroid Build Coastguard Worker 
RetCC_Hexagon32(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)446*9880d681SAndroid Build Coastguard Worker static bool RetCC_Hexagon32(unsigned ValNo, MVT ValVT,
447*9880d681SAndroid Build Coastguard Worker                             MVT LocVT, CCValAssign::LocInfo LocInfo,
448*9880d681SAndroid Build Coastguard Worker                             ISD::ArgFlagsTy ArgFlags, CCState &State) {
449*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::i32 || LocVT == MVT::f32) {
450*9880d681SAndroid Build Coastguard Worker     if (unsigned Reg = State.AllocateReg(Hexagon::R0)) {
451*9880d681SAndroid Build Coastguard Worker       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
452*9880d681SAndroid Build Coastguard Worker       return false;
453*9880d681SAndroid Build Coastguard Worker     }
454*9880d681SAndroid Build Coastguard Worker   }
455*9880d681SAndroid Build Coastguard Worker 
456*9880d681SAndroid Build Coastguard Worker   unsigned Offset = State.AllocateStack(4, 4);
457*9880d681SAndroid Build Coastguard Worker   State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
458*9880d681SAndroid Build Coastguard Worker   return false;
459*9880d681SAndroid Build Coastguard Worker }
460*9880d681SAndroid Build Coastguard Worker 
RetCC_Hexagon64(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)461*9880d681SAndroid Build Coastguard Worker static bool RetCC_Hexagon64(unsigned ValNo, MVT ValVT,
462*9880d681SAndroid Build Coastguard Worker                             MVT LocVT, CCValAssign::LocInfo LocInfo,
463*9880d681SAndroid Build Coastguard Worker                             ISD::ArgFlagsTy ArgFlags, CCState &State) {
464*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::i64 || LocVT == MVT::f64) {
465*9880d681SAndroid Build Coastguard Worker     if (unsigned Reg = State.AllocateReg(Hexagon::D0)) {
466*9880d681SAndroid Build Coastguard Worker       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
467*9880d681SAndroid Build Coastguard Worker       return false;
468*9880d681SAndroid Build Coastguard Worker     }
469*9880d681SAndroid Build Coastguard Worker   }
470*9880d681SAndroid Build Coastguard Worker 
471*9880d681SAndroid Build Coastguard Worker   unsigned Offset = State.AllocateStack(8, 8);
472*9880d681SAndroid Build Coastguard Worker   State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
473*9880d681SAndroid Build Coastguard Worker   return false;
474*9880d681SAndroid Build Coastguard Worker }
475*9880d681SAndroid Build Coastguard Worker 
RetCC_HexagonVector(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)476*9880d681SAndroid Build Coastguard Worker static bool RetCC_HexagonVector(unsigned ValNo, MVT ValVT,
477*9880d681SAndroid Build Coastguard Worker                                 MVT LocVT, CCValAssign::LocInfo LocInfo,
478*9880d681SAndroid Build Coastguard Worker                                 ISD::ArgFlagsTy ArgFlags, CCState &State) {
479*9880d681SAndroid Build Coastguard Worker   auto &MF = State.getMachineFunction();
480*9880d681SAndroid Build Coastguard Worker   auto &HST = MF.getSubtarget<HexagonSubtarget>();
481*9880d681SAndroid Build Coastguard Worker   bool UseHVX = HST.useHVXOps();
482*9880d681SAndroid Build Coastguard Worker   bool UseHVXDbl = HST.useHVXDblOps();
483*9880d681SAndroid Build Coastguard Worker 
484*9880d681SAndroid Build Coastguard Worker   unsigned OffSiz = 64;
485*9880d681SAndroid Build Coastguard Worker   if (LocVT == MVT::v16i32) {
486*9880d681SAndroid Build Coastguard Worker     if (unsigned Reg = State.AllocateReg(Hexagon::V0)) {
487*9880d681SAndroid Build Coastguard Worker       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
488*9880d681SAndroid Build Coastguard Worker       return false;
489*9880d681SAndroid Build Coastguard Worker     }
490*9880d681SAndroid Build Coastguard Worker   } else if (LocVT == MVT::v32i32) {
491*9880d681SAndroid Build Coastguard Worker     unsigned Req = (UseHVX && UseHVXDbl) ? Hexagon::V0 : Hexagon::W0;
492*9880d681SAndroid Build Coastguard Worker     if (unsigned Reg = State.AllocateReg(Req)) {
493*9880d681SAndroid Build Coastguard Worker       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
494*9880d681SAndroid Build Coastguard Worker       return false;
495*9880d681SAndroid Build Coastguard Worker     }
496*9880d681SAndroid Build Coastguard Worker     OffSiz = 128;
497*9880d681SAndroid Build Coastguard Worker   } else if (LocVT == MVT::v64i32) {
498*9880d681SAndroid Build Coastguard Worker     if (unsigned Reg = State.AllocateReg(Hexagon::W0)) {
499*9880d681SAndroid Build Coastguard Worker       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
500*9880d681SAndroid Build Coastguard Worker       return false;
501*9880d681SAndroid Build Coastguard Worker     }
502*9880d681SAndroid Build Coastguard Worker     OffSiz = 256;
503*9880d681SAndroid Build Coastguard Worker   }
504*9880d681SAndroid Build Coastguard Worker 
505*9880d681SAndroid Build Coastguard Worker   unsigned Offset = State.AllocateStack(OffSiz, OffSiz);
506*9880d681SAndroid Build Coastguard Worker   State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
507*9880d681SAndroid Build Coastguard Worker   return false;
508*9880d681SAndroid Build Coastguard Worker }
509*9880d681SAndroid Build Coastguard Worker 
promoteLdStType(MVT VT,MVT PromotedLdStVT)510*9880d681SAndroid Build Coastguard Worker void HexagonTargetLowering::promoteLdStType(MVT VT, MVT PromotedLdStVT) {
511*9880d681SAndroid Build Coastguard Worker   if (VT != PromotedLdStVT) {
512*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::LOAD, VT, Promote);
513*9880d681SAndroid Build Coastguard Worker     AddPromotedToType(ISD::LOAD, VT, PromotedLdStVT);
514*9880d681SAndroid Build Coastguard Worker 
515*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::STORE, VT, Promote);
516*9880d681SAndroid Build Coastguard Worker     AddPromotedToType(ISD::STORE, VT, PromotedLdStVT);
517*9880d681SAndroid Build Coastguard Worker   }
518*9880d681SAndroid Build Coastguard Worker }
519*9880d681SAndroid Build Coastguard Worker 
520*9880d681SAndroid Build Coastguard Worker SDValue
LowerINTRINSIC_WO_CHAIN(SDValue Op,SelectionDAG & DAG) const521*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG)
522*9880d681SAndroid Build Coastguard Worker const {
523*9880d681SAndroid Build Coastguard Worker   return SDValue();
524*9880d681SAndroid Build Coastguard Worker }
525*9880d681SAndroid Build Coastguard Worker 
526*9880d681SAndroid Build Coastguard Worker /// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified
527*9880d681SAndroid Build Coastguard Worker /// by "Src" to address "Dst" of size "Size".  Alignment information is
528*9880d681SAndroid Build Coastguard Worker /// specified by the specific parameter attribute. The copy will be passed as
529*9880d681SAndroid Build Coastguard Worker /// a byval function parameter.  Sometimes what we are copying is the end of a
530*9880d681SAndroid Build Coastguard Worker /// larger object, the part that does not fit in registers.
CreateCopyOfByValArgument(SDValue Src,SDValue Dst,SDValue Chain,ISD::ArgFlagsTy Flags,SelectionDAG & DAG,const SDLoc & dl)531*9880d681SAndroid Build Coastguard Worker static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst,
532*9880d681SAndroid Build Coastguard Worker                                          SDValue Chain, ISD::ArgFlagsTy Flags,
533*9880d681SAndroid Build Coastguard Worker                                          SelectionDAG &DAG, const SDLoc &dl) {
534*9880d681SAndroid Build Coastguard Worker 
535*9880d681SAndroid Build Coastguard Worker   SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), dl, MVT::i32);
536*9880d681SAndroid Build Coastguard Worker   return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(),
537*9880d681SAndroid Build Coastguard Worker                        /*isVolatile=*/false, /*AlwaysInline=*/false,
538*9880d681SAndroid Build Coastguard Worker                        /*isTailCall=*/false,
539*9880d681SAndroid Build Coastguard Worker                        MachinePointerInfo(), MachinePointerInfo());
540*9880d681SAndroid Build Coastguard Worker }
541*9880d681SAndroid Build Coastguard Worker 
IsHvxVectorType(MVT ty)542*9880d681SAndroid Build Coastguard Worker static bool IsHvxVectorType(MVT ty) {
543*9880d681SAndroid Build Coastguard Worker   return (ty == MVT::v8i64 || ty == MVT::v16i32 || ty == MVT::v32i16 ||
544*9880d681SAndroid Build Coastguard Worker           ty == MVT::v64i8 ||
545*9880d681SAndroid Build Coastguard Worker           ty == MVT::v16i64 || ty == MVT::v32i32 || ty == MVT::v64i16 ||
546*9880d681SAndroid Build Coastguard Worker           ty == MVT::v128i8 ||
547*9880d681SAndroid Build Coastguard Worker           ty == MVT::v32i64 || ty == MVT::v64i32 || ty == MVT::v128i16 ||
548*9880d681SAndroid Build Coastguard Worker           ty == MVT::v256i8 ||
549*9880d681SAndroid Build Coastguard Worker           ty == MVT::v512i1 || ty == MVT::v1024i1);
550*9880d681SAndroid Build Coastguard Worker }
551*9880d681SAndroid Build Coastguard Worker 
552*9880d681SAndroid Build Coastguard Worker // LowerReturn - Lower ISD::RET. If a struct is larger than 8 bytes and is
553*9880d681SAndroid Build Coastguard Worker // passed by value, the function prototype is modified to return void and
554*9880d681SAndroid Build Coastguard Worker // the value is stored in memory pointed by a pointer passed by caller.
555*9880d681SAndroid Build Coastguard Worker SDValue
LowerReturn(SDValue Chain,CallingConv::ID CallConv,bool isVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & dl,SelectionDAG & DAG) const556*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
557*9880d681SAndroid Build Coastguard Worker                                    bool isVarArg,
558*9880d681SAndroid Build Coastguard Worker                                    const SmallVectorImpl<ISD::OutputArg> &Outs,
559*9880d681SAndroid Build Coastguard Worker                                    const SmallVectorImpl<SDValue> &OutVals,
560*9880d681SAndroid Build Coastguard Worker                                    const SDLoc &dl, SelectionDAG &DAG) const {
561*9880d681SAndroid Build Coastguard Worker 
562*9880d681SAndroid Build Coastguard Worker   // CCValAssign - represent the assignment of the return value to locations.
563*9880d681SAndroid Build Coastguard Worker   SmallVector<CCValAssign, 16> RVLocs;
564*9880d681SAndroid Build Coastguard Worker 
565*9880d681SAndroid Build Coastguard Worker   // CCState - Info about the registers and stack slot.
566*9880d681SAndroid Build Coastguard Worker   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
567*9880d681SAndroid Build Coastguard Worker                  *DAG.getContext());
568*9880d681SAndroid Build Coastguard Worker 
569*9880d681SAndroid Build Coastguard Worker   // Analyze return values of ISD::RET
570*9880d681SAndroid Build Coastguard Worker   CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon);
571*9880d681SAndroid Build Coastguard Worker 
572*9880d681SAndroid Build Coastguard Worker   SDValue Flag;
573*9880d681SAndroid Build Coastguard Worker   SmallVector<SDValue, 4> RetOps(1, Chain);
574*9880d681SAndroid Build Coastguard Worker 
575*9880d681SAndroid Build Coastguard Worker   // Copy the result values into the output registers.
576*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i != RVLocs.size(); ++i) {
577*9880d681SAndroid Build Coastguard Worker     CCValAssign &VA = RVLocs[i];
578*9880d681SAndroid Build Coastguard Worker 
579*9880d681SAndroid Build Coastguard Worker     Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag);
580*9880d681SAndroid Build Coastguard Worker 
581*9880d681SAndroid Build Coastguard Worker     // Guarantee that all emitted copies are stuck together with flags.
582*9880d681SAndroid Build Coastguard Worker     Flag = Chain.getValue(1);
583*9880d681SAndroid Build Coastguard Worker     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
584*9880d681SAndroid Build Coastguard Worker   }
585*9880d681SAndroid Build Coastguard Worker 
586*9880d681SAndroid Build Coastguard Worker   RetOps[0] = Chain;  // Update chain.
587*9880d681SAndroid Build Coastguard Worker 
588*9880d681SAndroid Build Coastguard Worker   // Add the flag if we have it.
589*9880d681SAndroid Build Coastguard Worker   if (Flag.getNode())
590*9880d681SAndroid Build Coastguard Worker     RetOps.push_back(Flag);
591*9880d681SAndroid Build Coastguard Worker 
592*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(HexagonISD::RET_FLAG, dl, MVT::Other, RetOps);
593*9880d681SAndroid Build Coastguard Worker }
594*9880d681SAndroid Build Coastguard Worker 
mayBeEmittedAsTailCall(CallInst * CI) const595*9880d681SAndroid Build Coastguard Worker bool HexagonTargetLowering::mayBeEmittedAsTailCall(CallInst *CI) const {
596*9880d681SAndroid Build Coastguard Worker   // If either no tail call or told not to tail call at all, don't.
597*9880d681SAndroid Build Coastguard Worker   auto Attr =
598*9880d681SAndroid Build Coastguard Worker       CI->getParent()->getParent()->getFnAttribute("disable-tail-calls");
599*9880d681SAndroid Build Coastguard Worker   if (!CI->isTailCall() || Attr.getValueAsString() == "true")
600*9880d681SAndroid Build Coastguard Worker     return false;
601*9880d681SAndroid Build Coastguard Worker 
602*9880d681SAndroid Build Coastguard Worker   return true;
603*9880d681SAndroid Build Coastguard Worker }
604*9880d681SAndroid Build Coastguard Worker 
605*9880d681SAndroid Build Coastguard Worker /// LowerCallResult - Lower the result values of an ISD::CALL into the
606*9880d681SAndroid Build Coastguard Worker /// appropriate copies out of appropriate physical registers.  This assumes that
607*9880d681SAndroid Build Coastguard Worker /// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
608*9880d681SAndroid Build Coastguard Worker /// being lowered. Returns a SDNode with the same number of values as the
609*9880d681SAndroid Build Coastguard Worker /// ISD::CALL.
LowerCallResult(SDValue Chain,SDValue InFlag,CallingConv::ID CallConv,bool isVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & dl,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals,const SmallVectorImpl<SDValue> & OutVals,SDValue Callee) const610*9880d681SAndroid Build Coastguard Worker SDValue HexagonTargetLowering::LowerCallResult(
611*9880d681SAndroid Build Coastguard Worker     SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg,
612*9880d681SAndroid Build Coastguard Worker     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
613*9880d681SAndroid Build Coastguard Worker     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
614*9880d681SAndroid Build Coastguard Worker     const SmallVectorImpl<SDValue> &OutVals, SDValue Callee) const {
615*9880d681SAndroid Build Coastguard Worker   // Assign locations to each value returned by this call.
616*9880d681SAndroid Build Coastguard Worker   SmallVector<CCValAssign, 16> RVLocs;
617*9880d681SAndroid Build Coastguard Worker 
618*9880d681SAndroid Build Coastguard Worker   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
619*9880d681SAndroid Build Coastguard Worker                  *DAG.getContext());
620*9880d681SAndroid Build Coastguard Worker 
621*9880d681SAndroid Build Coastguard Worker   CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon);
622*9880d681SAndroid Build Coastguard Worker 
623*9880d681SAndroid Build Coastguard Worker   // Copy all of the result registers out of their specified physreg.
624*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i != RVLocs.size(); ++i) {
625*9880d681SAndroid Build Coastguard Worker     SDValue RetVal;
626*9880d681SAndroid Build Coastguard Worker     if (RVLocs[i].getValVT() == MVT::i1) {
627*9880d681SAndroid Build Coastguard Worker       // Return values of type MVT::i1 require special handling. The reason
628*9880d681SAndroid Build Coastguard Worker       // is that MVT::i1 is associated with the PredRegs register class, but
629*9880d681SAndroid Build Coastguard Worker       // values of that type are still returned in R0. Generate an explicit
630*9880d681SAndroid Build Coastguard Worker       // copy into a predicate register from R0, and treat the value of the
631*9880d681SAndroid Build Coastguard Worker       // predicate register as the call result.
632*9880d681SAndroid Build Coastguard Worker       auto &MRI = DAG.getMachineFunction().getRegInfo();
633*9880d681SAndroid Build Coastguard Worker       SDValue FR0 = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
634*9880d681SAndroid Build Coastguard Worker                                        MVT::i32, InFlag);
635*9880d681SAndroid Build Coastguard Worker       // FR0 = (Value, Chain, Glue)
636*9880d681SAndroid Build Coastguard Worker       unsigned PredR = MRI.createVirtualRegister(&Hexagon::PredRegsRegClass);
637*9880d681SAndroid Build Coastguard Worker       SDValue TPR = DAG.getCopyToReg(FR0.getValue(1), dl, PredR,
638*9880d681SAndroid Build Coastguard Worker                                      FR0.getValue(0), FR0.getValue(2));
639*9880d681SAndroid Build Coastguard Worker       // TPR = (Chain, Glue)
640*9880d681SAndroid Build Coastguard Worker       RetVal = DAG.getCopyFromReg(TPR.getValue(0), dl, PredR, MVT::i1,
641*9880d681SAndroid Build Coastguard Worker                                   TPR.getValue(1));
642*9880d681SAndroid Build Coastguard Worker     } else {
643*9880d681SAndroid Build Coastguard Worker       RetVal = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
644*9880d681SAndroid Build Coastguard Worker                                   RVLocs[i].getValVT(), InFlag);
645*9880d681SAndroid Build Coastguard Worker     }
646*9880d681SAndroid Build Coastguard Worker     InVals.push_back(RetVal.getValue(0));
647*9880d681SAndroid Build Coastguard Worker     Chain = RetVal.getValue(1);
648*9880d681SAndroid Build Coastguard Worker     InFlag = RetVal.getValue(2);
649*9880d681SAndroid Build Coastguard Worker   }
650*9880d681SAndroid Build Coastguard Worker 
651*9880d681SAndroid Build Coastguard Worker   return Chain;
652*9880d681SAndroid Build Coastguard Worker }
653*9880d681SAndroid Build Coastguard Worker 
654*9880d681SAndroid Build Coastguard Worker /// LowerCall - Functions arguments are copied from virtual regs to
655*9880d681SAndroid Build Coastguard Worker /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
656*9880d681SAndroid Build Coastguard Worker SDValue
LowerCall(TargetLowering::CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const657*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
658*9880d681SAndroid Build Coastguard Worker                                  SmallVectorImpl<SDValue> &InVals) const {
659*9880d681SAndroid Build Coastguard Worker   SelectionDAG &DAG                     = CLI.DAG;
660*9880d681SAndroid Build Coastguard Worker   SDLoc &dl                             = CLI.DL;
661*9880d681SAndroid Build Coastguard Worker   SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
662*9880d681SAndroid Build Coastguard Worker   SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
663*9880d681SAndroid Build Coastguard Worker   SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
664*9880d681SAndroid Build Coastguard Worker   SDValue Chain                         = CLI.Chain;
665*9880d681SAndroid Build Coastguard Worker   SDValue Callee                        = CLI.Callee;
666*9880d681SAndroid Build Coastguard Worker   bool &isTailCall                      = CLI.IsTailCall;
667*9880d681SAndroid Build Coastguard Worker   CallingConv::ID CallConv              = CLI.CallConv;
668*9880d681SAndroid Build Coastguard Worker   bool isVarArg                         = CLI.IsVarArg;
669*9880d681SAndroid Build Coastguard Worker   bool doesNotReturn                    = CLI.DoesNotReturn;
670*9880d681SAndroid Build Coastguard Worker 
671*9880d681SAndroid Build Coastguard Worker   bool IsStructRet    = (Outs.empty()) ? false : Outs[0].Flags.isSRet();
672*9880d681SAndroid Build Coastguard Worker   MachineFunction &MF = DAG.getMachineFunction();
673*9880d681SAndroid Build Coastguard Worker   auto PtrVT = getPointerTy(MF.getDataLayout());
674*9880d681SAndroid Build Coastguard Worker 
675*9880d681SAndroid Build Coastguard Worker   // Check for varargs.
676*9880d681SAndroid Build Coastguard Worker   int NumNamedVarArgParams = -1;
677*9880d681SAndroid Build Coastguard Worker   if (GlobalAddressSDNode *GAN = dyn_cast<GlobalAddressSDNode>(Callee)) {
678*9880d681SAndroid Build Coastguard Worker     const GlobalValue *GV = GAN->getGlobal();
679*9880d681SAndroid Build Coastguard Worker     Callee = DAG.getTargetGlobalAddress(GV, dl, MVT::i32);
680*9880d681SAndroid Build Coastguard Worker     if (const Function* F = dyn_cast<Function>(GV)) {
681*9880d681SAndroid Build Coastguard Worker       // If a function has zero args and is a vararg function, that's
682*9880d681SAndroid Build Coastguard Worker       // disallowed so it must be an undeclared function.  Do not assume
683*9880d681SAndroid Build Coastguard Worker       // varargs if the callee is undefined.
684*9880d681SAndroid Build Coastguard Worker       if (F->isVarArg() && F->getFunctionType()->getNumParams() != 0)
685*9880d681SAndroid Build Coastguard Worker         NumNamedVarArgParams = F->getFunctionType()->getNumParams();
686*9880d681SAndroid Build Coastguard Worker     }
687*9880d681SAndroid Build Coastguard Worker   }
688*9880d681SAndroid Build Coastguard Worker 
689*9880d681SAndroid Build Coastguard Worker   // Analyze operands of the call, assigning locations to each operand.
690*9880d681SAndroid Build Coastguard Worker   SmallVector<CCValAssign, 16> ArgLocs;
691*9880d681SAndroid Build Coastguard Worker   HexagonCCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
692*9880d681SAndroid Build Coastguard Worker                         *DAG.getContext(), NumNamedVarArgParams);
693*9880d681SAndroid Build Coastguard Worker 
694*9880d681SAndroid Build Coastguard Worker   if (isVarArg)
695*9880d681SAndroid Build Coastguard Worker     CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_VarArg);
696*9880d681SAndroid Build Coastguard Worker   else
697*9880d681SAndroid Build Coastguard Worker     CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon);
698*9880d681SAndroid Build Coastguard Worker 
699*9880d681SAndroid Build Coastguard Worker   auto Attr = MF.getFunction()->getFnAttribute("disable-tail-calls");
700*9880d681SAndroid Build Coastguard Worker   if (Attr.getValueAsString() == "true")
701*9880d681SAndroid Build Coastguard Worker     isTailCall = false;
702*9880d681SAndroid Build Coastguard Worker 
703*9880d681SAndroid Build Coastguard Worker   if (isTailCall) {
704*9880d681SAndroid Build Coastguard Worker     bool StructAttrFlag = MF.getFunction()->hasStructRetAttr();
705*9880d681SAndroid Build Coastguard Worker     isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv,
706*9880d681SAndroid Build Coastguard Worker                                                    isVarArg, IsStructRet,
707*9880d681SAndroid Build Coastguard Worker                                                    StructAttrFlag,
708*9880d681SAndroid Build Coastguard Worker                                                    Outs, OutVals, Ins, DAG);
709*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
710*9880d681SAndroid Build Coastguard Worker       CCValAssign &VA = ArgLocs[i];
711*9880d681SAndroid Build Coastguard Worker       if (VA.isMemLoc()) {
712*9880d681SAndroid Build Coastguard Worker         isTailCall = false;
713*9880d681SAndroid Build Coastguard Worker         break;
714*9880d681SAndroid Build Coastguard Worker       }
715*9880d681SAndroid Build Coastguard Worker     }
716*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << (isTailCall ? "Eligible for Tail Call\n"
717*9880d681SAndroid Build Coastguard Worker                                 : "Argument must be passed on stack. "
718*9880d681SAndroid Build Coastguard Worker                                   "Not eligible for Tail Call\n"));
719*9880d681SAndroid Build Coastguard Worker   }
720*9880d681SAndroid Build Coastguard Worker   // Get a count of how many bytes are to be pushed on the stack.
721*9880d681SAndroid Build Coastguard Worker   unsigned NumBytes = CCInfo.getNextStackOffset();
722*9880d681SAndroid Build Coastguard Worker   SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass;
723*9880d681SAndroid Build Coastguard Worker   SmallVector<SDValue, 8> MemOpChains;
724*9880d681SAndroid Build Coastguard Worker 
725*9880d681SAndroid Build Coastguard Worker   auto &HRI = *Subtarget.getRegisterInfo();
726*9880d681SAndroid Build Coastguard Worker   SDValue StackPtr =
727*9880d681SAndroid Build Coastguard Worker       DAG.getCopyFromReg(Chain, dl, HRI.getStackRegister(), PtrVT);
728*9880d681SAndroid Build Coastguard Worker 
729*9880d681SAndroid Build Coastguard Worker   bool NeedsArgAlign = false;
730*9880d681SAndroid Build Coastguard Worker   unsigned LargestAlignSeen = 0;
731*9880d681SAndroid Build Coastguard Worker   // Walk the register/memloc assignments, inserting copies/loads.
732*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
733*9880d681SAndroid Build Coastguard Worker     CCValAssign &VA = ArgLocs[i];
734*9880d681SAndroid Build Coastguard Worker     SDValue Arg = OutVals[i];
735*9880d681SAndroid Build Coastguard Worker     ISD::ArgFlagsTy Flags = Outs[i].Flags;
736*9880d681SAndroid Build Coastguard Worker     // Record if we need > 8 byte alignment on an argument.
737*9880d681SAndroid Build Coastguard Worker     bool ArgAlign = IsHvxVectorType(VA.getValVT());
738*9880d681SAndroid Build Coastguard Worker     NeedsArgAlign |= ArgAlign;
739*9880d681SAndroid Build Coastguard Worker 
740*9880d681SAndroid Build Coastguard Worker     // Promote the value if needed.
741*9880d681SAndroid Build Coastguard Worker     switch (VA.getLocInfo()) {
742*9880d681SAndroid Build Coastguard Worker       default:
743*9880d681SAndroid Build Coastguard Worker         // Loc info must be one of Full, SExt, ZExt, or AExt.
744*9880d681SAndroid Build Coastguard Worker         llvm_unreachable("Unknown loc info!");
745*9880d681SAndroid Build Coastguard Worker       case CCValAssign::BCvt:
746*9880d681SAndroid Build Coastguard Worker       case CCValAssign::Full:
747*9880d681SAndroid Build Coastguard Worker         break;
748*9880d681SAndroid Build Coastguard Worker       case CCValAssign::SExt:
749*9880d681SAndroid Build Coastguard Worker         Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
750*9880d681SAndroid Build Coastguard Worker         break;
751*9880d681SAndroid Build Coastguard Worker       case CCValAssign::ZExt:
752*9880d681SAndroid Build Coastguard Worker         Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
753*9880d681SAndroid Build Coastguard Worker         break;
754*9880d681SAndroid Build Coastguard Worker       case CCValAssign::AExt:
755*9880d681SAndroid Build Coastguard Worker         Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
756*9880d681SAndroid Build Coastguard Worker         break;
757*9880d681SAndroid Build Coastguard Worker     }
758*9880d681SAndroid Build Coastguard Worker 
759*9880d681SAndroid Build Coastguard Worker     if (VA.isMemLoc()) {
760*9880d681SAndroid Build Coastguard Worker       unsigned LocMemOffset = VA.getLocMemOffset();
761*9880d681SAndroid Build Coastguard Worker       SDValue MemAddr = DAG.getConstant(LocMemOffset, dl,
762*9880d681SAndroid Build Coastguard Worker                                         StackPtr.getValueType());
763*9880d681SAndroid Build Coastguard Worker       MemAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, MemAddr);
764*9880d681SAndroid Build Coastguard Worker       if (ArgAlign)
765*9880d681SAndroid Build Coastguard Worker         LargestAlignSeen = std::max(LargestAlignSeen,
766*9880d681SAndroid Build Coastguard Worker                                     VA.getLocVT().getStoreSizeInBits() >> 3);
767*9880d681SAndroid Build Coastguard Worker       if (Flags.isByVal()) {
768*9880d681SAndroid Build Coastguard Worker         // The argument is a struct passed by value. According to LLVM, "Arg"
769*9880d681SAndroid Build Coastguard Worker         // is is pointer.
770*9880d681SAndroid Build Coastguard Worker         MemOpChains.push_back(CreateCopyOfByValArgument(Arg, MemAddr, Chain,
771*9880d681SAndroid Build Coastguard Worker                                                         Flags, DAG, dl));
772*9880d681SAndroid Build Coastguard Worker       } else {
773*9880d681SAndroid Build Coastguard Worker         MachinePointerInfo LocPI = MachinePointerInfo::getStack(
774*9880d681SAndroid Build Coastguard Worker             DAG.getMachineFunction(), LocMemOffset);
775*9880d681SAndroid Build Coastguard Worker         SDValue S = DAG.getStore(Chain, dl, Arg, MemAddr, LocPI, false,
776*9880d681SAndroid Build Coastguard Worker                                  false, 0);
777*9880d681SAndroid Build Coastguard Worker         MemOpChains.push_back(S);
778*9880d681SAndroid Build Coastguard Worker       }
779*9880d681SAndroid Build Coastguard Worker       continue;
780*9880d681SAndroid Build Coastguard Worker     }
781*9880d681SAndroid Build Coastguard Worker 
782*9880d681SAndroid Build Coastguard Worker     // Arguments that can be passed on register must be kept at RegsToPass
783*9880d681SAndroid Build Coastguard Worker     // vector.
784*9880d681SAndroid Build Coastguard Worker     if (VA.isRegLoc())
785*9880d681SAndroid Build Coastguard Worker       RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
786*9880d681SAndroid Build Coastguard Worker   }
787*9880d681SAndroid Build Coastguard Worker 
788*9880d681SAndroid Build Coastguard Worker   if (NeedsArgAlign && Subtarget.hasV60TOps()) {
789*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "Function needs byte stack align due to call args\n");
790*9880d681SAndroid Build Coastguard Worker     MachineFrameInfo* MFI = DAG.getMachineFunction().getFrameInfo();
791*9880d681SAndroid Build Coastguard Worker     // V6 vectors passed by value have 64 or 128 byte alignment depending
792*9880d681SAndroid Build Coastguard Worker     // on whether we are 64 byte vector mode or 128 byte.
793*9880d681SAndroid Build Coastguard Worker     bool UseHVXDbl = Subtarget.useHVXDblOps();
794*9880d681SAndroid Build Coastguard Worker     assert(Subtarget.useHVXOps());
795*9880d681SAndroid Build Coastguard Worker     const unsigned ObjAlign = UseHVXDbl ? 128 : 64;
796*9880d681SAndroid Build Coastguard Worker     LargestAlignSeen = std::max(LargestAlignSeen, ObjAlign);
797*9880d681SAndroid Build Coastguard Worker     MFI->ensureMaxAlignment(LargestAlignSeen);
798*9880d681SAndroid Build Coastguard Worker   }
799*9880d681SAndroid Build Coastguard Worker   // Transform all store nodes into one single node because all store
800*9880d681SAndroid Build Coastguard Worker   // nodes are independent of each other.
801*9880d681SAndroid Build Coastguard Worker   if (!MemOpChains.empty())
802*9880d681SAndroid Build Coastguard Worker     Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
803*9880d681SAndroid Build Coastguard Worker 
804*9880d681SAndroid Build Coastguard Worker   if (!isTailCall) {
805*9880d681SAndroid Build Coastguard Worker     SDValue C = DAG.getConstant(NumBytes, dl, PtrVT, true);
806*9880d681SAndroid Build Coastguard Worker     Chain = DAG.getCALLSEQ_START(Chain, C, dl);
807*9880d681SAndroid Build Coastguard Worker   }
808*9880d681SAndroid Build Coastguard Worker 
809*9880d681SAndroid Build Coastguard Worker   // Build a sequence of copy-to-reg nodes chained together with token
810*9880d681SAndroid Build Coastguard Worker   // chain and flag operands which copy the outgoing args into registers.
811*9880d681SAndroid Build Coastguard Worker   // The InFlag in necessary since all emitted instructions must be
812*9880d681SAndroid Build Coastguard Worker   // stuck together.
813*9880d681SAndroid Build Coastguard Worker   SDValue InFlag;
814*9880d681SAndroid Build Coastguard Worker   if (!isTailCall) {
815*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
816*9880d681SAndroid Build Coastguard Worker       Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
817*9880d681SAndroid Build Coastguard Worker                                RegsToPass[i].second, InFlag);
818*9880d681SAndroid Build Coastguard Worker       InFlag = Chain.getValue(1);
819*9880d681SAndroid Build Coastguard Worker     }
820*9880d681SAndroid Build Coastguard Worker   } else {
821*9880d681SAndroid Build Coastguard Worker     // For tail calls lower the arguments to the 'real' stack slot.
822*9880d681SAndroid Build Coastguard Worker     //
823*9880d681SAndroid Build Coastguard Worker     // Force all the incoming stack arguments to be loaded from the stack
824*9880d681SAndroid Build Coastguard Worker     // before any new outgoing arguments are stored to the stack, because the
825*9880d681SAndroid Build Coastguard Worker     // outgoing stack slots may alias the incoming argument stack slots, and
826*9880d681SAndroid Build Coastguard Worker     // the alias isn't otherwise explicit. This is slightly more conservative
827*9880d681SAndroid Build Coastguard Worker     // than necessary, because it means that each store effectively depends
828*9880d681SAndroid Build Coastguard Worker     // on every argument instead of just those arguments it would clobber.
829*9880d681SAndroid Build Coastguard Worker     //
830*9880d681SAndroid Build Coastguard Worker     // Do not flag preceding copytoreg stuff together with the following stuff.
831*9880d681SAndroid Build Coastguard Worker     InFlag = SDValue();
832*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
833*9880d681SAndroid Build Coastguard Worker       Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
834*9880d681SAndroid Build Coastguard Worker                                RegsToPass[i].second, InFlag);
835*9880d681SAndroid Build Coastguard Worker       InFlag = Chain.getValue(1);
836*9880d681SAndroid Build Coastguard Worker     }
837*9880d681SAndroid Build Coastguard Worker     InFlag = SDValue();
838*9880d681SAndroid Build Coastguard Worker   }
839*9880d681SAndroid Build Coastguard Worker 
840*9880d681SAndroid Build Coastguard Worker   // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
841*9880d681SAndroid Build Coastguard Worker   // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
842*9880d681SAndroid Build Coastguard Worker   // node so that legalize doesn't hack it.
843*9880d681SAndroid Build Coastguard Worker   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
844*9880d681SAndroid Build Coastguard Worker     Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, PtrVT);
845*9880d681SAndroid Build Coastguard Worker   } else if (ExternalSymbolSDNode *S =
846*9880d681SAndroid Build Coastguard Worker              dyn_cast<ExternalSymbolSDNode>(Callee)) {
847*9880d681SAndroid Build Coastguard Worker     Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT);
848*9880d681SAndroid Build Coastguard Worker   }
849*9880d681SAndroid Build Coastguard Worker 
850*9880d681SAndroid Build Coastguard Worker   // Returns a chain & a flag for retval copy to use.
851*9880d681SAndroid Build Coastguard Worker   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
852*9880d681SAndroid Build Coastguard Worker   SmallVector<SDValue, 8> Ops;
853*9880d681SAndroid Build Coastguard Worker   Ops.push_back(Chain);
854*9880d681SAndroid Build Coastguard Worker   Ops.push_back(Callee);
855*9880d681SAndroid Build Coastguard Worker 
856*9880d681SAndroid Build Coastguard Worker   // Add argument registers to the end of the list so that they are
857*9880d681SAndroid Build Coastguard Worker   // known live into the call.
858*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
859*9880d681SAndroid Build Coastguard Worker     Ops.push_back(DAG.getRegister(RegsToPass[i].first,
860*9880d681SAndroid Build Coastguard Worker                                   RegsToPass[i].second.getValueType()));
861*9880d681SAndroid Build Coastguard Worker   }
862*9880d681SAndroid Build Coastguard Worker 
863*9880d681SAndroid Build Coastguard Worker   if (InFlag.getNode())
864*9880d681SAndroid Build Coastguard Worker     Ops.push_back(InFlag);
865*9880d681SAndroid Build Coastguard Worker 
866*9880d681SAndroid Build Coastguard Worker   if (isTailCall) {
867*9880d681SAndroid Build Coastguard Worker     MF.getFrameInfo()->setHasTailCall();
868*9880d681SAndroid Build Coastguard Worker     return DAG.getNode(HexagonISD::TC_RETURN, dl, NodeTys, Ops);
869*9880d681SAndroid Build Coastguard Worker   }
870*9880d681SAndroid Build Coastguard Worker 
871*9880d681SAndroid Build Coastguard Worker   int OpCode = doesNotReturn ? HexagonISD::CALLv3nr : HexagonISD::CALLv3;
872*9880d681SAndroid Build Coastguard Worker   Chain = DAG.getNode(OpCode, dl, NodeTys, Ops);
873*9880d681SAndroid Build Coastguard Worker   InFlag = Chain.getValue(1);
874*9880d681SAndroid Build Coastguard Worker 
875*9880d681SAndroid Build Coastguard Worker   // Create the CALLSEQ_END node.
876*9880d681SAndroid Build Coastguard Worker   Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, dl, true),
877*9880d681SAndroid Build Coastguard Worker                              DAG.getIntPtrConstant(0, dl, true), InFlag, dl);
878*9880d681SAndroid Build Coastguard Worker   InFlag = Chain.getValue(1);
879*9880d681SAndroid Build Coastguard Worker 
880*9880d681SAndroid Build Coastguard Worker   // Handle result values, copying them out of physregs into vregs that we
881*9880d681SAndroid Build Coastguard Worker   // return.
882*9880d681SAndroid Build Coastguard Worker   return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, DAG,
883*9880d681SAndroid Build Coastguard Worker                          InVals, OutVals, Callee);
884*9880d681SAndroid Build Coastguard Worker }
885*9880d681SAndroid Build Coastguard Worker 
getIndexedAddressParts(SDNode * Ptr,EVT VT,bool isSEXTLoad,SDValue & Base,SDValue & Offset,bool & isInc,SelectionDAG & DAG)886*9880d681SAndroid Build Coastguard Worker static bool getIndexedAddressParts(SDNode *Ptr, EVT VT,
887*9880d681SAndroid Build Coastguard Worker                                    bool isSEXTLoad, SDValue &Base,
888*9880d681SAndroid Build Coastguard Worker                                    SDValue &Offset, bool &isInc,
889*9880d681SAndroid Build Coastguard Worker                                    SelectionDAG &DAG) {
890*9880d681SAndroid Build Coastguard Worker   if (Ptr->getOpcode() != ISD::ADD)
891*9880d681SAndroid Build Coastguard Worker     return false;
892*9880d681SAndroid Build Coastguard Worker 
893*9880d681SAndroid Build Coastguard Worker   auto &HST = static_cast<const HexagonSubtarget&>(DAG.getSubtarget());
894*9880d681SAndroid Build Coastguard Worker   bool UseHVX = HST.useHVXOps();
895*9880d681SAndroid Build Coastguard Worker   bool UseHVXDbl = HST.useHVXDblOps();
896*9880d681SAndroid Build Coastguard Worker 
897*9880d681SAndroid Build Coastguard Worker   bool ValidHVXDblType =
898*9880d681SAndroid Build Coastguard Worker     (UseHVX && UseHVXDbl) && (VT == MVT::v32i32 || VT == MVT::v16i64 ||
899*9880d681SAndroid Build Coastguard Worker                               VT == MVT::v64i16 || VT == MVT::v128i8);
900*9880d681SAndroid Build Coastguard Worker   bool ValidHVXType =
901*9880d681SAndroid Build Coastguard Worker     UseHVX && !UseHVXDbl && (VT == MVT::v16i32 || VT == MVT::v8i64 ||
902*9880d681SAndroid Build Coastguard Worker                              VT == MVT::v32i16 || VT == MVT::v64i8);
903*9880d681SAndroid Build Coastguard Worker 
904*9880d681SAndroid Build Coastguard Worker   if (ValidHVXDblType || ValidHVXType ||
905*9880d681SAndroid Build Coastguard Worker       VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) {
906*9880d681SAndroid Build Coastguard Worker     isInc = (Ptr->getOpcode() == ISD::ADD);
907*9880d681SAndroid Build Coastguard Worker     Base = Ptr->getOperand(0);
908*9880d681SAndroid Build Coastguard Worker     Offset = Ptr->getOperand(1);
909*9880d681SAndroid Build Coastguard Worker     // Ensure that Offset is a constant.
910*9880d681SAndroid Build Coastguard Worker     return (isa<ConstantSDNode>(Offset));
911*9880d681SAndroid Build Coastguard Worker   }
912*9880d681SAndroid Build Coastguard Worker 
913*9880d681SAndroid Build Coastguard Worker   return false;
914*9880d681SAndroid Build Coastguard Worker }
915*9880d681SAndroid Build Coastguard Worker 
916*9880d681SAndroid Build Coastguard Worker /// getPostIndexedAddressParts - returns true by value, base pointer and
917*9880d681SAndroid Build Coastguard Worker /// offset pointer and addressing mode by reference if this node can be
918*9880d681SAndroid Build Coastguard Worker /// 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) const919*9880d681SAndroid Build Coastguard Worker bool HexagonTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
920*9880d681SAndroid Build Coastguard Worker                                                        SDValue &Base,
921*9880d681SAndroid Build Coastguard Worker                                                        SDValue &Offset,
922*9880d681SAndroid Build Coastguard Worker                                                        ISD::MemIndexedMode &AM,
923*9880d681SAndroid Build Coastguard Worker                                                        SelectionDAG &DAG) const
924*9880d681SAndroid Build Coastguard Worker {
925*9880d681SAndroid Build Coastguard Worker   EVT VT;
926*9880d681SAndroid Build Coastguard Worker   SDValue Ptr;
927*9880d681SAndroid Build Coastguard Worker   bool isSEXTLoad = false;
928*9880d681SAndroid Build Coastguard Worker 
929*9880d681SAndroid Build Coastguard Worker   if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
930*9880d681SAndroid Build Coastguard Worker     VT  = LD->getMemoryVT();
931*9880d681SAndroid Build Coastguard Worker     isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD;
932*9880d681SAndroid Build Coastguard Worker   } else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
933*9880d681SAndroid Build Coastguard Worker     VT  = ST->getMemoryVT();
934*9880d681SAndroid Build Coastguard Worker     if (ST->getValue().getValueType() == MVT::i64 && ST->isTruncatingStore()) {
935*9880d681SAndroid Build Coastguard Worker       return false;
936*9880d681SAndroid Build Coastguard Worker     }
937*9880d681SAndroid Build Coastguard Worker   } else {
938*9880d681SAndroid Build Coastguard Worker     return false;
939*9880d681SAndroid Build Coastguard Worker   }
940*9880d681SAndroid Build Coastguard Worker 
941*9880d681SAndroid Build Coastguard Worker   bool isInc = false;
942*9880d681SAndroid Build Coastguard Worker   bool isLegal = getIndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset,
943*9880d681SAndroid Build Coastguard Worker                                         isInc, DAG);
944*9880d681SAndroid Build Coastguard Worker   if (isLegal) {
945*9880d681SAndroid Build Coastguard Worker     auto &HII = *Subtarget.getInstrInfo();
946*9880d681SAndroid Build Coastguard Worker     int32_t OffsetVal = cast<ConstantSDNode>(Offset.getNode())->getSExtValue();
947*9880d681SAndroid Build Coastguard Worker     if (HII.isValidAutoIncImm(VT, OffsetVal)) {
948*9880d681SAndroid Build Coastguard Worker       AM = isInc ? ISD::POST_INC : ISD::POST_DEC;
949*9880d681SAndroid Build Coastguard Worker       return true;
950*9880d681SAndroid Build Coastguard Worker     }
951*9880d681SAndroid Build Coastguard Worker   }
952*9880d681SAndroid Build Coastguard Worker 
953*9880d681SAndroid Build Coastguard Worker   return false;
954*9880d681SAndroid Build Coastguard Worker }
955*9880d681SAndroid Build Coastguard Worker 
956*9880d681SAndroid Build Coastguard Worker SDValue
LowerINLINEASM(SDValue Op,SelectionDAG & DAG) const957*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
958*9880d681SAndroid Build Coastguard Worker   SDNode *Node = Op.getNode();
959*9880d681SAndroid Build Coastguard Worker   MachineFunction &MF = DAG.getMachineFunction();
960*9880d681SAndroid Build Coastguard Worker   auto &FuncInfo = *MF.getInfo<HexagonMachineFunctionInfo>();
961*9880d681SAndroid Build Coastguard Worker   switch (Node->getOpcode()) {
962*9880d681SAndroid Build Coastguard Worker     case ISD::INLINEASM: {
963*9880d681SAndroid Build Coastguard Worker       unsigned NumOps = Node->getNumOperands();
964*9880d681SAndroid Build Coastguard Worker       if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue)
965*9880d681SAndroid Build Coastguard Worker         --NumOps;  // Ignore the flag operand.
966*9880d681SAndroid Build Coastguard Worker 
967*9880d681SAndroid Build Coastguard Worker       for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
968*9880d681SAndroid Build Coastguard Worker         if (FuncInfo.hasClobberLR())
969*9880d681SAndroid Build Coastguard Worker           break;
970*9880d681SAndroid Build Coastguard Worker         unsigned Flags =
971*9880d681SAndroid Build Coastguard Worker           cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
972*9880d681SAndroid Build Coastguard Worker         unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
973*9880d681SAndroid Build Coastguard Worker         ++i;  // Skip the ID value.
974*9880d681SAndroid Build Coastguard Worker 
975*9880d681SAndroid Build Coastguard Worker         switch (InlineAsm::getKind(Flags)) {
976*9880d681SAndroid Build Coastguard Worker         default: llvm_unreachable("Bad flags!");
977*9880d681SAndroid Build Coastguard Worker           case InlineAsm::Kind_RegDef:
978*9880d681SAndroid Build Coastguard Worker           case InlineAsm::Kind_RegUse:
979*9880d681SAndroid Build Coastguard Worker           case InlineAsm::Kind_Imm:
980*9880d681SAndroid Build Coastguard Worker           case InlineAsm::Kind_Clobber:
981*9880d681SAndroid Build Coastguard Worker           case InlineAsm::Kind_Mem: {
982*9880d681SAndroid Build Coastguard Worker             for (; NumVals; --NumVals, ++i) {}
983*9880d681SAndroid Build Coastguard Worker             break;
984*9880d681SAndroid Build Coastguard Worker           }
985*9880d681SAndroid Build Coastguard Worker           case InlineAsm::Kind_RegDefEarlyClobber: {
986*9880d681SAndroid Build Coastguard Worker             for (; NumVals; --NumVals, ++i) {
987*9880d681SAndroid Build Coastguard Worker               unsigned Reg =
988*9880d681SAndroid Build Coastguard Worker                 cast<RegisterSDNode>(Node->getOperand(i))->getReg();
989*9880d681SAndroid Build Coastguard Worker 
990*9880d681SAndroid Build Coastguard Worker               // Check it to be lr
991*9880d681SAndroid Build Coastguard Worker               const HexagonRegisterInfo *QRI = Subtarget.getRegisterInfo();
992*9880d681SAndroid Build Coastguard Worker               if (Reg == QRI->getRARegister()) {
993*9880d681SAndroid Build Coastguard Worker                 FuncInfo.setHasClobberLR(true);
994*9880d681SAndroid Build Coastguard Worker                 break;
995*9880d681SAndroid Build Coastguard Worker               }
996*9880d681SAndroid Build Coastguard Worker             }
997*9880d681SAndroid Build Coastguard Worker             break;
998*9880d681SAndroid Build Coastguard Worker           }
999*9880d681SAndroid Build Coastguard Worker         }
1000*9880d681SAndroid Build Coastguard Worker       }
1001*9880d681SAndroid Build Coastguard Worker     }
1002*9880d681SAndroid Build Coastguard Worker   } // Node->getOpcode
1003*9880d681SAndroid Build Coastguard Worker   return Op;
1004*9880d681SAndroid Build Coastguard Worker }
1005*9880d681SAndroid Build Coastguard Worker 
1006*9880d681SAndroid Build Coastguard Worker // Need to transform ISD::PREFETCH into something that doesn't inherit
1007*9880d681SAndroid Build Coastguard Worker // all of the properties of ISD::PREFETCH, specifically SDNPMayLoad and
1008*9880d681SAndroid Build Coastguard Worker // SDNPMayStore.
LowerPREFETCH(SDValue Op,SelectionDAG & DAG) const1009*9880d681SAndroid Build Coastguard Worker SDValue HexagonTargetLowering::LowerPREFETCH(SDValue Op,
1010*9880d681SAndroid Build Coastguard Worker                                              SelectionDAG &DAG) const {
1011*9880d681SAndroid Build Coastguard Worker   SDValue Chain = Op.getOperand(0);
1012*9880d681SAndroid Build Coastguard Worker   SDValue Addr = Op.getOperand(1);
1013*9880d681SAndroid Build Coastguard Worker   // Lower it to DCFETCH($reg, #0).  A "pat" will try to merge the offset in,
1014*9880d681SAndroid Build Coastguard Worker   // if the "reg" is fed by an "add".
1015*9880d681SAndroid Build Coastguard Worker   SDLoc DL(Op);
1016*9880d681SAndroid Build Coastguard Worker   SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
1017*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(HexagonISD::DCFETCH, DL, MVT::Other, Chain, Addr, Zero);
1018*9880d681SAndroid Build Coastguard Worker }
1019*9880d681SAndroid Build Coastguard Worker 
LowerINTRINSIC_VOID(SDValue Op,SelectionDAG & DAG) const1020*9880d681SAndroid Build Coastguard Worker SDValue HexagonTargetLowering::LowerINTRINSIC_VOID(SDValue Op,
1021*9880d681SAndroid Build Coastguard Worker       SelectionDAG &DAG) const {
1022*9880d681SAndroid Build Coastguard Worker   SDValue Chain = Op.getOperand(0);
1023*9880d681SAndroid Build Coastguard Worker   unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
1024*9880d681SAndroid Build Coastguard Worker   // Lower the hexagon_prefetch builtin to DCFETCH, as above.
1025*9880d681SAndroid Build Coastguard Worker   if (IntNo == Intrinsic::hexagon_prefetch) {
1026*9880d681SAndroid Build Coastguard Worker     SDValue Addr = Op.getOperand(2);
1027*9880d681SAndroid Build Coastguard Worker     SDLoc DL(Op);
1028*9880d681SAndroid Build Coastguard Worker     SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
1029*9880d681SAndroid Build Coastguard Worker     return DAG.getNode(HexagonISD::DCFETCH, DL, MVT::Other, Chain, Addr, Zero);
1030*9880d681SAndroid Build Coastguard Worker   }
1031*9880d681SAndroid Build Coastguard Worker   return SDValue();
1032*9880d681SAndroid Build Coastguard Worker }
1033*9880d681SAndroid Build Coastguard Worker 
1034*9880d681SAndroid Build Coastguard Worker SDValue
LowerDYNAMIC_STACKALLOC(SDValue Op,SelectionDAG & DAG) const1035*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
1036*9880d681SAndroid Build Coastguard Worker                                                SelectionDAG &DAG) const {
1037*9880d681SAndroid Build Coastguard Worker   SDValue Chain = Op.getOperand(0);
1038*9880d681SAndroid Build Coastguard Worker   SDValue Size = Op.getOperand(1);
1039*9880d681SAndroid Build Coastguard Worker   SDValue Align = Op.getOperand(2);
1040*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
1041*9880d681SAndroid Build Coastguard Worker 
1042*9880d681SAndroid Build Coastguard Worker   ConstantSDNode *AlignConst = dyn_cast<ConstantSDNode>(Align);
1043*9880d681SAndroid Build Coastguard Worker   assert(AlignConst && "Non-constant Align in LowerDYNAMIC_STACKALLOC");
1044*9880d681SAndroid Build Coastguard Worker 
1045*9880d681SAndroid Build Coastguard Worker   unsigned A = AlignConst->getSExtValue();
1046*9880d681SAndroid Build Coastguard Worker   auto &HFI = *Subtarget.getFrameLowering();
1047*9880d681SAndroid Build Coastguard Worker   // "Zero" means natural stack alignment.
1048*9880d681SAndroid Build Coastguard Worker   if (A == 0)
1049*9880d681SAndroid Build Coastguard Worker     A = HFI.getStackAlignment();
1050*9880d681SAndroid Build Coastguard Worker 
1051*9880d681SAndroid Build Coastguard Worker   DEBUG({
1052*9880d681SAndroid Build Coastguard Worker     dbgs () << LLVM_FUNCTION_NAME << " Align: " << A << " Size: ";
1053*9880d681SAndroid Build Coastguard Worker     Size.getNode()->dump(&DAG);
1054*9880d681SAndroid Build Coastguard Worker     dbgs() << "\n";
1055*9880d681SAndroid Build Coastguard Worker   });
1056*9880d681SAndroid Build Coastguard Worker 
1057*9880d681SAndroid Build Coastguard Worker   SDValue AC = DAG.getConstant(A, dl, MVT::i32);
1058*9880d681SAndroid Build Coastguard Worker   SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Other);
1059*9880d681SAndroid Build Coastguard Worker   SDValue AA = DAG.getNode(HexagonISD::ALLOCA, dl, VTs, Chain, Size, AC);
1060*9880d681SAndroid Build Coastguard Worker 
1061*9880d681SAndroid Build Coastguard Worker   DAG.ReplaceAllUsesOfValueWith(Op, AA);
1062*9880d681SAndroid Build Coastguard Worker   return AA;
1063*9880d681SAndroid Build Coastguard Worker }
1064*9880d681SAndroid Build Coastguard Worker 
LowerFormalArguments(SDValue Chain,CallingConv::ID CallConv,bool isVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & dl,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const1065*9880d681SAndroid Build Coastguard Worker SDValue HexagonTargetLowering::LowerFormalArguments(
1066*9880d681SAndroid Build Coastguard Worker     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
1067*9880d681SAndroid Build Coastguard Worker     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
1068*9880d681SAndroid Build Coastguard Worker     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
1069*9880d681SAndroid Build Coastguard Worker 
1070*9880d681SAndroid Build Coastguard Worker   MachineFunction &MF = DAG.getMachineFunction();
1071*9880d681SAndroid Build Coastguard Worker   MachineFrameInfo *MFI = MF.getFrameInfo();
1072*9880d681SAndroid Build Coastguard Worker   MachineRegisterInfo &RegInfo = MF.getRegInfo();
1073*9880d681SAndroid Build Coastguard Worker   auto &FuncInfo = *MF.getInfo<HexagonMachineFunctionInfo>();
1074*9880d681SAndroid Build Coastguard Worker 
1075*9880d681SAndroid Build Coastguard Worker   // Assign locations to all of the incoming arguments.
1076*9880d681SAndroid Build Coastguard Worker   SmallVector<CCValAssign, 16> ArgLocs;
1077*9880d681SAndroid Build Coastguard Worker   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1078*9880d681SAndroid Build Coastguard Worker                  *DAG.getContext());
1079*9880d681SAndroid Build Coastguard Worker 
1080*9880d681SAndroid Build Coastguard Worker   CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon);
1081*9880d681SAndroid Build Coastguard Worker 
1082*9880d681SAndroid Build Coastguard Worker   // For LLVM, in the case when returning a struct by value (>8byte),
1083*9880d681SAndroid Build Coastguard Worker   // the first argument is a pointer that points to the location on caller's
1084*9880d681SAndroid Build Coastguard Worker   // stack where the return value will be stored. For Hexagon, the location on
1085*9880d681SAndroid Build Coastguard Worker   // caller's stack is passed only when the struct size is smaller than (and
1086*9880d681SAndroid Build Coastguard Worker   // equal to) 8 bytes. If not, no address will be passed into callee and
1087*9880d681SAndroid Build Coastguard Worker   // callee return the result direclty through R0/R1.
1088*9880d681SAndroid Build Coastguard Worker 
1089*9880d681SAndroid Build Coastguard Worker   SmallVector<SDValue, 8> MemOps;
1090*9880d681SAndroid Build Coastguard Worker   bool UseHVX = Subtarget.useHVXOps(), UseHVXDbl = Subtarget.useHVXDblOps();
1091*9880d681SAndroid Build Coastguard Worker 
1092*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1093*9880d681SAndroid Build Coastguard Worker     CCValAssign &VA = ArgLocs[i];
1094*9880d681SAndroid Build Coastguard Worker     ISD::ArgFlagsTy Flags = Ins[i].Flags;
1095*9880d681SAndroid Build Coastguard Worker     unsigned ObjSize;
1096*9880d681SAndroid Build Coastguard Worker     unsigned StackLocation;
1097*9880d681SAndroid Build Coastguard Worker     int FI;
1098*9880d681SAndroid Build Coastguard Worker 
1099*9880d681SAndroid Build Coastguard Worker     if (   (VA.isRegLoc() && !Flags.isByVal())
1100*9880d681SAndroid Build Coastguard Worker         || (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() > 8)) {
1101*9880d681SAndroid Build Coastguard Worker       // Arguments passed in registers
1102*9880d681SAndroid Build Coastguard Worker       // 1. int, long long, ptr args that get allocated in register.
1103*9880d681SAndroid Build Coastguard Worker       // 2. Large struct that gets an register to put its address in.
1104*9880d681SAndroid Build Coastguard Worker       EVT RegVT = VA.getLocVT();
1105*9880d681SAndroid Build Coastguard Worker       if (RegVT == MVT::i8 || RegVT == MVT::i16 ||
1106*9880d681SAndroid Build Coastguard Worker           RegVT == MVT::i32 || RegVT == MVT::f32) {
1107*9880d681SAndroid Build Coastguard Worker         unsigned VReg =
1108*9880d681SAndroid Build Coastguard Worker           RegInfo.createVirtualRegister(&Hexagon::IntRegsRegClass);
1109*9880d681SAndroid Build Coastguard Worker         RegInfo.addLiveIn(VA.getLocReg(), VReg);
1110*9880d681SAndroid Build Coastguard Worker         InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
1111*9880d681SAndroid Build Coastguard Worker       } else if (RegVT == MVT::i64 || RegVT == MVT::f64) {
1112*9880d681SAndroid Build Coastguard Worker         unsigned VReg =
1113*9880d681SAndroid Build Coastguard Worker           RegInfo.createVirtualRegister(&Hexagon::DoubleRegsRegClass);
1114*9880d681SAndroid Build Coastguard Worker         RegInfo.addLiveIn(VA.getLocReg(), VReg);
1115*9880d681SAndroid Build Coastguard Worker         InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
1116*9880d681SAndroid Build Coastguard Worker 
1117*9880d681SAndroid Build Coastguard Worker       // Single Vector
1118*9880d681SAndroid Build Coastguard Worker       } else if ((RegVT == MVT::v8i64 || RegVT == MVT::v16i32 ||
1119*9880d681SAndroid Build Coastguard Worker                   RegVT == MVT::v32i16 || RegVT == MVT::v64i8)) {
1120*9880d681SAndroid Build Coastguard Worker         unsigned VReg =
1121*9880d681SAndroid Build Coastguard Worker           RegInfo.createVirtualRegister(&Hexagon::VectorRegsRegClass);
1122*9880d681SAndroid Build Coastguard Worker         RegInfo.addLiveIn(VA.getLocReg(), VReg);
1123*9880d681SAndroid Build Coastguard Worker         InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
1124*9880d681SAndroid Build Coastguard Worker     } else if (UseHVX && UseHVXDbl &&
1125*9880d681SAndroid Build Coastguard Worker                ((RegVT == MVT::v16i64 || RegVT == MVT::v32i32 ||
1126*9880d681SAndroid Build Coastguard Worker                  RegVT == MVT::v64i16 || RegVT == MVT::v128i8))) {
1127*9880d681SAndroid Build Coastguard Worker         unsigned VReg =
1128*9880d681SAndroid Build Coastguard Worker           RegInfo.createVirtualRegister(&Hexagon::VectorRegs128BRegClass);
1129*9880d681SAndroid Build Coastguard Worker         RegInfo.addLiveIn(VA.getLocReg(), VReg);
1130*9880d681SAndroid Build Coastguard Worker         InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
1131*9880d681SAndroid Build Coastguard Worker 
1132*9880d681SAndroid Build Coastguard Worker       // Double Vector
1133*9880d681SAndroid Build Coastguard Worker       } else if ((RegVT == MVT::v16i64 || RegVT == MVT::v32i32 ||
1134*9880d681SAndroid Build Coastguard Worker                   RegVT == MVT::v64i16 || RegVT == MVT::v128i8)) {
1135*9880d681SAndroid Build Coastguard Worker         unsigned VReg =
1136*9880d681SAndroid Build Coastguard Worker           RegInfo.createVirtualRegister(&Hexagon::VecDblRegsRegClass);
1137*9880d681SAndroid Build Coastguard Worker         RegInfo.addLiveIn(VA.getLocReg(), VReg);
1138*9880d681SAndroid Build Coastguard Worker         InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
1139*9880d681SAndroid Build Coastguard Worker       } else if (UseHVX && UseHVXDbl &&
1140*9880d681SAndroid Build Coastguard Worker                 ((RegVT == MVT::v32i64 || RegVT == MVT::v64i32 ||
1141*9880d681SAndroid Build Coastguard Worker                   RegVT == MVT::v128i16 || RegVT == MVT::v256i8))) {
1142*9880d681SAndroid Build Coastguard Worker         unsigned VReg =
1143*9880d681SAndroid Build Coastguard Worker           RegInfo.createVirtualRegister(&Hexagon::VecDblRegs128BRegClass);
1144*9880d681SAndroid Build Coastguard Worker         RegInfo.addLiveIn(VA.getLocReg(), VReg);
1145*9880d681SAndroid Build Coastguard Worker         InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
1146*9880d681SAndroid Build Coastguard Worker       } else if (RegVT == MVT::v512i1 || RegVT == MVT::v1024i1) {
1147*9880d681SAndroid Build Coastguard Worker         assert(0 && "need to support VecPred regs");
1148*9880d681SAndroid Build Coastguard Worker         unsigned VReg =
1149*9880d681SAndroid Build Coastguard Worker           RegInfo.createVirtualRegister(&Hexagon::VecPredRegsRegClass);
1150*9880d681SAndroid Build Coastguard Worker         RegInfo.addLiveIn(VA.getLocReg(), VReg);
1151*9880d681SAndroid Build Coastguard Worker         InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
1152*9880d681SAndroid Build Coastguard Worker       } else {
1153*9880d681SAndroid Build Coastguard Worker         assert (0);
1154*9880d681SAndroid Build Coastguard Worker       }
1155*9880d681SAndroid Build Coastguard Worker     } else if (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() <= 8) {
1156*9880d681SAndroid Build Coastguard Worker       assert (0 && "ByValSize must be bigger than 8 bytes");
1157*9880d681SAndroid Build Coastguard Worker     } else {
1158*9880d681SAndroid Build Coastguard Worker       // Sanity check.
1159*9880d681SAndroid Build Coastguard Worker       assert(VA.isMemLoc());
1160*9880d681SAndroid Build Coastguard Worker 
1161*9880d681SAndroid Build Coastguard Worker       if (Flags.isByVal()) {
1162*9880d681SAndroid Build Coastguard Worker         // If it's a byval parameter, then we need to compute the
1163*9880d681SAndroid Build Coastguard Worker         // "real" size, not the size of the pointer.
1164*9880d681SAndroid Build Coastguard Worker         ObjSize = Flags.getByValSize();
1165*9880d681SAndroid Build Coastguard Worker       } else {
1166*9880d681SAndroid Build Coastguard Worker         ObjSize = VA.getLocVT().getStoreSizeInBits() >> 3;
1167*9880d681SAndroid Build Coastguard Worker       }
1168*9880d681SAndroid Build Coastguard Worker 
1169*9880d681SAndroid Build Coastguard Worker       StackLocation = HEXAGON_LRFP_SIZE + VA.getLocMemOffset();
1170*9880d681SAndroid Build Coastguard Worker       // Create the frame index object for this incoming parameter...
1171*9880d681SAndroid Build Coastguard Worker       FI = MFI->CreateFixedObject(ObjSize, StackLocation, true);
1172*9880d681SAndroid Build Coastguard Worker 
1173*9880d681SAndroid Build Coastguard Worker       // Create the SelectionDAG nodes cordl, responding to a load
1174*9880d681SAndroid Build Coastguard Worker       // from this parameter.
1175*9880d681SAndroid Build Coastguard Worker       SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1176*9880d681SAndroid Build Coastguard Worker 
1177*9880d681SAndroid Build Coastguard Worker       if (Flags.isByVal()) {
1178*9880d681SAndroid Build Coastguard Worker         // If it's a pass-by-value aggregate, then do not dereference the stack
1179*9880d681SAndroid Build Coastguard Worker         // location. Instead, we should generate a reference to the stack
1180*9880d681SAndroid Build Coastguard Worker         // location.
1181*9880d681SAndroid Build Coastguard Worker         InVals.push_back(FIN);
1182*9880d681SAndroid Build Coastguard Worker       } else {
1183*9880d681SAndroid Build Coastguard Worker         InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
1184*9880d681SAndroid Build Coastguard Worker                                      MachinePointerInfo(), false, false,
1185*9880d681SAndroid Build Coastguard Worker                                      false, 0));
1186*9880d681SAndroid Build Coastguard Worker       }
1187*9880d681SAndroid Build Coastguard Worker     }
1188*9880d681SAndroid Build Coastguard Worker   }
1189*9880d681SAndroid Build Coastguard Worker 
1190*9880d681SAndroid Build Coastguard Worker   if (!MemOps.empty())
1191*9880d681SAndroid Build Coastguard Worker     Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
1192*9880d681SAndroid Build Coastguard Worker 
1193*9880d681SAndroid Build Coastguard Worker   if (isVarArg) {
1194*9880d681SAndroid Build Coastguard Worker     // This will point to the next argument passed via stack.
1195*9880d681SAndroid Build Coastguard Worker     int FrameIndex = MFI->CreateFixedObject(Hexagon_PointerSize,
1196*9880d681SAndroid Build Coastguard Worker                                             HEXAGON_LRFP_SIZE +
1197*9880d681SAndroid Build Coastguard Worker                                             CCInfo.getNextStackOffset(),
1198*9880d681SAndroid Build Coastguard Worker                                             true);
1199*9880d681SAndroid Build Coastguard Worker     FuncInfo.setVarArgsFrameIndex(FrameIndex);
1200*9880d681SAndroid Build Coastguard Worker   }
1201*9880d681SAndroid Build Coastguard Worker 
1202*9880d681SAndroid Build Coastguard Worker   return Chain;
1203*9880d681SAndroid Build Coastguard Worker }
1204*9880d681SAndroid Build Coastguard Worker 
1205*9880d681SAndroid Build Coastguard Worker SDValue
LowerVASTART(SDValue Op,SelectionDAG & DAG) const1206*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
1207*9880d681SAndroid Build Coastguard Worker   // VASTART stores the address of the VarArgsFrameIndex slot into the
1208*9880d681SAndroid Build Coastguard Worker   // memory location argument.
1209*9880d681SAndroid Build Coastguard Worker   MachineFunction &MF = DAG.getMachineFunction();
1210*9880d681SAndroid Build Coastguard Worker   HexagonMachineFunctionInfo *QFI = MF.getInfo<HexagonMachineFunctionInfo>();
1211*9880d681SAndroid Build Coastguard Worker   SDValue Addr = DAG.getFrameIndex(QFI->getVarArgsFrameIndex(), MVT::i32);
1212*9880d681SAndroid Build Coastguard Worker   const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
1213*9880d681SAndroid Build Coastguard Worker   return DAG.getStore(Op.getOperand(0), SDLoc(Op), Addr,
1214*9880d681SAndroid Build Coastguard Worker                       Op.getOperand(1), MachinePointerInfo(SV), false,
1215*9880d681SAndroid Build Coastguard Worker                       false, 0);
1216*9880d681SAndroid Build Coastguard Worker }
1217*9880d681SAndroid Build Coastguard Worker 
1218*9880d681SAndroid Build Coastguard Worker // Creates a SPLAT instruction for a constant value VAL.
createSplat(SelectionDAG & DAG,const SDLoc & dl,EVT VT,SDValue Val)1219*9880d681SAndroid Build Coastguard Worker static SDValue createSplat(SelectionDAG &DAG, const SDLoc &dl, EVT VT,
1220*9880d681SAndroid Build Coastguard Worker                            SDValue Val) {
1221*9880d681SAndroid Build Coastguard Worker   if (VT.getSimpleVT() == MVT::v4i8)
1222*9880d681SAndroid Build Coastguard Worker     return DAG.getNode(HexagonISD::VSPLATB, dl, VT, Val);
1223*9880d681SAndroid Build Coastguard Worker 
1224*9880d681SAndroid Build Coastguard Worker   if (VT.getSimpleVT() == MVT::v4i16)
1225*9880d681SAndroid Build Coastguard Worker     return DAG.getNode(HexagonISD::VSPLATH, dl, VT, Val);
1226*9880d681SAndroid Build Coastguard Worker 
1227*9880d681SAndroid Build Coastguard Worker   return SDValue();
1228*9880d681SAndroid Build Coastguard Worker }
1229*9880d681SAndroid Build Coastguard Worker 
isSExtFree(SDValue N)1230*9880d681SAndroid Build Coastguard Worker static bool isSExtFree(SDValue N) {
1231*9880d681SAndroid Build Coastguard Worker   // A sign-extend of a truncate of a sign-extend is free.
1232*9880d681SAndroid Build Coastguard Worker   if (N.getOpcode() == ISD::TRUNCATE &&
1233*9880d681SAndroid Build Coastguard Worker       N.getOperand(0).getOpcode() == ISD::AssertSext)
1234*9880d681SAndroid Build Coastguard Worker     return true;
1235*9880d681SAndroid Build Coastguard Worker   // We have sign-extended loads.
1236*9880d681SAndroid Build Coastguard Worker   if (N.getOpcode() == ISD::LOAD)
1237*9880d681SAndroid Build Coastguard Worker     return true;
1238*9880d681SAndroid Build Coastguard Worker   return false;
1239*9880d681SAndroid Build Coastguard Worker }
1240*9880d681SAndroid Build Coastguard Worker 
LowerCTPOP(SDValue Op,SelectionDAG & DAG) const1241*9880d681SAndroid Build Coastguard Worker SDValue HexagonTargetLowering::LowerCTPOP(SDValue Op, SelectionDAG &DAG) const {
1242*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
1243*9880d681SAndroid Build Coastguard Worker   SDValue InpVal = Op.getOperand(0);
1244*9880d681SAndroid Build Coastguard Worker   if (isa<ConstantSDNode>(InpVal)) {
1245*9880d681SAndroid Build Coastguard Worker     uint64_t V = cast<ConstantSDNode>(InpVal)->getZExtValue();
1246*9880d681SAndroid Build Coastguard Worker     return DAG.getTargetConstant(countPopulation(V), dl, MVT::i64);
1247*9880d681SAndroid Build Coastguard Worker   }
1248*9880d681SAndroid Build Coastguard Worker   SDValue PopOut = DAG.getNode(HexagonISD::POPCOUNT, dl, MVT::i32, InpVal);
1249*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, PopOut);
1250*9880d681SAndroid Build Coastguard Worker }
1251*9880d681SAndroid Build Coastguard Worker 
LowerSETCC(SDValue Op,SelectionDAG & DAG) const1252*9880d681SAndroid Build Coastguard Worker SDValue HexagonTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
1253*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
1254*9880d681SAndroid Build Coastguard Worker 
1255*9880d681SAndroid Build Coastguard Worker   SDValue LHS = Op.getOperand(0);
1256*9880d681SAndroid Build Coastguard Worker   SDValue RHS = Op.getOperand(1);
1257*9880d681SAndroid Build Coastguard Worker   SDValue Cmp = Op.getOperand(2);
1258*9880d681SAndroid Build Coastguard Worker   ISD::CondCode CC = cast<CondCodeSDNode>(Cmp)->get();
1259*9880d681SAndroid Build Coastguard Worker 
1260*9880d681SAndroid Build Coastguard Worker   EVT VT = Op.getValueType();
1261*9880d681SAndroid Build Coastguard Worker   EVT LHSVT = LHS.getValueType();
1262*9880d681SAndroid Build Coastguard Worker   EVT RHSVT = RHS.getValueType();
1263*9880d681SAndroid Build Coastguard Worker 
1264*9880d681SAndroid Build Coastguard Worker   if (LHSVT == MVT::v2i16) {
1265*9880d681SAndroid Build Coastguard Worker     assert(ISD::isSignedIntSetCC(CC) || ISD::isUnsignedIntSetCC(CC));
1266*9880d681SAndroid Build Coastguard Worker     unsigned ExtOpc = ISD::isSignedIntSetCC(CC) ? ISD::SIGN_EXTEND
1267*9880d681SAndroid Build Coastguard Worker                                                 : ISD::ZERO_EXTEND;
1268*9880d681SAndroid Build Coastguard Worker     SDValue LX = DAG.getNode(ExtOpc, dl, MVT::v2i32, LHS);
1269*9880d681SAndroid Build Coastguard Worker     SDValue RX = DAG.getNode(ExtOpc, dl, MVT::v2i32, RHS);
1270*9880d681SAndroid Build Coastguard Worker     SDValue SC = DAG.getNode(ISD::SETCC, dl, MVT::v2i1, LX, RX, Cmp);
1271*9880d681SAndroid Build Coastguard Worker     return SC;
1272*9880d681SAndroid Build Coastguard Worker   }
1273*9880d681SAndroid Build Coastguard Worker 
1274*9880d681SAndroid Build Coastguard Worker   // Treat all other vector types as legal.
1275*9880d681SAndroid Build Coastguard Worker   if (VT.isVector())
1276*9880d681SAndroid Build Coastguard Worker     return Op;
1277*9880d681SAndroid Build Coastguard Worker 
1278*9880d681SAndroid Build Coastguard Worker   // Equals and not equals should use sign-extend, not zero-extend, since
1279*9880d681SAndroid Build Coastguard Worker   // we can represent small negative values in the compare instructions.
1280*9880d681SAndroid Build Coastguard Worker   // The LLVM default is to use zero-extend arbitrarily in these cases.
1281*9880d681SAndroid Build Coastguard Worker   if ((CC == ISD::SETEQ || CC == ISD::SETNE) &&
1282*9880d681SAndroid Build Coastguard Worker       (RHSVT == MVT::i8 || RHSVT == MVT::i16) &&
1283*9880d681SAndroid Build Coastguard Worker       (LHSVT == MVT::i8 || LHSVT == MVT::i16)) {
1284*9880d681SAndroid Build Coastguard Worker     ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS);
1285*9880d681SAndroid Build Coastguard Worker     if (C && C->getAPIntValue().isNegative()) {
1286*9880d681SAndroid Build Coastguard Worker       LHS = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, LHS);
1287*9880d681SAndroid Build Coastguard Worker       RHS = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, RHS);
1288*9880d681SAndroid Build Coastguard Worker       return DAG.getNode(ISD::SETCC, dl, Op.getValueType(),
1289*9880d681SAndroid Build Coastguard Worker                          LHS, RHS, Op.getOperand(2));
1290*9880d681SAndroid Build Coastguard Worker     }
1291*9880d681SAndroid Build Coastguard Worker     if (isSExtFree(LHS) || isSExtFree(RHS)) {
1292*9880d681SAndroid Build Coastguard Worker       LHS = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, LHS);
1293*9880d681SAndroid Build Coastguard Worker       RHS = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, RHS);
1294*9880d681SAndroid Build Coastguard Worker       return DAG.getNode(ISD::SETCC, dl, Op.getValueType(),
1295*9880d681SAndroid Build Coastguard Worker                          LHS, RHS, Op.getOperand(2));
1296*9880d681SAndroid Build Coastguard Worker     }
1297*9880d681SAndroid Build Coastguard Worker   }
1298*9880d681SAndroid Build Coastguard Worker   return SDValue();
1299*9880d681SAndroid Build Coastguard Worker }
1300*9880d681SAndroid Build Coastguard Worker 
1301*9880d681SAndroid Build Coastguard Worker SDValue
LowerVSELECT(SDValue Op,SelectionDAG & DAG) const1302*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerVSELECT(SDValue Op, SelectionDAG &DAG) const {
1303*9880d681SAndroid Build Coastguard Worker   SDValue PredOp = Op.getOperand(0);
1304*9880d681SAndroid Build Coastguard Worker   SDValue Op1 = Op.getOperand(1), Op2 = Op.getOperand(2);
1305*9880d681SAndroid Build Coastguard Worker   EVT OpVT = Op1.getValueType();
1306*9880d681SAndroid Build Coastguard Worker   SDLoc DL(Op);
1307*9880d681SAndroid Build Coastguard Worker 
1308*9880d681SAndroid Build Coastguard Worker   if (OpVT == MVT::v2i16) {
1309*9880d681SAndroid Build Coastguard Worker     SDValue X1 = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::v2i32, Op1);
1310*9880d681SAndroid Build Coastguard Worker     SDValue X2 = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::v2i32, Op2);
1311*9880d681SAndroid Build Coastguard Worker     SDValue SL = DAG.getNode(ISD::VSELECT, DL, MVT::v2i32, PredOp, X1, X2);
1312*9880d681SAndroid Build Coastguard Worker     SDValue TR = DAG.getNode(ISD::TRUNCATE, DL, MVT::v2i16, SL);
1313*9880d681SAndroid Build Coastguard Worker     return TR;
1314*9880d681SAndroid Build Coastguard Worker   }
1315*9880d681SAndroid Build Coastguard Worker 
1316*9880d681SAndroid Build Coastguard Worker   return SDValue();
1317*9880d681SAndroid Build Coastguard Worker }
1318*9880d681SAndroid Build Coastguard Worker 
1319*9880d681SAndroid Build Coastguard Worker // Handle only specific vector loads.
LowerLOAD(SDValue Op,SelectionDAG & DAG) const1320*9880d681SAndroid Build Coastguard Worker SDValue HexagonTargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
1321*9880d681SAndroid Build Coastguard Worker   EVT VT = Op.getValueType();
1322*9880d681SAndroid Build Coastguard Worker   SDLoc DL(Op);
1323*9880d681SAndroid Build Coastguard Worker   LoadSDNode *LoadNode = cast<LoadSDNode>(Op);
1324*9880d681SAndroid Build Coastguard Worker   SDValue Chain = LoadNode->getChain();
1325*9880d681SAndroid Build Coastguard Worker   SDValue Ptr = Op.getOperand(1);
1326*9880d681SAndroid Build Coastguard Worker   SDValue LoweredLoad;
1327*9880d681SAndroid Build Coastguard Worker   SDValue Result;
1328*9880d681SAndroid Build Coastguard Worker   SDValue Base = LoadNode->getBasePtr();
1329*9880d681SAndroid Build Coastguard Worker   ISD::LoadExtType Ext = LoadNode->getExtensionType();
1330*9880d681SAndroid Build Coastguard Worker   unsigned Alignment = LoadNode->getAlignment();
1331*9880d681SAndroid Build Coastguard Worker   SDValue LoadChain;
1332*9880d681SAndroid Build Coastguard Worker 
1333*9880d681SAndroid Build Coastguard Worker   if(Ext == ISD::NON_EXTLOAD)
1334*9880d681SAndroid Build Coastguard Worker     Ext = ISD::ZEXTLOAD;
1335*9880d681SAndroid Build Coastguard Worker 
1336*9880d681SAndroid Build Coastguard Worker   if (VT == MVT::v4i16) {
1337*9880d681SAndroid Build Coastguard Worker     if (Alignment == 2) {
1338*9880d681SAndroid Build Coastguard Worker       SDValue Loads[4];
1339*9880d681SAndroid Build Coastguard Worker       // Base load.
1340*9880d681SAndroid Build Coastguard Worker       Loads[0] = DAG.getExtLoad(Ext, DL, MVT::i32, Chain, Base,
1341*9880d681SAndroid Build Coastguard Worker                                 LoadNode->getPointerInfo(), MVT::i16,
1342*9880d681SAndroid Build Coastguard Worker                                 LoadNode->isVolatile(),
1343*9880d681SAndroid Build Coastguard Worker                                 LoadNode->isNonTemporal(),
1344*9880d681SAndroid Build Coastguard Worker                                 LoadNode->isInvariant(),
1345*9880d681SAndroid Build Coastguard Worker                                 Alignment);
1346*9880d681SAndroid Build Coastguard Worker       // Base+2 load.
1347*9880d681SAndroid Build Coastguard Worker       SDValue Increment = DAG.getConstant(2, DL, MVT::i32);
1348*9880d681SAndroid Build Coastguard Worker       Ptr = DAG.getNode(ISD::ADD, DL, Base.getValueType(), Base, Increment);
1349*9880d681SAndroid Build Coastguard Worker       Loads[1] = DAG.getExtLoad(Ext, DL, MVT::i32, Chain, Ptr,
1350*9880d681SAndroid Build Coastguard Worker                                 LoadNode->getPointerInfo(), MVT::i16,
1351*9880d681SAndroid Build Coastguard Worker                                 LoadNode->isVolatile(),
1352*9880d681SAndroid Build Coastguard Worker                                 LoadNode->isNonTemporal(),
1353*9880d681SAndroid Build Coastguard Worker                                 LoadNode->isInvariant(),
1354*9880d681SAndroid Build Coastguard Worker                                 Alignment);
1355*9880d681SAndroid Build Coastguard Worker       // SHL 16, then OR base and base+2.
1356*9880d681SAndroid Build Coastguard Worker       SDValue ShiftAmount = DAG.getConstant(16, DL, MVT::i32);
1357*9880d681SAndroid Build Coastguard Worker       SDValue Tmp1 = DAG.getNode(ISD::SHL, DL, MVT::i32, Loads[1], ShiftAmount);
1358*9880d681SAndroid Build Coastguard Worker       SDValue Tmp2 = DAG.getNode(ISD::OR, DL, MVT::i32, Tmp1, Loads[0]);
1359*9880d681SAndroid Build Coastguard Worker       // Base + 4.
1360*9880d681SAndroid Build Coastguard Worker       Increment = DAG.getConstant(4, DL, MVT::i32);
1361*9880d681SAndroid Build Coastguard Worker       Ptr = DAG.getNode(ISD::ADD, DL, Base.getValueType(), Base, Increment);
1362*9880d681SAndroid Build Coastguard Worker       Loads[2] = DAG.getExtLoad(Ext, DL, MVT::i32, Chain, Ptr,
1363*9880d681SAndroid Build Coastguard Worker                                 LoadNode->getPointerInfo(), MVT::i16,
1364*9880d681SAndroid Build Coastguard Worker                                 LoadNode->isVolatile(),
1365*9880d681SAndroid Build Coastguard Worker                                 LoadNode->isNonTemporal(),
1366*9880d681SAndroid Build Coastguard Worker                                 LoadNode->isInvariant(),
1367*9880d681SAndroid Build Coastguard Worker                                 Alignment);
1368*9880d681SAndroid Build Coastguard Worker       // Base + 6.
1369*9880d681SAndroid Build Coastguard Worker       Increment = DAG.getConstant(6, DL, MVT::i32);
1370*9880d681SAndroid Build Coastguard Worker       Ptr = DAG.getNode(ISD::ADD, DL, Base.getValueType(), Base, Increment);
1371*9880d681SAndroid Build Coastguard Worker       Loads[3] = DAG.getExtLoad(Ext, DL, MVT::i32, Chain, Ptr,
1372*9880d681SAndroid Build Coastguard Worker                                 LoadNode->getPointerInfo(), MVT::i16,
1373*9880d681SAndroid Build Coastguard Worker                                 LoadNode->isVolatile(),
1374*9880d681SAndroid Build Coastguard Worker                                 LoadNode->isNonTemporal(),
1375*9880d681SAndroid Build Coastguard Worker                                 LoadNode->isInvariant(),
1376*9880d681SAndroid Build Coastguard Worker                                 Alignment);
1377*9880d681SAndroid Build Coastguard Worker       // SHL 16, then OR base+4 and base+6.
1378*9880d681SAndroid Build Coastguard Worker       Tmp1 = DAG.getNode(ISD::SHL, DL, MVT::i32, Loads[3], ShiftAmount);
1379*9880d681SAndroid Build Coastguard Worker       SDValue Tmp4 = DAG.getNode(ISD::OR, DL, MVT::i32, Tmp1, Loads[2]);
1380*9880d681SAndroid Build Coastguard Worker       // Combine to i64. This could be optimised out later if we can
1381*9880d681SAndroid Build Coastguard Worker       // affect reg allocation of this code.
1382*9880d681SAndroid Build Coastguard Worker       Result = DAG.getNode(HexagonISD::COMBINE, DL, MVT::i64, Tmp4, Tmp2);
1383*9880d681SAndroid Build Coastguard Worker       LoadChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
1384*9880d681SAndroid Build Coastguard Worker                               Loads[0].getValue(1), Loads[1].getValue(1),
1385*9880d681SAndroid Build Coastguard Worker                               Loads[2].getValue(1), Loads[3].getValue(1));
1386*9880d681SAndroid Build Coastguard Worker     } else {
1387*9880d681SAndroid Build Coastguard Worker       // Perform default type expansion.
1388*9880d681SAndroid Build Coastguard Worker       Result = DAG.getLoad(MVT::i64, DL, Chain, Ptr, LoadNode->getPointerInfo(),
1389*9880d681SAndroid Build Coastguard Worker                            LoadNode->isVolatile(), LoadNode->isNonTemporal(),
1390*9880d681SAndroid Build Coastguard Worker                           LoadNode->isInvariant(), LoadNode->getAlignment());
1391*9880d681SAndroid Build Coastguard Worker       LoadChain = Result.getValue(1);
1392*9880d681SAndroid Build Coastguard Worker     }
1393*9880d681SAndroid Build Coastguard Worker   } else
1394*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Custom lowering unsupported load");
1395*9880d681SAndroid Build Coastguard Worker 
1396*9880d681SAndroid Build Coastguard Worker   Result = DAG.getNode(ISD::BITCAST, DL, VT, Result);
1397*9880d681SAndroid Build Coastguard Worker   // Since we pretend to lower a load, we need the original chain
1398*9880d681SAndroid Build Coastguard Worker   // info attached to the result.
1399*9880d681SAndroid Build Coastguard Worker   SDValue Ops[] = { Result, LoadChain };
1400*9880d681SAndroid Build Coastguard Worker 
1401*9880d681SAndroid Build Coastguard Worker   return DAG.getMergeValues(Ops, DL);
1402*9880d681SAndroid Build Coastguard Worker }
1403*9880d681SAndroid Build Coastguard Worker 
1404*9880d681SAndroid Build Coastguard Worker 
1405*9880d681SAndroid Build Coastguard Worker SDValue
LowerConstantPool(SDValue Op,SelectionDAG & DAG) const1406*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const {
1407*9880d681SAndroid Build Coastguard Worker   EVT ValTy = Op.getValueType();
1408*9880d681SAndroid Build Coastguard Worker   ConstantPoolSDNode *CPN = cast<ConstantPoolSDNode>(Op);
1409*9880d681SAndroid Build Coastguard Worker   unsigned Align = CPN->getAlignment();
1410*9880d681SAndroid Build Coastguard Worker   bool IsPositionIndependent = isPositionIndependent();
1411*9880d681SAndroid Build Coastguard Worker   unsigned char TF = IsPositionIndependent ? HexagonII::MO_PCREL : 0;
1412*9880d681SAndroid Build Coastguard Worker 
1413*9880d681SAndroid Build Coastguard Worker   SDValue T;
1414*9880d681SAndroid Build Coastguard Worker   if (CPN->isMachineConstantPoolEntry())
1415*9880d681SAndroid Build Coastguard Worker     T = DAG.getTargetConstantPool(CPN->getMachineCPVal(), ValTy, Align, TF);
1416*9880d681SAndroid Build Coastguard Worker   else
1417*9880d681SAndroid Build Coastguard Worker     T = DAG.getTargetConstantPool(CPN->getConstVal(), ValTy, Align, TF);
1418*9880d681SAndroid Build Coastguard Worker   if (IsPositionIndependent)
1419*9880d681SAndroid Build Coastguard Worker     return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), ValTy, T);
1420*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(HexagonISD::CP, SDLoc(Op), ValTy, T);
1421*9880d681SAndroid Build Coastguard Worker }
1422*9880d681SAndroid Build Coastguard Worker 
1423*9880d681SAndroid Build Coastguard Worker SDValue
LowerJumpTable(SDValue Op,SelectionDAG & DAG) const1424*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
1425*9880d681SAndroid Build Coastguard Worker   EVT VT = Op.getValueType();
1426*9880d681SAndroid Build Coastguard Worker   int Idx = cast<JumpTableSDNode>(Op)->getIndex();
1427*9880d681SAndroid Build Coastguard Worker   if (isPositionIndependent()) {
1428*9880d681SAndroid Build Coastguard Worker     SDValue T = DAG.getTargetJumpTable(Idx, VT, HexagonII::MO_PCREL);
1429*9880d681SAndroid Build Coastguard Worker     return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), VT, T);
1430*9880d681SAndroid Build Coastguard Worker   }
1431*9880d681SAndroid Build Coastguard Worker 
1432*9880d681SAndroid Build Coastguard Worker   SDValue T = DAG.getTargetJumpTable(Idx, VT);
1433*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(HexagonISD::JT, SDLoc(Op), VT, T);
1434*9880d681SAndroid Build Coastguard Worker }
1435*9880d681SAndroid Build Coastguard Worker 
1436*9880d681SAndroid Build Coastguard Worker SDValue
LowerRETURNADDR(SDValue Op,SelectionDAG & DAG) const1437*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
1438*9880d681SAndroid Build Coastguard Worker   const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
1439*9880d681SAndroid Build Coastguard Worker   MachineFunction &MF = DAG.getMachineFunction();
1440*9880d681SAndroid Build Coastguard Worker   MachineFrameInfo &MFI = *MF.getFrameInfo();
1441*9880d681SAndroid Build Coastguard Worker   MFI.setReturnAddressIsTaken(true);
1442*9880d681SAndroid Build Coastguard Worker 
1443*9880d681SAndroid Build Coastguard Worker   if (verifyReturnAddressArgumentIsConstant(Op, DAG))
1444*9880d681SAndroid Build Coastguard Worker     return SDValue();
1445*9880d681SAndroid Build Coastguard Worker 
1446*9880d681SAndroid Build Coastguard Worker   EVT VT = Op.getValueType();
1447*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
1448*9880d681SAndroid Build Coastguard Worker   unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1449*9880d681SAndroid Build Coastguard Worker   if (Depth) {
1450*9880d681SAndroid Build Coastguard Worker     SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
1451*9880d681SAndroid Build Coastguard Worker     SDValue Offset = DAG.getConstant(4, dl, MVT::i32);
1452*9880d681SAndroid Build Coastguard Worker     return DAG.getLoad(VT, dl, DAG.getEntryNode(),
1453*9880d681SAndroid Build Coastguard Worker                        DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset),
1454*9880d681SAndroid Build Coastguard Worker                        MachinePointerInfo(), false, false, false, 0);
1455*9880d681SAndroid Build Coastguard Worker   }
1456*9880d681SAndroid Build Coastguard Worker 
1457*9880d681SAndroid Build Coastguard Worker   // Return LR, which contains the return address. Mark it an implicit live-in.
1458*9880d681SAndroid Build Coastguard Worker   unsigned Reg = MF.addLiveIn(HRI.getRARegister(), getRegClassFor(MVT::i32));
1459*9880d681SAndroid Build Coastguard Worker   return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);
1460*9880d681SAndroid Build Coastguard Worker }
1461*9880d681SAndroid Build Coastguard Worker 
1462*9880d681SAndroid Build Coastguard Worker SDValue
LowerFRAMEADDR(SDValue Op,SelectionDAG & DAG) const1463*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
1464*9880d681SAndroid Build Coastguard Worker   const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
1465*9880d681SAndroid Build Coastguard Worker   MachineFrameInfo &MFI = *DAG.getMachineFunction().getFrameInfo();
1466*9880d681SAndroid Build Coastguard Worker   MFI.setFrameAddressIsTaken(true);
1467*9880d681SAndroid Build Coastguard Worker 
1468*9880d681SAndroid Build Coastguard Worker   EVT VT = Op.getValueType();
1469*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
1470*9880d681SAndroid Build Coastguard Worker   unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1471*9880d681SAndroid Build Coastguard Worker   SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl,
1472*9880d681SAndroid Build Coastguard Worker                                          HRI.getFrameRegister(), VT);
1473*9880d681SAndroid Build Coastguard Worker   while (Depth--)
1474*9880d681SAndroid Build Coastguard Worker     FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,
1475*9880d681SAndroid Build Coastguard Worker                             MachinePointerInfo(),
1476*9880d681SAndroid Build Coastguard Worker                             false, false, false, 0);
1477*9880d681SAndroid Build Coastguard Worker   return FrameAddr;
1478*9880d681SAndroid Build Coastguard Worker }
1479*9880d681SAndroid Build Coastguard Worker 
1480*9880d681SAndroid Build Coastguard Worker SDValue
LowerATOMIC_FENCE(SDValue Op,SelectionDAG & DAG) const1481*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const {
1482*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
1483*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(HexagonISD::BARRIER, dl, MVT::Other, Op.getOperand(0));
1484*9880d681SAndroid Build Coastguard Worker }
1485*9880d681SAndroid Build Coastguard Worker 
1486*9880d681SAndroid Build Coastguard Worker 
1487*9880d681SAndroid Build Coastguard Worker SDValue
LowerGLOBALADDRESS(SDValue Op,SelectionDAG & DAG) const1488*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerGLOBALADDRESS(SDValue Op, SelectionDAG &DAG) const {
1489*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
1490*9880d681SAndroid Build Coastguard Worker   auto *GAN = cast<GlobalAddressSDNode>(Op);
1491*9880d681SAndroid Build Coastguard Worker   auto PtrVT = getPointerTy(DAG.getDataLayout());
1492*9880d681SAndroid Build Coastguard Worker   auto *GV = GAN->getGlobal();
1493*9880d681SAndroid Build Coastguard Worker   int64_t Offset = GAN->getOffset();
1494*9880d681SAndroid Build Coastguard Worker 
1495*9880d681SAndroid Build Coastguard Worker   auto &HLOF = *HTM.getObjFileLowering();
1496*9880d681SAndroid Build Coastguard Worker   Reloc::Model RM = HTM.getRelocationModel();
1497*9880d681SAndroid Build Coastguard Worker 
1498*9880d681SAndroid Build Coastguard Worker   if (RM == Reloc::Static) {
1499*9880d681SAndroid Build Coastguard Worker     SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, Offset);
1500*9880d681SAndroid Build Coastguard Worker     if (HLOF.isGlobalInSmallSection(GV, HTM))
1501*9880d681SAndroid Build Coastguard Worker       return DAG.getNode(HexagonISD::CONST32_GP, dl, PtrVT, GA);
1502*9880d681SAndroid Build Coastguard Worker     return DAG.getNode(HexagonISD::CONST32, dl, PtrVT, GA);
1503*9880d681SAndroid Build Coastguard Worker   }
1504*9880d681SAndroid Build Coastguard Worker 
1505*9880d681SAndroid Build Coastguard Worker   bool UsePCRel = getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV);
1506*9880d681SAndroid Build Coastguard Worker   if (UsePCRel) {
1507*9880d681SAndroid Build Coastguard Worker     SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, Offset,
1508*9880d681SAndroid Build Coastguard Worker                                             HexagonII::MO_PCREL);
1509*9880d681SAndroid Build Coastguard Worker     return DAG.getNode(HexagonISD::AT_PCREL, dl, PtrVT, GA);
1510*9880d681SAndroid Build Coastguard Worker   }
1511*9880d681SAndroid Build Coastguard Worker 
1512*9880d681SAndroid Build Coastguard Worker   // Use GOT index.
1513*9880d681SAndroid Build Coastguard Worker   SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(PtrVT);
1514*9880d681SAndroid Build Coastguard Worker   SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, HexagonII::MO_GOT);
1515*9880d681SAndroid Build Coastguard Worker   SDValue Off = DAG.getConstant(Offset, dl, MVT::i32);
1516*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(HexagonISD::AT_GOT, dl, PtrVT, GOT, GA, Off);
1517*9880d681SAndroid Build Coastguard Worker }
1518*9880d681SAndroid Build Coastguard Worker 
1519*9880d681SAndroid Build Coastguard Worker // Specifies that for loads and stores VT can be promoted to PromotedLdStVT.
1520*9880d681SAndroid Build Coastguard Worker SDValue
LowerBlockAddress(SDValue Op,SelectionDAG & DAG) const1521*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const {
1522*9880d681SAndroid Build Coastguard Worker   const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
1523*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
1524*9880d681SAndroid Build Coastguard Worker   EVT PtrVT = getPointerTy(DAG.getDataLayout());
1525*9880d681SAndroid Build Coastguard Worker 
1526*9880d681SAndroid Build Coastguard Worker   Reloc::Model RM = HTM.getRelocationModel();
1527*9880d681SAndroid Build Coastguard Worker   if (RM == Reloc::Static) {
1528*9880d681SAndroid Build Coastguard Worker     SDValue A = DAG.getTargetBlockAddress(BA, PtrVT);
1529*9880d681SAndroid Build Coastguard Worker     return DAG.getNode(HexagonISD::CONST32_GP, dl, PtrVT, A);
1530*9880d681SAndroid Build Coastguard Worker   }
1531*9880d681SAndroid Build Coastguard Worker 
1532*9880d681SAndroid Build Coastguard Worker   SDValue A = DAG.getTargetBlockAddress(BA, PtrVT, 0, HexagonII::MO_PCREL);
1533*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(HexagonISD::AT_PCREL, dl, PtrVT, A);
1534*9880d681SAndroid Build Coastguard Worker }
1535*9880d681SAndroid Build Coastguard Worker 
1536*9880d681SAndroid Build Coastguard Worker SDValue
LowerGLOBAL_OFFSET_TABLE(SDValue Op,SelectionDAG & DAG) const1537*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG)
1538*9880d681SAndroid Build Coastguard Worker       const {
1539*9880d681SAndroid Build Coastguard Worker   EVT PtrVT = getPointerTy(DAG.getDataLayout());
1540*9880d681SAndroid Build Coastguard Worker   SDValue GOTSym = DAG.getTargetExternalSymbol(HEXAGON_GOT_SYM_NAME, PtrVT,
1541*9880d681SAndroid Build Coastguard Worker                                                HexagonII::MO_PCREL);
1542*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), PtrVT, GOTSym);
1543*9880d681SAndroid Build Coastguard Worker }
1544*9880d681SAndroid Build Coastguard Worker 
1545*9880d681SAndroid Build Coastguard Worker SDValue
GetDynamicTLSAddr(SelectionDAG & DAG,SDValue Chain,GlobalAddressSDNode * GA,SDValue * InFlag,EVT PtrVT,unsigned ReturnReg,unsigned char OperandFlags) const1546*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::GetDynamicTLSAddr(SelectionDAG &DAG, SDValue Chain,
1547*9880d681SAndroid Build Coastguard Worker       GlobalAddressSDNode *GA, SDValue *InFlag, EVT PtrVT, unsigned ReturnReg,
1548*9880d681SAndroid Build Coastguard Worker       unsigned char OperandFlags) const {
1549*9880d681SAndroid Build Coastguard Worker   MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
1550*9880d681SAndroid Build Coastguard Worker   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1551*9880d681SAndroid Build Coastguard Worker   SDLoc dl(GA);
1552*9880d681SAndroid Build Coastguard Worker   SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
1553*9880d681SAndroid Build Coastguard Worker                                            GA->getValueType(0),
1554*9880d681SAndroid Build Coastguard Worker                                            GA->getOffset(),
1555*9880d681SAndroid Build Coastguard Worker                                            OperandFlags);
1556*9880d681SAndroid Build Coastguard Worker   // Create Operands for the call.The Operands should have the following:
1557*9880d681SAndroid Build Coastguard Worker   // 1. Chain SDValue
1558*9880d681SAndroid Build Coastguard Worker   // 2. Callee which in this case is the Global address value.
1559*9880d681SAndroid Build Coastguard Worker   // 3. Registers live into the call.In this case its R0, as we
1560*9880d681SAndroid Build Coastguard Worker   //    have just one argument to be passed.
1561*9880d681SAndroid Build Coastguard Worker   // 4. InFlag if there is any.
1562*9880d681SAndroid Build Coastguard Worker   // Note: The order is important.
1563*9880d681SAndroid Build Coastguard Worker 
1564*9880d681SAndroid Build Coastguard Worker   if (InFlag) {
1565*9880d681SAndroid Build Coastguard Worker     SDValue Ops[] = { Chain, TGA,
1566*9880d681SAndroid Build Coastguard Worker                       DAG.getRegister(Hexagon::R0, PtrVT), *InFlag };
1567*9880d681SAndroid Build Coastguard Worker     Chain = DAG.getNode(HexagonISD::CALLv3, dl, NodeTys, Ops);
1568*9880d681SAndroid Build Coastguard Worker   } else {
1569*9880d681SAndroid Build Coastguard Worker     SDValue Ops[]  = { Chain, TGA, DAG.getRegister(Hexagon::R0, PtrVT)};
1570*9880d681SAndroid Build Coastguard Worker     Chain = DAG.getNode(HexagonISD::CALLv3, dl, NodeTys, Ops);
1571*9880d681SAndroid Build Coastguard Worker   }
1572*9880d681SAndroid Build Coastguard Worker 
1573*9880d681SAndroid Build Coastguard Worker   // Inform MFI that function has calls.
1574*9880d681SAndroid Build Coastguard Worker   MFI->setAdjustsStack(true);
1575*9880d681SAndroid Build Coastguard Worker 
1576*9880d681SAndroid Build Coastguard Worker   SDValue Flag = Chain.getValue(1);
1577*9880d681SAndroid Build Coastguard Worker   return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Flag);
1578*9880d681SAndroid Build Coastguard Worker }
1579*9880d681SAndroid Build Coastguard Worker 
1580*9880d681SAndroid Build Coastguard Worker //
1581*9880d681SAndroid Build Coastguard Worker // Lower using the intial executable model for TLS addresses
1582*9880d681SAndroid Build Coastguard Worker //
1583*9880d681SAndroid Build Coastguard Worker SDValue
LowerToTLSInitialExecModel(GlobalAddressSDNode * GA,SelectionDAG & DAG) const1584*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerToTLSInitialExecModel(GlobalAddressSDNode *GA,
1585*9880d681SAndroid Build Coastguard Worker       SelectionDAG &DAG) const {
1586*9880d681SAndroid Build Coastguard Worker   SDLoc dl(GA);
1587*9880d681SAndroid Build Coastguard Worker   int64_t Offset = GA->getOffset();
1588*9880d681SAndroid Build Coastguard Worker   auto PtrVT = getPointerTy(DAG.getDataLayout());
1589*9880d681SAndroid Build Coastguard Worker 
1590*9880d681SAndroid Build Coastguard Worker   // Get the thread pointer.
1591*9880d681SAndroid Build Coastguard Worker   SDValue TP = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Hexagon::UGP, PtrVT);
1592*9880d681SAndroid Build Coastguard Worker 
1593*9880d681SAndroid Build Coastguard Worker   bool IsPositionIndependent = isPositionIndependent();
1594*9880d681SAndroid Build Coastguard Worker   unsigned char TF =
1595*9880d681SAndroid Build Coastguard Worker       IsPositionIndependent ? HexagonII::MO_IEGOT : HexagonII::MO_IE;
1596*9880d681SAndroid Build Coastguard Worker 
1597*9880d681SAndroid Build Coastguard Worker   // First generate the TLS symbol address
1598*9880d681SAndroid Build Coastguard Worker   SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT,
1599*9880d681SAndroid Build Coastguard Worker                                            Offset, TF);
1600*9880d681SAndroid Build Coastguard Worker 
1601*9880d681SAndroid Build Coastguard Worker   SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
1602*9880d681SAndroid Build Coastguard Worker 
1603*9880d681SAndroid Build Coastguard Worker   if (IsPositionIndependent) {
1604*9880d681SAndroid Build Coastguard Worker     // Generate the GOT pointer in case of position independent code
1605*9880d681SAndroid Build Coastguard Worker     SDValue GOT = LowerGLOBAL_OFFSET_TABLE(Sym, DAG);
1606*9880d681SAndroid Build Coastguard Worker 
1607*9880d681SAndroid Build Coastguard Worker     // Add the TLS Symbol address to GOT pointer.This gives
1608*9880d681SAndroid Build Coastguard Worker     // GOT relative relocation for the symbol.
1609*9880d681SAndroid Build Coastguard Worker     Sym = DAG.getNode(ISD::ADD, dl, PtrVT, GOT, Sym);
1610*9880d681SAndroid Build Coastguard Worker   }
1611*9880d681SAndroid Build Coastguard Worker 
1612*9880d681SAndroid Build Coastguard Worker   // Load the offset value for TLS symbol.This offset is relative to
1613*9880d681SAndroid Build Coastguard Worker   // thread pointer.
1614*9880d681SAndroid Build Coastguard Worker   SDValue LoadOffset = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Sym,
1615*9880d681SAndroid Build Coastguard Worker                                    MachinePointerInfo(),
1616*9880d681SAndroid Build Coastguard Worker                                    false, false, false, 0);
1617*9880d681SAndroid Build Coastguard Worker 
1618*9880d681SAndroid Build Coastguard Worker   // Address of the thread local variable is the add of thread
1619*9880d681SAndroid Build Coastguard Worker   // pointer and the offset of the variable.
1620*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(ISD::ADD, dl, PtrVT, TP, LoadOffset);
1621*9880d681SAndroid Build Coastguard Worker }
1622*9880d681SAndroid Build Coastguard Worker 
1623*9880d681SAndroid Build Coastguard Worker //
1624*9880d681SAndroid Build Coastguard Worker // Lower using the local executable model for TLS addresses
1625*9880d681SAndroid Build Coastguard Worker //
1626*9880d681SAndroid Build Coastguard Worker SDValue
LowerToTLSLocalExecModel(GlobalAddressSDNode * GA,SelectionDAG & DAG) const1627*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerToTLSLocalExecModel(GlobalAddressSDNode *GA,
1628*9880d681SAndroid Build Coastguard Worker       SelectionDAG &DAG) const {
1629*9880d681SAndroid Build Coastguard Worker   SDLoc dl(GA);
1630*9880d681SAndroid Build Coastguard Worker   int64_t Offset = GA->getOffset();
1631*9880d681SAndroid Build Coastguard Worker   auto PtrVT = getPointerTy(DAG.getDataLayout());
1632*9880d681SAndroid Build Coastguard Worker 
1633*9880d681SAndroid Build Coastguard Worker   // Get the thread pointer.
1634*9880d681SAndroid Build Coastguard Worker   SDValue TP = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Hexagon::UGP, PtrVT);
1635*9880d681SAndroid Build Coastguard Worker   // Generate the TLS symbol address
1636*9880d681SAndroid Build Coastguard Worker   SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT, Offset,
1637*9880d681SAndroid Build Coastguard Worker                                            HexagonII::MO_TPREL);
1638*9880d681SAndroid Build Coastguard Worker   SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
1639*9880d681SAndroid Build Coastguard Worker 
1640*9880d681SAndroid Build Coastguard Worker   // Address of the thread local variable is the add of thread
1641*9880d681SAndroid Build Coastguard Worker   // pointer and the offset of the variable.
1642*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(ISD::ADD, dl, PtrVT, TP, Sym);
1643*9880d681SAndroid Build Coastguard Worker }
1644*9880d681SAndroid Build Coastguard Worker 
1645*9880d681SAndroid Build Coastguard Worker //
1646*9880d681SAndroid Build Coastguard Worker // Lower using the general dynamic model for TLS addresses
1647*9880d681SAndroid Build Coastguard Worker //
1648*9880d681SAndroid Build Coastguard Worker SDValue
LowerToTLSGeneralDynamicModel(GlobalAddressSDNode * GA,SelectionDAG & DAG) const1649*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,
1650*9880d681SAndroid Build Coastguard Worker       SelectionDAG &DAG) const {
1651*9880d681SAndroid Build Coastguard Worker   SDLoc dl(GA);
1652*9880d681SAndroid Build Coastguard Worker   int64_t Offset = GA->getOffset();
1653*9880d681SAndroid Build Coastguard Worker   auto PtrVT = getPointerTy(DAG.getDataLayout());
1654*9880d681SAndroid Build Coastguard Worker 
1655*9880d681SAndroid Build Coastguard Worker   // First generate the TLS symbol address
1656*9880d681SAndroid Build Coastguard Worker   SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT, Offset,
1657*9880d681SAndroid Build Coastguard Worker                                            HexagonII::MO_GDGOT);
1658*9880d681SAndroid Build Coastguard Worker 
1659*9880d681SAndroid Build Coastguard Worker   // Then, generate the GOT pointer
1660*9880d681SAndroid Build Coastguard Worker   SDValue GOT = LowerGLOBAL_OFFSET_TABLE(TGA, DAG);
1661*9880d681SAndroid Build Coastguard Worker 
1662*9880d681SAndroid Build Coastguard Worker   // Add the TLS symbol and the GOT pointer
1663*9880d681SAndroid Build Coastguard Worker   SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
1664*9880d681SAndroid Build Coastguard Worker   SDValue Chain = DAG.getNode(ISD::ADD, dl, PtrVT, GOT, Sym);
1665*9880d681SAndroid Build Coastguard Worker 
1666*9880d681SAndroid Build Coastguard Worker   // Copy over the argument to R0
1667*9880d681SAndroid Build Coastguard Worker   SDValue InFlag;
1668*9880d681SAndroid Build Coastguard Worker   Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, Hexagon::R0, Chain, InFlag);
1669*9880d681SAndroid Build Coastguard Worker   InFlag = Chain.getValue(1);
1670*9880d681SAndroid Build Coastguard Worker 
1671*9880d681SAndroid Build Coastguard Worker   return GetDynamicTLSAddr(DAG, Chain, GA, &InFlag, PtrVT,
1672*9880d681SAndroid Build Coastguard Worker                            Hexagon::R0, HexagonII::MO_GDPLT);
1673*9880d681SAndroid Build Coastguard Worker }
1674*9880d681SAndroid Build Coastguard Worker 
1675*9880d681SAndroid Build Coastguard Worker //
1676*9880d681SAndroid Build Coastguard Worker // Lower TLS addresses.
1677*9880d681SAndroid Build Coastguard Worker //
1678*9880d681SAndroid Build Coastguard Worker // For now for dynamic models, we only support the general dynamic model.
1679*9880d681SAndroid Build Coastguard Worker //
1680*9880d681SAndroid Build Coastguard Worker SDValue
LowerGlobalTLSAddress(SDValue Op,SelectionDAG & DAG) const1681*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerGlobalTLSAddress(SDValue Op,
1682*9880d681SAndroid Build Coastguard Worker       SelectionDAG &DAG) const {
1683*9880d681SAndroid Build Coastguard Worker   GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
1684*9880d681SAndroid Build Coastguard Worker 
1685*9880d681SAndroid Build Coastguard Worker   switch (HTM.getTLSModel(GA->getGlobal())) {
1686*9880d681SAndroid Build Coastguard Worker     case TLSModel::GeneralDynamic:
1687*9880d681SAndroid Build Coastguard Worker     case TLSModel::LocalDynamic:
1688*9880d681SAndroid Build Coastguard Worker       return LowerToTLSGeneralDynamicModel(GA, DAG);
1689*9880d681SAndroid Build Coastguard Worker     case TLSModel::InitialExec:
1690*9880d681SAndroid Build Coastguard Worker       return LowerToTLSInitialExecModel(GA, DAG);
1691*9880d681SAndroid Build Coastguard Worker     case TLSModel::LocalExec:
1692*9880d681SAndroid Build Coastguard Worker       return LowerToTLSLocalExecModel(GA, DAG);
1693*9880d681SAndroid Build Coastguard Worker   }
1694*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Bogus TLS model");
1695*9880d681SAndroid Build Coastguard Worker }
1696*9880d681SAndroid Build Coastguard Worker 
1697*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1698*9880d681SAndroid Build Coastguard Worker // TargetLowering Implementation
1699*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1700*9880d681SAndroid Build Coastguard Worker 
HexagonTargetLowering(const TargetMachine & TM,const HexagonSubtarget & ST)1701*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
1702*9880d681SAndroid Build Coastguard Worker                                              const HexagonSubtarget &ST)
1703*9880d681SAndroid Build Coastguard Worker     : TargetLowering(TM), HTM(static_cast<const HexagonTargetMachine&>(TM)),
1704*9880d681SAndroid Build Coastguard Worker       Subtarget(ST) {
1705*9880d681SAndroid Build Coastguard Worker   bool IsV4 = !Subtarget.hasV5TOps();
1706*9880d681SAndroid Build Coastguard Worker   auto &HRI = *Subtarget.getRegisterInfo();
1707*9880d681SAndroid Build Coastguard Worker   bool UseHVX = Subtarget.useHVXOps();
1708*9880d681SAndroid Build Coastguard Worker   bool UseHVXSgl = Subtarget.useHVXSglOps();
1709*9880d681SAndroid Build Coastguard Worker   bool UseHVXDbl = Subtarget.useHVXDblOps();
1710*9880d681SAndroid Build Coastguard Worker 
1711*9880d681SAndroid Build Coastguard Worker   setPrefLoopAlignment(4);
1712*9880d681SAndroid Build Coastguard Worker   setPrefFunctionAlignment(4);
1713*9880d681SAndroid Build Coastguard Worker   setMinFunctionAlignment(2);
1714*9880d681SAndroid Build Coastguard Worker   setStackPointerRegisterToSaveRestore(HRI.getStackRegister());
1715*9880d681SAndroid Build Coastguard Worker 
1716*9880d681SAndroid Build Coastguard Worker   setMaxAtomicSizeInBitsSupported(64);
1717*9880d681SAndroid Build Coastguard Worker   setMinCmpXchgSizeInBits(32);
1718*9880d681SAndroid Build Coastguard Worker 
1719*9880d681SAndroid Build Coastguard Worker   if (EnableHexSDNodeSched)
1720*9880d681SAndroid Build Coastguard Worker     setSchedulingPreference(Sched::VLIW);
1721*9880d681SAndroid Build Coastguard Worker   else
1722*9880d681SAndroid Build Coastguard Worker     setSchedulingPreference(Sched::Source);
1723*9880d681SAndroid Build Coastguard Worker 
1724*9880d681SAndroid Build Coastguard Worker   // Limits for inline expansion of memcpy/memmove
1725*9880d681SAndroid Build Coastguard Worker   MaxStoresPerMemcpy = MaxStoresPerMemcpyCL;
1726*9880d681SAndroid Build Coastguard Worker   MaxStoresPerMemcpyOptSize = MaxStoresPerMemcpyOptSizeCL;
1727*9880d681SAndroid Build Coastguard Worker   MaxStoresPerMemmove = MaxStoresPerMemmoveCL;
1728*9880d681SAndroid Build Coastguard Worker   MaxStoresPerMemmoveOptSize = MaxStoresPerMemmoveOptSizeCL;
1729*9880d681SAndroid Build Coastguard Worker   MaxStoresPerMemset = MaxStoresPerMemsetCL;
1730*9880d681SAndroid Build Coastguard Worker   MaxStoresPerMemsetOptSize = MaxStoresPerMemsetOptSizeCL;
1731*9880d681SAndroid Build Coastguard Worker 
1732*9880d681SAndroid Build Coastguard Worker   //
1733*9880d681SAndroid Build Coastguard Worker   // Set up register classes.
1734*9880d681SAndroid Build Coastguard Worker   //
1735*9880d681SAndroid Build Coastguard Worker 
1736*9880d681SAndroid Build Coastguard Worker   addRegisterClass(MVT::i1,    &Hexagon::PredRegsRegClass);
1737*9880d681SAndroid Build Coastguard Worker   addRegisterClass(MVT::v2i1,  &Hexagon::PredRegsRegClass);  // bbbbaaaa
1738*9880d681SAndroid Build Coastguard Worker   addRegisterClass(MVT::v4i1,  &Hexagon::PredRegsRegClass);  // ddccbbaa
1739*9880d681SAndroid Build Coastguard Worker   addRegisterClass(MVT::v8i1,  &Hexagon::PredRegsRegClass);  // hgfedcba
1740*9880d681SAndroid Build Coastguard Worker   addRegisterClass(MVT::i32,   &Hexagon::IntRegsRegClass);
1741*9880d681SAndroid Build Coastguard Worker   addRegisterClass(MVT::v4i8,  &Hexagon::IntRegsRegClass);
1742*9880d681SAndroid Build Coastguard Worker   addRegisterClass(MVT::v2i16, &Hexagon::IntRegsRegClass);
1743*9880d681SAndroid Build Coastguard Worker   addRegisterClass(MVT::i64,   &Hexagon::DoubleRegsRegClass);
1744*9880d681SAndroid Build Coastguard Worker   addRegisterClass(MVT::v8i8,  &Hexagon::DoubleRegsRegClass);
1745*9880d681SAndroid Build Coastguard Worker   addRegisterClass(MVT::v4i16, &Hexagon::DoubleRegsRegClass);
1746*9880d681SAndroid Build Coastguard Worker   addRegisterClass(MVT::v2i32, &Hexagon::DoubleRegsRegClass);
1747*9880d681SAndroid Build Coastguard Worker 
1748*9880d681SAndroid Build Coastguard Worker   if (Subtarget.hasV5TOps()) {
1749*9880d681SAndroid Build Coastguard Worker     addRegisterClass(MVT::f32, &Hexagon::IntRegsRegClass);
1750*9880d681SAndroid Build Coastguard Worker     addRegisterClass(MVT::f64, &Hexagon::DoubleRegsRegClass);
1751*9880d681SAndroid Build Coastguard Worker   }
1752*9880d681SAndroid Build Coastguard Worker 
1753*9880d681SAndroid Build Coastguard Worker   if (Subtarget.hasV60TOps()) {
1754*9880d681SAndroid Build Coastguard Worker     if (Subtarget.useHVXSglOps()) {
1755*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v64i8,  &Hexagon::VectorRegsRegClass);
1756*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v32i16, &Hexagon::VectorRegsRegClass);
1757*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v16i32, &Hexagon::VectorRegsRegClass);
1758*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v8i64,  &Hexagon::VectorRegsRegClass);
1759*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v128i8, &Hexagon::VecDblRegsRegClass);
1760*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v64i16, &Hexagon::VecDblRegsRegClass);
1761*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v32i32, &Hexagon::VecDblRegsRegClass);
1762*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v16i64, &Hexagon::VecDblRegsRegClass);
1763*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v512i1, &Hexagon::VecPredRegsRegClass);
1764*9880d681SAndroid Build Coastguard Worker     } else if (Subtarget.useHVXDblOps()) {
1765*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v128i8,  &Hexagon::VectorRegs128BRegClass);
1766*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v64i16,  &Hexagon::VectorRegs128BRegClass);
1767*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v32i32,  &Hexagon::VectorRegs128BRegClass);
1768*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v16i64,  &Hexagon::VectorRegs128BRegClass);
1769*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v256i8,  &Hexagon::VecDblRegs128BRegClass);
1770*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v128i16, &Hexagon::VecDblRegs128BRegClass);
1771*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v64i32,  &Hexagon::VecDblRegs128BRegClass);
1772*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v32i64,  &Hexagon::VecDblRegs128BRegClass);
1773*9880d681SAndroid Build Coastguard Worker       addRegisterClass(MVT::v1024i1, &Hexagon::VecPredRegs128BRegClass);
1774*9880d681SAndroid Build Coastguard Worker     }
1775*9880d681SAndroid Build Coastguard Worker 
1776*9880d681SAndroid Build Coastguard Worker   }
1777*9880d681SAndroid Build Coastguard Worker 
1778*9880d681SAndroid Build Coastguard Worker   //
1779*9880d681SAndroid Build Coastguard Worker   // Handling of scalar operations.
1780*9880d681SAndroid Build Coastguard Worker   //
1781*9880d681SAndroid Build Coastguard Worker   // All operations default to "legal", except:
1782*9880d681SAndroid Build Coastguard Worker   // - indexed loads and stores (pre-/post-incremented),
1783*9880d681SAndroid Build Coastguard Worker   // - ANY_EXTEND_VECTOR_INREG, ATOMIC_CMP_SWAP_WITH_SUCCESS, CONCAT_VECTORS,
1784*9880d681SAndroid Build Coastguard Worker   //   ConstantFP, DEBUGTRAP, FCEIL, FCOPYSIGN, FEXP, FEXP2, FFLOOR, FGETSIGN,
1785*9880d681SAndroid Build Coastguard Worker   //   FLOG, FLOG2, FLOG10, FMAXNUM, FMINNUM, FNEARBYINT, FRINT, FROUND, TRAP,
1786*9880d681SAndroid Build Coastguard Worker   //   FTRUNC, PREFETCH, SIGN_EXTEND_VECTOR_INREG, ZERO_EXTEND_VECTOR_INREG,
1787*9880d681SAndroid Build Coastguard Worker   // which default to "expand" for at least one type.
1788*9880d681SAndroid Build Coastguard Worker 
1789*9880d681SAndroid Build Coastguard Worker   // Misc operations.
1790*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::ConstantFP, MVT::f32, Legal); // Default: expand
1791*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::ConstantFP, MVT::f64, Legal); // Default: expand
1792*9880d681SAndroid Build Coastguard Worker 
1793*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
1794*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::JumpTable, MVT::i32, Custom);
1795*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
1796*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
1797*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::INLINEASM, MVT::Other, Custom);
1798*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::PREFETCH, MVT::Other, Custom);
1799*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
1800*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);
1801*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::GLOBAL_OFFSET_TABLE, MVT::i32, Custom);
1802*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
1803*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
1804*9880d681SAndroid Build Coastguard Worker 
1805*9880d681SAndroid Build Coastguard Worker   // Custom legalize GlobalAddress nodes into CONST32.
1806*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
1807*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::GlobalAddress, MVT::i8,  Custom);
1808*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::BlockAddress,  MVT::i32, Custom);
1809*9880d681SAndroid Build Coastguard Worker 
1810*9880d681SAndroid Build Coastguard Worker   // Hexagon needs to optimize cases with negative constants.
1811*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::SETCC, MVT::i8,  Custom);
1812*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::SETCC, MVT::i16, Custom);
1813*9880d681SAndroid Build Coastguard Worker 
1814*9880d681SAndroid Build Coastguard Worker   // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
1815*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::VASTART, MVT::Other, Custom);
1816*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::VAEND,   MVT::Other, Expand);
1817*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::VAARG,   MVT::Other, Expand);
1818*9880d681SAndroid Build Coastguard Worker 
1819*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
1820*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
1821*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
1822*9880d681SAndroid Build Coastguard Worker 
1823*9880d681SAndroid Build Coastguard Worker   if (EmitJumpTables)
1824*9880d681SAndroid Build Coastguard Worker     setMinimumJumpTableEntries(MinimumJumpTables);
1825*9880d681SAndroid Build Coastguard Worker   else
1826*9880d681SAndroid Build Coastguard Worker     setMinimumJumpTableEntries(INT_MAX);
1827*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::BR_JT, MVT::Other, Expand);
1828*9880d681SAndroid Build Coastguard Worker 
1829*9880d681SAndroid Build Coastguard Worker   // Hexagon has instructions for add/sub with carry. The problem with
1830*9880d681SAndroid Build Coastguard Worker   // modeling these instructions is that they produce 2 results: Rdd and Px.
1831*9880d681SAndroid Build Coastguard Worker   // To model the update of Px, we will have to use Defs[p0..p3] which will
1832*9880d681SAndroid Build Coastguard Worker   // cause any predicate live range to spill. So, we pretend we dont't have
1833*9880d681SAndroid Build Coastguard Worker   // these instructions.
1834*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::ADDE, MVT::i8,  Expand);
1835*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::ADDE, MVT::i16, Expand);
1836*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::ADDE, MVT::i32, Expand);
1837*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::ADDE, MVT::i64, Expand);
1838*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::SUBE, MVT::i8,  Expand);
1839*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::SUBE, MVT::i16, Expand);
1840*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::SUBE, MVT::i32, Expand);
1841*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::SUBE, MVT::i64, Expand);
1842*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::ADDC, MVT::i8,  Expand);
1843*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::ADDC, MVT::i16, Expand);
1844*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::ADDC, MVT::i32, Expand);
1845*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::ADDC, MVT::i64, Expand);
1846*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::SUBC, MVT::i8,  Expand);
1847*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::SUBC, MVT::i16, Expand);
1848*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::SUBC, MVT::i32, Expand);
1849*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::SUBC, MVT::i64, Expand);
1850*9880d681SAndroid Build Coastguard Worker 
1851*9880d681SAndroid Build Coastguard Worker   // Only add and sub that detect overflow are the saturating ones.
1852*9880d681SAndroid Build Coastguard Worker   for (MVT VT : MVT::integer_valuetypes()) {
1853*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::UADDO, VT, Expand);
1854*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SADDO, VT, Expand);
1855*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::USUBO, VT, Expand);
1856*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SSUBO, VT, Expand);
1857*9880d681SAndroid Build Coastguard Worker   }
1858*9880d681SAndroid Build Coastguard Worker 
1859*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::CTLZ, MVT::i8,  Promote);
1860*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::CTLZ, MVT::i16, Promote);
1861*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::CTTZ, MVT::i8,  Promote);
1862*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::CTTZ, MVT::i16, Promote);
1863*9880d681SAndroid Build Coastguard Worker 
1864*9880d681SAndroid Build Coastguard Worker   // In V5, popcount can count # of 1s in i64 but returns i32.
1865*9880d681SAndroid Build Coastguard Worker   // On V4 it will be expanded (set later).
1866*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::CTPOP, MVT::i8,  Promote);
1867*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::CTPOP, MVT::i16, Promote);
1868*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::CTPOP, MVT::i32, Promote);
1869*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::CTPOP, MVT::i64, Custom);
1870*9880d681SAndroid Build Coastguard Worker 
1871*9880d681SAndroid Build Coastguard Worker   // We custom lower i64 to i64 mul, so that it is not considered as a legal
1872*9880d681SAndroid Build Coastguard Worker   // operation. There is a pattern that will match i64 mul and transform it
1873*9880d681SAndroid Build Coastguard Worker   // to a series of instructions.
1874*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::MUL,   MVT::i64, Expand);
1875*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::MULHS, MVT::i64, Expand);
1876*9880d681SAndroid Build Coastguard Worker 
1877*9880d681SAndroid Build Coastguard Worker   for (unsigned IntExpOp :
1878*9880d681SAndroid Build Coastguard Worker        { ISD::SDIV,      ISD::UDIV,      ISD::SREM,      ISD::UREM,
1879*9880d681SAndroid Build Coastguard Worker          ISD::SDIVREM,   ISD::UDIVREM,   ISD::ROTL,      ISD::ROTR,
1880*9880d681SAndroid Build Coastguard Worker          ISD::BSWAP,     ISD::SHL_PARTS, ISD::SRA_PARTS, ISD::SRL_PARTS,
1881*9880d681SAndroid Build Coastguard Worker          ISD::SMUL_LOHI, ISD::UMUL_LOHI }) {
1882*9880d681SAndroid Build Coastguard Worker     setOperationAction(IntExpOp, MVT::i32, Expand);
1883*9880d681SAndroid Build Coastguard Worker     setOperationAction(IntExpOp, MVT::i64, Expand);
1884*9880d681SAndroid Build Coastguard Worker   }
1885*9880d681SAndroid Build Coastguard Worker 
1886*9880d681SAndroid Build Coastguard Worker   for (unsigned FPExpOp :
1887*9880d681SAndroid Build Coastguard Worker        {ISD::FDIV, ISD::FREM, ISD::FSQRT, ISD::FSIN, ISD::FCOS, ISD::FSINCOS,
1888*9880d681SAndroid Build Coastguard Worker         ISD::FPOW, ISD::FCOPYSIGN}) {
1889*9880d681SAndroid Build Coastguard Worker     setOperationAction(FPExpOp, MVT::f32, Expand);
1890*9880d681SAndroid Build Coastguard Worker     setOperationAction(FPExpOp, MVT::f64, Expand);
1891*9880d681SAndroid Build Coastguard Worker   }
1892*9880d681SAndroid Build Coastguard Worker 
1893*9880d681SAndroid Build Coastguard Worker   // No extending loads from i32.
1894*9880d681SAndroid Build Coastguard Worker   for (MVT VT : MVT::integer_valuetypes()) {
1895*9880d681SAndroid Build Coastguard Worker     setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i32, Expand);
1896*9880d681SAndroid Build Coastguard Worker     setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i32, Expand);
1897*9880d681SAndroid Build Coastguard Worker     setLoadExtAction(ISD::EXTLOAD,  VT, MVT::i32, Expand);
1898*9880d681SAndroid Build Coastguard Worker   }
1899*9880d681SAndroid Build Coastguard Worker   // Turn FP truncstore into trunc + store.
1900*9880d681SAndroid Build Coastguard Worker   setTruncStoreAction(MVT::f64, MVT::f32, Expand);
1901*9880d681SAndroid Build Coastguard Worker   // Turn FP extload into load/fextend.
1902*9880d681SAndroid Build Coastguard Worker   for (MVT VT : MVT::fp_valuetypes())
1903*9880d681SAndroid Build Coastguard Worker     setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand);
1904*9880d681SAndroid Build Coastguard Worker 
1905*9880d681SAndroid Build Coastguard Worker   // Expand BR_CC and SELECT_CC for all integer and fp types.
1906*9880d681SAndroid Build Coastguard Worker   for (MVT VT : MVT::integer_valuetypes()) {
1907*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::BR_CC,     VT, Expand);
1908*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SELECT_CC, VT, Expand);
1909*9880d681SAndroid Build Coastguard Worker   }
1910*9880d681SAndroid Build Coastguard Worker   for (MVT VT : MVT::fp_valuetypes()) {
1911*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::BR_CC,     VT, Expand);
1912*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SELECT_CC, VT, Expand);
1913*9880d681SAndroid Build Coastguard Worker   }
1914*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::BR_CC, MVT::Other, Expand);
1915*9880d681SAndroid Build Coastguard Worker 
1916*9880d681SAndroid Build Coastguard Worker   //
1917*9880d681SAndroid Build Coastguard Worker   // Handling of vector operations.
1918*9880d681SAndroid Build Coastguard Worker   //
1919*9880d681SAndroid Build Coastguard Worker 
1920*9880d681SAndroid Build Coastguard Worker   // Custom lower v4i16 load only. Let v4i16 store to be
1921*9880d681SAndroid Build Coastguard Worker   // promoted for now.
1922*9880d681SAndroid Build Coastguard Worker   promoteLdStType(MVT::v4i8,  MVT::i32);
1923*9880d681SAndroid Build Coastguard Worker   promoteLdStType(MVT::v2i16, MVT::i32);
1924*9880d681SAndroid Build Coastguard Worker   promoteLdStType(MVT::v8i8,  MVT::i64);
1925*9880d681SAndroid Build Coastguard Worker   promoteLdStType(MVT::v2i32, MVT::i64);
1926*9880d681SAndroid Build Coastguard Worker 
1927*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::LOAD,  MVT::v4i16, Custom);
1928*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::STORE, MVT::v4i16, Promote);
1929*9880d681SAndroid Build Coastguard Worker   AddPromotedToType(ISD::LOAD,  MVT::v4i16, MVT::i64);
1930*9880d681SAndroid Build Coastguard Worker   AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::i64);
1931*9880d681SAndroid Build Coastguard Worker 
1932*9880d681SAndroid Build Coastguard Worker   // Set the action for vector operations to "expand", then override it with
1933*9880d681SAndroid Build Coastguard Worker   // either "custom" or "legal" for specific cases.
1934*9880d681SAndroid Build Coastguard Worker   static const unsigned VectExpOps[] = {
1935*9880d681SAndroid Build Coastguard Worker     // Integer arithmetic:
1936*9880d681SAndroid Build Coastguard Worker     ISD::ADD,     ISD::SUB,     ISD::MUL,     ISD::SDIV,    ISD::UDIV,
1937*9880d681SAndroid Build Coastguard Worker     ISD::SREM,    ISD::UREM,    ISD::SDIVREM, ISD::UDIVREM, ISD::ADDC,
1938*9880d681SAndroid Build Coastguard Worker     ISD::SUBC,    ISD::SADDO,   ISD::UADDO,   ISD::SSUBO,   ISD::USUBO,
1939*9880d681SAndroid Build Coastguard Worker     ISD::SMUL_LOHI,             ISD::UMUL_LOHI,
1940*9880d681SAndroid Build Coastguard Worker     // Logical/bit:
1941*9880d681SAndroid Build Coastguard Worker     ISD::AND,     ISD::OR,      ISD::XOR,     ISD::ROTL,    ISD::ROTR,
1942*9880d681SAndroid Build Coastguard Worker     ISD::CTPOP,   ISD::CTLZ,    ISD::CTTZ,
1943*9880d681SAndroid Build Coastguard Worker     // Floating point arithmetic/math functions:
1944*9880d681SAndroid Build Coastguard Worker     ISD::FADD,    ISD::FSUB,    ISD::FMUL,    ISD::FMA,     ISD::FDIV,
1945*9880d681SAndroid Build Coastguard Worker     ISD::FREM,    ISD::FNEG,    ISD::FABS,    ISD::FSQRT,   ISD::FSIN,
1946*9880d681SAndroid Build Coastguard Worker     ISD::FCOS,    ISD::FPOWI,   ISD::FPOW,    ISD::FLOG,    ISD::FLOG2,
1947*9880d681SAndroid Build Coastguard Worker     ISD::FLOG10,  ISD::FEXP,    ISD::FEXP2,   ISD::FCEIL,   ISD::FTRUNC,
1948*9880d681SAndroid Build Coastguard Worker     ISD::FRINT,   ISD::FNEARBYINT,            ISD::FROUND,  ISD::FFLOOR,
1949*9880d681SAndroid Build Coastguard Worker     ISD::FMINNUM, ISD::FMAXNUM, ISD::FSINCOS,
1950*9880d681SAndroid Build Coastguard Worker     // Misc:
1951*9880d681SAndroid Build Coastguard Worker     ISD::SELECT,  ISD::ConstantPool,
1952*9880d681SAndroid Build Coastguard Worker     // Vector:
1953*9880d681SAndroid Build Coastguard Worker     ISD::BUILD_VECTOR,          ISD::SCALAR_TO_VECTOR,
1954*9880d681SAndroid Build Coastguard Worker     ISD::EXTRACT_VECTOR_ELT,    ISD::INSERT_VECTOR_ELT,
1955*9880d681SAndroid Build Coastguard Worker     ISD::EXTRACT_SUBVECTOR,     ISD::INSERT_SUBVECTOR,
1956*9880d681SAndroid Build Coastguard Worker     ISD::CONCAT_VECTORS,        ISD::VECTOR_SHUFFLE
1957*9880d681SAndroid Build Coastguard Worker   };
1958*9880d681SAndroid Build Coastguard Worker 
1959*9880d681SAndroid Build Coastguard Worker   for (MVT VT : MVT::vector_valuetypes()) {
1960*9880d681SAndroid Build Coastguard Worker     for (unsigned VectExpOp : VectExpOps)
1961*9880d681SAndroid Build Coastguard Worker       setOperationAction(VectExpOp, VT, Expand);
1962*9880d681SAndroid Build Coastguard Worker 
1963*9880d681SAndroid Build Coastguard Worker     // Expand all extended loads and truncating stores:
1964*9880d681SAndroid Build Coastguard Worker     for (MVT TargetVT : MVT::vector_valuetypes()) {
1965*9880d681SAndroid Build Coastguard Worker       setLoadExtAction(ISD::EXTLOAD, TargetVT, VT, Expand);
1966*9880d681SAndroid Build Coastguard Worker       setTruncStoreAction(VT, TargetVT, Expand);
1967*9880d681SAndroid Build Coastguard Worker     }
1968*9880d681SAndroid Build Coastguard Worker 
1969*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SRA, VT, Custom);
1970*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SHL, VT, Custom);
1971*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SRL, VT, Custom);
1972*9880d681SAndroid Build Coastguard Worker   }
1973*9880d681SAndroid Build Coastguard Worker 
1974*9880d681SAndroid Build Coastguard Worker   // Types natively supported:
1975*9880d681SAndroid Build Coastguard Worker   for (MVT NativeVT : {MVT::v2i1, MVT::v4i1, MVT::v8i1, MVT::v32i1, MVT::v64i1,
1976*9880d681SAndroid Build Coastguard Worker                        MVT::v4i8, MVT::v8i8, MVT::v2i16, MVT::v4i16, MVT::v1i32,
1977*9880d681SAndroid Build Coastguard Worker                        MVT::v2i32, MVT::v1i64}) {
1978*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::BUILD_VECTOR,       NativeVT, Custom);
1979*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::EXTRACT_VECTOR_ELT, NativeVT, Custom);
1980*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::INSERT_VECTOR_ELT,  NativeVT, Custom);
1981*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::EXTRACT_SUBVECTOR,  NativeVT, Custom);
1982*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::INSERT_SUBVECTOR,   NativeVT, Custom);
1983*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::CONCAT_VECTORS,     NativeVT, Custom);
1984*9880d681SAndroid Build Coastguard Worker 
1985*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::ADD, NativeVT, Legal);
1986*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SUB, NativeVT, Legal);
1987*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::MUL, NativeVT, Legal);
1988*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::AND, NativeVT, Legal);
1989*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::OR,  NativeVT, Legal);
1990*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::XOR, NativeVT, Legal);
1991*9880d681SAndroid Build Coastguard Worker   }
1992*9880d681SAndroid Build Coastguard Worker 
1993*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::SETCC,          MVT::v2i16, Custom);
1994*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::VSELECT,        MVT::v2i16, Custom);
1995*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v4i16, Custom);
1996*9880d681SAndroid Build Coastguard Worker   setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v8i8,  Custom);
1997*9880d681SAndroid Build Coastguard Worker   if (UseHVX) {
1998*9880d681SAndroid Build Coastguard Worker     if (UseHVXSgl) {
1999*9880d681SAndroid Build Coastguard Worker       setOperationAction(ISD::CONCAT_VECTORS, MVT::v128i8,  Custom);
2000*9880d681SAndroid Build Coastguard Worker       setOperationAction(ISD::CONCAT_VECTORS, MVT::v64i16,  Custom);
2001*9880d681SAndroid Build Coastguard Worker       setOperationAction(ISD::CONCAT_VECTORS, MVT::v32i32,  Custom);
2002*9880d681SAndroid Build Coastguard Worker       setOperationAction(ISD::CONCAT_VECTORS, MVT::v16i64,  Custom);
2003*9880d681SAndroid Build Coastguard Worker     } else if (UseHVXDbl) {
2004*9880d681SAndroid Build Coastguard Worker       setOperationAction(ISD::CONCAT_VECTORS, MVT::v256i8,  Custom);
2005*9880d681SAndroid Build Coastguard Worker       setOperationAction(ISD::CONCAT_VECTORS, MVT::v128i16, Custom);
2006*9880d681SAndroid Build Coastguard Worker       setOperationAction(ISD::CONCAT_VECTORS, MVT::v64i32,  Custom);
2007*9880d681SAndroid Build Coastguard Worker       setOperationAction(ISD::CONCAT_VECTORS, MVT::v32i64,  Custom);
2008*9880d681SAndroid Build Coastguard Worker     } else {
2009*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Unrecognized HVX mode");
2010*9880d681SAndroid Build Coastguard Worker     }
2011*9880d681SAndroid Build Coastguard Worker   }
2012*9880d681SAndroid Build Coastguard Worker   // Subtarget-specific operation actions.
2013*9880d681SAndroid Build Coastguard Worker   //
2014*9880d681SAndroid Build Coastguard Worker   if (Subtarget.hasV5TOps()) {
2015*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FMA,  MVT::f64, Expand);
2016*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FADD, MVT::f64, Expand);
2017*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FSUB, MVT::f64, Expand);
2018*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FMUL, MVT::f64, Expand);
2019*9880d681SAndroid Build Coastguard Worker 
2020*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FP_TO_UINT, MVT::i1,  Promote);
2021*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FP_TO_UINT, MVT::i8,  Promote);
2022*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FP_TO_UINT, MVT::i16, Promote);
2023*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FP_TO_SINT, MVT::i1,  Promote);
2024*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FP_TO_SINT, MVT::i8,  Promote);
2025*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FP_TO_SINT, MVT::i16, Promote);
2026*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::UINT_TO_FP, MVT::i1,  Promote);
2027*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::UINT_TO_FP, MVT::i8,  Promote);
2028*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
2029*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SINT_TO_FP, MVT::i1,  Promote);
2030*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SINT_TO_FP, MVT::i8,  Promote);
2031*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
2032*9880d681SAndroid Build Coastguard Worker 
2033*9880d681SAndroid Build Coastguard Worker   } else { // V4
2034*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand);
2035*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::SINT_TO_FP, MVT::i64, Expand);
2036*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand);
2037*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand);
2038*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FP_TO_SINT, MVT::f64, Expand);
2039*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FP_TO_SINT, MVT::f32, Expand);
2040*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FP_EXTEND,  MVT::f32, Expand);
2041*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::FP_ROUND,   MVT::f64, Expand);
2042*9880d681SAndroid Build Coastguard Worker     setCondCodeAction(ISD::SETUNE, MVT::f64, Expand);
2043*9880d681SAndroid Build Coastguard Worker 
2044*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::CTPOP, MVT::i8,  Expand);
2045*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::CTPOP, MVT::i16, Expand);
2046*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::CTPOP, MVT::i32, Expand);
2047*9880d681SAndroid Build Coastguard Worker     setOperationAction(ISD::CTPOP, MVT::i64, Expand);
2048*9880d681SAndroid Build Coastguard Worker 
2049*9880d681SAndroid Build Coastguard Worker     // Expand these operations for both f32 and f64:
2050*9880d681SAndroid Build Coastguard Worker     for (unsigned FPExpOpV4 :
2051*9880d681SAndroid Build Coastguard Worker          {ISD::FADD, ISD::FSUB, ISD::FMUL, ISD::FABS, ISD::FNEG, ISD::FMA}) {
2052*9880d681SAndroid Build Coastguard Worker       setOperationAction(FPExpOpV4, MVT::f32, Expand);
2053*9880d681SAndroid Build Coastguard Worker       setOperationAction(FPExpOpV4, MVT::f64, Expand);
2054*9880d681SAndroid Build Coastguard Worker     }
2055*9880d681SAndroid Build Coastguard Worker 
2056*9880d681SAndroid Build Coastguard Worker     for (ISD::CondCode FPExpCCV4 :
2057*9880d681SAndroid Build Coastguard Worker          {ISD::SETOEQ, ISD::SETOGT, ISD::SETOLT, ISD::SETOGE, ISD::SETOLE,
2058*9880d681SAndroid Build Coastguard Worker           ISD::SETUO,  ISD::SETO}) {
2059*9880d681SAndroid Build Coastguard Worker       setCondCodeAction(FPExpCCV4, MVT::f32, Expand);
2060*9880d681SAndroid Build Coastguard Worker       setCondCodeAction(FPExpCCV4, MVT::f64, Expand);
2061*9880d681SAndroid Build Coastguard Worker     }
2062*9880d681SAndroid Build Coastguard Worker   }
2063*9880d681SAndroid Build Coastguard Worker 
2064*9880d681SAndroid Build Coastguard Worker   // Handling of indexed loads/stores: default is "expand".
2065*9880d681SAndroid Build Coastguard Worker   //
2066*9880d681SAndroid Build Coastguard Worker   for (MVT LSXTy : {MVT::i8, MVT::i16, MVT::i32, MVT::i64}) {
2067*9880d681SAndroid Build Coastguard Worker     setIndexedLoadAction(ISD::POST_INC, LSXTy, Legal);
2068*9880d681SAndroid Build Coastguard Worker     setIndexedStoreAction(ISD::POST_INC, LSXTy, Legal);
2069*9880d681SAndroid Build Coastguard Worker   }
2070*9880d681SAndroid Build Coastguard Worker 
2071*9880d681SAndroid Build Coastguard Worker   if (UseHVXDbl) {
2072*9880d681SAndroid Build Coastguard Worker     for (MVT VT : {MVT::v128i8, MVT::v64i16, MVT::v32i32, MVT::v16i64}) {
2073*9880d681SAndroid Build Coastguard Worker       setIndexedLoadAction(ISD::POST_INC, VT, Legal);
2074*9880d681SAndroid Build Coastguard Worker       setIndexedStoreAction(ISD::POST_INC, VT, Legal);
2075*9880d681SAndroid Build Coastguard Worker     }
2076*9880d681SAndroid Build Coastguard Worker   }
2077*9880d681SAndroid Build Coastguard Worker 
2078*9880d681SAndroid Build Coastguard Worker   computeRegisterProperties(&HRI);
2079*9880d681SAndroid Build Coastguard Worker 
2080*9880d681SAndroid Build Coastguard Worker   //
2081*9880d681SAndroid Build Coastguard Worker   // Library calls for unsupported operations
2082*9880d681SAndroid Build Coastguard Worker   //
2083*9880d681SAndroid Build Coastguard Worker   bool FastMath  = EnableFastMath;
2084*9880d681SAndroid Build Coastguard Worker 
2085*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::SDIV_I32, "__hexagon_divsi3");
2086*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::SDIV_I64, "__hexagon_divdi3");
2087*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::UDIV_I32, "__hexagon_udivsi3");
2088*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::UDIV_I64, "__hexagon_udivdi3");
2089*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::SREM_I32, "__hexagon_modsi3");
2090*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::SREM_I64, "__hexagon_moddi3");
2091*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::UREM_I32, "__hexagon_umodsi3");
2092*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::UREM_I64, "__hexagon_umoddi3");
2093*9880d681SAndroid Build Coastguard Worker 
2094*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::SINTTOFP_I128_F64, "__hexagon_floattidf");
2095*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::SINTTOFP_I128_F32, "__hexagon_floattisf");
2096*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::FPTOUINT_F32_I128, "__hexagon_fixunssfti");
2097*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::FPTOUINT_F64_I128, "__hexagon_fixunsdfti");
2098*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::FPTOSINT_F32_I128, "__hexagon_fixsfti");
2099*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::FPTOSINT_F64_I128, "__hexagon_fixdfti");
2100*9880d681SAndroid Build Coastguard Worker 
2101*9880d681SAndroid Build Coastguard Worker   if (IsV4) {
2102*9880d681SAndroid Build Coastguard Worker     // Handle single-precision floating point operations on V4.
2103*9880d681SAndroid Build Coastguard Worker     if (FastMath) {
2104*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::ADD_F32, "__hexagon_fast_addsf3");
2105*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::SUB_F32, "__hexagon_fast_subsf3");
2106*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::MUL_F32, "__hexagon_fast_mulsf3");
2107*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::OGT_F32, "__hexagon_fast_gtsf2");
2108*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::OLT_F32, "__hexagon_fast_ltsf2");
2109*9880d681SAndroid Build Coastguard Worker       // Double-precision compares.
2110*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::OGT_F64, "__hexagon_fast_gtdf2");
2111*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::OLT_F64, "__hexagon_fast_ltdf2");
2112*9880d681SAndroid Build Coastguard Worker     } else {
2113*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::ADD_F32, "__hexagon_addsf3");
2114*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::SUB_F32, "__hexagon_subsf3");
2115*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::MUL_F32, "__hexagon_mulsf3");
2116*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::OGT_F32, "__hexagon_gtsf2");
2117*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::OLT_F32, "__hexagon_ltsf2");
2118*9880d681SAndroid Build Coastguard Worker       // Double-precision compares.
2119*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::OGT_F64, "__hexagon_gtdf2");
2120*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::OLT_F64, "__hexagon_ltdf2");
2121*9880d681SAndroid Build Coastguard Worker     }
2122*9880d681SAndroid Build Coastguard Worker   }
2123*9880d681SAndroid Build Coastguard Worker 
2124*9880d681SAndroid Build Coastguard Worker   // This is the only fast library function for sqrtd.
2125*9880d681SAndroid Build Coastguard Worker   if (FastMath)
2126*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::SQRT_F64, "__hexagon_fast2_sqrtdf2");
2127*9880d681SAndroid Build Coastguard Worker 
2128*9880d681SAndroid Build Coastguard Worker   // Prefix is: nothing  for "slow-math",
2129*9880d681SAndroid Build Coastguard Worker   //            "fast2_" for V4 fast-math and V5+ fast-math double-precision
2130*9880d681SAndroid Build Coastguard Worker   // (actually, keep fast-math and fast-math2 separate for now)
2131*9880d681SAndroid Build Coastguard Worker   if (FastMath) {
2132*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::ADD_F64, "__hexagon_fast_adddf3");
2133*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::SUB_F64, "__hexagon_fast_subdf3");
2134*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::MUL_F64, "__hexagon_fast_muldf3");
2135*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::DIV_F64, "__hexagon_fast_divdf3");
2136*9880d681SAndroid Build Coastguard Worker     // Calling __hexagon_fast2_divsf3 with fast-math on V5 (ok).
2137*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::DIV_F32, "__hexagon_fast_divsf3");
2138*9880d681SAndroid Build Coastguard Worker   } else {
2139*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::ADD_F64, "__hexagon_adddf3");
2140*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::SUB_F64, "__hexagon_subdf3");
2141*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::MUL_F64, "__hexagon_muldf3");
2142*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::DIV_F64, "__hexagon_divdf3");
2143*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::DIV_F32, "__hexagon_divsf3");
2144*9880d681SAndroid Build Coastguard Worker   }
2145*9880d681SAndroid Build Coastguard Worker 
2146*9880d681SAndroid Build Coastguard Worker   if (Subtarget.hasV5TOps()) {
2147*9880d681SAndroid Build Coastguard Worker     if (FastMath)
2148*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::SQRT_F32, "__hexagon_fast2_sqrtf");
2149*9880d681SAndroid Build Coastguard Worker     else
2150*9880d681SAndroid Build Coastguard Worker       setLibcallName(RTLIB::SQRT_F32, "__hexagon_sqrtf");
2151*9880d681SAndroid Build Coastguard Worker   } else {
2152*9880d681SAndroid Build Coastguard Worker     // V4
2153*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::SINTTOFP_I32_F32, "__hexagon_floatsisf");
2154*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::SINTTOFP_I32_F64, "__hexagon_floatsidf");
2155*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::SINTTOFP_I64_F32, "__hexagon_floatdisf");
2156*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::SINTTOFP_I64_F64, "__hexagon_floatdidf");
2157*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::UINTTOFP_I32_F32, "__hexagon_floatunsisf");
2158*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::UINTTOFP_I32_F64, "__hexagon_floatunsidf");
2159*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::UINTTOFP_I64_F32, "__hexagon_floatundisf");
2160*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::UINTTOFP_I64_F64, "__hexagon_floatundidf");
2161*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::FPTOUINT_F32_I32, "__hexagon_fixunssfsi");
2162*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::FPTOUINT_F32_I64, "__hexagon_fixunssfdi");
2163*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::FPTOUINT_F64_I32, "__hexagon_fixunsdfsi");
2164*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::FPTOUINT_F64_I64, "__hexagon_fixunsdfdi");
2165*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::FPTOSINT_F32_I32, "__hexagon_fixsfsi");
2166*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::FPTOSINT_F32_I64, "__hexagon_fixsfdi");
2167*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::FPTOSINT_F64_I32, "__hexagon_fixdfsi");
2168*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::FPTOSINT_F64_I64, "__hexagon_fixdfdi");
2169*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::FPEXT_F32_F64,    "__hexagon_extendsfdf2");
2170*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::FPROUND_F64_F32,  "__hexagon_truncdfsf2");
2171*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::OEQ_F32, "__hexagon_eqsf2");
2172*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::OEQ_F64, "__hexagon_eqdf2");
2173*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::OGE_F32, "__hexagon_gesf2");
2174*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::OGE_F64, "__hexagon_gedf2");
2175*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::OLE_F32, "__hexagon_lesf2");
2176*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::OLE_F64, "__hexagon_ledf2");
2177*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::UNE_F32, "__hexagon_nesf2");
2178*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::UNE_F64, "__hexagon_nedf2");
2179*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::UO_F32,  "__hexagon_unordsf2");
2180*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::UO_F64,  "__hexagon_unorddf2");
2181*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::O_F32,   "__hexagon_unordsf2");
2182*9880d681SAndroid Build Coastguard Worker     setLibcallName(RTLIB::O_F64,   "__hexagon_unorddf2");
2183*9880d681SAndroid Build Coastguard Worker   }
2184*9880d681SAndroid Build Coastguard Worker 
2185*9880d681SAndroid Build Coastguard Worker   // These cause problems when the shift amount is non-constant.
2186*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::SHL_I128, nullptr);
2187*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::SRL_I128, nullptr);
2188*9880d681SAndroid Build Coastguard Worker   setLibcallName(RTLIB::SRA_I128, nullptr);
2189*9880d681SAndroid Build Coastguard Worker }
2190*9880d681SAndroid Build Coastguard Worker 
2191*9880d681SAndroid Build Coastguard Worker 
getTargetNodeName(unsigned Opcode) const2192*9880d681SAndroid Build Coastguard Worker const char* HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {
2193*9880d681SAndroid Build Coastguard Worker   switch ((HexagonISD::NodeType)Opcode) {
2194*9880d681SAndroid Build Coastguard Worker   case HexagonISD::ALLOCA:        return "HexagonISD::ALLOCA";
2195*9880d681SAndroid Build Coastguard Worker   case HexagonISD::ARGEXTEND:     return "HexagonISD::ARGEXTEND";
2196*9880d681SAndroid Build Coastguard Worker   case HexagonISD::AT_GOT:        return "HexagonISD::AT_GOT";
2197*9880d681SAndroid Build Coastguard Worker   case HexagonISD::AT_PCREL:      return "HexagonISD::AT_PCREL";
2198*9880d681SAndroid Build Coastguard Worker   case HexagonISD::BARRIER:       return "HexagonISD::BARRIER";
2199*9880d681SAndroid Build Coastguard Worker   case HexagonISD::CALLR:         return "HexagonISD::CALLR";
2200*9880d681SAndroid Build Coastguard Worker   case HexagonISD::CALLv3nr:      return "HexagonISD::CALLv3nr";
2201*9880d681SAndroid Build Coastguard Worker   case HexagonISD::CALLv3:        return "HexagonISD::CALLv3";
2202*9880d681SAndroid Build Coastguard Worker   case HexagonISD::COMBINE:       return "HexagonISD::COMBINE";
2203*9880d681SAndroid Build Coastguard Worker   case HexagonISD::CONST32_GP:    return "HexagonISD::CONST32_GP";
2204*9880d681SAndroid Build Coastguard Worker   case HexagonISD::CONST32:       return "HexagonISD::CONST32";
2205*9880d681SAndroid Build Coastguard Worker   case HexagonISD::CP:            return "HexagonISD::CP";
2206*9880d681SAndroid Build Coastguard Worker   case HexagonISD::DCFETCH:       return "HexagonISD::DCFETCH";
2207*9880d681SAndroid Build Coastguard Worker   case HexagonISD::EH_RETURN:     return "HexagonISD::EH_RETURN";
2208*9880d681SAndroid Build Coastguard Worker   case HexagonISD::EXTRACTU:      return "HexagonISD::EXTRACTU";
2209*9880d681SAndroid Build Coastguard Worker   case HexagonISD::EXTRACTURP:    return "HexagonISD::EXTRACTURP";
2210*9880d681SAndroid Build Coastguard Worker   case HexagonISD::FCONST32:      return "HexagonISD::FCONST32";
2211*9880d681SAndroid Build Coastguard Worker   case HexagonISD::INSERT:        return "HexagonISD::INSERT";
2212*9880d681SAndroid Build Coastguard Worker   case HexagonISD::INSERTRP:      return "HexagonISD::INSERTRP";
2213*9880d681SAndroid Build Coastguard Worker   case HexagonISD::JT:            return "HexagonISD::JT";
2214*9880d681SAndroid Build Coastguard Worker   case HexagonISD::PACKHL:        return "HexagonISD::PACKHL";
2215*9880d681SAndroid Build Coastguard Worker   case HexagonISD::POPCOUNT:      return "HexagonISD::POPCOUNT";
2216*9880d681SAndroid Build Coastguard Worker   case HexagonISD::RET_FLAG:      return "HexagonISD::RET_FLAG";
2217*9880d681SAndroid Build Coastguard Worker   case HexagonISD::SHUFFEB:       return "HexagonISD::SHUFFEB";
2218*9880d681SAndroid Build Coastguard Worker   case HexagonISD::SHUFFEH:       return "HexagonISD::SHUFFEH";
2219*9880d681SAndroid Build Coastguard Worker   case HexagonISD::SHUFFOB:       return "HexagonISD::SHUFFOB";
2220*9880d681SAndroid Build Coastguard Worker   case HexagonISD::SHUFFOH:       return "HexagonISD::SHUFFOH";
2221*9880d681SAndroid Build Coastguard Worker   case HexagonISD::TC_RETURN:     return "HexagonISD::TC_RETURN";
2222*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VCMPBEQ:       return "HexagonISD::VCMPBEQ";
2223*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VCMPBGT:       return "HexagonISD::VCMPBGT";
2224*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VCMPBGTU:      return "HexagonISD::VCMPBGTU";
2225*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VCMPHEQ:       return "HexagonISD::VCMPHEQ";
2226*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VCMPHGT:       return "HexagonISD::VCMPHGT";
2227*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VCMPHGTU:      return "HexagonISD::VCMPHGTU";
2228*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VCMPWEQ:       return "HexagonISD::VCMPWEQ";
2229*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VCMPWGT:       return "HexagonISD::VCMPWGT";
2230*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VCMPWGTU:      return "HexagonISD::VCMPWGTU";
2231*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VCOMBINE:      return "HexagonISD::VCOMBINE";
2232*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VSHLH:         return "HexagonISD::VSHLH";
2233*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VSHLW:         return "HexagonISD::VSHLW";
2234*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VSPLATB:       return "HexagonISD::VSPLTB";
2235*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VSPLATH:       return "HexagonISD::VSPLATH";
2236*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VSRAH:         return "HexagonISD::VSRAH";
2237*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VSRAW:         return "HexagonISD::VSRAW";
2238*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VSRLH:         return "HexagonISD::VSRLH";
2239*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VSRLW:         return "HexagonISD::VSRLW";
2240*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VSXTBH:        return "HexagonISD::VSXTBH";
2241*9880d681SAndroid Build Coastguard Worker   case HexagonISD::VSXTBW:        return "HexagonISD::VSXTBW";
2242*9880d681SAndroid Build Coastguard Worker   case HexagonISD::OP_END:        break;
2243*9880d681SAndroid Build Coastguard Worker   }
2244*9880d681SAndroid Build Coastguard Worker   return nullptr;
2245*9880d681SAndroid Build Coastguard Worker }
2246*9880d681SAndroid Build Coastguard Worker 
isTruncateFree(Type * Ty1,Type * Ty2) const2247*9880d681SAndroid Build Coastguard Worker bool HexagonTargetLowering::isTruncateFree(Type *Ty1, Type *Ty2) const {
2248*9880d681SAndroid Build Coastguard Worker   EVT MTy1 = EVT::getEVT(Ty1);
2249*9880d681SAndroid Build Coastguard Worker   EVT MTy2 = EVT::getEVT(Ty2);
2250*9880d681SAndroid Build Coastguard Worker   if (!MTy1.isSimple() || !MTy2.isSimple())
2251*9880d681SAndroid Build Coastguard Worker     return false;
2252*9880d681SAndroid Build Coastguard Worker   return (MTy1.getSimpleVT() == MVT::i64) && (MTy2.getSimpleVT() == MVT::i32);
2253*9880d681SAndroid Build Coastguard Worker }
2254*9880d681SAndroid Build Coastguard Worker 
isTruncateFree(EVT VT1,EVT VT2) const2255*9880d681SAndroid Build Coastguard Worker bool HexagonTargetLowering::isTruncateFree(EVT VT1, EVT VT2) const {
2256*9880d681SAndroid Build Coastguard Worker   if (!VT1.isSimple() || !VT2.isSimple())
2257*9880d681SAndroid Build Coastguard Worker     return false;
2258*9880d681SAndroid Build Coastguard Worker   return (VT1.getSimpleVT() == MVT::i64) && (VT2.getSimpleVT() == MVT::i32);
2259*9880d681SAndroid Build Coastguard Worker }
2260*9880d681SAndroid Build Coastguard Worker 
2261*9880d681SAndroid Build Coastguard Worker // shouldExpandBuildVectorWithShuffles
2262*9880d681SAndroid Build Coastguard Worker // Should we expand the build vector with shuffles?
2263*9880d681SAndroid Build Coastguard Worker bool
shouldExpandBuildVectorWithShuffles(EVT VT,unsigned DefinedValues) const2264*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::shouldExpandBuildVectorWithShuffles(EVT VT,
2265*9880d681SAndroid Build Coastguard Worker                                   unsigned DefinedValues) const {
2266*9880d681SAndroid Build Coastguard Worker 
2267*9880d681SAndroid Build Coastguard Worker   // Hexagon vector shuffle operates on element sizes of bytes or halfwords
2268*9880d681SAndroid Build Coastguard Worker   EVT EltVT = VT.getVectorElementType();
2269*9880d681SAndroid Build Coastguard Worker   int EltBits = EltVT.getSizeInBits();
2270*9880d681SAndroid Build Coastguard Worker   if ((EltBits != 8) && (EltBits != 16))
2271*9880d681SAndroid Build Coastguard Worker     return false;
2272*9880d681SAndroid Build Coastguard Worker 
2273*9880d681SAndroid Build Coastguard Worker   return TargetLowering::shouldExpandBuildVectorWithShuffles(VT, DefinedValues);
2274*9880d681SAndroid Build Coastguard Worker }
2275*9880d681SAndroid Build Coastguard Worker 
2276*9880d681SAndroid Build Coastguard Worker // LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3).  V1 and
2277*9880d681SAndroid Build Coastguard Worker // V2 are the two vectors to select data from, V3 is the permutation.
LowerVECTOR_SHUFFLE(SDValue Op,SelectionDAG & DAG)2278*9880d681SAndroid Build Coastguard Worker static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
2279*9880d681SAndroid Build Coastguard Worker   const ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op);
2280*9880d681SAndroid Build Coastguard Worker   SDValue V1 = Op.getOperand(0);
2281*9880d681SAndroid Build Coastguard Worker   SDValue V2 = Op.getOperand(1);
2282*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
2283*9880d681SAndroid Build Coastguard Worker   EVT VT = Op.getValueType();
2284*9880d681SAndroid Build Coastguard Worker 
2285*9880d681SAndroid Build Coastguard Worker   if (V2.isUndef())
2286*9880d681SAndroid Build Coastguard Worker     V2 = V1;
2287*9880d681SAndroid Build Coastguard Worker 
2288*9880d681SAndroid Build Coastguard Worker   if (SVN->isSplat()) {
2289*9880d681SAndroid Build Coastguard Worker     int Lane = SVN->getSplatIndex();
2290*9880d681SAndroid Build Coastguard Worker     if (Lane == -1) Lane = 0;
2291*9880d681SAndroid Build Coastguard Worker 
2292*9880d681SAndroid Build Coastguard Worker     // Test if V1 is a SCALAR_TO_VECTOR.
2293*9880d681SAndroid Build Coastguard Worker     if (Lane == 0 && V1.getOpcode() == ISD::SCALAR_TO_VECTOR)
2294*9880d681SAndroid Build Coastguard Worker       return createSplat(DAG, dl, VT, V1.getOperand(0));
2295*9880d681SAndroid Build Coastguard Worker 
2296*9880d681SAndroid Build Coastguard Worker     // Test if V1 is a BUILD_VECTOR which is equivalent to a SCALAR_TO_VECTOR
2297*9880d681SAndroid Build Coastguard Worker     // (and probably will turn into a SCALAR_TO_VECTOR once legalization
2298*9880d681SAndroid Build Coastguard Worker     // reaches it).
2299*9880d681SAndroid Build Coastguard Worker     if (Lane == 0 && V1.getOpcode() == ISD::BUILD_VECTOR &&
2300*9880d681SAndroid Build Coastguard Worker         !isa<ConstantSDNode>(V1.getOperand(0))) {
2301*9880d681SAndroid Build Coastguard Worker       bool IsScalarToVector = true;
2302*9880d681SAndroid Build Coastguard Worker       for (unsigned i = 1, e = V1.getNumOperands(); i != e; ++i)
2303*9880d681SAndroid Build Coastguard Worker         if (!V1.getOperand(i).isUndef()) {
2304*9880d681SAndroid Build Coastguard Worker           IsScalarToVector = false;
2305*9880d681SAndroid Build Coastguard Worker           break;
2306*9880d681SAndroid Build Coastguard Worker         }
2307*9880d681SAndroid Build Coastguard Worker       if (IsScalarToVector)
2308*9880d681SAndroid Build Coastguard Worker         return createSplat(DAG, dl, VT, V1.getOperand(0));
2309*9880d681SAndroid Build Coastguard Worker     }
2310*9880d681SAndroid Build Coastguard Worker     return createSplat(DAG, dl, VT, DAG.getConstant(Lane, dl, MVT::i32));
2311*9880d681SAndroid Build Coastguard Worker   }
2312*9880d681SAndroid Build Coastguard Worker 
2313*9880d681SAndroid Build Coastguard Worker   // FIXME: We need to support more general vector shuffles.  See
2314*9880d681SAndroid Build Coastguard Worker   // below the comment from the ARM backend that deals in the general
2315*9880d681SAndroid Build Coastguard Worker   // case with the vector shuffles.  For now, let expand handle these.
2316*9880d681SAndroid Build Coastguard Worker   return SDValue();
2317*9880d681SAndroid Build Coastguard Worker 
2318*9880d681SAndroid Build Coastguard Worker   // If the shuffle is not directly supported and it has 4 elements, use
2319*9880d681SAndroid Build Coastguard Worker   // the PerfectShuffle-generated table to synthesize it from other shuffles.
2320*9880d681SAndroid Build Coastguard Worker }
2321*9880d681SAndroid Build Coastguard Worker 
2322*9880d681SAndroid Build Coastguard Worker // If BUILD_VECTOR has same base element repeated several times,
2323*9880d681SAndroid Build Coastguard Worker // report true.
isCommonSplatElement(BuildVectorSDNode * BVN)2324*9880d681SAndroid Build Coastguard Worker static bool isCommonSplatElement(BuildVectorSDNode *BVN) {
2325*9880d681SAndroid Build Coastguard Worker   unsigned NElts = BVN->getNumOperands();
2326*9880d681SAndroid Build Coastguard Worker   SDValue V0 = BVN->getOperand(0);
2327*9880d681SAndroid Build Coastguard Worker 
2328*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 1, e = NElts; i != e; ++i) {
2329*9880d681SAndroid Build Coastguard Worker     if (BVN->getOperand(i) != V0)
2330*9880d681SAndroid Build Coastguard Worker       return false;
2331*9880d681SAndroid Build Coastguard Worker   }
2332*9880d681SAndroid Build Coastguard Worker   return true;
2333*9880d681SAndroid Build Coastguard Worker }
2334*9880d681SAndroid Build Coastguard Worker 
2335*9880d681SAndroid Build Coastguard Worker // LowerVECTOR_SHIFT - Lower a vector shift. Try to convert
2336*9880d681SAndroid Build Coastguard Worker // <VT> = SHL/SRA/SRL <VT> by <VT> to Hexagon specific
2337*9880d681SAndroid Build Coastguard Worker // <VT> = SHL/SRA/SRL <VT> by <IT/i32>.
LowerVECTOR_SHIFT(SDValue Op,SelectionDAG & DAG)2338*9880d681SAndroid Build Coastguard Worker static SDValue LowerVECTOR_SHIFT(SDValue Op, SelectionDAG &DAG) {
2339*9880d681SAndroid Build Coastguard Worker   BuildVectorSDNode *BVN = 0;
2340*9880d681SAndroid Build Coastguard Worker   SDValue V1 = Op.getOperand(0);
2341*9880d681SAndroid Build Coastguard Worker   SDValue V2 = Op.getOperand(1);
2342*9880d681SAndroid Build Coastguard Worker   SDValue V3;
2343*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
2344*9880d681SAndroid Build Coastguard Worker   EVT VT = Op.getValueType();
2345*9880d681SAndroid Build Coastguard Worker 
2346*9880d681SAndroid Build Coastguard Worker   if ((BVN = dyn_cast<BuildVectorSDNode>(V1.getNode())) &&
2347*9880d681SAndroid Build Coastguard Worker       isCommonSplatElement(BVN))
2348*9880d681SAndroid Build Coastguard Worker     V3 = V2;
2349*9880d681SAndroid Build Coastguard Worker   else if ((BVN = dyn_cast<BuildVectorSDNode>(V2.getNode())) &&
2350*9880d681SAndroid Build Coastguard Worker            isCommonSplatElement(BVN))
2351*9880d681SAndroid Build Coastguard Worker     V3 = V1;
2352*9880d681SAndroid Build Coastguard Worker   else
2353*9880d681SAndroid Build Coastguard Worker     return SDValue();
2354*9880d681SAndroid Build Coastguard Worker 
2355*9880d681SAndroid Build Coastguard Worker   SDValue CommonSplat = BVN->getOperand(0);
2356*9880d681SAndroid Build Coastguard Worker   SDValue Result;
2357*9880d681SAndroid Build Coastguard Worker 
2358*9880d681SAndroid Build Coastguard Worker   if (VT.getSimpleVT() == MVT::v4i16) {
2359*9880d681SAndroid Build Coastguard Worker     switch (Op.getOpcode()) {
2360*9880d681SAndroid Build Coastguard Worker     case ISD::SRA:
2361*9880d681SAndroid Build Coastguard Worker       Result = DAG.getNode(HexagonISD::VSRAH, dl, VT, V3, CommonSplat);
2362*9880d681SAndroid Build Coastguard Worker       break;
2363*9880d681SAndroid Build Coastguard Worker     case ISD::SHL:
2364*9880d681SAndroid Build Coastguard Worker       Result = DAG.getNode(HexagonISD::VSHLH, dl, VT, V3, CommonSplat);
2365*9880d681SAndroid Build Coastguard Worker       break;
2366*9880d681SAndroid Build Coastguard Worker     case ISD::SRL:
2367*9880d681SAndroid Build Coastguard Worker       Result = DAG.getNode(HexagonISD::VSRLH, dl, VT, V3, CommonSplat);
2368*9880d681SAndroid Build Coastguard Worker       break;
2369*9880d681SAndroid Build Coastguard Worker     default:
2370*9880d681SAndroid Build Coastguard Worker       return SDValue();
2371*9880d681SAndroid Build Coastguard Worker     }
2372*9880d681SAndroid Build Coastguard Worker   } else if (VT.getSimpleVT() == MVT::v2i32) {
2373*9880d681SAndroid Build Coastguard Worker     switch (Op.getOpcode()) {
2374*9880d681SAndroid Build Coastguard Worker     case ISD::SRA:
2375*9880d681SAndroid Build Coastguard Worker       Result = DAG.getNode(HexagonISD::VSRAW, dl, VT, V3, CommonSplat);
2376*9880d681SAndroid Build Coastguard Worker       break;
2377*9880d681SAndroid Build Coastguard Worker     case ISD::SHL:
2378*9880d681SAndroid Build Coastguard Worker       Result = DAG.getNode(HexagonISD::VSHLW, dl, VT, V3, CommonSplat);
2379*9880d681SAndroid Build Coastguard Worker       break;
2380*9880d681SAndroid Build Coastguard Worker     case ISD::SRL:
2381*9880d681SAndroid Build Coastguard Worker       Result = DAG.getNode(HexagonISD::VSRLW, dl, VT, V3, CommonSplat);
2382*9880d681SAndroid Build Coastguard Worker       break;
2383*9880d681SAndroid Build Coastguard Worker     default:
2384*9880d681SAndroid Build Coastguard Worker       return SDValue();
2385*9880d681SAndroid Build Coastguard Worker     }
2386*9880d681SAndroid Build Coastguard Worker   } else {
2387*9880d681SAndroid Build Coastguard Worker     return SDValue();
2388*9880d681SAndroid Build Coastguard Worker   }
2389*9880d681SAndroid Build Coastguard Worker 
2390*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(ISD::BITCAST, dl, VT, Result);
2391*9880d681SAndroid Build Coastguard Worker }
2392*9880d681SAndroid Build Coastguard Worker 
2393*9880d681SAndroid Build Coastguard Worker SDValue
LowerBUILD_VECTOR(SDValue Op,SelectionDAG & DAG) const2394*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
2395*9880d681SAndroid Build Coastguard Worker   BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Op.getNode());
2396*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
2397*9880d681SAndroid Build Coastguard Worker   EVT VT = Op.getValueType();
2398*9880d681SAndroid Build Coastguard Worker 
2399*9880d681SAndroid Build Coastguard Worker   unsigned Size = VT.getSizeInBits();
2400*9880d681SAndroid Build Coastguard Worker 
2401*9880d681SAndroid Build Coastguard Worker   // Only handle vectors of 64 bits or shorter.
2402*9880d681SAndroid Build Coastguard Worker   if (Size > 64)
2403*9880d681SAndroid Build Coastguard Worker     return SDValue();
2404*9880d681SAndroid Build Coastguard Worker 
2405*9880d681SAndroid Build Coastguard Worker   APInt APSplatBits, APSplatUndef;
2406*9880d681SAndroid Build Coastguard Worker   unsigned SplatBitSize;
2407*9880d681SAndroid Build Coastguard Worker   bool HasAnyUndefs;
2408*9880d681SAndroid Build Coastguard Worker   unsigned NElts = BVN->getNumOperands();
2409*9880d681SAndroid Build Coastguard Worker 
2410*9880d681SAndroid Build Coastguard Worker   // Try to generate a SPLAT instruction.
2411*9880d681SAndroid Build Coastguard Worker   if ((VT.getSimpleVT() == MVT::v4i8 || VT.getSimpleVT() == MVT::v4i16) &&
2412*9880d681SAndroid Build Coastguard Worker       (BVN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize,
2413*9880d681SAndroid Build Coastguard Worker                             HasAnyUndefs, 0, true) && SplatBitSize <= 16)) {
2414*9880d681SAndroid Build Coastguard Worker     unsigned SplatBits = APSplatBits.getZExtValue();
2415*9880d681SAndroid Build Coastguard Worker     int32_t SextVal = ((int32_t) (SplatBits << (32 - SplatBitSize)) >>
2416*9880d681SAndroid Build Coastguard Worker                        (32 - SplatBitSize));
2417*9880d681SAndroid Build Coastguard Worker     return createSplat(DAG, dl, VT, DAG.getConstant(SextVal, dl, MVT::i32));
2418*9880d681SAndroid Build Coastguard Worker   }
2419*9880d681SAndroid Build Coastguard Worker 
2420*9880d681SAndroid Build Coastguard Worker   // Try to generate COMBINE to build v2i32 vectors.
2421*9880d681SAndroid Build Coastguard Worker   if (VT.getSimpleVT() == MVT::v2i32) {
2422*9880d681SAndroid Build Coastguard Worker     SDValue V0 = BVN->getOperand(0);
2423*9880d681SAndroid Build Coastguard Worker     SDValue V1 = BVN->getOperand(1);
2424*9880d681SAndroid Build Coastguard Worker 
2425*9880d681SAndroid Build Coastguard Worker     if (V0.isUndef())
2426*9880d681SAndroid Build Coastguard Worker       V0 = DAG.getConstant(0, dl, MVT::i32);
2427*9880d681SAndroid Build Coastguard Worker     if (V1.isUndef())
2428*9880d681SAndroid Build Coastguard Worker       V1 = DAG.getConstant(0, dl, MVT::i32);
2429*9880d681SAndroid Build Coastguard Worker 
2430*9880d681SAndroid Build Coastguard Worker     ConstantSDNode *C0 = dyn_cast<ConstantSDNode>(V0);
2431*9880d681SAndroid Build Coastguard Worker     ConstantSDNode *C1 = dyn_cast<ConstantSDNode>(V1);
2432*9880d681SAndroid Build Coastguard Worker     // If the element isn't a constant, it is in a register:
2433*9880d681SAndroid Build Coastguard Worker     // generate a COMBINE Register Register instruction.
2434*9880d681SAndroid Build Coastguard Worker     if (!C0 || !C1)
2435*9880d681SAndroid Build Coastguard Worker       return DAG.getNode(HexagonISD::COMBINE, dl, VT, V1, V0);
2436*9880d681SAndroid Build Coastguard Worker 
2437*9880d681SAndroid Build Coastguard Worker     // If one of the operands is an 8 bit integer constant, generate
2438*9880d681SAndroid Build Coastguard Worker     // a COMBINE Immediate Immediate instruction.
2439*9880d681SAndroid Build Coastguard Worker     if (isInt<8>(C0->getSExtValue()) ||
2440*9880d681SAndroid Build Coastguard Worker         isInt<8>(C1->getSExtValue()))
2441*9880d681SAndroid Build Coastguard Worker       return DAG.getNode(HexagonISD::COMBINE, dl, VT, V1, V0);
2442*9880d681SAndroid Build Coastguard Worker   }
2443*9880d681SAndroid Build Coastguard Worker 
2444*9880d681SAndroid Build Coastguard Worker   // Try to generate a S2_packhl to build v2i16 vectors.
2445*9880d681SAndroid Build Coastguard Worker   if (VT.getSimpleVT() == MVT::v2i16) {
2446*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = NElts; i != e; ++i) {
2447*9880d681SAndroid Build Coastguard Worker       if (BVN->getOperand(i).isUndef())
2448*9880d681SAndroid Build Coastguard Worker         continue;
2449*9880d681SAndroid Build Coastguard Worker       ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(BVN->getOperand(i));
2450*9880d681SAndroid Build Coastguard Worker       // If the element isn't a constant, it is in a register:
2451*9880d681SAndroid Build Coastguard Worker       // generate a S2_packhl instruction.
2452*9880d681SAndroid Build Coastguard Worker       if (!Cst) {
2453*9880d681SAndroid Build Coastguard Worker         SDValue pack = DAG.getNode(HexagonISD::PACKHL, dl, MVT::v4i16,
2454*9880d681SAndroid Build Coastguard Worker                                    BVN->getOperand(1), BVN->getOperand(0));
2455*9880d681SAndroid Build Coastguard Worker 
2456*9880d681SAndroid Build Coastguard Worker         return DAG.getTargetExtractSubreg(Hexagon::subreg_loreg, dl, MVT::v2i16,
2457*9880d681SAndroid Build Coastguard Worker                                           pack);
2458*9880d681SAndroid Build Coastguard Worker       }
2459*9880d681SAndroid Build Coastguard Worker     }
2460*9880d681SAndroid Build Coastguard Worker   }
2461*9880d681SAndroid Build Coastguard Worker 
2462*9880d681SAndroid Build Coastguard Worker   // In the general case, generate a CONST32 or a CONST64 for constant vectors,
2463*9880d681SAndroid Build Coastguard Worker   // and insert_vector_elt for all the other cases.
2464*9880d681SAndroid Build Coastguard Worker   uint64_t Res = 0;
2465*9880d681SAndroid Build Coastguard Worker   unsigned EltSize = Size / NElts;
2466*9880d681SAndroid Build Coastguard Worker   SDValue ConstVal;
2467*9880d681SAndroid Build Coastguard Worker   uint64_t Mask = ~uint64_t(0ULL) >> (64 - EltSize);
2468*9880d681SAndroid Build Coastguard Worker   bool HasNonConstantElements = false;
2469*9880d681SAndroid Build Coastguard Worker 
2470*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = NElts; i != e; ++i) {
2471*9880d681SAndroid Build Coastguard Worker     // LLVM's BUILD_VECTOR operands are in Little Endian mode, whereas Hexagon's
2472*9880d681SAndroid Build Coastguard Worker     // combine, const64, etc. are Big Endian.
2473*9880d681SAndroid Build Coastguard Worker     unsigned OpIdx = NElts - i - 1;
2474*9880d681SAndroid Build Coastguard Worker     SDValue Operand = BVN->getOperand(OpIdx);
2475*9880d681SAndroid Build Coastguard Worker     if (Operand.isUndef())
2476*9880d681SAndroid Build Coastguard Worker       continue;
2477*9880d681SAndroid Build Coastguard Worker 
2478*9880d681SAndroid Build Coastguard Worker     int64_t Val = 0;
2479*9880d681SAndroid Build Coastguard Worker     if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Operand))
2480*9880d681SAndroid Build Coastguard Worker       Val = Cst->getSExtValue();
2481*9880d681SAndroid Build Coastguard Worker     else
2482*9880d681SAndroid Build Coastguard Worker       HasNonConstantElements = true;
2483*9880d681SAndroid Build Coastguard Worker 
2484*9880d681SAndroid Build Coastguard Worker     Val &= Mask;
2485*9880d681SAndroid Build Coastguard Worker     Res = (Res << EltSize) | Val;
2486*9880d681SAndroid Build Coastguard Worker   }
2487*9880d681SAndroid Build Coastguard Worker 
2488*9880d681SAndroid Build Coastguard Worker   if (Size == 64)
2489*9880d681SAndroid Build Coastguard Worker     ConstVal = DAG.getConstant(Res, dl, MVT::i64);
2490*9880d681SAndroid Build Coastguard Worker   else
2491*9880d681SAndroid Build Coastguard Worker     ConstVal = DAG.getConstant(Res, dl, MVT::i32);
2492*9880d681SAndroid Build Coastguard Worker 
2493*9880d681SAndroid Build Coastguard Worker   // When there are non constant operands, add them with INSERT_VECTOR_ELT to
2494*9880d681SAndroid Build Coastguard Worker   // ConstVal, the constant part of the vector.
2495*9880d681SAndroid Build Coastguard Worker   if (HasNonConstantElements) {
2496*9880d681SAndroid Build Coastguard Worker     EVT EltVT = VT.getVectorElementType();
2497*9880d681SAndroid Build Coastguard Worker     SDValue Width = DAG.getConstant(EltVT.getSizeInBits(), dl, MVT::i64);
2498*9880d681SAndroid Build Coastguard Worker     SDValue Shifted = DAG.getNode(ISD::SHL, dl, MVT::i64, Width,
2499*9880d681SAndroid Build Coastguard Worker                                   DAG.getConstant(32, dl, MVT::i64));
2500*9880d681SAndroid Build Coastguard Worker 
2501*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = NElts; i != e; ++i) {
2502*9880d681SAndroid Build Coastguard Worker       // LLVM's BUILD_VECTOR operands are in Little Endian mode, whereas Hexagon
2503*9880d681SAndroid Build Coastguard Worker       // is Big Endian.
2504*9880d681SAndroid Build Coastguard Worker       unsigned OpIdx = NElts - i - 1;
2505*9880d681SAndroid Build Coastguard Worker       SDValue Operand = BVN->getOperand(OpIdx);
2506*9880d681SAndroid Build Coastguard Worker       if (isa<ConstantSDNode>(Operand))
2507*9880d681SAndroid Build Coastguard Worker         // This operand is already in ConstVal.
2508*9880d681SAndroid Build Coastguard Worker         continue;
2509*9880d681SAndroid Build Coastguard Worker 
2510*9880d681SAndroid Build Coastguard Worker       if (VT.getSizeInBits() == 64 &&
2511*9880d681SAndroid Build Coastguard Worker           Operand.getValueType().getSizeInBits() == 32) {
2512*9880d681SAndroid Build Coastguard Worker         SDValue C = DAG.getConstant(0, dl, MVT::i32);
2513*9880d681SAndroid Build Coastguard Worker         Operand = DAG.getNode(HexagonISD::COMBINE, dl, VT, C, Operand);
2514*9880d681SAndroid Build Coastguard Worker       }
2515*9880d681SAndroid Build Coastguard Worker 
2516*9880d681SAndroid Build Coastguard Worker       SDValue Idx = DAG.getConstant(OpIdx, dl, MVT::i64);
2517*9880d681SAndroid Build Coastguard Worker       SDValue Offset = DAG.getNode(ISD::MUL, dl, MVT::i64, Idx, Width);
2518*9880d681SAndroid Build Coastguard Worker       SDValue Combined = DAG.getNode(ISD::OR, dl, MVT::i64, Shifted, Offset);
2519*9880d681SAndroid Build Coastguard Worker       const SDValue Ops[] = {ConstVal, Operand, Combined};
2520*9880d681SAndroid Build Coastguard Worker 
2521*9880d681SAndroid Build Coastguard Worker       if (VT.getSizeInBits() == 32)
2522*9880d681SAndroid Build Coastguard Worker         ConstVal = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i32, Ops);
2523*9880d681SAndroid Build Coastguard Worker       else
2524*9880d681SAndroid Build Coastguard Worker         ConstVal = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i64, Ops);
2525*9880d681SAndroid Build Coastguard Worker     }
2526*9880d681SAndroid Build Coastguard Worker   }
2527*9880d681SAndroid Build Coastguard Worker 
2528*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(ISD::BITCAST, dl, VT, ConstVal);
2529*9880d681SAndroid Build Coastguard Worker }
2530*9880d681SAndroid Build Coastguard Worker 
2531*9880d681SAndroid Build Coastguard Worker SDValue
LowerCONCAT_VECTORS(SDValue Op,SelectionDAG & DAG) const2532*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerCONCAT_VECTORS(SDValue Op,
2533*9880d681SAndroid Build Coastguard Worker                                            SelectionDAG &DAG) const {
2534*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
2535*9880d681SAndroid Build Coastguard Worker   bool UseHVX = Subtarget.useHVXOps();
2536*9880d681SAndroid Build Coastguard Worker   EVT VT = Op.getValueType();
2537*9880d681SAndroid Build Coastguard Worker   unsigned NElts = Op.getNumOperands();
2538*9880d681SAndroid Build Coastguard Worker   SDValue Vec0 = Op.getOperand(0);
2539*9880d681SAndroid Build Coastguard Worker   EVT VecVT = Vec0.getValueType();
2540*9880d681SAndroid Build Coastguard Worker   unsigned Width = VecVT.getSizeInBits();
2541*9880d681SAndroid Build Coastguard Worker 
2542*9880d681SAndroid Build Coastguard Worker   if (NElts == 2) {
2543*9880d681SAndroid Build Coastguard Worker     MVT ST = VecVT.getSimpleVT();
2544*9880d681SAndroid Build Coastguard Worker     // We are trying to concat two v2i16 to a single v4i16, or two v4i8
2545*9880d681SAndroid Build Coastguard Worker     // into a single v8i8.
2546*9880d681SAndroid Build Coastguard Worker     if (ST == MVT::v2i16 || ST == MVT::v4i8)
2547*9880d681SAndroid Build Coastguard Worker       return DAG.getNode(HexagonISD::COMBINE, dl, VT, Op.getOperand(1), Vec0);
2548*9880d681SAndroid Build Coastguard Worker 
2549*9880d681SAndroid Build Coastguard Worker     if (UseHVX) {
2550*9880d681SAndroid Build Coastguard Worker       assert((Width ==  64*8 && Subtarget.useHVXSglOps()) ||
2551*9880d681SAndroid Build Coastguard Worker              (Width == 128*8 && Subtarget.useHVXDblOps()));
2552*9880d681SAndroid Build Coastguard Worker       SDValue Vec1 = Op.getOperand(1);
2553*9880d681SAndroid Build Coastguard Worker       MVT OpTy = Subtarget.useHVXSglOps() ? MVT::v16i32 : MVT::v32i32;
2554*9880d681SAndroid Build Coastguard Worker       MVT ReTy = Subtarget.useHVXSglOps() ? MVT::v32i32 : MVT::v64i32;
2555*9880d681SAndroid Build Coastguard Worker       SDValue B0 = DAG.getNode(ISD::BITCAST, dl, OpTy, Vec0);
2556*9880d681SAndroid Build Coastguard Worker       SDValue B1 = DAG.getNode(ISD::BITCAST, dl, OpTy, Vec1);
2557*9880d681SAndroid Build Coastguard Worker       SDValue VC = DAG.getNode(HexagonISD::VCOMBINE, dl, ReTy, B1, B0);
2558*9880d681SAndroid Build Coastguard Worker       return DAG.getNode(ISD::BITCAST, dl, VT, VC);
2559*9880d681SAndroid Build Coastguard Worker     }
2560*9880d681SAndroid Build Coastguard Worker   }
2561*9880d681SAndroid Build Coastguard Worker 
2562*9880d681SAndroid Build Coastguard Worker   if (VT.getSizeInBits() != 32 && VT.getSizeInBits() != 64)
2563*9880d681SAndroid Build Coastguard Worker     return SDValue();
2564*9880d681SAndroid Build Coastguard Worker 
2565*9880d681SAndroid Build Coastguard Worker   SDValue C0 = DAG.getConstant(0, dl, MVT::i64);
2566*9880d681SAndroid Build Coastguard Worker   SDValue C32 = DAG.getConstant(32, dl, MVT::i64);
2567*9880d681SAndroid Build Coastguard Worker   SDValue W = DAG.getConstant(Width, dl, MVT::i64);
2568*9880d681SAndroid Build Coastguard Worker   // Create the "width" part of the argument to insert_rp/insertp_rp.
2569*9880d681SAndroid Build Coastguard Worker   SDValue S = DAG.getNode(ISD::SHL, dl, MVT::i64, W, C32);
2570*9880d681SAndroid Build Coastguard Worker   SDValue V = C0;
2571*9880d681SAndroid Build Coastguard Worker 
2572*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = NElts; i != e; ++i) {
2573*9880d681SAndroid Build Coastguard Worker     unsigned N = NElts-i-1;
2574*9880d681SAndroid Build Coastguard Worker     SDValue OpN = Op.getOperand(N);
2575*9880d681SAndroid Build Coastguard Worker 
2576*9880d681SAndroid Build Coastguard Worker     if (VT.getSizeInBits() == 64 && OpN.getValueType().getSizeInBits() == 32) {
2577*9880d681SAndroid Build Coastguard Worker       SDValue C = DAG.getConstant(0, dl, MVT::i32);
2578*9880d681SAndroid Build Coastguard Worker       OpN = DAG.getNode(HexagonISD::COMBINE, dl, VT, C, OpN);
2579*9880d681SAndroid Build Coastguard Worker     }
2580*9880d681SAndroid Build Coastguard Worker     SDValue Idx = DAG.getConstant(N, dl, MVT::i64);
2581*9880d681SAndroid Build Coastguard Worker     SDValue Offset = DAG.getNode(ISD::MUL, dl, MVT::i64, Idx, W);
2582*9880d681SAndroid Build Coastguard Worker     SDValue Or = DAG.getNode(ISD::OR, dl, MVT::i64, S, Offset);
2583*9880d681SAndroid Build Coastguard Worker     if (VT.getSizeInBits() == 32)
2584*9880d681SAndroid Build Coastguard Worker       V = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i32, {V, OpN, Or});
2585*9880d681SAndroid Build Coastguard Worker     else
2586*9880d681SAndroid Build Coastguard Worker       V = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i64, {V, OpN, Or});
2587*9880d681SAndroid Build Coastguard Worker   }
2588*9880d681SAndroid Build Coastguard Worker 
2589*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(ISD::BITCAST, dl, VT, V);
2590*9880d681SAndroid Build Coastguard Worker }
2591*9880d681SAndroid Build Coastguard Worker 
2592*9880d681SAndroid Build Coastguard Worker SDValue
LowerEXTRACT_VECTOR(SDValue Op,SelectionDAG & DAG) const2593*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerEXTRACT_VECTOR(SDValue Op,
2594*9880d681SAndroid Build Coastguard Worker                                            SelectionDAG &DAG) const {
2595*9880d681SAndroid Build Coastguard Worker   EVT VT = Op.getValueType();
2596*9880d681SAndroid Build Coastguard Worker   int VTN = VT.isVector() ? VT.getVectorNumElements() : 1;
2597*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
2598*9880d681SAndroid Build Coastguard Worker   SDValue Idx = Op.getOperand(1);
2599*9880d681SAndroid Build Coastguard Worker   SDValue Vec = Op.getOperand(0);
2600*9880d681SAndroid Build Coastguard Worker   EVT VecVT = Vec.getValueType();
2601*9880d681SAndroid Build Coastguard Worker   EVT EltVT = VecVT.getVectorElementType();
2602*9880d681SAndroid Build Coastguard Worker   int EltSize = EltVT.getSizeInBits();
2603*9880d681SAndroid Build Coastguard Worker   SDValue Width = DAG.getConstant(Op.getOpcode() == ISD::EXTRACT_VECTOR_ELT ?
2604*9880d681SAndroid Build Coastguard Worker                                   EltSize : VTN * EltSize, dl, MVT::i64);
2605*9880d681SAndroid Build Coastguard Worker 
2606*9880d681SAndroid Build Coastguard Worker   // Constant element number.
2607*9880d681SAndroid Build Coastguard Worker   if (ConstantSDNode *CI = dyn_cast<ConstantSDNode>(Idx)) {
2608*9880d681SAndroid Build Coastguard Worker     uint64_t X = CI->getZExtValue();
2609*9880d681SAndroid Build Coastguard Worker     SDValue Offset = DAG.getConstant(X * EltSize, dl, MVT::i32);
2610*9880d681SAndroid Build Coastguard Worker     const SDValue Ops[] = {Vec, Width, Offset};
2611*9880d681SAndroid Build Coastguard Worker 
2612*9880d681SAndroid Build Coastguard Worker     ConstantSDNode *CW = dyn_cast<ConstantSDNode>(Width);
2613*9880d681SAndroid Build Coastguard Worker     assert(CW && "Non constant width in LowerEXTRACT_VECTOR");
2614*9880d681SAndroid Build Coastguard Worker 
2615*9880d681SAndroid Build Coastguard Worker     SDValue N;
2616*9880d681SAndroid Build Coastguard Worker     MVT SVT = VecVT.getSimpleVT();
2617*9880d681SAndroid Build Coastguard Worker     uint64_t W = CW->getZExtValue();
2618*9880d681SAndroid Build Coastguard Worker 
2619*9880d681SAndroid Build Coastguard Worker     if (W == 32) {
2620*9880d681SAndroid Build Coastguard Worker       // Translate this node into EXTRACT_SUBREG.
2621*9880d681SAndroid Build Coastguard Worker       unsigned Subreg = (X == 0) ? Hexagon::subreg_loreg : 0;
2622*9880d681SAndroid Build Coastguard Worker 
2623*9880d681SAndroid Build Coastguard Worker       if (X == 0)
2624*9880d681SAndroid Build Coastguard Worker         Subreg = Hexagon::subreg_loreg;
2625*9880d681SAndroid Build Coastguard Worker       else if (SVT == MVT::v2i32 && X == 1)
2626*9880d681SAndroid Build Coastguard Worker         Subreg = Hexagon::subreg_hireg;
2627*9880d681SAndroid Build Coastguard Worker       else if (SVT == MVT::v4i16 && X == 2)
2628*9880d681SAndroid Build Coastguard Worker         Subreg = Hexagon::subreg_hireg;
2629*9880d681SAndroid Build Coastguard Worker       else if (SVT == MVT::v8i8 && X == 4)
2630*9880d681SAndroid Build Coastguard Worker         Subreg = Hexagon::subreg_hireg;
2631*9880d681SAndroid Build Coastguard Worker       else
2632*9880d681SAndroid Build Coastguard Worker         llvm_unreachable("Bad offset");
2633*9880d681SAndroid Build Coastguard Worker       N = DAG.getTargetExtractSubreg(Subreg, dl, MVT::i32, Vec);
2634*9880d681SAndroid Build Coastguard Worker 
2635*9880d681SAndroid Build Coastguard Worker     } else if (VecVT.getSizeInBits() == 32) {
2636*9880d681SAndroid Build Coastguard Worker       N = DAG.getNode(HexagonISD::EXTRACTU, dl, MVT::i32, Ops);
2637*9880d681SAndroid Build Coastguard Worker     } else {
2638*9880d681SAndroid Build Coastguard Worker       N = DAG.getNode(HexagonISD::EXTRACTU, dl, MVT::i64, Ops);
2639*9880d681SAndroid Build Coastguard Worker       if (VT.getSizeInBits() == 32)
2640*9880d681SAndroid Build Coastguard Worker         N = DAG.getTargetExtractSubreg(Hexagon::subreg_loreg, dl, MVT::i32, N);
2641*9880d681SAndroid Build Coastguard Worker     }
2642*9880d681SAndroid Build Coastguard Worker 
2643*9880d681SAndroid Build Coastguard Worker     return DAG.getNode(ISD::BITCAST, dl, VT, N);
2644*9880d681SAndroid Build Coastguard Worker   }
2645*9880d681SAndroid Build Coastguard Worker 
2646*9880d681SAndroid Build Coastguard Worker   // Variable element number.
2647*9880d681SAndroid Build Coastguard Worker   SDValue Offset = DAG.getNode(ISD::MUL, dl, MVT::i32, Idx,
2648*9880d681SAndroid Build Coastguard Worker                                DAG.getConstant(EltSize, dl, MVT::i32));
2649*9880d681SAndroid Build Coastguard Worker   SDValue Shifted = DAG.getNode(ISD::SHL, dl, MVT::i64, Width,
2650*9880d681SAndroid Build Coastguard Worker                                 DAG.getConstant(32, dl, MVT::i64));
2651*9880d681SAndroid Build Coastguard Worker   SDValue Combined = DAG.getNode(ISD::OR, dl, MVT::i64, Shifted, Offset);
2652*9880d681SAndroid Build Coastguard Worker 
2653*9880d681SAndroid Build Coastguard Worker   const SDValue Ops[] = {Vec, Combined};
2654*9880d681SAndroid Build Coastguard Worker 
2655*9880d681SAndroid Build Coastguard Worker   SDValue N;
2656*9880d681SAndroid Build Coastguard Worker   if (VecVT.getSizeInBits() == 32) {
2657*9880d681SAndroid Build Coastguard Worker     N = DAG.getNode(HexagonISD::EXTRACTURP, dl, MVT::i32, Ops);
2658*9880d681SAndroid Build Coastguard Worker   } else {
2659*9880d681SAndroid Build Coastguard Worker     N = DAG.getNode(HexagonISD::EXTRACTURP, dl, MVT::i64, Ops);
2660*9880d681SAndroid Build Coastguard Worker     if (VT.getSizeInBits() == 32)
2661*9880d681SAndroid Build Coastguard Worker       N = DAG.getTargetExtractSubreg(Hexagon::subreg_loreg, dl, MVT::i32, N);
2662*9880d681SAndroid Build Coastguard Worker   }
2663*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(ISD::BITCAST, dl, VT, N);
2664*9880d681SAndroid Build Coastguard Worker }
2665*9880d681SAndroid Build Coastguard Worker 
2666*9880d681SAndroid Build Coastguard Worker SDValue
LowerINSERT_VECTOR(SDValue Op,SelectionDAG & DAG) const2667*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerINSERT_VECTOR(SDValue Op,
2668*9880d681SAndroid Build Coastguard Worker                                           SelectionDAG &DAG) const {
2669*9880d681SAndroid Build Coastguard Worker   EVT VT = Op.getValueType();
2670*9880d681SAndroid Build Coastguard Worker   int VTN = VT.isVector() ? VT.getVectorNumElements() : 1;
2671*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
2672*9880d681SAndroid Build Coastguard Worker   SDValue Vec = Op.getOperand(0);
2673*9880d681SAndroid Build Coastguard Worker   SDValue Val = Op.getOperand(1);
2674*9880d681SAndroid Build Coastguard Worker   SDValue Idx = Op.getOperand(2);
2675*9880d681SAndroid Build Coastguard Worker   EVT VecVT = Vec.getValueType();
2676*9880d681SAndroid Build Coastguard Worker   EVT EltVT = VecVT.getVectorElementType();
2677*9880d681SAndroid Build Coastguard Worker   int EltSize = EltVT.getSizeInBits();
2678*9880d681SAndroid Build Coastguard Worker   SDValue Width = DAG.getConstant(Op.getOpcode() == ISD::INSERT_VECTOR_ELT ?
2679*9880d681SAndroid Build Coastguard Worker                                   EltSize : VTN * EltSize, dl, MVT::i64);
2680*9880d681SAndroid Build Coastguard Worker 
2681*9880d681SAndroid Build Coastguard Worker   if (ConstantSDNode *C = cast<ConstantSDNode>(Idx)) {
2682*9880d681SAndroid Build Coastguard Worker     SDValue Offset = DAG.getConstant(C->getSExtValue() * EltSize, dl, MVT::i32);
2683*9880d681SAndroid Build Coastguard Worker     const SDValue Ops[] = {Vec, Val, Width, Offset};
2684*9880d681SAndroid Build Coastguard Worker 
2685*9880d681SAndroid Build Coastguard Worker     SDValue N;
2686*9880d681SAndroid Build Coastguard Worker     if (VT.getSizeInBits() == 32)
2687*9880d681SAndroid Build Coastguard Worker       N = DAG.getNode(HexagonISD::INSERT, dl, MVT::i32, Ops);
2688*9880d681SAndroid Build Coastguard Worker     else
2689*9880d681SAndroid Build Coastguard Worker       N = DAG.getNode(HexagonISD::INSERT, dl, MVT::i64, Ops);
2690*9880d681SAndroid Build Coastguard Worker 
2691*9880d681SAndroid Build Coastguard Worker     return DAG.getNode(ISD::BITCAST, dl, VT, N);
2692*9880d681SAndroid Build Coastguard Worker   }
2693*9880d681SAndroid Build Coastguard Worker 
2694*9880d681SAndroid Build Coastguard Worker   // Variable element number.
2695*9880d681SAndroid Build Coastguard Worker   SDValue Offset = DAG.getNode(ISD::MUL, dl, MVT::i32, Idx,
2696*9880d681SAndroid Build Coastguard Worker                                DAG.getConstant(EltSize, dl, MVT::i32));
2697*9880d681SAndroid Build Coastguard Worker   SDValue Shifted = DAG.getNode(ISD::SHL, dl, MVT::i64, Width,
2698*9880d681SAndroid Build Coastguard Worker                                 DAG.getConstant(32, dl, MVT::i64));
2699*9880d681SAndroid Build Coastguard Worker   SDValue Combined = DAG.getNode(ISD::OR, dl, MVT::i64, Shifted, Offset);
2700*9880d681SAndroid Build Coastguard Worker 
2701*9880d681SAndroid Build Coastguard Worker   if (VT.getSizeInBits() == 64 &&
2702*9880d681SAndroid Build Coastguard Worker       Val.getValueType().getSizeInBits() == 32) {
2703*9880d681SAndroid Build Coastguard Worker     SDValue C = DAG.getConstant(0, dl, MVT::i32);
2704*9880d681SAndroid Build Coastguard Worker     Val = DAG.getNode(HexagonISD::COMBINE, dl, VT, C, Val);
2705*9880d681SAndroid Build Coastguard Worker   }
2706*9880d681SAndroid Build Coastguard Worker 
2707*9880d681SAndroid Build Coastguard Worker   const SDValue Ops[] = {Vec, Val, Combined};
2708*9880d681SAndroid Build Coastguard Worker 
2709*9880d681SAndroid Build Coastguard Worker   SDValue N;
2710*9880d681SAndroid Build Coastguard Worker   if (VT.getSizeInBits() == 32)
2711*9880d681SAndroid Build Coastguard Worker     N = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i32, Ops);
2712*9880d681SAndroid Build Coastguard Worker   else
2713*9880d681SAndroid Build Coastguard Worker     N = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i64, Ops);
2714*9880d681SAndroid Build Coastguard Worker 
2715*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(ISD::BITCAST, dl, VT, N);
2716*9880d681SAndroid Build Coastguard Worker }
2717*9880d681SAndroid Build Coastguard Worker 
2718*9880d681SAndroid Build Coastguard Worker bool
allowTruncateForTailCall(Type * Ty1,Type * Ty2) const2719*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::allowTruncateForTailCall(Type *Ty1, Type *Ty2) const {
2720*9880d681SAndroid Build Coastguard Worker   // Assuming the caller does not have either a signext or zeroext modifier, and
2721*9880d681SAndroid Build Coastguard Worker   // only one value is accepted, any reasonable truncation is allowed.
2722*9880d681SAndroid Build Coastguard Worker   if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())
2723*9880d681SAndroid Build Coastguard Worker     return false;
2724*9880d681SAndroid Build Coastguard Worker 
2725*9880d681SAndroid Build Coastguard Worker   // FIXME: in principle up to 64-bit could be made safe, but it would be very
2726*9880d681SAndroid Build Coastguard Worker   // fragile at the moment: any support for multiple value returns would be
2727*9880d681SAndroid Build Coastguard Worker   // liable to disallow tail calls involving i64 -> iN truncation in many cases.
2728*9880d681SAndroid Build Coastguard Worker   return Ty1->getPrimitiveSizeInBits() <= 32;
2729*9880d681SAndroid Build Coastguard Worker }
2730*9880d681SAndroid Build Coastguard Worker 
2731*9880d681SAndroid Build Coastguard Worker SDValue
LowerEH_RETURN(SDValue Op,SelectionDAG & DAG) const2732*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
2733*9880d681SAndroid Build Coastguard Worker   SDValue Chain     = Op.getOperand(0);
2734*9880d681SAndroid Build Coastguard Worker   SDValue Offset    = Op.getOperand(1);
2735*9880d681SAndroid Build Coastguard Worker   SDValue Handler   = Op.getOperand(2);
2736*9880d681SAndroid Build Coastguard Worker   SDLoc dl(Op);
2737*9880d681SAndroid Build Coastguard Worker   auto PtrVT = getPointerTy(DAG.getDataLayout());
2738*9880d681SAndroid Build Coastguard Worker 
2739*9880d681SAndroid Build Coastguard Worker   // Mark function as containing a call to EH_RETURN.
2740*9880d681SAndroid Build Coastguard Worker   HexagonMachineFunctionInfo *FuncInfo =
2741*9880d681SAndroid Build Coastguard Worker     DAG.getMachineFunction().getInfo<HexagonMachineFunctionInfo>();
2742*9880d681SAndroid Build Coastguard Worker   FuncInfo->setHasEHReturn();
2743*9880d681SAndroid Build Coastguard Worker 
2744*9880d681SAndroid Build Coastguard Worker   unsigned OffsetReg = Hexagon::R28;
2745*9880d681SAndroid Build Coastguard Worker 
2746*9880d681SAndroid Build Coastguard Worker   SDValue StoreAddr =
2747*9880d681SAndroid Build Coastguard Worker       DAG.getNode(ISD::ADD, dl, PtrVT, DAG.getRegister(Hexagon::R30, PtrVT),
2748*9880d681SAndroid Build Coastguard Worker                   DAG.getIntPtrConstant(4, dl));
2749*9880d681SAndroid Build Coastguard Worker   Chain = DAG.getStore(Chain, dl, Handler, StoreAddr, MachinePointerInfo(),
2750*9880d681SAndroid Build Coastguard Worker                        false, false, 0);
2751*9880d681SAndroid Build Coastguard Worker   Chain = DAG.getCopyToReg(Chain, dl, OffsetReg, Offset);
2752*9880d681SAndroid Build Coastguard Worker 
2753*9880d681SAndroid Build Coastguard Worker   // Not needed we already use it as explict input to EH_RETURN.
2754*9880d681SAndroid Build Coastguard Worker   // MF.getRegInfo().addLiveOut(OffsetReg);
2755*9880d681SAndroid Build Coastguard Worker 
2756*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(HexagonISD::EH_RETURN, dl, MVT::Other, Chain);
2757*9880d681SAndroid Build Coastguard Worker }
2758*9880d681SAndroid Build Coastguard Worker 
2759*9880d681SAndroid Build Coastguard Worker SDValue
LowerOperation(SDValue Op,SelectionDAG & DAG) const2760*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
2761*9880d681SAndroid Build Coastguard Worker   unsigned Opc = Op.getOpcode();
2762*9880d681SAndroid Build Coastguard Worker   switch (Opc) {
2763*9880d681SAndroid Build Coastguard Worker     default:
2764*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
2765*9880d681SAndroid Build Coastguard Worker       Op.getNode()->dumpr(&DAG);
2766*9880d681SAndroid Build Coastguard Worker       if (Opc > HexagonISD::OP_BEGIN && Opc < HexagonISD::OP_END)
2767*9880d681SAndroid Build Coastguard Worker         errs() << "Check for a non-legal type in this operation\n";
2768*9880d681SAndroid Build Coastguard Worker #endif
2769*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Should not custom lower this!");
2770*9880d681SAndroid Build Coastguard Worker     case ISD::CONCAT_VECTORS:       return LowerCONCAT_VECTORS(Op, DAG);
2771*9880d681SAndroid Build Coastguard Worker     case ISD::INSERT_SUBVECTOR:     return LowerINSERT_VECTOR(Op, DAG);
2772*9880d681SAndroid Build Coastguard Worker     case ISD::INSERT_VECTOR_ELT:    return LowerINSERT_VECTOR(Op, DAG);
2773*9880d681SAndroid Build Coastguard Worker     case ISD::EXTRACT_SUBVECTOR:    return LowerEXTRACT_VECTOR(Op, DAG);
2774*9880d681SAndroid Build Coastguard Worker     case ISD::EXTRACT_VECTOR_ELT:   return LowerEXTRACT_VECTOR(Op, DAG);
2775*9880d681SAndroid Build Coastguard Worker     case ISD::BUILD_VECTOR:         return LowerBUILD_VECTOR(Op, DAG);
2776*9880d681SAndroid Build Coastguard Worker     case ISD::VECTOR_SHUFFLE:       return LowerVECTOR_SHUFFLE(Op, DAG);
2777*9880d681SAndroid Build Coastguard Worker     case ISD::SRA:
2778*9880d681SAndroid Build Coastguard Worker     case ISD::SHL:
2779*9880d681SAndroid Build Coastguard Worker     case ISD::SRL:                  return LowerVECTOR_SHIFT(Op, DAG);
2780*9880d681SAndroid Build Coastguard Worker     case ISD::ConstantPool:         return LowerConstantPool(Op, DAG);
2781*9880d681SAndroid Build Coastguard Worker     case ISD::JumpTable:            return LowerJumpTable(Op, DAG);
2782*9880d681SAndroid Build Coastguard Worker     case ISD::EH_RETURN:            return LowerEH_RETURN(Op, DAG);
2783*9880d681SAndroid Build Coastguard Worker       // Frame & Return address. Currently unimplemented.
2784*9880d681SAndroid Build Coastguard Worker     case ISD::RETURNADDR:           return LowerRETURNADDR(Op, DAG);
2785*9880d681SAndroid Build Coastguard Worker     case ISD::FRAMEADDR:            return LowerFRAMEADDR(Op, DAG);
2786*9880d681SAndroid Build Coastguard Worker     case ISD::GlobalTLSAddress:     return LowerGlobalTLSAddress(Op, DAG);
2787*9880d681SAndroid Build Coastguard Worker     case ISD::ATOMIC_FENCE:         return LowerATOMIC_FENCE(Op, DAG);
2788*9880d681SAndroid Build Coastguard Worker     case ISD::GlobalAddress:        return LowerGLOBALADDRESS(Op, DAG);
2789*9880d681SAndroid Build Coastguard Worker     case ISD::BlockAddress:         return LowerBlockAddress(Op, DAG);
2790*9880d681SAndroid Build Coastguard Worker     case ISD::GLOBAL_OFFSET_TABLE:  return LowerGLOBAL_OFFSET_TABLE(Op, DAG);
2791*9880d681SAndroid Build Coastguard Worker     case ISD::VASTART:              return LowerVASTART(Op, DAG);
2792*9880d681SAndroid Build Coastguard Worker     // Custom lower some vector loads.
2793*9880d681SAndroid Build Coastguard Worker     case ISD::LOAD:                 return LowerLOAD(Op, DAG);
2794*9880d681SAndroid Build Coastguard Worker     case ISD::DYNAMIC_STACKALLOC:   return LowerDYNAMIC_STACKALLOC(Op, DAG);
2795*9880d681SAndroid Build Coastguard Worker     case ISD::SETCC:                return LowerSETCC(Op, DAG);
2796*9880d681SAndroid Build Coastguard Worker     case ISD::VSELECT:              return LowerVSELECT(Op, DAG);
2797*9880d681SAndroid Build Coastguard Worker     case ISD::CTPOP:                return LowerCTPOP(Op, DAG);
2798*9880d681SAndroid Build Coastguard Worker     case ISD::INTRINSIC_WO_CHAIN:   return LowerINTRINSIC_WO_CHAIN(Op, DAG);
2799*9880d681SAndroid Build Coastguard Worker     case ISD::INTRINSIC_VOID:       return LowerINTRINSIC_VOID(Op, DAG);
2800*9880d681SAndroid Build Coastguard Worker     case ISD::INLINEASM:            return LowerINLINEASM(Op, DAG);
2801*9880d681SAndroid Build Coastguard Worker     case ISD::PREFETCH:             return LowerPREFETCH(Op, DAG);
2802*9880d681SAndroid Build Coastguard Worker   }
2803*9880d681SAndroid Build Coastguard Worker }
2804*9880d681SAndroid Build Coastguard Worker 
2805*9880d681SAndroid Build Coastguard Worker /// Returns relocation base for the given PIC jumptable.
2806*9880d681SAndroid Build Coastguard Worker SDValue
getPICJumpTableRelocBase(SDValue Table,SelectionDAG & DAG) const2807*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::getPICJumpTableRelocBase(SDValue Table,
2808*9880d681SAndroid Build Coastguard Worker                                                 SelectionDAG &DAG) const {
2809*9880d681SAndroid Build Coastguard Worker   int Idx = cast<JumpTableSDNode>(Table)->getIndex();
2810*9880d681SAndroid Build Coastguard Worker   EVT VT = Table.getValueType();
2811*9880d681SAndroid Build Coastguard Worker   SDValue T = DAG.getTargetJumpTable(Idx, VT, HexagonII::MO_PCREL);
2812*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Table), VT, T);
2813*9880d681SAndroid Build Coastguard Worker }
2814*9880d681SAndroid Build Coastguard Worker 
EmitInstrWithCustomInserter(MachineInstr & MI,MachineBasicBlock * BB) const2815*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *HexagonTargetLowering::EmitInstrWithCustomInserter(
2816*9880d681SAndroid Build Coastguard Worker     MachineInstr &MI, MachineBasicBlock *BB) const {
2817*9880d681SAndroid Build Coastguard Worker   switch (MI.getOpcode()) {
2818*9880d681SAndroid Build Coastguard Worker   case Hexagon::ALLOCA: {
2819*9880d681SAndroid Build Coastguard Worker     MachineFunction *MF = BB->getParent();
2820*9880d681SAndroid Build Coastguard Worker     auto *FuncInfo = MF->getInfo<HexagonMachineFunctionInfo>();
2821*9880d681SAndroid Build Coastguard Worker     FuncInfo->addAllocaAdjustInst(&MI);
2822*9880d681SAndroid Build Coastguard Worker     return BB;
2823*9880d681SAndroid Build Coastguard Worker   }
2824*9880d681SAndroid Build Coastguard Worker   default:
2825*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Unexpected instr type to insert");
2826*9880d681SAndroid Build Coastguard Worker   } // switch
2827*9880d681SAndroid Build Coastguard Worker }
2828*9880d681SAndroid Build Coastguard Worker 
2829*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2830*9880d681SAndroid Build Coastguard Worker // Inline Assembly Support
2831*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2832*9880d681SAndroid Build Coastguard Worker 
2833*9880d681SAndroid Build Coastguard Worker TargetLowering::ConstraintType
getConstraintType(StringRef Constraint) const2834*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::getConstraintType(StringRef Constraint) const {
2835*9880d681SAndroid Build Coastguard Worker   if (Constraint.size() == 1) {
2836*9880d681SAndroid Build Coastguard Worker     switch (Constraint[0]) {
2837*9880d681SAndroid Build Coastguard Worker       case 'q':
2838*9880d681SAndroid Build Coastguard Worker       case 'v':
2839*9880d681SAndroid Build Coastguard Worker         if (Subtarget.useHVXOps())
2840*9880d681SAndroid Build Coastguard Worker           return C_Register;
2841*9880d681SAndroid Build Coastguard Worker         break;
2842*9880d681SAndroid Build Coastguard Worker     }
2843*9880d681SAndroid Build Coastguard Worker   }
2844*9880d681SAndroid Build Coastguard Worker   return TargetLowering::getConstraintType(Constraint);
2845*9880d681SAndroid Build Coastguard Worker }
2846*9880d681SAndroid Build Coastguard Worker 
2847*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo * TRI,StringRef Constraint,MVT VT) const2848*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::getRegForInlineAsmConstraint(
2849*9880d681SAndroid Build Coastguard Worker     const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
2850*9880d681SAndroid Build Coastguard Worker   bool UseHVX = Subtarget.useHVXOps(), UseHVXDbl = Subtarget.useHVXDblOps();
2851*9880d681SAndroid Build Coastguard Worker 
2852*9880d681SAndroid Build Coastguard Worker   if (Constraint.size() == 1) {
2853*9880d681SAndroid Build Coastguard Worker     switch (Constraint[0]) {
2854*9880d681SAndroid Build Coastguard Worker     case 'r':   // R0-R31
2855*9880d681SAndroid Build Coastguard Worker        switch (VT.SimpleTy) {
2856*9880d681SAndroid Build Coastguard Worker        default:
2857*9880d681SAndroid Build Coastguard Worker          llvm_unreachable("getRegForInlineAsmConstraint Unhandled data type");
2858*9880d681SAndroid Build Coastguard Worker        case MVT::i32:
2859*9880d681SAndroid Build Coastguard Worker        case MVT::i16:
2860*9880d681SAndroid Build Coastguard Worker        case MVT::i8:
2861*9880d681SAndroid Build Coastguard Worker        case MVT::f32:
2862*9880d681SAndroid Build Coastguard Worker          return std::make_pair(0U, &Hexagon::IntRegsRegClass);
2863*9880d681SAndroid Build Coastguard Worker        case MVT::i64:
2864*9880d681SAndroid Build Coastguard Worker        case MVT::f64:
2865*9880d681SAndroid Build Coastguard Worker          return std::make_pair(0U, &Hexagon::DoubleRegsRegClass);
2866*9880d681SAndroid Build Coastguard Worker       }
2867*9880d681SAndroid Build Coastguard Worker     case 'q': // q0-q3
2868*9880d681SAndroid Build Coastguard Worker        switch (VT.SimpleTy) {
2869*9880d681SAndroid Build Coastguard Worker        default:
2870*9880d681SAndroid Build Coastguard Worker          llvm_unreachable("getRegForInlineAsmConstraint Unhandled data type");
2871*9880d681SAndroid Build Coastguard Worker        case MVT::v1024i1:
2872*9880d681SAndroid Build Coastguard Worker        case MVT::v512i1:
2873*9880d681SAndroid Build Coastguard Worker        case MVT::v32i16:
2874*9880d681SAndroid Build Coastguard Worker        case MVT::v16i32:
2875*9880d681SAndroid Build Coastguard Worker        case MVT::v64i8:
2876*9880d681SAndroid Build Coastguard Worker        case MVT::v8i64:
2877*9880d681SAndroid Build Coastguard Worker          return std::make_pair(0U, &Hexagon::VecPredRegsRegClass);
2878*9880d681SAndroid Build Coastguard Worker     }
2879*9880d681SAndroid Build Coastguard Worker     case 'v': // V0-V31
2880*9880d681SAndroid Build Coastguard Worker        switch (VT.SimpleTy) {
2881*9880d681SAndroid Build Coastguard Worker        default:
2882*9880d681SAndroid Build Coastguard Worker          llvm_unreachable("getRegForInlineAsmConstraint Unhandled data type");
2883*9880d681SAndroid Build Coastguard Worker        case MVT::v16i32:
2884*9880d681SAndroid Build Coastguard Worker        case MVT::v32i16:
2885*9880d681SAndroid Build Coastguard Worker        case MVT::v64i8:
2886*9880d681SAndroid Build Coastguard Worker        case MVT::v8i64:
2887*9880d681SAndroid Build Coastguard Worker          return std::make_pair(0U, &Hexagon::VectorRegsRegClass);
2888*9880d681SAndroid Build Coastguard Worker        case MVT::v32i32:
2889*9880d681SAndroid Build Coastguard Worker        case MVT::v64i16:
2890*9880d681SAndroid Build Coastguard Worker        case MVT::v16i64:
2891*9880d681SAndroid Build Coastguard Worker        case MVT::v128i8:
2892*9880d681SAndroid Build Coastguard Worker          if (Subtarget.hasV60TOps() && UseHVX && UseHVXDbl)
2893*9880d681SAndroid Build Coastguard Worker            return std::make_pair(0U, &Hexagon::VectorRegs128BRegClass);
2894*9880d681SAndroid Build Coastguard Worker          else
2895*9880d681SAndroid Build Coastguard Worker            return std::make_pair(0U, &Hexagon::VecDblRegsRegClass);
2896*9880d681SAndroid Build Coastguard Worker        case MVT::v256i8:
2897*9880d681SAndroid Build Coastguard Worker        case MVT::v128i16:
2898*9880d681SAndroid Build Coastguard Worker        case MVT::v64i32:
2899*9880d681SAndroid Build Coastguard Worker        case MVT::v32i64:
2900*9880d681SAndroid Build Coastguard Worker          return std::make_pair(0U, &Hexagon::VecDblRegs128BRegClass);
2901*9880d681SAndroid Build Coastguard Worker        }
2902*9880d681SAndroid Build Coastguard Worker 
2903*9880d681SAndroid Build Coastguard Worker     default:
2904*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Unknown asm register class");
2905*9880d681SAndroid Build Coastguard Worker     }
2906*9880d681SAndroid Build Coastguard Worker   }
2907*9880d681SAndroid Build Coastguard Worker 
2908*9880d681SAndroid Build Coastguard Worker   return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
2909*9880d681SAndroid Build Coastguard Worker }
2910*9880d681SAndroid Build Coastguard Worker 
2911*9880d681SAndroid Build Coastguard Worker /// isFPImmLegal - Returns true if the target can instruction select the
2912*9880d681SAndroid Build Coastguard Worker /// specified FP immediate natively. If false, the legalizer will
2913*9880d681SAndroid Build Coastguard Worker /// materialize the FP immediate as a load from a constant pool.
isFPImmLegal(const APFloat & Imm,EVT VT) const2914*9880d681SAndroid Build Coastguard Worker bool HexagonTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
2915*9880d681SAndroid Build Coastguard Worker   return Subtarget.hasV5TOps();
2916*9880d681SAndroid Build Coastguard Worker }
2917*9880d681SAndroid Build Coastguard Worker 
2918*9880d681SAndroid Build Coastguard Worker /// isLegalAddressingMode - Return true if the addressing mode represented by
2919*9880d681SAndroid Build Coastguard Worker /// AM is legal for this target, for a load/store of the specified type.
isLegalAddressingMode(const DataLayout & DL,const AddrMode & AM,Type * Ty,unsigned AS) const2920*9880d681SAndroid Build Coastguard Worker bool HexagonTargetLowering::isLegalAddressingMode(const DataLayout &DL,
2921*9880d681SAndroid Build Coastguard Worker                                                   const AddrMode &AM, Type *Ty,
2922*9880d681SAndroid Build Coastguard Worker                                                   unsigned AS) const {
2923*9880d681SAndroid Build Coastguard Worker   // Allows a signed-extended 11-bit immediate field.
2924*9880d681SAndroid Build Coastguard Worker   if (AM.BaseOffs <= -(1LL << 13) || AM.BaseOffs >= (1LL << 13)-1)
2925*9880d681SAndroid Build Coastguard Worker     return false;
2926*9880d681SAndroid Build Coastguard Worker 
2927*9880d681SAndroid Build Coastguard Worker   // No global is ever allowed as a base.
2928*9880d681SAndroid Build Coastguard Worker   if (AM.BaseGV)
2929*9880d681SAndroid Build Coastguard Worker     return false;
2930*9880d681SAndroid Build Coastguard Worker 
2931*9880d681SAndroid Build Coastguard Worker   int Scale = AM.Scale;
2932*9880d681SAndroid Build Coastguard Worker   if (Scale < 0) Scale = -Scale;
2933*9880d681SAndroid Build Coastguard Worker   switch (Scale) {
2934*9880d681SAndroid Build Coastguard Worker   case 0:  // No scale reg, "r+i", "r", or just "i".
2935*9880d681SAndroid Build Coastguard Worker     break;
2936*9880d681SAndroid Build Coastguard Worker   default: // No scaled addressing mode.
2937*9880d681SAndroid Build Coastguard Worker     return false;
2938*9880d681SAndroid Build Coastguard Worker   }
2939*9880d681SAndroid Build Coastguard Worker   return true;
2940*9880d681SAndroid Build Coastguard Worker }
2941*9880d681SAndroid Build Coastguard Worker 
2942*9880d681SAndroid Build Coastguard Worker /// Return true if folding a constant offset with the given GlobalAddress is
2943*9880d681SAndroid Build Coastguard Worker /// legal.  It is frequently not legal in PIC relocation models.
isOffsetFoldingLegal(const GlobalAddressSDNode * GA) const2944*9880d681SAndroid Build Coastguard Worker bool HexagonTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA)
2945*9880d681SAndroid Build Coastguard Worker       const {
2946*9880d681SAndroid Build Coastguard Worker   return HTM.getRelocationModel() == Reloc::Static;
2947*9880d681SAndroid Build Coastguard Worker }
2948*9880d681SAndroid Build Coastguard Worker 
2949*9880d681SAndroid Build Coastguard Worker 
2950*9880d681SAndroid Build Coastguard Worker /// isLegalICmpImmediate - Return true if the specified immediate is legal
2951*9880d681SAndroid Build Coastguard Worker /// icmp immediate, that is the target has icmp instructions which can compare
2952*9880d681SAndroid Build Coastguard Worker /// a register against the immediate without having to materialize the
2953*9880d681SAndroid Build Coastguard Worker /// immediate into a register.
isLegalICmpImmediate(int64_t Imm) const2954*9880d681SAndroid Build Coastguard Worker bool HexagonTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
2955*9880d681SAndroid Build Coastguard Worker   return Imm >= -512 && Imm <= 511;
2956*9880d681SAndroid Build Coastguard Worker }
2957*9880d681SAndroid Build Coastguard Worker 
2958*9880d681SAndroid Build Coastguard Worker /// IsEligibleForTailCallOptimization - Check whether the call is eligible
2959*9880d681SAndroid Build Coastguard Worker /// for tail call optimization. Targets which want to do tail call
2960*9880d681SAndroid Build Coastguard Worker /// 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) const2961*9880d681SAndroid Build Coastguard Worker bool HexagonTargetLowering::IsEligibleForTailCallOptimization(
2962*9880d681SAndroid Build Coastguard Worker                                  SDValue Callee,
2963*9880d681SAndroid Build Coastguard Worker                                  CallingConv::ID CalleeCC,
2964*9880d681SAndroid Build Coastguard Worker                                  bool isVarArg,
2965*9880d681SAndroid Build Coastguard Worker                                  bool isCalleeStructRet,
2966*9880d681SAndroid Build Coastguard Worker                                  bool isCallerStructRet,
2967*9880d681SAndroid Build Coastguard Worker                                  const SmallVectorImpl<ISD::OutputArg> &Outs,
2968*9880d681SAndroid Build Coastguard Worker                                  const SmallVectorImpl<SDValue> &OutVals,
2969*9880d681SAndroid Build Coastguard Worker                                  const SmallVectorImpl<ISD::InputArg> &Ins,
2970*9880d681SAndroid Build Coastguard Worker                                  SelectionDAG& DAG) const {
2971*9880d681SAndroid Build Coastguard Worker   const Function *CallerF = DAG.getMachineFunction().getFunction();
2972*9880d681SAndroid Build Coastguard Worker   CallingConv::ID CallerCC = CallerF->getCallingConv();
2973*9880d681SAndroid Build Coastguard Worker   bool CCMatch = CallerCC == CalleeCC;
2974*9880d681SAndroid Build Coastguard Worker 
2975*9880d681SAndroid Build Coastguard Worker   // ***************************************************************************
2976*9880d681SAndroid Build Coastguard Worker   //  Look for obvious safe cases to perform tail call optimization that do not
2977*9880d681SAndroid Build Coastguard Worker   //  require ABI changes.
2978*9880d681SAndroid Build Coastguard Worker   // ***************************************************************************
2979*9880d681SAndroid Build Coastguard Worker 
2980*9880d681SAndroid Build Coastguard Worker   // If this is a tail call via a function pointer, then don't do it!
2981*9880d681SAndroid Build Coastguard Worker   if (!(isa<GlobalAddressSDNode>(Callee)) &&
2982*9880d681SAndroid Build Coastguard Worker       !(isa<ExternalSymbolSDNode>(Callee))) {
2983*9880d681SAndroid Build Coastguard Worker     return false;
2984*9880d681SAndroid Build Coastguard Worker   }
2985*9880d681SAndroid Build Coastguard Worker 
2986*9880d681SAndroid Build Coastguard Worker   // Do not optimize if the calling conventions do not match.
2987*9880d681SAndroid Build Coastguard Worker   if (!CCMatch)
2988*9880d681SAndroid Build Coastguard Worker     return false;
2989*9880d681SAndroid Build Coastguard Worker 
2990*9880d681SAndroid Build Coastguard Worker   // Do not tail call optimize vararg calls.
2991*9880d681SAndroid Build Coastguard Worker   if (isVarArg)
2992*9880d681SAndroid Build Coastguard Worker     return false;
2993*9880d681SAndroid Build Coastguard Worker 
2994*9880d681SAndroid Build Coastguard Worker   // Also avoid tail call optimization if either caller or callee uses struct
2995*9880d681SAndroid Build Coastguard Worker   // return semantics.
2996*9880d681SAndroid Build Coastguard Worker   if (isCalleeStructRet || isCallerStructRet)
2997*9880d681SAndroid Build Coastguard Worker     return false;
2998*9880d681SAndroid Build Coastguard Worker 
2999*9880d681SAndroid Build Coastguard Worker   // In addition to the cases above, we also disable Tail Call Optimization if
3000*9880d681SAndroid Build Coastguard Worker   // the calling convention code that at least one outgoing argument needs to
3001*9880d681SAndroid Build Coastguard Worker   // go on the stack. We cannot check that here because at this point that
3002*9880d681SAndroid Build Coastguard Worker   // information is not available.
3003*9880d681SAndroid Build Coastguard Worker   return true;
3004*9880d681SAndroid Build Coastguard Worker }
3005*9880d681SAndroid Build Coastguard Worker 
3006*9880d681SAndroid Build Coastguard Worker // Return true when the given node fits in a positive half word.
isPositiveHalfWord(SDNode * N)3007*9880d681SAndroid Build Coastguard Worker bool llvm::isPositiveHalfWord(SDNode *N) {
3008*9880d681SAndroid Build Coastguard Worker   ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N);
3009*9880d681SAndroid Build Coastguard Worker   if (CN && CN->getSExtValue() > 0 && isInt<16>(CN->getSExtValue()))
3010*9880d681SAndroid Build Coastguard Worker     return true;
3011*9880d681SAndroid Build Coastguard Worker 
3012*9880d681SAndroid Build Coastguard Worker   switch (N->getOpcode()) {
3013*9880d681SAndroid Build Coastguard Worker   default:
3014*9880d681SAndroid Build Coastguard Worker     return false;
3015*9880d681SAndroid Build Coastguard Worker   case ISD::SIGN_EXTEND_INREG:
3016*9880d681SAndroid Build Coastguard Worker     return true;
3017*9880d681SAndroid Build Coastguard Worker   }
3018*9880d681SAndroid Build Coastguard Worker }
3019*9880d681SAndroid Build Coastguard Worker 
allowsMisalignedMemoryAccesses(EVT VT,unsigned AS,unsigned Align,bool * Fast) const3020*9880d681SAndroid Build Coastguard Worker bool HexagonTargetLowering::allowsMisalignedMemoryAccesses(EVT VT,
3021*9880d681SAndroid Build Coastguard Worker       unsigned AS, unsigned Align, bool *Fast) const {
3022*9880d681SAndroid Build Coastguard Worker   if (Fast)
3023*9880d681SAndroid Build Coastguard Worker     *Fast = false;
3024*9880d681SAndroid Build Coastguard Worker 
3025*9880d681SAndroid Build Coastguard Worker   switch (VT.getSimpleVT().SimpleTy) {
3026*9880d681SAndroid Build Coastguard Worker   default:
3027*9880d681SAndroid Build Coastguard Worker     return false;
3028*9880d681SAndroid Build Coastguard Worker   case MVT::v64i8:
3029*9880d681SAndroid Build Coastguard Worker   case MVT::v128i8:
3030*9880d681SAndroid Build Coastguard Worker   case MVT::v256i8:
3031*9880d681SAndroid Build Coastguard Worker   case MVT::v32i16:
3032*9880d681SAndroid Build Coastguard Worker   case MVT::v64i16:
3033*9880d681SAndroid Build Coastguard Worker   case MVT::v128i16:
3034*9880d681SAndroid Build Coastguard Worker   case MVT::v16i32:
3035*9880d681SAndroid Build Coastguard Worker   case MVT::v32i32:
3036*9880d681SAndroid Build Coastguard Worker   case MVT::v64i32:
3037*9880d681SAndroid Build Coastguard Worker   case MVT::v8i64:
3038*9880d681SAndroid Build Coastguard Worker   case MVT::v16i64:
3039*9880d681SAndroid Build Coastguard Worker   case MVT::v32i64:
3040*9880d681SAndroid Build Coastguard Worker     return true;
3041*9880d681SAndroid Build Coastguard Worker   }
3042*9880d681SAndroid Build Coastguard Worker   return false;
3043*9880d681SAndroid Build Coastguard Worker }
3044*9880d681SAndroid Build Coastguard Worker 
3045*9880d681SAndroid Build Coastguard Worker 
3046*9880d681SAndroid Build Coastguard Worker std::pair<const TargetRegisterClass*, uint8_t>
findRepresentativeClass(const TargetRegisterInfo * TRI,MVT VT) const3047*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::findRepresentativeClass(const TargetRegisterInfo *TRI,
3048*9880d681SAndroid Build Coastguard Worker       MVT VT) const {
3049*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *RRC = nullptr;
3050*9880d681SAndroid Build Coastguard Worker 
3051*9880d681SAndroid Build Coastguard Worker   uint8_t Cost = 1;
3052*9880d681SAndroid Build Coastguard Worker   switch (VT.SimpleTy) {
3053*9880d681SAndroid Build Coastguard Worker   default:
3054*9880d681SAndroid Build Coastguard Worker     return TargetLowering::findRepresentativeClass(TRI, VT);
3055*9880d681SAndroid Build Coastguard Worker   case MVT::v64i8:
3056*9880d681SAndroid Build Coastguard Worker   case MVT::v32i16:
3057*9880d681SAndroid Build Coastguard Worker   case MVT::v16i32:
3058*9880d681SAndroid Build Coastguard Worker   case MVT::v8i64:
3059*9880d681SAndroid Build Coastguard Worker     RRC = &Hexagon::VectorRegsRegClass;
3060*9880d681SAndroid Build Coastguard Worker     break;
3061*9880d681SAndroid Build Coastguard Worker   case MVT::v128i8:
3062*9880d681SAndroid Build Coastguard Worker   case MVT::v64i16:
3063*9880d681SAndroid Build Coastguard Worker   case MVT::v32i32:
3064*9880d681SAndroid Build Coastguard Worker   case MVT::v16i64:
3065*9880d681SAndroid Build Coastguard Worker     if (Subtarget.hasV60TOps() && Subtarget.useHVXOps() &&
3066*9880d681SAndroid Build Coastguard Worker         Subtarget.useHVXDblOps())
3067*9880d681SAndroid Build Coastguard Worker       RRC = &Hexagon::VectorRegs128BRegClass;
3068*9880d681SAndroid Build Coastguard Worker     else
3069*9880d681SAndroid Build Coastguard Worker       RRC = &Hexagon::VecDblRegsRegClass;
3070*9880d681SAndroid Build Coastguard Worker     break;
3071*9880d681SAndroid Build Coastguard Worker   case MVT::v256i8:
3072*9880d681SAndroid Build Coastguard Worker   case MVT::v128i16:
3073*9880d681SAndroid Build Coastguard Worker   case MVT::v64i32:
3074*9880d681SAndroid Build Coastguard Worker   case MVT::v32i64:
3075*9880d681SAndroid Build Coastguard Worker     RRC = &Hexagon::VecDblRegs128BRegClass;
3076*9880d681SAndroid Build Coastguard Worker     break;
3077*9880d681SAndroid Build Coastguard Worker   }
3078*9880d681SAndroid Build Coastguard Worker   return std::make_pair(RRC, Cost);
3079*9880d681SAndroid Build Coastguard Worker }
3080*9880d681SAndroid Build Coastguard Worker 
emitLoadLinked(IRBuilder<> & Builder,Value * Addr,AtomicOrdering Ord) const3081*9880d681SAndroid Build Coastguard Worker Value *HexagonTargetLowering::emitLoadLinked(IRBuilder<> &Builder, Value *Addr,
3082*9880d681SAndroid Build Coastguard Worker       AtomicOrdering Ord) const {
3083*9880d681SAndroid Build Coastguard Worker   BasicBlock *BB = Builder.GetInsertBlock();
3084*9880d681SAndroid Build Coastguard Worker   Module *M = BB->getParent()->getParent();
3085*9880d681SAndroid Build Coastguard Worker   Type *Ty = cast<PointerType>(Addr->getType())->getElementType();
3086*9880d681SAndroid Build Coastguard Worker   unsigned SZ = Ty->getPrimitiveSizeInBits();
3087*9880d681SAndroid Build Coastguard Worker   assert((SZ == 32 || SZ == 64) && "Only 32/64-bit atomic loads supported");
3088*9880d681SAndroid Build Coastguard Worker   Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_L2_loadw_locked
3089*9880d681SAndroid Build Coastguard Worker                                    : Intrinsic::hexagon_L4_loadd_locked;
3090*9880d681SAndroid Build Coastguard Worker   Value *Fn = Intrinsic::getDeclaration(M, IntID);
3091*9880d681SAndroid Build Coastguard Worker   return Builder.CreateCall(Fn, Addr, "larx");
3092*9880d681SAndroid Build Coastguard Worker }
3093*9880d681SAndroid Build Coastguard Worker 
3094*9880d681SAndroid Build Coastguard Worker /// Perform a store-conditional operation to Addr. Return the status of the
3095*9880d681SAndroid Build Coastguard Worker /// store. This should be 0 if the store succeeded, non-zero otherwise.
emitStoreConditional(IRBuilder<> & Builder,Value * Val,Value * Addr,AtomicOrdering Ord) const3096*9880d681SAndroid Build Coastguard Worker Value *HexagonTargetLowering::emitStoreConditional(IRBuilder<> &Builder,
3097*9880d681SAndroid Build Coastguard Worker       Value *Val, Value *Addr, AtomicOrdering Ord) const {
3098*9880d681SAndroid Build Coastguard Worker   BasicBlock *BB = Builder.GetInsertBlock();
3099*9880d681SAndroid Build Coastguard Worker   Module *M = BB->getParent()->getParent();
3100*9880d681SAndroid Build Coastguard Worker   Type *Ty = Val->getType();
3101*9880d681SAndroid Build Coastguard Worker   unsigned SZ = Ty->getPrimitiveSizeInBits();
3102*9880d681SAndroid Build Coastguard Worker   assert((SZ == 32 || SZ == 64) && "Only 32/64-bit atomic stores supported");
3103*9880d681SAndroid Build Coastguard Worker   Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_S2_storew_locked
3104*9880d681SAndroid Build Coastguard Worker                                    : Intrinsic::hexagon_S4_stored_locked;
3105*9880d681SAndroid Build Coastguard Worker   Value *Fn = Intrinsic::getDeclaration(M, IntID);
3106*9880d681SAndroid Build Coastguard Worker   Value *Call = Builder.CreateCall(Fn, {Addr, Val}, "stcx");
3107*9880d681SAndroid Build Coastguard Worker   Value *Cmp = Builder.CreateICmpEQ(Call, Builder.getInt32(0), "");
3108*9880d681SAndroid Build Coastguard Worker   Value *Ext = Builder.CreateZExt(Cmp, Type::getInt32Ty(M->getContext()));
3109*9880d681SAndroid Build Coastguard Worker   return Ext;
3110*9880d681SAndroid Build Coastguard Worker }
3111*9880d681SAndroid Build Coastguard Worker 
3112*9880d681SAndroid Build Coastguard Worker TargetLowering::AtomicExpansionKind
shouldExpandAtomicLoadInIR(LoadInst * LI) const3113*9880d681SAndroid Build Coastguard Worker HexagonTargetLowering::shouldExpandAtomicLoadInIR(LoadInst *LI) const {
3114*9880d681SAndroid Build Coastguard Worker   // Do not expand loads and stores that don't exceed 64 bits.
3115*9880d681SAndroid Build Coastguard Worker   return LI->getType()->getPrimitiveSizeInBits() > 64
3116*9880d681SAndroid Build Coastguard Worker              ? AtomicExpansionKind::LLOnly
3117*9880d681SAndroid Build Coastguard Worker              : AtomicExpansionKind::None;
3118*9880d681SAndroid Build Coastguard Worker }
3119*9880d681SAndroid Build Coastguard Worker 
shouldExpandAtomicStoreInIR(StoreInst * SI) const3120*9880d681SAndroid Build Coastguard Worker bool HexagonTargetLowering::shouldExpandAtomicStoreInIR(StoreInst *SI) const {
3121*9880d681SAndroid Build Coastguard Worker   // Do not expand loads and stores that don't exceed 64 bits.
3122*9880d681SAndroid Build Coastguard Worker   return SI->getValueOperand()->getType()->getPrimitiveSizeInBits() > 64;
3123*9880d681SAndroid Build Coastguard Worker }
3124*9880d681SAndroid Build Coastguard Worker 
shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst * AI) const3125*9880d681SAndroid Build Coastguard Worker bool HexagonTargetLowering::shouldExpandAtomicCmpXchgInIR(
3126*9880d681SAndroid Build Coastguard Worker       AtomicCmpXchgInst *AI) const {
3127*9880d681SAndroid Build Coastguard Worker   const DataLayout &DL = AI->getModule()->getDataLayout();
3128*9880d681SAndroid Build Coastguard Worker   unsigned Size = DL.getTypeStoreSize(AI->getCompareOperand()->getType());
3129*9880d681SAndroid Build Coastguard Worker   return Size >= 4 && Size <= 8;
3130*9880d681SAndroid Build Coastguard Worker }
3131