blob: 9e78e518c2fe4201678bf6a89a0462d43c17306c [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
14#define DEBUG_TYPE "hexagon-isel"
Chandler Carruthed0881b2012-12-03 16:50:05 +000015#include "Hexagon.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000016#include "HexagonISelLowering.h"
17#include "HexagonTargetMachine.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000018#include "llvm/ADT/DenseMap.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000019#include "llvm/IR/Intrinsics.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000020#include "llvm/CodeGen/SelectionDAGISel.h"
21#include "llvm/Support/CommandLine.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000022#include "llvm/Support/Compiler.h"
23#include "llvm/Support/Debug.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000024using namespace llvm;
25
Jyotsna Vermad9225242013-02-13 21:38:46 +000026static
27cl::opt<unsigned>
28MaxNumOfUsesForConstExtenders("ga-max-num-uses-for-constant-extenders",
29 cl::Hidden, cl::init(2),
30 cl::desc("Maximum number of uses of a global address such that we still us a"
31 "constant extended instruction"));
Tony Linthicum1213a7a2011-12-12 21:14:40 +000032
33//===----------------------------------------------------------------------===//
34// Instruction Selector Implementation
35//===----------------------------------------------------------------------===//
36
Jyotsna Vermad9225242013-02-13 21:38:46 +000037namespace llvm {
38 void initializeHexagonDAGToDAGISelPass(PassRegistry&);
39}
40
Tony Linthicum1213a7a2011-12-12 21:14:40 +000041//===--------------------------------------------------------------------===//
42/// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine
43/// instructions for SelectionDAG operations.
44///
45namespace {
46class HexagonDAGToDAGISel : public SelectionDAGISel {
47 /// Subtarget - Keep a pointer to the Hexagon Subtarget around so that we can
48 /// make the right decision when generating code for different targets.
49 const HexagonSubtarget &Subtarget;
50
51 // Keep a reference to HexagonTargetMachine.
Krzysztof Parzyszekd5007472013-05-06 18:38:37 +000052 const HexagonTargetMachine& TM;
Jyotsna Vermad9225242013-02-13 21:38:46 +000053 DenseMap<const GlobalValue *, unsigned> GlobalAddressUseCountMap;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000054public:
Bill Wendlinga3cd3502013-06-19 21:36:55 +000055 explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine,
Jyotsna Vermad9225242013-02-13 21:38:46 +000056 CodeGenOpt::Level OptLevel)
57 : SelectionDAGISel(targetmachine, OptLevel),
Tony Linthicum1213a7a2011-12-12 21:14:40 +000058 Subtarget(targetmachine.getSubtarget<HexagonSubtarget>()),
Bill Wendling4a7a4082013-06-07 06:19:56 +000059 TM(targetmachine) {
Jyotsna Vermad9225242013-02-13 21:38:46 +000060 initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry());
Tony Linthicum1213a7a2011-12-12 21:14:40 +000061 }
Jyotsna Vermad9225242013-02-13 21:38:46 +000062 bool hasNumUsesBelowThresGA(SDNode *N) const;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000063
64 SDNode *Select(SDNode *N);
65
66 // Complex Pattern Selectors.
Jyotsna Vermad9225242013-02-13 21:38:46 +000067 inline bool foldGlobalAddress(SDValue &N, SDValue &R);
68 inline bool foldGlobalAddressGP(SDValue &N, SDValue &R);
69 bool foldGlobalAddressImpl(SDValue &N, SDValue &R, bool ShouldLookForGP);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000070 bool SelectADDRri(SDValue& N, SDValue &R1, SDValue &R2);
71 bool SelectADDRriS11_0(SDValue& N, SDValue &R1, SDValue &R2);
72 bool SelectADDRriS11_1(SDValue& N, SDValue &R1, SDValue &R2);
73 bool SelectADDRriS11_2(SDValue& N, SDValue &R1, SDValue &R2);
74 bool SelectMEMriS11_2(SDValue& Addr, SDValue &Base, SDValue &Offset);
75 bool SelectADDRriS11_3(SDValue& N, SDValue &R1, SDValue &R2);
76 bool SelectADDRrr(SDValue &Addr, SDValue &Base, SDValue &Offset);
77 bool SelectADDRriU6_0(SDValue& N, SDValue &R1, SDValue &R2);
78 bool SelectADDRriU6_1(SDValue& N, SDValue &R1, SDValue &R2);
79 bool SelectADDRriU6_2(SDValue& N, SDValue &R1, SDValue &R2);
80
81 virtual const char *getPassName() const {
82 return "Hexagon DAG->DAG Pattern Instruction Selection";
83 }
84
85 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
86 /// inline asm expressions.
87 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
88 char ConstraintCode,
89 std::vector<SDValue> &OutOps);
90 bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset);
91
92 SDNode *SelectLoad(SDNode *N);
Andrew Trickef9de2a2013-05-25 02:42:55 +000093 SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl);
94 SDNode *SelectIndexedLoad(LoadSDNode *LD, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000095 SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +000096 SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000097 SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +000098 SDLoc dl);
99 SDNode *SelectBaseOffsetStore(StoreSDNode *ST, SDLoc dl);
100 SDNode *SelectIndexedStore(StoreSDNode *ST, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000101 SDNode *SelectStore(SDNode *N);
102 SDNode *SelectSHL(SDNode *N);
103 SDNode *SelectSelect(SDNode *N);
104 SDNode *SelectTruncate(SDNode *N);
105 SDNode *SelectMul(SDNode *N);
106 SDNode *SelectZeroExtend(SDNode *N);
107 SDNode *SelectIntrinsicWOChain(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000108 SDNode *SelectIntrinsicWChain(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000109 SDNode *SelectConstant(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000110 SDNode *SelectConstantFP(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000111 SDNode *SelectAdd(SDNode *N);
Jyotsna Verma519b3852012-11-28 20:58:14 +0000112 bool isConstExtProfitable(SDNode *N) const;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000113
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000114// XformMskToBitPosU5Imm - Returns the bit position which
115// the single bit 32 bit mask represents.
116// Used in Clr and Set bit immediate memops.
117SDValue XformMskToBitPosU5Imm(uint32_t Imm) {
118 int32_t bitPos;
119 bitPos = Log2_32(Imm);
120 assert(bitPos >= 0 && bitPos < 32 &&
121 "Constant out of range for 32 BitPos Memops");
122 return CurDAG->getTargetConstant(bitPos, MVT::i32);
123}
124
125// XformMskToBitPosU4Imm - Returns the bit position which the single bit 16 bit
126// mask represents. Used in Clr and Set bit immediate memops.
127SDValue XformMskToBitPosU4Imm(uint16_t Imm) {
128 return XformMskToBitPosU5Imm(Imm);
129}
130
131// XformMskToBitPosU3Imm - Returns the bit position which the single bit 8 bit
132// mask represents. Used in Clr and Set bit immediate memops.
133SDValue XformMskToBitPosU3Imm(uint8_t Imm) {
134 return XformMskToBitPosU5Imm(Imm);
135}
136
137// Return true if there is exactly one bit set in V, i.e., if V is one of the
138// following integers: 2^0, 2^1, ..., 2^31.
139bool ImmIsSingleBit(uint32_t v) const {
140 uint32_t c = CountPopulation_64(v);
141 // Only return true if we counted 1 bit.
142 return c == 1;
143}
144
145// XformM5ToU5Imm - Return a target constant with the specified value, of type
146// i32 where the negative literal is transformed into a positive literal for
147// use in -= memops.
148inline SDValue XformM5ToU5Imm(signed Imm) {
149 assert( (Imm >= -31 && Imm <= -1) && "Constant out of range for Memops");
150 return CurDAG->getTargetConstant( - Imm, MVT::i32);
151}
152
153
Jyotsna Verma60316252013-02-05 19:20:45 +0000154// XformU7ToU7M1Imm - Return a target constant decremented by 1, in range
155// [1..128], used in cmpb.gtu instructions.
156inline SDValue XformU7ToU7M1Imm(signed Imm) {
157 assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op");
158 return CurDAG->getTargetConstant(Imm - 1, MVT::i8);
159}
160
Jyotsna Verma89c84822013-04-23 19:15:55 +0000161// XformS8ToS8M1Imm - Return a target constant decremented by 1.
162inline SDValue XformSToSM1Imm(signed Imm) {
163 return CurDAG->getTargetConstant(Imm - 1, MVT::i32);
164}
165
166// XformU8ToU8M1Imm - Return a target constant decremented by 1.
167inline SDValue XformUToUM1Imm(unsigned Imm) {
168 assert((Imm >= 1) && "Cannot decrement unsigned int less than 1");
169 return CurDAG->getTargetConstant(Imm - 1, MVT::i32);
170}
171
Jyotsna Verma60316252013-02-05 19:20:45 +0000172// Include the pieces autogenerated from the target description.
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000173#include "HexagonGenDAGISel.inc"
174};
175} // end anonymous namespace
176
177
178/// createHexagonISelDag - This pass converts a legalized DAG into a
179/// Hexagon-specific DAG, ready for instruction scheduling.
180///
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000181FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM,
Jyotsna Vermad9225242013-02-13 21:38:46 +0000182 CodeGenOpt::Level OptLevel) {
183 return new HexagonDAGToDAGISel(TM, OptLevel);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000184}
185
Jyotsna Vermad9225242013-02-13 21:38:46 +0000186static void initializePassOnce(PassRegistry &Registry) {
187 const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection";
188 PassInfo *PI = new PassInfo(Name, "hexagon-isel",
189 &SelectionDAGISel::ID, 0, false, false);
190 Registry.registerPass(*PI, true);
191}
192
193void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) {
194 CALL_ONCE_INITIALIZATION(initializePassOnce)
195}
196
197
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000198static bool IsS11_0_Offset(SDNode * S) {
199 ConstantSDNode *N = cast<ConstantSDNode>(S);
200
201 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
202 // field.
203 int64_t v = (int64_t)N->getSExtValue();
204 return isInt<11>(v);
205}
206
207
208static bool IsS11_1_Offset(SDNode * S) {
209 ConstantSDNode *N = cast<ConstantSDNode>(S);
210
211 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
212 // field.
213 int64_t v = (int64_t)N->getSExtValue();
214 return isShiftedInt<11,1>(v);
215}
216
217
218static bool IsS11_2_Offset(SDNode * S) {
219 ConstantSDNode *N = cast<ConstantSDNode>(S);
220
221 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
222 // field.
223 int64_t v = (int64_t)N->getSExtValue();
224 return isShiftedInt<11,2>(v);
225}
226
227
228static bool IsS11_3_Offset(SDNode * S) {
229 ConstantSDNode *N = cast<ConstantSDNode>(S);
230
231 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
232 // field.
233 int64_t v = (int64_t)N->getSExtValue();
234 return isShiftedInt<11,3>(v);
235}
236
237
238static bool IsU6_0_Offset(SDNode * S) {
239 ConstantSDNode *N = cast<ConstantSDNode>(S);
240
241 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
242 // field.
243 int64_t v = (int64_t)N->getSExtValue();
244 return isUInt<6>(v);
245}
246
247
248static bool IsU6_1_Offset(SDNode * S) {
249 ConstantSDNode *N = cast<ConstantSDNode>(S);
250
251 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
252 // field.
253 int64_t v = (int64_t)N->getSExtValue();
254 return isShiftedUInt<6,1>(v);
255}
256
257
258static bool IsU6_2_Offset(SDNode * S) {
259 ConstantSDNode *N = cast<ConstantSDNode>(S);
260
261 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
262 // field.
263 int64_t v = (int64_t)N->getSExtValue();
264 return isShiftedUInt<6,2>(v);
265}
266
267
268// Intrinsics that return a a predicate.
269static unsigned doesIntrinsicReturnPredicate(unsigned ID)
270{
271 switch (ID) {
272 default:
273 return 0;
274 case Intrinsic::hexagon_C2_cmpeq:
275 case Intrinsic::hexagon_C2_cmpgt:
276 case Intrinsic::hexagon_C2_cmpgtu:
277 case Intrinsic::hexagon_C2_cmpgtup:
278 case Intrinsic::hexagon_C2_cmpgtp:
279 case Intrinsic::hexagon_C2_cmpeqp:
280 case Intrinsic::hexagon_C2_bitsset:
281 case Intrinsic::hexagon_C2_bitsclr:
282 case Intrinsic::hexagon_C2_cmpeqi:
283 case Intrinsic::hexagon_C2_cmpgti:
284 case Intrinsic::hexagon_C2_cmpgtui:
285 case Intrinsic::hexagon_C2_cmpgei:
286 case Intrinsic::hexagon_C2_cmpgeui:
287 case Intrinsic::hexagon_C2_cmplt:
288 case Intrinsic::hexagon_C2_cmpltu:
289 case Intrinsic::hexagon_C2_bitsclri:
290 case Intrinsic::hexagon_C2_and:
291 case Intrinsic::hexagon_C2_or:
292 case Intrinsic::hexagon_C2_xor:
293 case Intrinsic::hexagon_C2_andn:
294 case Intrinsic::hexagon_C2_not:
295 case Intrinsic::hexagon_C2_orn:
296 case Intrinsic::hexagon_C2_pxfer_map:
297 case Intrinsic::hexagon_C2_any8:
298 case Intrinsic::hexagon_C2_all8:
299 case Intrinsic::hexagon_A2_vcmpbeq:
300 case Intrinsic::hexagon_A2_vcmpbgtu:
301 case Intrinsic::hexagon_A2_vcmpheq:
302 case Intrinsic::hexagon_A2_vcmphgt:
303 case Intrinsic::hexagon_A2_vcmphgtu:
304 case Intrinsic::hexagon_A2_vcmpweq:
305 case Intrinsic::hexagon_A2_vcmpwgt:
306 case Intrinsic::hexagon_A2_vcmpwgtu:
307 case Intrinsic::hexagon_C2_tfrrp:
308 case Intrinsic::hexagon_S2_tstbit_i:
309 case Intrinsic::hexagon_S2_tstbit_r:
310 return 1;
311 }
312}
313
314
315// Intrinsics that have predicate operands.
316static unsigned doesIntrinsicContainPredicate(unsigned ID)
317{
318 switch (ID) {
319 default:
320 return 0;
321 case Intrinsic::hexagon_C2_tfrpr:
322 return Hexagon::TFR_RsPd;
323 case Intrinsic::hexagon_C2_and:
324 return Hexagon::AND_pp;
325 case Intrinsic::hexagon_C2_xor:
326 return Hexagon::XOR_pp;
327 case Intrinsic::hexagon_C2_or:
328 return Hexagon::OR_pp;
329 case Intrinsic::hexagon_C2_not:
Sirish Pande30804c22012-02-15 18:52:27 +0000330 return Hexagon::NOT_p;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000331 case Intrinsic::hexagon_C2_any8:
332 return Hexagon::ANY_pp;
333 case Intrinsic::hexagon_C2_all8:
334 return Hexagon::ALL_pp;
335 case Intrinsic::hexagon_C2_vitpack:
336 return Hexagon::VITPACK_pp;
337 case Intrinsic::hexagon_C2_mask:
338 return Hexagon::MASK_p;
339 case Intrinsic::hexagon_C2_mux:
340 return Hexagon::MUX_rr;
341
342 // Mapping hexagon_C2_muxir to MUX_pri. This is pretty weird - but
343 // that's how it's mapped in q6protos.h.
344 case Intrinsic::hexagon_C2_muxir:
345 return Hexagon::MUX_ri;
346
347 // Mapping hexagon_C2_muxri to MUX_pir. This is pretty weird - but
348 // that's how it's mapped in q6protos.h.
349 case Intrinsic::hexagon_C2_muxri:
350 return Hexagon::MUX_ir;
351
352 case Intrinsic::hexagon_C2_muxii:
353 return Hexagon::MUX_ii;
354 case Intrinsic::hexagon_C2_vmux:
355 return Hexagon::VMUX_prr64;
356 case Intrinsic::hexagon_S2_valignrb:
357 return Hexagon::VALIGN_rrp;
358 case Intrinsic::hexagon_S2_vsplicerb:
359 return Hexagon::VSPLICE_rrp;
360 }
361}
362
363
364static bool OffsetFitsS11(EVT MemType, int64_t Offset) {
365 if (MemType == MVT::i64 && isShiftedInt<11,3>(Offset)) {
366 return true;
367 }
368 if (MemType == MVT::i32 && isShiftedInt<11,2>(Offset)) {
369 return true;
370 }
371 if (MemType == MVT::i16 && isShiftedInt<11,1>(Offset)) {
372 return true;
373 }
374 if (MemType == MVT::i8 && isInt<11>(Offset)) {
375 return true;
376 }
377 return false;
378}
379
380
381//
382// Try to lower loads of GlobalAdresses into base+offset loads. Custom
383// lowering for GlobalAddress nodes has already turned it into a
384// CONST32.
385//
Andrew Trickef9de2a2013-05-25 02:42:55 +0000386SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000387 SDValue Chain = LD->getChain();
388 SDNode* Const32 = LD->getBasePtr().getNode();
389 unsigned Opcode = 0;
390
391 if (Const32->getOpcode() == HexagonISD::CONST32 &&
392 ISD::isNormalLoad(LD)) {
393 SDValue Base = Const32->getOperand(0);
394 EVT LoadedVT = LD->getMemoryVT();
395 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
396 if (Offset != 0 && OffsetFitsS11(LoadedVT, Offset)) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000397 MVT PointerTy = getTargetLowering()->getPointerTy();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000398 const GlobalValue* GV =
399 cast<GlobalAddressSDNode>(Base)->getGlobal();
400 SDValue TargAddr =
401 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0);
Brendon Cahoonf6b687e2012-05-14 19:35:42 +0000402 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
403 dl, PointerTy,
404 TargAddr);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000405 // Figure out base + offset opcode
406 if (LoadedVT == MVT::i64) Opcode = Hexagon::LDrid_indexed;
407 else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed;
408 else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed;
409 else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000410 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000411
412 // Build indexed load.
413 SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy);
414 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
415 LD->getValueType(0),
416 MVT::Other,
417 SDValue(NewBase,0),
418 TargetConstOff,
419 Chain);
420 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
421 MemOp[0] = LD->getMemOperand();
422 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
423 ReplaceUses(LD, Result);
424 return Result;
425 }
426 }
427
428 return SelectCode(LD);
429}
430
431
432SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
433 unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000434 SDLoc dl)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000435{
436 SDValue Chain = LD->getChain();
437 EVT LoadedVT = LD->getMemoryVT();
438 SDValue Base = LD->getBasePtr();
439 SDValue Offset = LD->getOffset();
440 SDNode *OffsetNode = Offset.getNode();
441 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
442 SDValue N1 = LD->getOperand(1);
443 SDValue CPTmpN1_0;
444 SDValue CPTmpN1_1;
Bill Wendling4a7a4082013-06-07 06:19:56 +0000445
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000446 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
447 N1.getNode()->getValueType(0) == MVT::i32) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000448 const HexagonInstrInfo *TII =
449 static_cast<const HexagonInstrInfo*>(TM.getInstrInfo());
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000450 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
451 SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32);
452 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
453 MVT::Other, Base, TargetConst,
454 Chain);
455 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, MVT::i64,
456 SDValue(Result_1, 0));
457 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
458 MemOp[0] = LD->getMemOperand();
459 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
460 const SDValue Froms[] = { SDValue(LD, 0),
461 SDValue(LD, 1),
462 SDValue(LD, 2)
463 };
464 const SDValue Tos[] = { SDValue(Result_2, 0),
465 SDValue(Result_1, 1),
466 SDValue(Result_1, 2)
467 };
468 ReplaceUses(Froms, Tos, 3);
469 return Result_2;
Sirish Pandec92c3162012-05-03 16:18:50 +0000470 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000471 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
472 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
473 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
474 MVT::Other, Base, TargetConst0,
475 Chain);
476 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl,
477 MVT::i64, SDValue(Result_1, 0));
478 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl,
479 MVT::i32, Base, TargetConstVal,
480 SDValue(Result_1, 1));
481 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
482 MemOp[0] = LD->getMemOperand();
483 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
484 const SDValue Froms[] = { SDValue(LD, 0),
485 SDValue(LD, 1),
486 SDValue(LD, 2)
487 };
488 const SDValue Tos[] = { SDValue(Result_2, 0),
489 SDValue(Result_3, 0),
490 SDValue(Result_1, 1)
491 };
492 ReplaceUses(Froms, Tos, 3);
493 return Result_2;
494 }
495 return SelectCode(LD);
496}
497
498
499SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
500 unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000501 SDLoc dl)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000502{
503 SDValue Chain = LD->getChain();
504 EVT LoadedVT = LD->getMemoryVT();
505 SDValue Base = LD->getBasePtr();
506 SDValue Offset = LD->getOffset();
507 SDNode *OffsetNode = Offset.getNode();
508 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
509 SDValue N1 = LD->getOperand(1);
510 SDValue CPTmpN1_0;
511 SDValue CPTmpN1_1;
Bill Wendling4a7a4082013-06-07 06:19:56 +0000512
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000513 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
514 N1.getNode()->getValueType(0) == MVT::i32) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000515 const HexagonInstrInfo *TII =
516 static_cast<const HexagonInstrInfo*>(TM.getInstrInfo());
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000517 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
518 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
519 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
520 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
521 MVT::i32, MVT::Other, Base,
522 TargetConstVal, Chain);
523 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
524 TargetConst0);
525 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
526 MVT::i64, MVT::Other,
527 SDValue(Result_2,0),
528 SDValue(Result_1,0));
529 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
530 MemOp[0] = LD->getMemOperand();
531 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
532 const SDValue Froms[] = { SDValue(LD, 0),
533 SDValue(LD, 1),
534 SDValue(LD, 2)
535 };
536 const SDValue Tos[] = { SDValue(Result_3, 0),
537 SDValue(Result_1, 1),
538 SDValue(Result_1, 2)
539 };
540 ReplaceUses(Froms, Tos, 3);
541 return Result_3;
542 }
543
544 // Generate an indirect load.
545 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
546 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
547 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
548 MVT::Other,
549 Base, TargetConst0, Chain);
550 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
551 TargetConst0);
552 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
553 MVT::i64, MVT::Other,
554 SDValue(Result_2,0),
555 SDValue(Result_1,0));
556 // Add offset to base.
557 SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
558 Base, TargetConstVal,
559 SDValue(Result_1, 1));
560 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
561 MemOp[0] = LD->getMemOperand();
562 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
563 const SDValue Froms[] = { SDValue(LD, 0),
564 SDValue(LD, 1),
565 SDValue(LD, 2)
566 };
567 const SDValue Tos[] = { SDValue(Result_3, 0), // Load value.
568 SDValue(Result_4, 0), // New address.
569 SDValue(Result_1, 1)
570 };
571 ReplaceUses(Froms, Tos, 3);
572 return Result_3;
573 }
574
575 return SelectCode(LD);
576}
577
578
Andrew Trickef9de2a2013-05-25 02:42:55 +0000579SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000580 SDValue Chain = LD->getChain();
581 SDValue Base = LD->getBasePtr();
582 SDValue Offset = LD->getOffset();
583 SDNode *OffsetNode = Offset.getNode();
584 // Get the constant value.
585 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
586 EVT LoadedVT = LD->getMemoryVT();
587 unsigned Opcode = 0;
588
589 // Check for zero ext loads.
590 bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD);
591
592 // Figure out the opcode.
Bill Wendling4a7a4082013-06-07 06:19:56 +0000593 const HexagonInstrInfo *TII =
594 static_cast<const HexagonInstrInfo*>(TM.getInstrInfo());
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000595 if (LoadedVT == MVT::i64) {
596 if (TII->isValidAutoIncImm(LoadedVT, Val))
597 Opcode = Hexagon::POST_LDrid;
598 else
599 Opcode = Hexagon::LDrid;
600 } else if (LoadedVT == MVT::i32) {
601 if (TII->isValidAutoIncImm(LoadedVT, Val))
602 Opcode = Hexagon::POST_LDriw;
603 else
604 Opcode = Hexagon::LDriw;
605 } else if (LoadedVT == MVT::i16) {
606 if (TII->isValidAutoIncImm(LoadedVT, Val))
607 Opcode = zextval ? Hexagon::POST_LDriuh : Hexagon::POST_LDrih;
608 else
609 Opcode = zextval ? Hexagon::LDriuh : Hexagon::LDrih;
610 } else if (LoadedVT == MVT::i8) {
611 if (TII->isValidAutoIncImm(LoadedVT, Val))
612 Opcode = zextval ? Hexagon::POST_LDriub : Hexagon::POST_LDrib;
613 else
614 Opcode = zextval ? Hexagon::LDriub : Hexagon::LDrib;
615 } else
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000616 llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000617
618 // For zero ext i64 loads, we need to add combine instructions.
619 if (LD->getValueType(0) == MVT::i64 &&
620 LD->getExtensionType() == ISD::ZEXTLOAD) {
621 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl);
622 }
623 if (LD->getValueType(0) == MVT::i64 &&
624 LD->getExtensionType() == ISD::SEXTLOAD) {
625 // Handle sign ext i64 loads.
626 return SelectIndexedLoadSignExtend64(LD, Opcode, dl);
627 }
628 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
629 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
630 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
631 LD->getValueType(0),
632 MVT::i32, MVT::Other, Base,
633 TargetConstVal, Chain);
634 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
635 MemOp[0] = LD->getMemOperand();
636 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
637 const SDValue Froms[] = { SDValue(LD, 0),
638 SDValue(LD, 1),
639 SDValue(LD, 2)
640 };
641 const SDValue Tos[] = { SDValue(Result, 0),
642 SDValue(Result, 1),
643 SDValue(Result, 2)
644 };
645 ReplaceUses(Froms, Tos, 3);
646 return Result;
647 } else {
648 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
649 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
650 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl,
651 LD->getValueType(0),
652 MVT::Other, Base, TargetConst0,
653 Chain);
654 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
655 Base, TargetConstVal,
656 SDValue(Result_1, 1));
657 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
658 MemOp[0] = LD->getMemOperand();
659 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
660 const SDValue Froms[] = { SDValue(LD, 0),
661 SDValue(LD, 1),
662 SDValue(LD, 2)
663 };
664 const SDValue Tos[] = { SDValue(Result_1, 0),
665 SDValue(Result_2, 0),
666 SDValue(Result_1, 1)
667 };
668 ReplaceUses(Froms, Tos, 3);
669 return Result_1;
670 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000671}
672
673
674SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
675 SDNode *result;
Andrew Trickef9de2a2013-05-25 02:42:55 +0000676 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000677 LoadSDNode *LD = cast<LoadSDNode>(N);
678 ISD::MemIndexedMode AM = LD->getAddressingMode();
679
680 // Handle indexed loads.
681 if (AM != ISD::UNINDEXED) {
682 result = SelectIndexedLoad(LD, dl);
683 } else {
684 result = SelectBaseOffsetLoad(LD, dl);
685 }
686
687 return result;
688}
689
690
Andrew Trickef9de2a2013-05-25 02:42:55 +0000691SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000692 SDValue Chain = ST->getChain();
693 SDValue Base = ST->getBasePtr();
694 SDValue Offset = ST->getOffset();
695 SDValue Value = ST->getValue();
696 SDNode *OffsetNode = Offset.getNode();
697 // Get the constant value.
698 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
699 EVT StoredVT = ST->getMemoryVT();
700
701 // Offset value must be within representable range
702 // and must have correct alignment properties.
Bill Wendling4a7a4082013-06-07 06:19:56 +0000703 const HexagonInstrInfo *TII =
704 static_cast<const HexagonInstrInfo*>(TM.getInstrInfo());
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000705 if (TII->isValidAutoIncImm(StoredVT, Val)) {
Jyotsna Vermab16a9cb2013-01-29 18:42:41 +0000706 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value,
707 Chain};
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000708 unsigned Opcode = 0;
709
710 // Figure out the post inc version of opcode.
711 if (StoredVT == MVT::i64) Opcode = Hexagon::POST_STdri;
712 else if (StoredVT == MVT::i32) Opcode = Hexagon::POST_STwri;
713 else if (StoredVT == MVT::i16) Opcode = Hexagon::POST_SThri;
714 else if (StoredVT == MVT::i8) Opcode = Hexagon::POST_STbri;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000715 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000716
717 // Build post increment store.
718 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +0000719 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000720 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
721 MemOp[0] = ST->getMemOperand();
722 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
723
724 ReplaceUses(ST, Result);
725 ReplaceUses(SDValue(ST,1), SDValue(Result,1));
726 return Result;
727 }
728
729 // Note: Order of operands matches the def of instruction:
730 // def STrid : STInst<(outs), (ins MEMri:$addr, DoubleRegs:$src1), ...
731 // and it differs for POST_ST* for instance.
732 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value,
733 Chain};
734 unsigned Opcode = 0;
735
736 // Figure out the opcode.
737 if (StoredVT == MVT::i64) Opcode = Hexagon::STrid;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000738 else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000739 else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih;
740 else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000741 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000742
743 // Build regular store.
744 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
Michael Liaob53d8962013-04-19 22:22:57 +0000745 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000746 // Build splitted incriment instruction.
747 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
748 Base,
749 TargetConstVal,
750 SDValue(Result_1, 0));
751 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
752 MemOp[0] = ST->getMemOperand();
753 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
754
755 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0));
756 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0));
757 return Result_2;
758}
759
760
761SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000762 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000763 SDValue Chain = ST->getChain();
764 SDNode* Const32 = ST->getBasePtr().getNode();
765 SDValue Value = ST->getValue();
766 unsigned Opcode = 0;
767
768 // Try to lower stores of GlobalAdresses into indexed stores. Custom
769 // lowering for GlobalAddress nodes has already turned it into a
770 // CONST32. Avoid truncating stores for the moment. Post-inc stores
771 // do the same. Don't think there's a reason for it, so will file a
772 // bug to fix.
773 if ((Const32->getOpcode() == HexagonISD::CONST32) &&
774 !(Value.getValueType() == MVT::i64 && ST->isTruncatingStore())) {
775 SDValue Base = Const32->getOperand(0);
776 if (Base.getOpcode() == ISD::TargetGlobalAddress) {
777 EVT StoredVT = ST->getMemoryVT();
778 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
779 if (Offset != 0 && OffsetFitsS11(StoredVT, Offset)) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000780 MVT PointerTy = getTargetLowering()->getPointerTy();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000781 const GlobalValue* GV =
782 cast<GlobalAddressSDNode>(Base)->getGlobal();
783 SDValue TargAddr =
784 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0);
Brendon Cahoonf6b687e2012-05-14 19:35:42 +0000785 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
786 dl, PointerTy,
787 TargAddr);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000788
789 // Figure out base + offset opcode
790 if (StoredVT == MVT::i64) Opcode = Hexagon::STrid_indexed;
791 else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed;
792 else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed;
793 else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000794 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000795
796 SDValue Ops[] = {SDValue(NewBase,0),
797 CurDAG->getTargetConstant(Offset,PointerTy),
798 Value, Chain};
799 // build indexed store
800 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
Michael Liaob53d8962013-04-19 22:22:57 +0000801 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000802 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
803 MemOp[0] = ST->getMemOperand();
804 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
805 ReplaceUses(ST, Result);
806 return Result;
807 }
808 }
809 }
810
811 return SelectCode(ST);
812}
813
814
815SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000816 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000817 StoreSDNode *ST = cast<StoreSDNode>(N);
818 ISD::MemIndexedMode AM = ST->getAddressingMode();
819
820 // Handle indexed stores.
821 if (AM != ISD::UNINDEXED) {
822 return SelectIndexedStore(ST, dl);
823 }
Sirish Pandec92c3162012-05-03 16:18:50 +0000824
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000825 return SelectBaseOffsetStore(ST, dl);
826}
827
828SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000829 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000830
831 //
832 // %conv.i = sext i32 %tmp1 to i64
833 // %conv2.i = sext i32 %add to i64
834 // %mul.i = mul nsw i64 %conv2.i, %conv.i
835 //
836 // --- match with the following ---
837 //
838 // %mul.i = mpy (%tmp1, %add)
839 //
840
841 if (N->getValueType(0) == MVT::i64) {
842 // Shifting a i64 signed multiply.
843 SDValue MulOp0 = N->getOperand(0);
844 SDValue MulOp1 = N->getOperand(1);
845
846 SDValue OP0;
847 SDValue OP1;
848
849 // Handle sign_extend and sextload.
850 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
851 SDValue Sext0 = MulOp0.getOperand(0);
852 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000853 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000854 }
855
856 OP0 = Sext0;
857 } else if (MulOp0.getOpcode() == ISD::LOAD) {
858 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
859 if (LD->getMemoryVT() != MVT::i32 ||
860 LD->getExtensionType() != ISD::SEXTLOAD ||
861 LD->getAddressingMode() != ISD::UNINDEXED) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000862 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000863 }
864
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000865 SDValue Chain = LD->getChain();
866 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
867 OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
868 MVT::Other,
869 LD->getBasePtr(), TargetConst0,
870 Chain), 0);
871 } else {
872 return SelectCode(N);
873 }
874
875 // Same goes for the second operand.
876 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
877 SDValue Sext1 = MulOp1.getOperand(0);
878 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
879 return SelectCode(N);
880 }
881
882 OP1 = Sext1;
883 } else if (MulOp1.getOpcode() == ISD::LOAD) {
884 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
885 if (LD->getMemoryVT() != MVT::i32 ||
886 LD->getExtensionType() != ISD::SEXTLOAD ||
887 LD->getAddressingMode() != ISD::UNINDEXED) {
888 return SelectCode(N);
889 }
890
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000891 SDValue Chain = LD->getChain();
892 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
893 OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
894 MVT::Other,
895 LD->getBasePtr(), TargetConst0,
896 Chain), 0);
897 } else {
898 return SelectCode(N);
899 }
900
901 // Generate a mpy instruction.
902 SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY64, dl, MVT::i64,
903 OP0, OP1);
904 ReplaceUses(N, Result);
905 return Result;
906 }
907
908 return SelectCode(N);
909}
910
911
912SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000913 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000914 SDValue N0 = N->getOperand(0);
915 if (N0.getOpcode() == ISD::SETCC) {
916 SDValue N00 = N0.getOperand(0);
917 if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) {
918 SDValue N000 = N00.getOperand(0);
919 SDValue N001 = N00.getOperand(1);
920 if (cast<VTSDNode>(N001)->getVT() == MVT::i16) {
921 SDValue N01 = N0.getOperand(1);
922 SDValue N02 = N0.getOperand(2);
923
924 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
925 // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1,
926 // IntRegs:i32:$src2)
927 // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
928 // Pattern complexity = 9 cost = 1 size = 0.
929 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) {
930 SDValue N1 = N->getOperand(1);
931 if (N01 == N1) {
932 SDValue N2 = N->getOperand(2);
933 if (N000 == N2 &&
934 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
935 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
936 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl,
937 MVT::i32, N000);
938 SDNode *Result = CurDAG->getMachineNode(Hexagon::MAXw_rr, dl,
939 MVT::i32,
940 SDValue(SextNode, 0),
941 N1);
942 ReplaceUses(N, Result);
943 return Result;
944 }
945 }
946 }
947
948 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
949 // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1,
950 // IntRegs:i32:$src2)
951 // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
952 // Pattern complexity = 9 cost = 1 size = 0.
953 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) {
954 SDValue N1 = N->getOperand(1);
955 if (N01 == N1) {
956 SDValue N2 = N->getOperand(2);
957 if (N000 == N2 &&
958 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
959 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
960 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl,
961 MVT::i32, N000);
962 SDNode *Result = CurDAG->getMachineNode(Hexagon::MINw_rr, dl,
963 MVT::i32,
964 SDValue(SextNode, 0),
965 N1);
966 ReplaceUses(N, Result);
967 return Result;
968 }
969 }
970 }
971 }
972 }
973 }
974
975 return SelectCode(N);
976}
977
978
979SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000980 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000981 SDValue Shift = N->getOperand(0);
982
983 //
984 // %conv.i = sext i32 %tmp1 to i64
985 // %conv2.i = sext i32 %add to i64
986 // %mul.i = mul nsw i64 %conv2.i, %conv.i
987 // %shr5.i = lshr i64 %mul.i, 32
988 // %conv3.i = trunc i64 %shr5.i to i32
989 //
990 // --- match with the following ---
991 //
992 // %conv3.i = mpy (%tmp1, %add)
993 //
994 // Trunc to i32.
995 if (N->getValueType(0) == MVT::i32) {
996 // Trunc from i64.
997 if (Shift.getNode()->getValueType(0) == MVT::i64) {
998 // Trunc child is logical shift right.
999 if (Shift.getOpcode() != ISD::SRL) {
1000 return SelectCode(N);
1001 }
1002
1003 SDValue ShiftOp0 = Shift.getOperand(0);
1004 SDValue ShiftOp1 = Shift.getOperand(1);
1005
1006 // Shift by const 32
1007 if (ShiftOp1.getOpcode() != ISD::Constant) {
1008 return SelectCode(N);
1009 }
1010
1011 int32_t ShiftConst =
1012 cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue();
1013 if (ShiftConst != 32) {
1014 return SelectCode(N);
1015 }
1016
1017 // Shifting a i64 signed multiply
1018 SDValue Mul = ShiftOp0;
1019 if (Mul.getOpcode() != ISD::MUL) {
1020 return SelectCode(N);
1021 }
1022
1023 SDValue MulOp0 = Mul.getOperand(0);
1024 SDValue MulOp1 = Mul.getOperand(1);
1025
1026 SDValue OP0;
1027 SDValue OP1;
1028
1029 // Handle sign_extend and sextload
1030 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
1031 SDValue Sext0 = MulOp0.getOperand(0);
1032 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
1033 return SelectCode(N);
1034 }
1035
1036 OP0 = Sext0;
1037 } else if (MulOp0.getOpcode() == ISD::LOAD) {
1038 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
1039 if (LD->getMemoryVT() != MVT::i32 ||
1040 LD->getExtensionType() != ISD::SEXTLOAD ||
1041 LD->getAddressingMode() != ISD::UNINDEXED) {
1042 return SelectCode(N);
1043 }
1044
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001045 SDValue Chain = LD->getChain();
1046 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
1047 OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
1048 MVT::Other,
1049 LD->getBasePtr(),
1050 TargetConst0, Chain), 0);
1051 } else {
1052 return SelectCode(N);
1053 }
1054
1055 // Same goes for the second operand.
1056 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
1057 SDValue Sext1 = MulOp1.getOperand(0);
1058 if (Sext1.getNode()->getValueType(0) != MVT::i32)
1059 return SelectCode(N);
1060
1061 OP1 = Sext1;
1062 } else if (MulOp1.getOpcode() == ISD::LOAD) {
1063 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
1064 if (LD->getMemoryVT() != MVT::i32 ||
1065 LD->getExtensionType() != ISD::SEXTLOAD ||
1066 LD->getAddressingMode() != ISD::UNINDEXED) {
1067 return SelectCode(N);
1068 }
1069
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001070 SDValue Chain = LD->getChain();
1071 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
1072 OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
1073 MVT::Other,
1074 LD->getBasePtr(),
1075 TargetConst0, Chain), 0);
1076 } else {
1077 return SelectCode(N);
1078 }
1079
1080 // Generate a mpy instruction.
1081 SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY, dl, MVT::i32,
1082 OP0, OP1);
1083 ReplaceUses(N, Result);
1084 return Result;
1085 }
1086 }
1087
1088 return SelectCode(N);
1089}
1090
1091
1092SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001093 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001094 if (N->getValueType(0) == MVT::i32) {
1095 SDValue Shl_0 = N->getOperand(0);
1096 SDValue Shl_1 = N->getOperand(1);
1097 // RHS is const.
1098 if (Shl_1.getOpcode() == ISD::Constant) {
1099 if (Shl_0.getOpcode() == ISD::MUL) {
1100 SDValue Mul_0 = Shl_0.getOperand(0); // Val
1101 SDValue Mul_1 = Shl_0.getOperand(1); // Const
1102 // RHS of mul is const.
1103 if (Mul_1.getOpcode() == ISD::Constant) {
1104 int32_t ShlConst =
1105 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1106 int32_t MulConst =
1107 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
1108 int32_t ValConst = MulConst << ShlConst;
1109 SDValue Val = CurDAG->getTargetConstant(ValConst,
1110 MVT::i32);
1111 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
1112 if (isInt<9>(CN->getSExtValue())) {
1113 SDNode* Result =
1114 CurDAG->getMachineNode(Hexagon::MPYI_ri, dl,
1115 MVT::i32, Mul_0, Val);
1116 ReplaceUses(N, Result);
1117 return Result;
1118 }
1119
1120 }
1121 } else if (Shl_0.getOpcode() == ISD::SUB) {
1122 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
1123 SDValue Sub_1 = Shl_0.getOperand(1); // Val
1124 if (Sub_0.getOpcode() == ISD::Constant) {
1125 int32_t SubConst =
1126 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
1127 if (SubConst == 0) {
1128 if (Sub_1.getOpcode() == ISD::SHL) {
1129 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
1130 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
1131 if (Shl2_1.getOpcode() == ISD::Constant) {
1132 int32_t ShlConst =
1133 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1134 int32_t Shl2Const =
1135 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
1136 int32_t ValConst = 1 << (ShlConst+Shl2Const);
1137 SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32);
1138 if (ConstantSDNode *CN =
1139 dyn_cast<ConstantSDNode>(Val.getNode()))
1140 if (isInt<9>(CN->getSExtValue())) {
1141 SDNode* Result =
1142 CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, MVT::i32,
1143 Shl2_0, Val);
1144 ReplaceUses(N, Result);
1145 return Result;
1146 }
1147 }
1148 }
1149 }
1150 }
1151 }
1152 }
1153 }
1154 return SelectCode(N);
1155}
1156
1157
1158//
1159// If there is an zero_extend followed an intrinsic in DAG (this means - the
1160// result of the intrinsic is predicate); convert the zero_extend to
1161// transfer instruction.
1162//
1163// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
1164// converted into a MUX as predicate registers defined as 1 bit in the
1165// compiler. Architecture defines them as 8-bit registers.
1166// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
1167//
1168SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001169 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001170 SDNode *IsIntrinsic = N->getOperand(0).getNode();
1171 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
1172 unsigned ID =
1173 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
1174 if (doesIntrinsicReturnPredicate(ID)) {
1175 // Now we need to differentiate target data types.
1176 if (N->getValueType(0) == MVT::i64) {
1177 // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs).
1178 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
1179 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl,
1180 MVT::i32,
1181 SDValue(IsIntrinsic, 0));
1182 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl,
1183 MVT::i32,
1184 TargetConst0);
1185 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
1186 MVT::i64, MVT::Other,
1187 SDValue(Result_2, 0),
1188 SDValue(Result_1, 0));
1189 ReplaceUses(N, Result_3);
1190 return Result_3;
1191 }
1192 if (N->getValueType(0) == MVT::i32) {
1193 // Convert the zero_extend to Rs = Pd
1194 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl,
1195 MVT::i32,
1196 SDValue(IsIntrinsic, 0));
1197 ReplaceUses(N, RsPd);
1198 return RsPd;
1199 }
Craig Toppere55c5562012-02-07 02:50:20 +00001200 llvm_unreachable("Unexpected value type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001201 }
1202 }
1203 return SelectCode(N);
1204}
1205
1206
1207//
1208// Checking for intrinsics which have predicate registers as operand(s)
1209// and lowering to the actual intrinsic.
1210//
1211SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001212 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001213 unsigned ID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
1214 unsigned IntrinsicWithPred = doesIntrinsicContainPredicate(ID);
1215
1216 // We are concerned with only those intrinsics that have predicate registers
1217 // as at least one of the operands.
1218 if (IntrinsicWithPred) {
1219 SmallVector<SDValue, 8> Ops;
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001220 const HexagonInstrInfo *TII =
1221 static_cast<const HexagonInstrInfo*>(TM.getInstrInfo());
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001222 const MCInstrDesc &MCID = TII->get(IntrinsicWithPred);
1223 const TargetRegisterInfo *TRI = TM.getRegisterInfo();
1224
1225 // Iterate over all the operands of the intrinsics.
1226 // For PredRegs, do the transfer.
1227 // For Double/Int Regs, just preserve the value
1228 // For immediates, lower it.
1229 for (unsigned i = 1; i < N->getNumOperands(); ++i) {
1230 SDNode *Arg = N->getOperand(i).getNode();
Jakob Stoklund Olesen3c52f022012-05-07 22:10:26 +00001231 const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI, *MF);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001232
Craig Topperc7242e02012-04-20 07:30:17 +00001233 if (RC == &Hexagon::IntRegsRegClass ||
1234 RC == &Hexagon::DoubleRegsRegClass) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001235 Ops.push_back(SDValue(Arg, 0));
Craig Topperc7242e02012-04-20 07:30:17 +00001236 } else if (RC == &Hexagon::PredRegsRegClass) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001237 // Do the transfer.
1238 SDNode *PdRs = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1,
1239 SDValue(Arg, 0));
1240 Ops.push_back(SDValue(PdRs,0));
1241 } else if (RC == NULL && (dyn_cast<ConstantSDNode>(Arg) != NULL)) {
1242 // This is immediate operand. Lower it here making sure that we DO have
1243 // const SDNode for immediate value.
1244 int32_t Val = cast<ConstantSDNode>(Arg)->getSExtValue();
1245 SDValue SDVal = CurDAG->getTargetConstant(Val, MVT::i32);
1246 Ops.push_back(SDVal);
1247 } else {
Craig Toppere55c5562012-02-07 02:50:20 +00001248 llvm_unreachable("Unimplemented");
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001249 }
1250 }
1251 EVT ReturnValueVT = N->getValueType(0);
1252 SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001253 ReturnValueVT, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001254 ReplaceUses(N, Result);
1255 return Result;
1256 }
1257 return SelectCode(N);
1258}
1259
Sirish Pande69295b82012-05-10 20:20:25 +00001260//
1261// Map floating point constant values.
1262//
1263SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001264 SDLoc dl(N);
Sirish Pande69295b82012-05-10 20:20:25 +00001265 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
1266 APFloat APF = CN->getValueAPF();
1267 if (N->getValueType(0) == MVT::f32) {
1268 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
1269 CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32));
1270 }
1271 else if (N->getValueType(0) == MVT::f64) {
1272 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
1273 CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64));
1274 }
1275
1276 return SelectCode(N);
1277}
1278
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001279
1280//
1281// Map predicate true (encoded as -1 in LLVM) to a XOR.
1282//
1283SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001284 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001285 if (N->getValueType(0) == MVT::i1) {
1286 SDNode* Result;
1287 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
1288 if (Val == -1) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001289 // Create the IntReg = 1 node.
1290 SDNode* IntRegTFR =
1291 CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
1292 CurDAG->getTargetConstant(0, MVT::i32));
1293
1294 // Pd = IntReg
1295 SDNode* Pd = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1,
1296 SDValue(IntRegTFR, 0));
1297
1298 // not(Pd)
Sirish Pande30804c22012-02-15 18:52:27 +00001299 SDNode* NotPd = CurDAG->getMachineNode(Hexagon::NOT_p, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001300 SDValue(Pd, 0));
1301
1302 // xor(not(Pd))
1303 Result = CurDAG->getMachineNode(Hexagon::XOR_pp, dl, MVT::i1,
1304 SDValue(Pd, 0), SDValue(NotPd, 0));
1305
1306 // We have just built:
1307 // Rs = Pd
1308 // Pd = xor(not(Pd), Pd)
1309
1310 ReplaceUses(N, Result);
1311 return Result;
1312 }
1313 }
1314
1315 return SelectCode(N);
1316}
1317
1318
1319//
1320// Map add followed by a asr -> asr +=.
1321//
1322SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001323 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001324 if (N->getValueType(0) != MVT::i32) {
1325 return SelectCode(N);
1326 }
1327 // Identify nodes of the form: add(asr(...)).
1328 SDNode* Src1 = N->getOperand(0).getNode();
1329 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1330 || Src1->getValueType(0) != MVT::i32) {
1331 return SelectCode(N);
1332 }
1333
1334 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1335 // Rd and Rd' are assigned to the same register
Sirish Pandec92c3162012-05-03 16:18:50 +00001336 SDNode* Result = CurDAG->getMachineNode(Hexagon::ASR_ADD_rr, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001337 N->getOperand(1),
1338 Src1->getOperand(0),
1339 Src1->getOperand(1));
1340 ReplaceUses(N, Result);
1341
1342 return Result;
1343}
1344
1345
1346SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
1347 if (N->isMachineOpcode())
1348 return NULL; // Already selected.
1349
1350
1351 switch (N->getOpcode()) {
1352 case ISD::Constant:
1353 return SelectConstant(N);
1354
Sirish Pande69295b82012-05-10 20:20:25 +00001355 case ISD::ConstantFP:
1356 return SelectConstantFP(N);
1357
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001358 case ISD::ADD:
1359 return SelectAdd(N);
1360
1361 case ISD::SHL:
1362 return SelectSHL(N);
1363
1364 case ISD::LOAD:
1365 return SelectLoad(N);
1366
1367 case ISD::STORE:
1368 return SelectStore(N);
1369
1370 case ISD::SELECT:
1371 return SelectSelect(N);
1372
1373 case ISD::TRUNCATE:
1374 return SelectTruncate(N);
1375
1376 case ISD::MUL:
1377 return SelectMul(N);
1378
1379 case ISD::ZERO_EXTEND:
1380 return SelectZeroExtend(N);
1381
1382 case ISD::INTRINSIC_WO_CHAIN:
1383 return SelectIntrinsicWOChain(N);
1384 }
1385
1386 return SelectCode(N);
1387}
1388
1389
1390//
1391// Hexagon_TODO: Five functions for ADDRri?! Surely there must be a better way
1392// to define these instructions.
1393//
1394bool HexagonDAGToDAGISel::SelectADDRri(SDValue& Addr, SDValue &Base,
1395 SDValue &Offset) {
1396 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1397 Addr.getOpcode() == ISD::TargetGlobalAddress)
1398 return false; // Direct calls.
1399
1400 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1401 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1402 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1403 return true;
1404 }
1405 Base = Addr;
1406 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1407 return true;
1408}
1409
1410
1411bool HexagonDAGToDAGISel::SelectADDRriS11_0(SDValue& Addr, SDValue &Base,
1412 SDValue &Offset) {
1413 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1414 Addr.getOpcode() == ISD::TargetGlobalAddress)
1415 return false; // Direct calls.
1416
1417 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1418 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1419 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1420 return (IsS11_0_Offset(Offset.getNode()));
1421 }
1422 Base = Addr;
1423 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1424 return (IsS11_0_Offset(Offset.getNode()));
1425}
1426
1427
1428bool HexagonDAGToDAGISel::SelectADDRriS11_1(SDValue& Addr, SDValue &Base,
1429 SDValue &Offset) {
1430 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1431 Addr.getOpcode() == ISD::TargetGlobalAddress)
1432 return false; // Direct calls.
1433
1434 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1435 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1436 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1437 return (IsS11_1_Offset(Offset.getNode()));
1438 }
1439 Base = Addr;
1440 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1441 return (IsS11_1_Offset(Offset.getNode()));
1442}
1443
1444
1445bool HexagonDAGToDAGISel::SelectADDRriS11_2(SDValue& Addr, SDValue &Base,
1446 SDValue &Offset) {
1447 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1448 Addr.getOpcode() == ISD::TargetGlobalAddress)
1449 return false; // Direct calls.
1450
1451 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1452 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1453 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1454 return (IsS11_2_Offset(Offset.getNode()));
1455 }
1456 Base = Addr;
1457 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1458 return (IsS11_2_Offset(Offset.getNode()));
1459}
1460
1461
1462bool HexagonDAGToDAGISel::SelectADDRriU6_0(SDValue& Addr, SDValue &Base,
1463 SDValue &Offset) {
1464 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1465 Addr.getOpcode() == ISD::TargetGlobalAddress)
1466 return false; // Direct calls.
1467
1468 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1469 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1470 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1471 return (IsU6_0_Offset(Offset.getNode()));
1472 }
1473 Base = Addr;
1474 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1475 return (IsU6_0_Offset(Offset.getNode()));
1476}
1477
1478
1479bool HexagonDAGToDAGISel::SelectADDRriU6_1(SDValue& Addr, SDValue &Base,
1480 SDValue &Offset) {
1481 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1482 Addr.getOpcode() == ISD::TargetGlobalAddress)
1483 return false; // Direct calls.
1484
1485 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1486 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1487 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1488 return (IsU6_1_Offset(Offset.getNode()));
1489 }
1490 Base = Addr;
1491 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1492 return (IsU6_1_Offset(Offset.getNode()));
1493}
1494
1495
1496bool HexagonDAGToDAGISel::SelectADDRriU6_2(SDValue& Addr, SDValue &Base,
1497 SDValue &Offset) {
1498 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1499 Addr.getOpcode() == ISD::TargetGlobalAddress)
1500 return false; // Direct calls.
1501
1502 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1503 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1504 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1505 return (IsU6_2_Offset(Offset.getNode()));
1506 }
1507 Base = Addr;
1508 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1509 return (IsU6_2_Offset(Offset.getNode()));
1510}
1511
1512
1513bool HexagonDAGToDAGISel::SelectMEMriS11_2(SDValue& Addr, SDValue &Base,
1514 SDValue &Offset) {
1515
1516 if (Addr.getOpcode() != ISD::ADD) {
1517 return(SelectADDRriS11_2(Addr, Base, Offset));
1518 }
1519
1520 return SelectADDRriS11_2(Addr, Base, Offset);
1521}
1522
1523
1524bool HexagonDAGToDAGISel::SelectADDRriS11_3(SDValue& Addr, SDValue &Base,
1525 SDValue &Offset) {
1526 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1527 Addr.getOpcode() == ISD::TargetGlobalAddress)
1528 return false; // Direct calls.
1529
1530 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1531 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1532 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1533 return (IsS11_3_Offset(Offset.getNode()));
1534 }
1535 Base = Addr;
1536 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1537 return (IsS11_3_Offset(Offset.getNode()));
1538}
1539
1540bool HexagonDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1,
1541 SDValue &R2) {
1542 if (Addr.getOpcode() == ISD::FrameIndex) return false;
1543 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1544 Addr.getOpcode() == ISD::TargetGlobalAddress)
1545 return false; // Direct calls.
1546
1547 if (Addr.getOpcode() == ISD::ADD) {
1548 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
1549 if (isInt<13>(CN->getSExtValue()))
1550 return false; // Let the reg+imm pattern catch this!
1551 R1 = Addr.getOperand(0);
1552 R2 = Addr.getOperand(1);
1553 return true;
1554 }
1555
1556 R1 = Addr;
1557
1558 return true;
1559}
1560
1561
1562// Handle generic address case. It is accessed from inlined asm =m constraints,
1563// which could have any kind of pointer.
1564bool HexagonDAGToDAGISel::SelectAddr(SDNode *Op, SDValue Addr,
1565 SDValue &Base, SDValue &Offset) {
1566 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1567 Addr.getOpcode() == ISD::TargetGlobalAddress)
1568 return false; // Direct calls.
1569
1570 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1571 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1572 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1573 return true;
1574 }
1575
1576 if (Addr.getOpcode() == ISD::ADD) {
1577 Base = Addr.getOperand(0);
1578 Offset = Addr.getOperand(1);
1579 return true;
1580 }
1581
1582 Base = Addr;
1583 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1584 return true;
1585}
1586
1587
1588bool HexagonDAGToDAGISel::
1589SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
1590 std::vector<SDValue> &OutOps) {
1591 SDValue Op0, Op1;
1592
1593 switch (ConstraintCode) {
1594 case 'o': // Offsetable.
1595 case 'v': // Not offsetable.
1596 default: return true;
1597 case 'm': // Memory.
1598 if (!SelectAddr(Op.getNode(), Op, Op0, Op1))
1599 return true;
1600 break;
1601 }
1602
1603 OutOps.push_back(Op0);
1604 OutOps.push_back(Op1);
1605 return false;
1606}
Jyotsna Verma519b3852012-11-28 20:58:14 +00001607
1608bool HexagonDAGToDAGISel::isConstExtProfitable(SDNode *N) const {
1609 unsigned UseCount = 0;
1610 for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
1611 UseCount++;
1612 }
1613
1614 return (UseCount <= 1);
1615
1616}
Jyotsna Vermad9225242013-02-13 21:38:46 +00001617
1618//===--------------------------------------------------------------------===//
1619// Return 'true' if use count of the global address is below threshold.
1620//===--------------------------------------------------------------------===//
1621bool HexagonDAGToDAGISel::hasNumUsesBelowThresGA(SDNode *N) const {
1622 assert(N->getOpcode() == ISD::TargetGlobalAddress &&
1623 "Expecting a target global address");
1624
1625 // Always try to fold the address.
1626 if (TM.getOptLevel() == CodeGenOpt::Aggressive)
1627 return true;
1628
1629 GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N);
1630 DenseMap<const GlobalValue *, unsigned>::const_iterator GI =
1631 GlobalAddressUseCountMap.find(GA->getGlobal());
1632
1633 if (GI == GlobalAddressUseCountMap.end())
1634 return false;
1635
1636 return GI->second <= MaxNumOfUsesForConstExtenders;
1637}
1638
1639//===--------------------------------------------------------------------===//
1640// Return true if the non GP-relative global address can be folded.
1641//===--------------------------------------------------------------------===//
1642inline bool HexagonDAGToDAGISel::foldGlobalAddress(SDValue &N, SDValue &R) {
1643 return foldGlobalAddressImpl(N, R, false);
1644}
1645
1646//===--------------------------------------------------------------------===//
1647// Return true if the GP-relative global address can be folded.
1648//===--------------------------------------------------------------------===//
1649inline bool HexagonDAGToDAGISel::foldGlobalAddressGP(SDValue &N, SDValue &R) {
1650 return foldGlobalAddressImpl(N, R, true);
1651}
1652
1653//===--------------------------------------------------------------------===//
1654// Fold offset of the global address if number of uses are below threshold.
1655//===--------------------------------------------------------------------===//
1656bool HexagonDAGToDAGISel::foldGlobalAddressImpl(SDValue &N, SDValue &R,
1657 bool ShouldLookForGP) {
1658 if (N.getOpcode() == ISD::ADD) {
1659 SDValue N0 = N.getOperand(0);
1660 SDValue N1 = N.getOperand(1);
1661 if ((ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32_GP)) ||
1662 (!ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32))) {
1663 ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1);
1664 GlobalAddressSDNode *GA =
1665 dyn_cast<GlobalAddressSDNode>(N0.getOperand(0));
1666
1667 if (Const && GA &&
1668 (GA->getOpcode() == ISD::TargetGlobalAddress)) {
1669 if ((N0.getOpcode() == HexagonISD::CONST32) &&
1670 !hasNumUsesBelowThresGA(GA))
1671 return false;
1672 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(),
Andrew Trickef9de2a2013-05-25 02:42:55 +00001673 SDLoc(Const),
Jyotsna Vermad9225242013-02-13 21:38:46 +00001674 N.getValueType(),
1675 GA->getOffset() +
1676 (uint64_t)Const->getSExtValue());
1677 return true;
1678 }
1679 }
1680 }
1681 return false;
1682}