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