blob: ea3a1770ac3143e7aed9b7a6ea7ab2fb3118ce3b [file] [log] [blame]
Jia Liub22310f2012-02-18 12:03:15 +00001//===-- HexagonISelDAGToDAG.cpp - A dag to dag inst selector for Hexagon --===//
Tony Linthicum1213a7a2011-12-12 21:14:40 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the Hexagon target.
11//
12//===----------------------------------------------------------------------===//
13
Chandler Carruthed0881b2012-12-03 16:50:05 +000014#include "Hexagon.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000015#include "HexagonISelLowering.h"
16#include "HexagonTargetMachine.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000017#include "llvm/ADT/DenseMap.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000018#include "llvm/CodeGen/SelectionDAGISel.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000019#include "llvm/IR/Intrinsics.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000020#include "llvm/Support/CommandLine.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000021#include "llvm/Support/Compiler.h"
22#include "llvm/Support/Debug.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000023using namespace llvm;
24
Chandler Carruth84e68b22014-04-22 02:41:26 +000025#define DEBUG_TYPE "hexagon-isel"
26
Jyotsna Vermad9225242013-02-13 21:38:46 +000027static
28cl::opt<unsigned>
29MaxNumOfUsesForConstExtenders("ga-max-num-uses-for-constant-extenders",
30 cl::Hidden, cl::init(2),
31 cl::desc("Maximum number of uses of a global address such that we still us a"
32 "constant extended instruction"));
Tony Linthicum1213a7a2011-12-12 21:14:40 +000033
34//===----------------------------------------------------------------------===//
35// Instruction Selector Implementation
36//===----------------------------------------------------------------------===//
37
Jyotsna Vermad9225242013-02-13 21:38:46 +000038namespace llvm {
39 void initializeHexagonDAGToDAGISelPass(PassRegistry&);
40}
41
Tony Linthicum1213a7a2011-12-12 21:14:40 +000042//===--------------------------------------------------------------------===//
43/// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine
44/// instructions for SelectionDAG operations.
45///
46namespace {
47class HexagonDAGToDAGISel : public SelectionDAGISel {
48 /// Subtarget - Keep a pointer to the Hexagon Subtarget around so that we can
49 /// make the right decision when generating code for different targets.
50 const HexagonSubtarget &Subtarget;
51
52 // Keep a reference to HexagonTargetMachine.
Krzysztof Parzyszekd5007472013-05-06 18:38:37 +000053 const HexagonTargetMachine& TM;
Jyotsna Vermad9225242013-02-13 21:38:46 +000054 DenseMap<const GlobalValue *, unsigned> GlobalAddressUseCountMap;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000055public:
Bill Wendlinga3cd3502013-06-19 21:36:55 +000056 explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine,
Jyotsna Vermad9225242013-02-13 21:38:46 +000057 CodeGenOpt::Level OptLevel)
58 : SelectionDAGISel(targetmachine, OptLevel),
Tony Linthicum1213a7a2011-12-12 21:14:40 +000059 Subtarget(targetmachine.getSubtarget<HexagonSubtarget>()),
Bill Wendling4a7a4082013-06-07 06:19:56 +000060 TM(targetmachine) {
Jyotsna Vermad9225242013-02-13 21:38:46 +000061 initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry());
Tony Linthicum1213a7a2011-12-12 21:14:40 +000062 }
Jyotsna Vermad9225242013-02-13 21:38:46 +000063 bool hasNumUsesBelowThresGA(SDNode *N) const;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000064
Craig Topper906c2cd2014-04-29 07:58:16 +000065 SDNode *Select(SDNode *N) override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000066
67 // Complex Pattern Selectors.
Jyotsna Vermad9225242013-02-13 21:38:46 +000068 inline bool foldGlobalAddress(SDValue &N, SDValue &R);
69 inline bool foldGlobalAddressGP(SDValue &N, SDValue &R);
70 bool foldGlobalAddressImpl(SDValue &N, SDValue &R, bool ShouldLookForGP);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000071 bool SelectADDRri(SDValue& N, SDValue &R1, SDValue &R2);
72 bool SelectADDRriS11_0(SDValue& N, SDValue &R1, SDValue &R2);
73 bool SelectADDRriS11_1(SDValue& N, SDValue &R1, SDValue &R2);
74 bool SelectADDRriS11_2(SDValue& N, SDValue &R1, SDValue &R2);
75 bool SelectMEMriS11_2(SDValue& Addr, SDValue &Base, SDValue &Offset);
76 bool SelectADDRriS11_3(SDValue& N, SDValue &R1, SDValue &R2);
77 bool SelectADDRrr(SDValue &Addr, SDValue &Base, SDValue &Offset);
78 bool SelectADDRriU6_0(SDValue& N, SDValue &R1, SDValue &R2);
79 bool SelectADDRriU6_1(SDValue& N, SDValue &R1, SDValue &R2);
80 bool SelectADDRriU6_2(SDValue& N, SDValue &R1, SDValue &R2);
81
Craig Topper906c2cd2014-04-29 07:58:16 +000082 const char *getPassName() const override {
Tony Linthicum1213a7a2011-12-12 21:14:40 +000083 return "Hexagon DAG->DAG Pattern Instruction Selection";
84 }
85
86 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
87 /// inline asm expressions.
Craig Topper906c2cd2014-04-29 07:58:16 +000088 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
89 char ConstraintCode,
90 std::vector<SDValue> &OutOps) override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000091 bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset);
92
93 SDNode *SelectLoad(SDNode *N);
Andrew Trickef9de2a2013-05-25 02:42:55 +000094 SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl);
95 SDNode *SelectIndexedLoad(LoadSDNode *LD, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000096 SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +000097 SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000098 SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +000099 SDLoc dl);
100 SDNode *SelectBaseOffsetStore(StoreSDNode *ST, SDLoc dl);
101 SDNode *SelectIndexedStore(StoreSDNode *ST, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000102 SDNode *SelectStore(SDNode *N);
103 SDNode *SelectSHL(SDNode *N);
104 SDNode *SelectSelect(SDNode *N);
105 SDNode *SelectTruncate(SDNode *N);
106 SDNode *SelectMul(SDNode *N);
107 SDNode *SelectZeroExtend(SDNode *N);
108 SDNode *SelectIntrinsicWOChain(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000109 SDNode *SelectIntrinsicWChain(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000110 SDNode *SelectConstant(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000111 SDNode *SelectConstantFP(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000112 SDNode *SelectAdd(SDNode *N);
Jyotsna Verma519b3852012-11-28 20:58:14 +0000113 bool isConstExtProfitable(SDNode *N) const;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000114
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000115// XformMskToBitPosU5Imm - Returns the bit position which
116// the single bit 32 bit mask represents.
117// Used in Clr and Set bit immediate memops.
118SDValue XformMskToBitPosU5Imm(uint32_t Imm) {
119 int32_t bitPos;
120 bitPos = Log2_32(Imm);
121 assert(bitPos >= 0 && bitPos < 32 &&
122 "Constant out of range for 32 BitPos Memops");
123 return CurDAG->getTargetConstant(bitPos, MVT::i32);
124}
125
126// XformMskToBitPosU4Imm - Returns the bit position which the single bit 16 bit
127// mask represents. Used in Clr and Set bit immediate memops.
128SDValue XformMskToBitPosU4Imm(uint16_t Imm) {
129 return XformMskToBitPosU5Imm(Imm);
130}
131
132// XformMskToBitPosU3Imm - Returns the bit position which the single bit 8 bit
133// mask represents. Used in Clr and Set bit immediate memops.
134SDValue XformMskToBitPosU3Imm(uint8_t Imm) {
135 return XformMskToBitPosU5Imm(Imm);
136}
137
138// Return true if there is exactly one bit set in V, i.e., if V is one of the
139// following integers: 2^0, 2^1, ..., 2^31.
140bool ImmIsSingleBit(uint32_t v) const {
141 uint32_t c = CountPopulation_64(v);
142 // Only return true if we counted 1 bit.
143 return c == 1;
144}
145
146// XformM5ToU5Imm - Return a target constant with the specified value, of type
147// i32 where the negative literal is transformed into a positive literal for
148// use in -= memops.
149inline SDValue XformM5ToU5Imm(signed Imm) {
150 assert( (Imm >= -31 && Imm <= -1) && "Constant out of range for Memops");
151 return CurDAG->getTargetConstant( - Imm, MVT::i32);
152}
153
154
Jyotsna Verma60316252013-02-05 19:20:45 +0000155// XformU7ToU7M1Imm - Return a target constant decremented by 1, in range
156// [1..128], used in cmpb.gtu instructions.
157inline SDValue XformU7ToU7M1Imm(signed Imm) {
158 assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op");
159 return CurDAG->getTargetConstant(Imm - 1, MVT::i8);
160}
161
Jyotsna Verma89c84822013-04-23 19:15:55 +0000162// XformS8ToS8M1Imm - Return a target constant decremented by 1.
163inline SDValue XformSToSM1Imm(signed Imm) {
164 return CurDAG->getTargetConstant(Imm - 1, MVT::i32);
165}
166
167// XformU8ToU8M1Imm - Return a target constant decremented by 1.
168inline SDValue XformUToUM1Imm(unsigned Imm) {
169 assert((Imm >= 1) && "Cannot decrement unsigned int less than 1");
170 return CurDAG->getTargetConstant(Imm - 1, MVT::i32);
171}
172
Jyotsna Verma60316252013-02-05 19:20:45 +0000173// Include the pieces autogenerated from the target description.
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000174#include "HexagonGenDAGISel.inc"
175};
176} // end anonymous namespace
177
178
179/// createHexagonISelDag - This pass converts a legalized DAG into a
180/// Hexagon-specific DAG, ready for instruction scheduling.
181///
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000182FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM,
Jyotsna Vermad9225242013-02-13 21:38:46 +0000183 CodeGenOpt::Level OptLevel) {
184 return new HexagonDAGToDAGISel(TM, OptLevel);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000185}
186
Jyotsna Vermad9225242013-02-13 21:38:46 +0000187static void initializePassOnce(PassRegistry &Registry) {
188 const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection";
189 PassInfo *PI = new PassInfo(Name, "hexagon-isel",
Craig Topper062a2ba2014-04-25 05:30:21 +0000190 &SelectionDAGISel::ID, nullptr, false, false);
Jyotsna Vermad9225242013-02-13 21:38:46 +0000191 Registry.registerPass(*PI, true);
192}
193
194void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) {
195 CALL_ONCE_INITIALIZATION(initializePassOnce)
196}
197
198
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000199static bool IsS11_0_Offset(SDNode * S) {
200 ConstantSDNode *N = cast<ConstantSDNode>(S);
201
202 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
203 // field.
204 int64_t v = (int64_t)N->getSExtValue();
205 return isInt<11>(v);
206}
207
208
209static bool IsS11_1_Offset(SDNode * S) {
210 ConstantSDNode *N = cast<ConstantSDNode>(S);
211
212 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
213 // field.
214 int64_t v = (int64_t)N->getSExtValue();
215 return isShiftedInt<11,1>(v);
216}
217
218
219static bool IsS11_2_Offset(SDNode * S) {
220 ConstantSDNode *N = cast<ConstantSDNode>(S);
221
222 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
223 // field.
224 int64_t v = (int64_t)N->getSExtValue();
225 return isShiftedInt<11,2>(v);
226}
227
228
229static bool IsS11_3_Offset(SDNode * S) {
230 ConstantSDNode *N = cast<ConstantSDNode>(S);
231
232 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
233 // field.
234 int64_t v = (int64_t)N->getSExtValue();
235 return isShiftedInt<11,3>(v);
236}
237
238
239static bool IsU6_0_Offset(SDNode * S) {
240 ConstantSDNode *N = cast<ConstantSDNode>(S);
241
242 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
243 // field.
244 int64_t v = (int64_t)N->getSExtValue();
245 return isUInt<6>(v);
246}
247
248
249static bool IsU6_1_Offset(SDNode * S) {
250 ConstantSDNode *N = cast<ConstantSDNode>(S);
251
252 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
253 // field.
254 int64_t v = (int64_t)N->getSExtValue();
255 return isShiftedUInt<6,1>(v);
256}
257
258
259static bool IsU6_2_Offset(SDNode * S) {
260 ConstantSDNode *N = cast<ConstantSDNode>(S);
261
262 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
263 // field.
264 int64_t v = (int64_t)N->getSExtValue();
265 return isShiftedUInt<6,2>(v);
266}
267
268
269// Intrinsics that return a a predicate.
270static unsigned doesIntrinsicReturnPredicate(unsigned ID)
271{
272 switch (ID) {
273 default:
274 return 0;
275 case Intrinsic::hexagon_C2_cmpeq:
276 case Intrinsic::hexagon_C2_cmpgt:
277 case Intrinsic::hexagon_C2_cmpgtu:
278 case Intrinsic::hexagon_C2_cmpgtup:
279 case Intrinsic::hexagon_C2_cmpgtp:
280 case Intrinsic::hexagon_C2_cmpeqp:
281 case Intrinsic::hexagon_C2_bitsset:
282 case Intrinsic::hexagon_C2_bitsclr:
283 case Intrinsic::hexagon_C2_cmpeqi:
284 case Intrinsic::hexagon_C2_cmpgti:
285 case Intrinsic::hexagon_C2_cmpgtui:
286 case Intrinsic::hexagon_C2_cmpgei:
287 case Intrinsic::hexagon_C2_cmpgeui:
288 case Intrinsic::hexagon_C2_cmplt:
289 case Intrinsic::hexagon_C2_cmpltu:
290 case Intrinsic::hexagon_C2_bitsclri:
291 case Intrinsic::hexagon_C2_and:
292 case Intrinsic::hexagon_C2_or:
293 case Intrinsic::hexagon_C2_xor:
294 case Intrinsic::hexagon_C2_andn:
295 case Intrinsic::hexagon_C2_not:
296 case Intrinsic::hexagon_C2_orn:
297 case Intrinsic::hexagon_C2_pxfer_map:
298 case Intrinsic::hexagon_C2_any8:
299 case Intrinsic::hexagon_C2_all8:
300 case Intrinsic::hexagon_A2_vcmpbeq:
301 case Intrinsic::hexagon_A2_vcmpbgtu:
302 case Intrinsic::hexagon_A2_vcmpheq:
303 case Intrinsic::hexagon_A2_vcmphgt:
304 case Intrinsic::hexagon_A2_vcmphgtu:
305 case Intrinsic::hexagon_A2_vcmpweq:
306 case Intrinsic::hexagon_A2_vcmpwgt:
307 case Intrinsic::hexagon_A2_vcmpwgtu:
308 case Intrinsic::hexagon_C2_tfrrp:
309 case Intrinsic::hexagon_S2_tstbit_i:
310 case Intrinsic::hexagon_S2_tstbit_r:
311 return 1;
312 }
313}
314
315
316// Intrinsics that have predicate operands.
317static unsigned doesIntrinsicContainPredicate(unsigned ID)
318{
319 switch (ID) {
320 default:
321 return 0;
322 case Intrinsic::hexagon_C2_tfrpr:
Colin LeMahieu30dcb232014-12-09 18:16:49 +0000323 return Hexagon::C2_tfrpr;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000324 case Intrinsic::hexagon_C2_and:
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000325 return Hexagon::C2_and;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000326 case Intrinsic::hexagon_C2_xor:
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000327 return Hexagon::C2_xor;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000328 case Intrinsic::hexagon_C2_or:
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000329 return Hexagon::C2_or;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000330 case Intrinsic::hexagon_C2_not:
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000331 return Hexagon::C2_not;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000332 case Intrinsic::hexagon_C2_any8:
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000333 return Hexagon::C2_any8;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000334 case Intrinsic::hexagon_C2_all8:
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000335 return Hexagon::C2_all8;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000336 case Intrinsic::hexagon_C2_vitpack:
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000337 return Hexagon::C2_vitpack;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000338 case Intrinsic::hexagon_C2_mask:
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000339 return Hexagon::C2_mask;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000340 case Intrinsic::hexagon_C2_mux:
Colin LeMahieue83bc742014-11-25 20:20:09 +0000341 return Hexagon::C2_mux;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000342
343 // Mapping hexagon_C2_muxir to MUX_pri. This is pretty weird - but
344 // that's how it's mapped in q6protos.h.
345 case Intrinsic::hexagon_C2_muxir:
Colin LeMahieu9665f982014-12-05 21:09:27 +0000346 return Hexagon::C2_muxri;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000347
348 // Mapping hexagon_C2_muxri to MUX_pir. This is pretty weird - but
349 // that's how it's mapped in q6protos.h.
350 case Intrinsic::hexagon_C2_muxri:
Colin LeMahieu9665f982014-12-05 21:09:27 +0000351 return Hexagon::C2_muxir;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000352
353 case Intrinsic::hexagon_C2_muxii:
Colin LeMahieu9665f982014-12-05 21:09:27 +0000354 return Hexagon::C2_muxii;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000355 case Intrinsic::hexagon_C2_vmux:
356 return Hexagon::VMUX_prr64;
357 case Intrinsic::hexagon_S2_valignrb:
358 return Hexagon::VALIGN_rrp;
359 case Intrinsic::hexagon_S2_vsplicerb:
360 return Hexagon::VSPLICE_rrp;
361 }
362}
363
364
365static bool OffsetFitsS11(EVT MemType, int64_t Offset) {
366 if (MemType == MVT::i64 && isShiftedInt<11,3>(Offset)) {
367 return true;
368 }
369 if (MemType == MVT::i32 && isShiftedInt<11,2>(Offset)) {
370 return true;
371 }
372 if (MemType == MVT::i16 && isShiftedInt<11,1>(Offset)) {
373 return true;
374 }
375 if (MemType == MVT::i8 && isInt<11>(Offset)) {
376 return true;
377 }
378 return false;
379}
380
381
382//
383// Try to lower loads of GlobalAdresses into base+offset loads. Custom
384// lowering for GlobalAddress nodes has already turned it into a
385// CONST32.
386//
Andrew Trickef9de2a2013-05-25 02:42:55 +0000387SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000388 SDValue Chain = LD->getChain();
389 SDNode* Const32 = LD->getBasePtr().getNode();
390 unsigned Opcode = 0;
391
392 if (Const32->getOpcode() == HexagonISD::CONST32 &&
393 ISD::isNormalLoad(LD)) {
394 SDValue Base = Const32->getOperand(0);
395 EVT LoadedVT = LD->getMemoryVT();
396 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
397 if (Offset != 0 && OffsetFitsS11(LoadedVT, Offset)) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000398 MVT PointerTy = getTargetLowering()->getPointerTy();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000399 const GlobalValue* GV =
400 cast<GlobalAddressSDNode>(Base)->getGlobal();
401 SDValue TargAddr =
402 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0);
Brendon Cahoonf6b687e2012-05-14 19:35:42 +0000403 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
404 dl, PointerTy,
405 TargAddr);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000406 // Figure out base + offset opcode
Colin LeMahieu947cd702014-12-23 20:44:59 +0000407 if (LoadedVT == MVT::i64) Opcode = Hexagon::L2_loadrd_io;
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000408 else if (LoadedVT == MVT::i32) Opcode = Hexagon::L2_loadri_io;
Colin LeMahieu8e39cad2014-12-23 17:25:57 +0000409 else if (LoadedVT == MVT::i16) Opcode = Hexagon::L2_loadrh_io;
Colin LeMahieu4b1eac42014-12-22 21:40:43 +0000410 else if (LoadedVT == MVT::i8) Opcode = Hexagon::L2_loadrb_io;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000411 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000412
413 // Build indexed load.
414 SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy);
415 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
416 LD->getValueType(0),
417 MVT::Other,
418 SDValue(NewBase,0),
419 TargetConstOff,
420 Chain);
421 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
422 MemOp[0] = LD->getMemOperand();
423 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
424 ReplaceUses(LD, Result);
425 return Result;
426 }
427 }
428
429 return SelectCode(LD);
430}
431
432
433SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
434 unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000435 SDLoc dl)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000436{
437 SDValue Chain = LD->getChain();
438 EVT LoadedVT = LD->getMemoryVT();
439 SDValue Base = LD->getBasePtr();
440 SDValue Offset = LD->getOffset();
441 SDNode *OffsetNode = Offset.getNode();
442 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
443 SDValue N1 = LD->getOperand(1);
444 SDValue CPTmpN1_0;
445 SDValue CPTmpN1_1;
Bill Wendling4a7a4082013-06-07 06:19:56 +0000446
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000447 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
448 N1.getNode()->getValueType(0) == MVT::i32) {
Eric Christopherd9134482014-08-04 21:25:23 +0000449 const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>(
450 TM.getSubtargetImpl()->getInstrInfo());
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000451 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
452 SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32);
453 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
454 MVT::Other, Base, TargetConst,
455 Chain);
Colin LeMahieueb52f692014-12-11 16:43:06 +0000456 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000457 SDValue(Result_1, 0));
458 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
459 MemOp[0] = LD->getMemOperand();
460 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
461 const SDValue Froms[] = { SDValue(LD, 0),
462 SDValue(LD, 1),
463 SDValue(LD, 2)
464 };
465 const SDValue Tos[] = { SDValue(Result_2, 0),
466 SDValue(Result_1, 1),
467 SDValue(Result_1, 2)
468 };
469 ReplaceUses(Froms, Tos, 3);
470 return Result_2;
Sirish Pandec92c3162012-05-03 16:18:50 +0000471 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000472 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
473 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
474 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
475 MVT::Other, Base, TargetConst0,
476 Chain);
Colin LeMahieueb52f692014-12-11 16:43:06 +0000477 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000478 MVT::i64, SDValue(Result_1, 0));
479 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl,
480 MVT::i32, Base, TargetConstVal,
481 SDValue(Result_1, 1));
482 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
483 MemOp[0] = LD->getMemOperand();
484 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
485 const SDValue Froms[] = { SDValue(LD, 0),
486 SDValue(LD, 1),
487 SDValue(LD, 2)
488 };
489 const SDValue Tos[] = { SDValue(Result_2, 0),
490 SDValue(Result_3, 0),
491 SDValue(Result_1, 1)
492 };
493 ReplaceUses(Froms, Tos, 3);
494 return Result_2;
495 }
496 return SelectCode(LD);
497}
498
499
500SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
501 unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000502 SDLoc dl)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000503{
504 SDValue Chain = LD->getChain();
505 EVT LoadedVT = LD->getMemoryVT();
506 SDValue Base = LD->getBasePtr();
507 SDValue Offset = LD->getOffset();
508 SDNode *OffsetNode = Offset.getNode();
509 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
510 SDValue N1 = LD->getOperand(1);
511 SDValue CPTmpN1_0;
512 SDValue CPTmpN1_1;
Bill Wendling4a7a4082013-06-07 06:19:56 +0000513
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000514 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
515 N1.getNode()->getValueType(0) == MVT::i32) {
Eric Christopherd9134482014-08-04 21:25:23 +0000516 const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>(
517 TM.getSubtargetImpl()->getInstrInfo());
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000518 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
519 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
520 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
521 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
522 MVT::i32, MVT::Other, Base,
523 TargetConstVal, Chain);
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000524 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000525 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +0000526 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000527 MVT::i64, MVT::Other,
528 SDValue(Result_2,0),
529 SDValue(Result_1,0));
530 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
531 MemOp[0] = LD->getMemOperand();
532 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
533 const SDValue Froms[] = { SDValue(LD, 0),
534 SDValue(LD, 1),
535 SDValue(LD, 2)
536 };
537 const SDValue Tos[] = { SDValue(Result_3, 0),
538 SDValue(Result_1, 1),
539 SDValue(Result_1, 2)
540 };
541 ReplaceUses(Froms, Tos, 3);
542 return Result_3;
543 }
544
545 // Generate an indirect load.
546 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
547 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
548 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
549 MVT::Other,
550 Base, TargetConst0, Chain);
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000551 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000552 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +0000553 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000554 MVT::i64, MVT::Other,
555 SDValue(Result_2,0),
556 SDValue(Result_1,0));
557 // Add offset to base.
558 SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
559 Base, TargetConstVal,
560 SDValue(Result_1, 1));
561 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
562 MemOp[0] = LD->getMemOperand();
563 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
564 const SDValue Froms[] = { SDValue(LD, 0),
565 SDValue(LD, 1),
566 SDValue(LD, 2)
567 };
568 const SDValue Tos[] = { SDValue(Result_3, 0), // Load value.
569 SDValue(Result_4, 0), // New address.
570 SDValue(Result_1, 1)
571 };
572 ReplaceUses(Froms, Tos, 3);
573 return Result_3;
574 }
575
576 return SelectCode(LD);
577}
578
579
Andrew Trickef9de2a2013-05-25 02:42:55 +0000580SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000581 SDValue Chain = LD->getChain();
582 SDValue Base = LD->getBasePtr();
583 SDValue Offset = LD->getOffset();
584 SDNode *OffsetNode = Offset.getNode();
585 // Get the constant value.
586 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
587 EVT LoadedVT = LD->getMemoryVT();
588 unsigned Opcode = 0;
589
590 // Check for zero ext loads.
591 bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD);
592
593 // Figure out the opcode.
Eric Christopherd9134482014-08-04 21:25:23 +0000594 const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>(
595 TM.getSubtargetImpl()->getInstrInfo());
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000596 if (LoadedVT == MVT::i64) {
597 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000598 Opcode = Hexagon::L2_loadrd_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000599 else
Colin LeMahieu947cd702014-12-23 20:44:59 +0000600 Opcode = Hexagon::L2_loadrd_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000601 } else if (LoadedVT == MVT::i32) {
602 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000603 Opcode = Hexagon::L2_loadri_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000604 else
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000605 Opcode = Hexagon::L2_loadri_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000606 } else if (LoadedVT == MVT::i16) {
607 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000608 Opcode = zextval ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000609 else
Colin LeMahieu8e39cad2014-12-23 17:25:57 +0000610 Opcode = zextval ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000611 } else if (LoadedVT == MVT::i8) {
612 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieufe9612e2014-12-26 19:12:11 +0000613 Opcode = zextval ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000614 else
Colin LeMahieu4b1eac42014-12-22 21:40:43 +0000615 Opcode = zextval ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000616 } else
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000617 llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000618
619 // For zero ext i64 loads, we need to add combine instructions.
620 if (LD->getValueType(0) == MVT::i64 &&
621 LD->getExtensionType() == ISD::ZEXTLOAD) {
622 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl);
623 }
624 if (LD->getValueType(0) == MVT::i64 &&
625 LD->getExtensionType() == ISD::SEXTLOAD) {
626 // Handle sign ext i64 loads.
627 return SelectIndexedLoadSignExtend64(LD, Opcode, dl);
628 }
629 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
630 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
631 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
632 LD->getValueType(0),
633 MVT::i32, MVT::Other, Base,
634 TargetConstVal, Chain);
635 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
636 MemOp[0] = LD->getMemOperand();
637 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
638 const SDValue Froms[] = { SDValue(LD, 0),
639 SDValue(LD, 1),
640 SDValue(LD, 2)
641 };
642 const SDValue Tos[] = { SDValue(Result, 0),
643 SDValue(Result, 1),
644 SDValue(Result, 2)
645 };
646 ReplaceUses(Froms, Tos, 3);
647 return Result;
648 } else {
649 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
650 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
651 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl,
652 LD->getValueType(0),
653 MVT::Other, Base, TargetConst0,
654 Chain);
655 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
656 Base, TargetConstVal,
657 SDValue(Result_1, 1));
658 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
659 MemOp[0] = LD->getMemOperand();
660 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
661 const SDValue Froms[] = { SDValue(LD, 0),
662 SDValue(LD, 1),
663 SDValue(LD, 2)
664 };
665 const SDValue Tos[] = { SDValue(Result_1, 0),
666 SDValue(Result_2, 0),
667 SDValue(Result_1, 1)
668 };
669 ReplaceUses(Froms, Tos, 3);
670 return Result_1;
671 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000672}
673
674
675SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
676 SDNode *result;
Andrew Trickef9de2a2013-05-25 02:42:55 +0000677 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000678 LoadSDNode *LD = cast<LoadSDNode>(N);
679 ISD::MemIndexedMode AM = LD->getAddressingMode();
680
681 // Handle indexed loads.
682 if (AM != ISD::UNINDEXED) {
683 result = SelectIndexedLoad(LD, dl);
684 } else {
685 result = SelectBaseOffsetLoad(LD, dl);
686 }
687
688 return result;
689}
690
691
Andrew Trickef9de2a2013-05-25 02:42:55 +0000692SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000693 SDValue Chain = ST->getChain();
694 SDValue Base = ST->getBasePtr();
695 SDValue Offset = ST->getOffset();
696 SDValue Value = ST->getValue();
697 SDNode *OffsetNode = Offset.getNode();
698 // Get the constant value.
699 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
700 EVT StoredVT = ST->getMemoryVT();
701
702 // Offset value must be within representable range
703 // and must have correct alignment properties.
Eric Christopherd9134482014-08-04 21:25:23 +0000704 const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>(
705 TM.getSubtargetImpl()->getInstrInfo());
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000706 if (TII->isValidAutoIncImm(StoredVT, Val)) {
Jyotsna Vermab16a9cb2013-01-29 18:42:41 +0000707 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value,
708 Chain};
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000709 unsigned Opcode = 0;
710
711 // Figure out the post inc version of opcode.
Colin LeMahieu9a3cd3f2014-12-29 20:00:43 +0000712 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi;
713 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi;
714 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi;
Colin LeMahieu3d34afb2014-12-29 19:42:14 +0000715 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000716 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000717
718 // Build post increment store.
719 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +0000720 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000721 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
722 MemOp[0] = ST->getMemOperand();
723 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
724
725 ReplaceUses(ST, Result);
726 ReplaceUses(SDValue(ST,1), SDValue(Result,1));
727 return Result;
728 }
729
730 // Note: Order of operands matches the def of instruction:
731 // def STrid : STInst<(outs), (ins MEMri:$addr, DoubleRegs:$src1), ...
732 // and it differs for POST_ST* for instance.
733 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value,
734 Chain};
735 unsigned Opcode = 0;
736
737 // Figure out the opcode.
Colin LeMahieubda31b42014-12-29 20:44:51 +0000738 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
739 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
740 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
741 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000742 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000743
744 // Build regular store.
745 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
Michael Liaob53d8962013-04-19 22:22:57 +0000746 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000747 // Build splitted incriment instruction.
748 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
749 Base,
750 TargetConstVal,
751 SDValue(Result_1, 0));
752 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
753 MemOp[0] = ST->getMemOperand();
754 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
755
756 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0));
757 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0));
758 return Result_2;
759}
760
761
762SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000763 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000764 SDValue Chain = ST->getChain();
765 SDNode* Const32 = ST->getBasePtr().getNode();
766 SDValue Value = ST->getValue();
767 unsigned Opcode = 0;
768
769 // Try to lower stores of GlobalAdresses into indexed stores. Custom
770 // lowering for GlobalAddress nodes has already turned it into a
771 // CONST32. Avoid truncating stores for the moment. Post-inc stores
772 // do the same. Don't think there's a reason for it, so will file a
773 // bug to fix.
774 if ((Const32->getOpcode() == HexagonISD::CONST32) &&
775 !(Value.getValueType() == MVT::i64 && ST->isTruncatingStore())) {
776 SDValue Base = Const32->getOperand(0);
777 if (Base.getOpcode() == ISD::TargetGlobalAddress) {
778 EVT StoredVT = ST->getMemoryVT();
779 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
780 if (Offset != 0 && OffsetFitsS11(StoredVT, Offset)) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000781 MVT PointerTy = getTargetLowering()->getPointerTy();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000782 const GlobalValue* GV =
783 cast<GlobalAddressSDNode>(Base)->getGlobal();
784 SDValue TargAddr =
785 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0);
Brendon Cahoonf6b687e2012-05-14 19:35:42 +0000786 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
787 dl, PointerTy,
788 TargAddr);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000789
790 // Figure out base + offset opcode
Colin LeMahieubda31b42014-12-29 20:44:51 +0000791 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
792 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
793 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
794 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000795 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000796
797 SDValue Ops[] = {SDValue(NewBase,0),
798 CurDAG->getTargetConstant(Offset,PointerTy),
799 Value, Chain};
800 // build indexed store
801 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
Michael Liaob53d8962013-04-19 22:22:57 +0000802 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000803 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
804 MemOp[0] = ST->getMemOperand();
805 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
806 ReplaceUses(ST, Result);
807 return Result;
808 }
809 }
810 }
811
812 return SelectCode(ST);
813}
814
815
816SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000817 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000818 StoreSDNode *ST = cast<StoreSDNode>(N);
819 ISD::MemIndexedMode AM = ST->getAddressingMode();
820
821 // Handle indexed stores.
822 if (AM != ISD::UNINDEXED) {
823 return SelectIndexedStore(ST, dl);
824 }
Sirish Pandec92c3162012-05-03 16:18:50 +0000825
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000826 return SelectBaseOffsetStore(ST, dl);
827}
828
829SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000830 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000831
832 //
833 // %conv.i = sext i32 %tmp1 to i64
834 // %conv2.i = sext i32 %add to i64
835 // %mul.i = mul nsw i64 %conv2.i, %conv.i
836 //
837 // --- match with the following ---
838 //
839 // %mul.i = mpy (%tmp1, %add)
840 //
841
842 if (N->getValueType(0) == MVT::i64) {
843 // Shifting a i64 signed multiply.
844 SDValue MulOp0 = N->getOperand(0);
845 SDValue MulOp1 = N->getOperand(1);
846
847 SDValue OP0;
848 SDValue OP1;
849
850 // Handle sign_extend and sextload.
851 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
852 SDValue Sext0 = MulOp0.getOperand(0);
853 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000854 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000855 }
856
857 OP0 = Sext0;
858 } else if (MulOp0.getOpcode() == ISD::LOAD) {
859 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
860 if (LD->getMemoryVT() != MVT::i32 ||
861 LD->getExtensionType() != ISD::SEXTLOAD ||
862 LD->getAddressingMode() != ISD::UNINDEXED) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000863 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000864 }
865
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000866 SDValue Chain = LD->getChain();
867 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000868 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000869 MVT::Other,
870 LD->getBasePtr(), TargetConst0,
871 Chain), 0);
872 } else {
873 return SelectCode(N);
874 }
875
876 // Same goes for the second operand.
877 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
878 SDValue Sext1 = MulOp1.getOperand(0);
879 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
880 return SelectCode(N);
881 }
882
883 OP1 = Sext1;
884 } else if (MulOp1.getOpcode() == ISD::LOAD) {
885 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
886 if (LD->getMemoryVT() != MVT::i32 ||
887 LD->getExtensionType() != ISD::SEXTLOAD ||
888 LD->getAddressingMode() != ISD::UNINDEXED) {
889 return SelectCode(N);
890 }
891
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000892 SDValue Chain = LD->getChain();
893 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000894 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000895 MVT::Other,
896 LD->getBasePtr(), TargetConst0,
897 Chain), 0);
898 } else {
899 return SelectCode(N);
900 }
901
902 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +0000903 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000904 OP0, OP1);
905 ReplaceUses(N, Result);
906 return Result;
907 }
908
909 return SelectCode(N);
910}
911
912
913SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000914 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000915 SDValue N0 = N->getOperand(0);
916 if (N0.getOpcode() == ISD::SETCC) {
917 SDValue N00 = N0.getOperand(0);
918 if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) {
919 SDValue N000 = N00.getOperand(0);
920 SDValue N001 = N00.getOperand(1);
921 if (cast<VTSDNode>(N001)->getVT() == MVT::i16) {
922 SDValue N01 = N0.getOperand(1);
923 SDValue N02 = N0.getOperand(2);
924
925 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
926 // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1,
927 // IntRegs:i32:$src2)
928 // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
929 // Pattern complexity = 9 cost = 1 size = 0.
930 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) {
931 SDValue N1 = N->getOperand(1);
932 if (N01 == N1) {
933 SDValue N2 = N->getOperand(2);
934 if (N000 == N2 &&
935 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
936 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
Colin LeMahieu310991c2014-11-21 21:54:59 +0000937 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000938 MVT::i32, N000);
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000939 SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_max, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000940 MVT::i32,
941 SDValue(SextNode, 0),
942 N1);
943 ReplaceUses(N, Result);
944 return Result;
945 }
946 }
947 }
948
949 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
950 // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1,
951 // IntRegs:i32:$src2)
952 // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
953 // Pattern complexity = 9 cost = 1 size = 0.
954 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) {
955 SDValue N1 = N->getOperand(1);
956 if (N01 == N1) {
957 SDValue N2 = N->getOperand(2);
958 if (N000 == N2 &&
959 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
960 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
Colin LeMahieu310991c2014-11-21 21:54:59 +0000961 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000962 MVT::i32, N000);
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000963 SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_min, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000964 MVT::i32,
965 SDValue(SextNode, 0),
966 N1);
967 ReplaceUses(N, Result);
968 return Result;
969 }
970 }
971 }
972 }
973 }
974 }
975
976 return SelectCode(N);
977}
978
979
980SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000981 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000982 SDValue Shift = N->getOperand(0);
983
984 //
985 // %conv.i = sext i32 %tmp1 to i64
986 // %conv2.i = sext i32 %add to i64
987 // %mul.i = mul nsw i64 %conv2.i, %conv.i
988 // %shr5.i = lshr i64 %mul.i, 32
989 // %conv3.i = trunc i64 %shr5.i to i32
990 //
991 // --- match with the following ---
992 //
993 // %conv3.i = mpy (%tmp1, %add)
994 //
995 // Trunc to i32.
996 if (N->getValueType(0) == MVT::i32) {
997 // Trunc from i64.
998 if (Shift.getNode()->getValueType(0) == MVT::i64) {
999 // Trunc child is logical shift right.
1000 if (Shift.getOpcode() != ISD::SRL) {
1001 return SelectCode(N);
1002 }
1003
1004 SDValue ShiftOp0 = Shift.getOperand(0);
1005 SDValue ShiftOp1 = Shift.getOperand(1);
1006
1007 // Shift by const 32
1008 if (ShiftOp1.getOpcode() != ISD::Constant) {
1009 return SelectCode(N);
1010 }
1011
1012 int32_t ShiftConst =
1013 cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue();
1014 if (ShiftConst != 32) {
1015 return SelectCode(N);
1016 }
1017
1018 // Shifting a i64 signed multiply
1019 SDValue Mul = ShiftOp0;
1020 if (Mul.getOpcode() != ISD::MUL) {
1021 return SelectCode(N);
1022 }
1023
1024 SDValue MulOp0 = Mul.getOperand(0);
1025 SDValue MulOp1 = Mul.getOperand(1);
1026
1027 SDValue OP0;
1028 SDValue OP1;
1029
1030 // Handle sign_extend and sextload
1031 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
1032 SDValue Sext0 = MulOp0.getOperand(0);
1033 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
1034 return SelectCode(N);
1035 }
1036
1037 OP0 = Sext0;
1038 } else if (MulOp0.getOpcode() == ISD::LOAD) {
1039 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
1040 if (LD->getMemoryVT() != MVT::i32 ||
1041 LD->getExtensionType() != ISD::SEXTLOAD ||
1042 LD->getAddressingMode() != ISD::UNINDEXED) {
1043 return SelectCode(N);
1044 }
1045
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001046 SDValue Chain = LD->getChain();
1047 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +00001048 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001049 MVT::Other,
1050 LD->getBasePtr(),
1051 TargetConst0, Chain), 0);
1052 } else {
1053 return SelectCode(N);
1054 }
1055
1056 // Same goes for the second operand.
1057 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
1058 SDValue Sext1 = MulOp1.getOperand(0);
1059 if (Sext1.getNode()->getValueType(0) != MVT::i32)
1060 return SelectCode(N);
1061
1062 OP1 = Sext1;
1063 } else if (MulOp1.getOpcode() == ISD::LOAD) {
1064 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
1065 if (LD->getMemoryVT() != MVT::i32 ||
1066 LD->getExtensionType() != ISD::SEXTLOAD ||
1067 LD->getAddressingMode() != ISD::UNINDEXED) {
1068 return SelectCode(N);
1069 }
1070
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001071 SDValue Chain = LD->getChain();
1072 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +00001073 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001074 MVT::Other,
1075 LD->getBasePtr(),
1076 TargetConst0, Chain), 0);
1077 } else {
1078 return SelectCode(N);
1079 }
1080
1081 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +00001082 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpy_up, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001083 OP0, OP1);
1084 ReplaceUses(N, Result);
1085 return Result;
1086 }
1087 }
1088
1089 return SelectCode(N);
1090}
1091
1092
1093SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001094 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001095 if (N->getValueType(0) == MVT::i32) {
1096 SDValue Shl_0 = N->getOperand(0);
1097 SDValue Shl_1 = N->getOperand(1);
1098 // RHS is const.
1099 if (Shl_1.getOpcode() == ISD::Constant) {
1100 if (Shl_0.getOpcode() == ISD::MUL) {
1101 SDValue Mul_0 = Shl_0.getOperand(0); // Val
1102 SDValue Mul_1 = Shl_0.getOperand(1); // Const
1103 // RHS of mul is const.
1104 if (Mul_1.getOpcode() == ISD::Constant) {
1105 int32_t ShlConst =
1106 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1107 int32_t MulConst =
1108 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
1109 int32_t ValConst = MulConst << ShlConst;
1110 SDValue Val = CurDAG->getTargetConstant(ValConst,
1111 MVT::i32);
1112 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
1113 if (isInt<9>(CN->getSExtValue())) {
1114 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +00001115 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001116 MVT::i32, Mul_0, Val);
1117 ReplaceUses(N, Result);
1118 return Result;
1119 }
1120
1121 }
1122 } else if (Shl_0.getOpcode() == ISD::SUB) {
1123 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
1124 SDValue Sub_1 = Shl_0.getOperand(1); // Val
1125 if (Sub_0.getOpcode() == ISD::Constant) {
1126 int32_t SubConst =
1127 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
1128 if (SubConst == 0) {
1129 if (Sub_1.getOpcode() == ISD::SHL) {
1130 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
1131 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
1132 if (Shl2_1.getOpcode() == ISD::Constant) {
1133 int32_t ShlConst =
1134 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1135 int32_t Shl2Const =
1136 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
1137 int32_t ValConst = 1 << (ShlConst+Shl2Const);
1138 SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32);
1139 if (ConstantSDNode *CN =
1140 dyn_cast<ConstantSDNode>(Val.getNode()))
1141 if (isInt<9>(CN->getSExtValue())) {
1142 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +00001143 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001144 Shl2_0, Val);
1145 ReplaceUses(N, Result);
1146 return Result;
1147 }
1148 }
1149 }
1150 }
1151 }
1152 }
1153 }
1154 }
1155 return SelectCode(N);
1156}
1157
1158
1159//
1160// If there is an zero_extend followed an intrinsic in DAG (this means - the
1161// result of the intrinsic is predicate); convert the zero_extend to
1162// transfer instruction.
1163//
1164// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
1165// converted into a MUX as predicate registers defined as 1 bit in the
1166// compiler. Architecture defines them as 8-bit registers.
1167// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
1168//
1169SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001170 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001171 SDNode *IsIntrinsic = N->getOperand(0).getNode();
1172 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
1173 unsigned ID =
1174 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
1175 if (doesIntrinsicReturnPredicate(ID)) {
1176 // Now we need to differentiate target data types.
1177 if (N->getValueType(0) == MVT::i64) {
1178 // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs).
1179 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001180 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001181 MVT::i32,
1182 SDValue(IsIntrinsic, 0));
Colin LeMahieu4af437f2014-12-09 20:23:30 +00001183 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001184 MVT::i32,
1185 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +00001186 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001187 MVT::i64, MVT::Other,
1188 SDValue(Result_2, 0),
1189 SDValue(Result_1, 0));
1190 ReplaceUses(N, Result_3);
1191 return Result_3;
1192 }
1193 if (N->getValueType(0) == MVT::i32) {
1194 // Convert the zero_extend to Rs = Pd
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001195 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001196 MVT::i32,
1197 SDValue(IsIntrinsic, 0));
1198 ReplaceUses(N, RsPd);
1199 return RsPd;
1200 }
Craig Toppere55c5562012-02-07 02:50:20 +00001201 llvm_unreachable("Unexpected value type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001202 }
1203 }
1204 return SelectCode(N);
1205}
1206
1207
1208//
1209// Checking for intrinsics which have predicate registers as operand(s)
1210// and lowering to the actual intrinsic.
1211//
1212SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001213 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001214 unsigned ID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
1215 unsigned IntrinsicWithPred = doesIntrinsicContainPredicate(ID);
1216
1217 // We are concerned with only those intrinsics that have predicate registers
1218 // as at least one of the operands.
1219 if (IntrinsicWithPred) {
1220 SmallVector<SDValue, 8> Ops;
Eric Christopherd9134482014-08-04 21:25:23 +00001221 const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>(
1222 TM.getSubtargetImpl()->getInstrInfo());
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001223 const MCInstrDesc &MCID = TII->get(IntrinsicWithPred);
Eric Christopherd9134482014-08-04 21:25:23 +00001224 const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001225
1226 // Iterate over all the operands of the intrinsics.
1227 // For PredRegs, do the transfer.
1228 // For Double/Int Regs, just preserve the value
1229 // For immediates, lower it.
1230 for (unsigned i = 1; i < N->getNumOperands(); ++i) {
1231 SDNode *Arg = N->getOperand(i).getNode();
Jakob Stoklund Olesen3c52f022012-05-07 22:10:26 +00001232 const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI, *MF);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001233
Craig Topperc7242e02012-04-20 07:30:17 +00001234 if (RC == &Hexagon::IntRegsRegClass ||
1235 RC == &Hexagon::DoubleRegsRegClass) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001236 Ops.push_back(SDValue(Arg, 0));
Craig Topperc7242e02012-04-20 07:30:17 +00001237 } else if (RC == &Hexagon::PredRegsRegClass) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001238 // Do the transfer.
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001239 SDNode *PdRs = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001240 SDValue(Arg, 0));
1241 Ops.push_back(SDValue(PdRs,0));
Craig Topper062a2ba2014-04-25 05:30:21 +00001242 } else if (!RC && (dyn_cast<ConstantSDNode>(Arg) != nullptr)) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001243 // This is immediate operand. Lower it here making sure that we DO have
1244 // const SDNode for immediate value.
1245 int32_t Val = cast<ConstantSDNode>(Arg)->getSExtValue();
1246 SDValue SDVal = CurDAG->getTargetConstant(Val, MVT::i32);
1247 Ops.push_back(SDVal);
1248 } else {
Craig Toppere55c5562012-02-07 02:50:20 +00001249 llvm_unreachable("Unimplemented");
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001250 }
1251 }
1252 EVT ReturnValueVT = N->getValueType(0);
1253 SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001254 ReturnValueVT, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001255 ReplaceUses(N, Result);
1256 return Result;
1257 }
1258 return SelectCode(N);
1259}
1260
Sirish Pande69295b82012-05-10 20:20:25 +00001261//
1262// Map floating point constant values.
1263//
1264SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001265 SDLoc dl(N);
Sirish Pande69295b82012-05-10 20:20:25 +00001266 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
1267 APFloat APF = CN->getValueAPF();
1268 if (N->getValueType(0) == MVT::f32) {
1269 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
1270 CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32));
1271 }
1272 else if (N->getValueType(0) == MVT::f64) {
1273 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
1274 CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64));
1275 }
1276
1277 return SelectCode(N);
1278}
1279
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001280
1281//
1282// Map predicate true (encoded as -1 in LLVM) to a XOR.
1283//
1284SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001285 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001286 if (N->getValueType(0) == MVT::i1) {
1287 SDNode* Result;
1288 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
1289 if (Val == -1) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001290 // Create the IntReg = 1 node.
1291 SDNode* IntRegTFR =
Colin LeMahieu4af437f2014-12-09 20:23:30 +00001292 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001293 CurDAG->getTargetConstant(0, MVT::i32));
1294
1295 // Pd = IntReg
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001296 SDNode* Pd = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001297 SDValue(IntRegTFR, 0));
1298
1299 // not(Pd)
Colin LeMahieu5cf56322014-12-08 23:55:43 +00001300 SDNode* NotPd = CurDAG->getMachineNode(Hexagon::C2_not, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001301 SDValue(Pd, 0));
1302
1303 // xor(not(Pd))
Colin LeMahieu5cf56322014-12-08 23:55:43 +00001304 Result = CurDAG->getMachineNode(Hexagon::C2_xor, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001305 SDValue(Pd, 0), SDValue(NotPd, 0));
1306
1307 // We have just built:
1308 // Rs = Pd
1309 // Pd = xor(not(Pd), Pd)
1310
1311 ReplaceUses(N, Result);
1312 return Result;
1313 }
1314 }
1315
1316 return SelectCode(N);
1317}
1318
1319
1320//
1321// Map add followed by a asr -> asr +=.
1322//
1323SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001324 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001325 if (N->getValueType(0) != MVT::i32) {
1326 return SelectCode(N);
1327 }
1328 // Identify nodes of the form: add(asr(...)).
1329 SDNode* Src1 = N->getOperand(0).getNode();
1330 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1331 || Src1->getValueType(0) != MVT::i32) {
1332 return SelectCode(N);
1333 }
1334
1335 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1336 // Rd and Rd' are assigned to the same register
Colin LeMahieu0f850bd2014-12-19 20:29:29 +00001337 SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001338 N->getOperand(1),
1339 Src1->getOperand(0),
1340 Src1->getOperand(1));
1341 ReplaceUses(N, Result);
1342
1343 return Result;
1344}
1345
1346
1347SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
Tim Northover31d093c2013-09-22 08:21:56 +00001348 if (N->isMachineOpcode()) {
1349 N->setNodeId(-1);
Craig Topper062a2ba2014-04-25 05:30:21 +00001350 return nullptr; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00001351 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001352
1353
1354 switch (N->getOpcode()) {
1355 case ISD::Constant:
1356 return SelectConstant(N);
1357
Sirish Pande69295b82012-05-10 20:20:25 +00001358 case ISD::ConstantFP:
1359 return SelectConstantFP(N);
1360
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001361 case ISD::ADD:
1362 return SelectAdd(N);
1363
1364 case ISD::SHL:
1365 return SelectSHL(N);
1366
1367 case ISD::LOAD:
1368 return SelectLoad(N);
1369
1370 case ISD::STORE:
1371 return SelectStore(N);
1372
1373 case ISD::SELECT:
1374 return SelectSelect(N);
1375
1376 case ISD::TRUNCATE:
1377 return SelectTruncate(N);
1378
1379 case ISD::MUL:
1380 return SelectMul(N);
1381
1382 case ISD::ZERO_EXTEND:
1383 return SelectZeroExtend(N);
1384
1385 case ISD::INTRINSIC_WO_CHAIN:
1386 return SelectIntrinsicWOChain(N);
1387 }
1388
1389 return SelectCode(N);
1390}
1391
1392
1393//
1394// Hexagon_TODO: Five functions for ADDRri?! Surely there must be a better way
1395// to define these instructions.
1396//
1397bool HexagonDAGToDAGISel::SelectADDRri(SDValue& Addr, SDValue &Base,
1398 SDValue &Offset) {
1399 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1400 Addr.getOpcode() == ISD::TargetGlobalAddress)
1401 return false; // Direct calls.
1402
1403 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1404 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1405 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1406 return true;
1407 }
1408 Base = Addr;
1409 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1410 return true;
1411}
1412
1413
1414bool HexagonDAGToDAGISel::SelectADDRriS11_0(SDValue& Addr, SDValue &Base,
1415 SDValue &Offset) {
1416 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1417 Addr.getOpcode() == ISD::TargetGlobalAddress)
1418 return false; // Direct calls.
1419
1420 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1421 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1422 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1423 return (IsS11_0_Offset(Offset.getNode()));
1424 }
1425 Base = Addr;
1426 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1427 return (IsS11_0_Offset(Offset.getNode()));
1428}
1429
1430
1431bool HexagonDAGToDAGISel::SelectADDRriS11_1(SDValue& Addr, SDValue &Base,
1432 SDValue &Offset) {
1433 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1434 Addr.getOpcode() == ISD::TargetGlobalAddress)
1435 return false; // Direct calls.
1436
1437 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1438 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1439 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1440 return (IsS11_1_Offset(Offset.getNode()));
1441 }
1442 Base = Addr;
1443 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1444 return (IsS11_1_Offset(Offset.getNode()));
1445}
1446
1447
1448bool HexagonDAGToDAGISel::SelectADDRriS11_2(SDValue& Addr, SDValue &Base,
1449 SDValue &Offset) {
1450 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1451 Addr.getOpcode() == ISD::TargetGlobalAddress)
1452 return false; // Direct calls.
1453
1454 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1455 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1456 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1457 return (IsS11_2_Offset(Offset.getNode()));
1458 }
1459 Base = Addr;
1460 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1461 return (IsS11_2_Offset(Offset.getNode()));
1462}
1463
1464
1465bool HexagonDAGToDAGISel::SelectADDRriU6_0(SDValue& Addr, SDValue &Base,
1466 SDValue &Offset) {
1467 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1468 Addr.getOpcode() == ISD::TargetGlobalAddress)
1469 return false; // Direct calls.
1470
1471 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1472 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1473 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1474 return (IsU6_0_Offset(Offset.getNode()));
1475 }
1476 Base = Addr;
1477 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1478 return (IsU6_0_Offset(Offset.getNode()));
1479}
1480
1481
1482bool HexagonDAGToDAGISel::SelectADDRriU6_1(SDValue& Addr, SDValue &Base,
1483 SDValue &Offset) {
1484 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1485 Addr.getOpcode() == ISD::TargetGlobalAddress)
1486 return false; // Direct calls.
1487
1488 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1489 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1490 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1491 return (IsU6_1_Offset(Offset.getNode()));
1492 }
1493 Base = Addr;
1494 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1495 return (IsU6_1_Offset(Offset.getNode()));
1496}
1497
1498
1499bool HexagonDAGToDAGISel::SelectADDRriU6_2(SDValue& Addr, SDValue &Base,
1500 SDValue &Offset) {
1501 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1502 Addr.getOpcode() == ISD::TargetGlobalAddress)
1503 return false; // Direct calls.
1504
1505 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1506 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1507 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1508 return (IsU6_2_Offset(Offset.getNode()));
1509 }
1510 Base = Addr;
1511 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1512 return (IsU6_2_Offset(Offset.getNode()));
1513}
1514
1515
1516bool HexagonDAGToDAGISel::SelectMEMriS11_2(SDValue& Addr, SDValue &Base,
1517 SDValue &Offset) {
1518
1519 if (Addr.getOpcode() != ISD::ADD) {
1520 return(SelectADDRriS11_2(Addr, Base, Offset));
1521 }
1522
1523 return SelectADDRriS11_2(Addr, Base, Offset);
1524}
1525
1526
1527bool HexagonDAGToDAGISel::SelectADDRriS11_3(SDValue& Addr, SDValue &Base,
1528 SDValue &Offset) {
1529 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1530 Addr.getOpcode() == ISD::TargetGlobalAddress)
1531 return false; // Direct calls.
1532
1533 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1534 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1535 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1536 return (IsS11_3_Offset(Offset.getNode()));
1537 }
1538 Base = Addr;
1539 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1540 return (IsS11_3_Offset(Offset.getNode()));
1541}
1542
1543bool HexagonDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1,
1544 SDValue &R2) {
1545 if (Addr.getOpcode() == ISD::FrameIndex) return false;
1546 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1547 Addr.getOpcode() == ISD::TargetGlobalAddress)
1548 return false; // Direct calls.
1549
1550 if (Addr.getOpcode() == ISD::ADD) {
1551 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
1552 if (isInt<13>(CN->getSExtValue()))
1553 return false; // Let the reg+imm pattern catch this!
1554 R1 = Addr.getOperand(0);
1555 R2 = Addr.getOperand(1);
1556 return true;
1557 }
1558
1559 R1 = Addr;
1560
1561 return true;
1562}
1563
1564
1565// Handle generic address case. It is accessed from inlined asm =m constraints,
1566// which could have any kind of pointer.
1567bool HexagonDAGToDAGISel::SelectAddr(SDNode *Op, SDValue Addr,
1568 SDValue &Base, SDValue &Offset) {
1569 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1570 Addr.getOpcode() == ISD::TargetGlobalAddress)
1571 return false; // Direct calls.
1572
1573 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1574 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1575 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1576 return true;
1577 }
1578
1579 if (Addr.getOpcode() == ISD::ADD) {
1580 Base = Addr.getOperand(0);
1581 Offset = Addr.getOperand(1);
1582 return true;
1583 }
1584
1585 Base = Addr;
1586 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1587 return true;
1588}
1589
1590
1591bool HexagonDAGToDAGISel::
1592SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
1593 std::vector<SDValue> &OutOps) {
1594 SDValue Op0, Op1;
1595
1596 switch (ConstraintCode) {
1597 case 'o': // Offsetable.
1598 case 'v': // Not offsetable.
1599 default: return true;
1600 case 'm': // Memory.
1601 if (!SelectAddr(Op.getNode(), Op, Op0, Op1))
1602 return true;
1603 break;
1604 }
1605
1606 OutOps.push_back(Op0);
1607 OutOps.push_back(Op1);
1608 return false;
1609}
Jyotsna Verma519b3852012-11-28 20:58:14 +00001610
1611bool HexagonDAGToDAGISel::isConstExtProfitable(SDNode *N) const {
1612 unsigned UseCount = 0;
1613 for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
1614 UseCount++;
1615 }
1616
1617 return (UseCount <= 1);
1618
1619}
Jyotsna Vermad9225242013-02-13 21:38:46 +00001620
1621//===--------------------------------------------------------------------===//
1622// Return 'true' if use count of the global address is below threshold.
1623//===--------------------------------------------------------------------===//
1624bool HexagonDAGToDAGISel::hasNumUsesBelowThresGA(SDNode *N) const {
1625 assert(N->getOpcode() == ISD::TargetGlobalAddress &&
1626 "Expecting a target global address");
1627
1628 // Always try to fold the address.
1629 if (TM.getOptLevel() == CodeGenOpt::Aggressive)
1630 return true;
1631
1632 GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N);
1633 DenseMap<const GlobalValue *, unsigned>::const_iterator GI =
1634 GlobalAddressUseCountMap.find(GA->getGlobal());
1635
1636 if (GI == GlobalAddressUseCountMap.end())
1637 return false;
1638
1639 return GI->second <= MaxNumOfUsesForConstExtenders;
1640}
1641
1642//===--------------------------------------------------------------------===//
Alp Tokerf907b892013-12-05 05:44:44 +00001643// Return true if the non-GP-relative global address can be folded.
Jyotsna Vermad9225242013-02-13 21:38:46 +00001644//===--------------------------------------------------------------------===//
1645inline bool HexagonDAGToDAGISel::foldGlobalAddress(SDValue &N, SDValue &R) {
1646 return foldGlobalAddressImpl(N, R, false);
1647}
1648
1649//===--------------------------------------------------------------------===//
1650// Return true if the GP-relative global address can be folded.
1651//===--------------------------------------------------------------------===//
1652inline bool HexagonDAGToDAGISel::foldGlobalAddressGP(SDValue &N, SDValue &R) {
1653 return foldGlobalAddressImpl(N, R, true);
1654}
1655
1656//===--------------------------------------------------------------------===//
1657// Fold offset of the global address if number of uses are below threshold.
1658//===--------------------------------------------------------------------===//
1659bool HexagonDAGToDAGISel::foldGlobalAddressImpl(SDValue &N, SDValue &R,
1660 bool ShouldLookForGP) {
1661 if (N.getOpcode() == ISD::ADD) {
1662 SDValue N0 = N.getOperand(0);
1663 SDValue N1 = N.getOperand(1);
1664 if ((ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32_GP)) ||
1665 (!ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32))) {
1666 ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1);
1667 GlobalAddressSDNode *GA =
1668 dyn_cast<GlobalAddressSDNode>(N0.getOperand(0));
1669
1670 if (Const && GA &&
1671 (GA->getOpcode() == ISD::TargetGlobalAddress)) {
1672 if ((N0.getOpcode() == HexagonISD::CONST32) &&
1673 !hasNumUsesBelowThresGA(GA))
1674 return false;
1675 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(),
Andrew Trickef9de2a2013-05-25 02:42:55 +00001676 SDLoc(Const),
Jyotsna Vermad9225242013-02-13 21:38:46 +00001677 N.getValueType(),
1678 GA->getOffset() +
1679 (uint64_t)Const->getSExtValue());
1680 return true;
1681 }
1682 }
1683 }
1684 return false;
1685}