blob: 4ff31353a96b8d3b04676ea8a08a96503138a65c [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"
15#include "HexagonISelLowering.h"
16#include "HexagonTargetMachine.h"
17#include "llvm/Intrinsics.h"
18#include "llvm/CodeGen/SelectionDAGISel.h"
19#include "llvm/Support/Compiler.h"
20#include "llvm/Support/Debug.h"
21
22using namespace llvm;
23
24
25//===----------------------------------------------------------------------===//
26// Instruction Selector Implementation
27//===----------------------------------------------------------------------===//
28
29//===--------------------------------------------------------------------===//
30/// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine
31/// instructions for SelectionDAG operations.
32///
33namespace {
34class HexagonDAGToDAGISel : public SelectionDAGISel {
35 /// Subtarget - Keep a pointer to the Hexagon Subtarget around so that we can
36 /// make the right decision when generating code for different targets.
37 const HexagonSubtarget &Subtarget;
38
39 // Keep a reference to HexagonTargetMachine.
40 HexagonTargetMachine& TM;
41 const HexagonInstrInfo *TII;
42
43public:
44 explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine)
45 : SelectionDAGISel(targetmachine),
46 Subtarget(targetmachine.getSubtarget<HexagonSubtarget>()),
47 TM(targetmachine),
48 TII(static_cast<const HexagonInstrInfo*>(TM.getInstrInfo())) {
49
50 }
51
52 SDNode *Select(SDNode *N);
53
54 // Complex Pattern Selectors.
55 bool SelectADDRri(SDValue& N, SDValue &R1, SDValue &R2);
56 bool SelectADDRriS11_0(SDValue& N, SDValue &R1, SDValue &R2);
57 bool SelectADDRriS11_1(SDValue& N, SDValue &R1, SDValue &R2);
58 bool SelectADDRriS11_2(SDValue& N, SDValue &R1, SDValue &R2);
59 bool SelectMEMriS11_2(SDValue& Addr, SDValue &Base, SDValue &Offset);
60 bool SelectADDRriS11_3(SDValue& N, SDValue &R1, SDValue &R2);
61 bool SelectADDRrr(SDValue &Addr, SDValue &Base, SDValue &Offset);
62 bool SelectADDRriU6_0(SDValue& N, SDValue &R1, SDValue &R2);
63 bool SelectADDRriU6_1(SDValue& N, SDValue &R1, SDValue &R2);
64 bool SelectADDRriU6_2(SDValue& N, SDValue &R1, SDValue &R2);
65
66 virtual const char *getPassName() const {
67 return "Hexagon DAG->DAG Pattern Instruction Selection";
68 }
69
70 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
71 /// inline asm expressions.
72 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
73 char ConstraintCode,
74 std::vector<SDValue> &OutOps);
75 bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset);
76
77 SDNode *SelectLoad(SDNode *N);
78 SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl);
79 SDNode *SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl);
80 SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode,
81 DebugLoc dl);
82 SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode,
83 DebugLoc dl);
84 SDNode *SelectBaseOffsetStore(StoreSDNode *ST, DebugLoc dl);
85 SDNode *SelectIndexedStore(StoreSDNode *ST, DebugLoc dl);
86 SDNode *SelectStore(SDNode *N);
87 SDNode *SelectSHL(SDNode *N);
88 SDNode *SelectSelect(SDNode *N);
89 SDNode *SelectTruncate(SDNode *N);
90 SDNode *SelectMul(SDNode *N);
91 SDNode *SelectZeroExtend(SDNode *N);
92 SDNode *SelectIntrinsicWOChain(SDNode *N);
Sirish Pande7517bbc2012-05-10 20:20:25 +000093 SDNode *SelectIntrinsicWChain(SDNode *N);
Tony Linthicumb4b54152011-12-12 21:14:40 +000094 SDNode *SelectConstant(SDNode *N);
Sirish Pande7517bbc2012-05-10 20:20:25 +000095 SDNode *SelectConstantFP(SDNode *N);
Tony Linthicumb4b54152011-12-12 21:14:40 +000096 SDNode *SelectAdd(SDNode *N);
Jyotsna Verma61c654c2012-11-28 20:58:14 +000097 bool isConstExtProfitable(SDNode *N) const;
Tony Linthicumb4b54152011-12-12 21:14:40 +000098
99 // Include the pieces autogenerated from the target description.
100#include "HexagonGenDAGISel.inc"
101};
102} // end anonymous namespace
103
104
105/// createHexagonISelDag - This pass converts a legalized DAG into a
106/// Hexagon-specific DAG, ready for instruction scheduling.
107///
108FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM) {
109 return new HexagonDAGToDAGISel(TM);
110}
111
112static bool IsS11_0_Offset(SDNode * S) {
113 ConstantSDNode *N = cast<ConstantSDNode>(S);
114
115 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
116 // field.
117 int64_t v = (int64_t)N->getSExtValue();
118 return isInt<11>(v);
119}
120
121
122static bool IsS11_1_Offset(SDNode * S) {
123 ConstantSDNode *N = cast<ConstantSDNode>(S);
124
125 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
126 // field.
127 int64_t v = (int64_t)N->getSExtValue();
128 return isShiftedInt<11,1>(v);
129}
130
131
132static bool IsS11_2_Offset(SDNode * S) {
133 ConstantSDNode *N = cast<ConstantSDNode>(S);
134
135 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
136 // field.
137 int64_t v = (int64_t)N->getSExtValue();
138 return isShiftedInt<11,2>(v);
139}
140
141
142static bool IsS11_3_Offset(SDNode * S) {
143 ConstantSDNode *N = cast<ConstantSDNode>(S);
144
145 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
146 // field.
147 int64_t v = (int64_t)N->getSExtValue();
148 return isShiftedInt<11,3>(v);
149}
150
151
152static bool IsU6_0_Offset(SDNode * S) {
153 ConstantSDNode *N = cast<ConstantSDNode>(S);
154
155 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
156 // field.
157 int64_t v = (int64_t)N->getSExtValue();
158 return isUInt<6>(v);
159}
160
161
162static bool IsU6_1_Offset(SDNode * S) {
163 ConstantSDNode *N = cast<ConstantSDNode>(S);
164
165 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
166 // field.
167 int64_t v = (int64_t)N->getSExtValue();
168 return isShiftedUInt<6,1>(v);
169}
170
171
172static bool IsU6_2_Offset(SDNode * S) {
173 ConstantSDNode *N = cast<ConstantSDNode>(S);
174
175 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
176 // field.
177 int64_t v = (int64_t)N->getSExtValue();
178 return isShiftedUInt<6,2>(v);
179}
180
181
182// Intrinsics that return a a predicate.
183static unsigned doesIntrinsicReturnPredicate(unsigned ID)
184{
185 switch (ID) {
186 default:
187 return 0;
188 case Intrinsic::hexagon_C2_cmpeq:
189 case Intrinsic::hexagon_C2_cmpgt:
190 case Intrinsic::hexagon_C2_cmpgtu:
191 case Intrinsic::hexagon_C2_cmpgtup:
192 case Intrinsic::hexagon_C2_cmpgtp:
193 case Intrinsic::hexagon_C2_cmpeqp:
194 case Intrinsic::hexagon_C2_bitsset:
195 case Intrinsic::hexagon_C2_bitsclr:
196 case Intrinsic::hexagon_C2_cmpeqi:
197 case Intrinsic::hexagon_C2_cmpgti:
198 case Intrinsic::hexagon_C2_cmpgtui:
199 case Intrinsic::hexagon_C2_cmpgei:
200 case Intrinsic::hexagon_C2_cmpgeui:
201 case Intrinsic::hexagon_C2_cmplt:
202 case Intrinsic::hexagon_C2_cmpltu:
203 case Intrinsic::hexagon_C2_bitsclri:
204 case Intrinsic::hexagon_C2_and:
205 case Intrinsic::hexagon_C2_or:
206 case Intrinsic::hexagon_C2_xor:
207 case Intrinsic::hexagon_C2_andn:
208 case Intrinsic::hexagon_C2_not:
209 case Intrinsic::hexagon_C2_orn:
210 case Intrinsic::hexagon_C2_pxfer_map:
211 case Intrinsic::hexagon_C2_any8:
212 case Intrinsic::hexagon_C2_all8:
213 case Intrinsic::hexagon_A2_vcmpbeq:
214 case Intrinsic::hexagon_A2_vcmpbgtu:
215 case Intrinsic::hexagon_A2_vcmpheq:
216 case Intrinsic::hexagon_A2_vcmphgt:
217 case Intrinsic::hexagon_A2_vcmphgtu:
218 case Intrinsic::hexagon_A2_vcmpweq:
219 case Intrinsic::hexagon_A2_vcmpwgt:
220 case Intrinsic::hexagon_A2_vcmpwgtu:
221 case Intrinsic::hexagon_C2_tfrrp:
222 case Intrinsic::hexagon_S2_tstbit_i:
223 case Intrinsic::hexagon_S2_tstbit_r:
224 return 1;
225 }
226}
227
228
229// Intrinsics that have predicate operands.
230static unsigned doesIntrinsicContainPredicate(unsigned ID)
231{
232 switch (ID) {
233 default:
234 return 0;
235 case Intrinsic::hexagon_C2_tfrpr:
236 return Hexagon::TFR_RsPd;
237 case Intrinsic::hexagon_C2_and:
238 return Hexagon::AND_pp;
239 case Intrinsic::hexagon_C2_xor:
240 return Hexagon::XOR_pp;
241 case Intrinsic::hexagon_C2_or:
242 return Hexagon::OR_pp;
243 case Intrinsic::hexagon_C2_not:
Sirish Pandeab7955b2012-02-15 18:52:27 +0000244 return Hexagon::NOT_p;
Tony Linthicumb4b54152011-12-12 21:14:40 +0000245 case Intrinsic::hexagon_C2_any8:
246 return Hexagon::ANY_pp;
247 case Intrinsic::hexagon_C2_all8:
248 return Hexagon::ALL_pp;
249 case Intrinsic::hexagon_C2_vitpack:
250 return Hexagon::VITPACK_pp;
251 case Intrinsic::hexagon_C2_mask:
252 return Hexagon::MASK_p;
253 case Intrinsic::hexagon_C2_mux:
254 return Hexagon::MUX_rr;
255
256 // Mapping hexagon_C2_muxir to MUX_pri. This is pretty weird - but
257 // that's how it's mapped in q6protos.h.
258 case Intrinsic::hexagon_C2_muxir:
259 return Hexagon::MUX_ri;
260
261 // Mapping hexagon_C2_muxri to MUX_pir. This is pretty weird - but
262 // that's how it's mapped in q6protos.h.
263 case Intrinsic::hexagon_C2_muxri:
264 return Hexagon::MUX_ir;
265
266 case Intrinsic::hexagon_C2_muxii:
267 return Hexagon::MUX_ii;
268 case Intrinsic::hexagon_C2_vmux:
269 return Hexagon::VMUX_prr64;
270 case Intrinsic::hexagon_S2_valignrb:
271 return Hexagon::VALIGN_rrp;
272 case Intrinsic::hexagon_S2_vsplicerb:
273 return Hexagon::VSPLICE_rrp;
274 }
275}
276
277
278static bool OffsetFitsS11(EVT MemType, int64_t Offset) {
279 if (MemType == MVT::i64 && isShiftedInt<11,3>(Offset)) {
280 return true;
281 }
282 if (MemType == MVT::i32 && isShiftedInt<11,2>(Offset)) {
283 return true;
284 }
285 if (MemType == MVT::i16 && isShiftedInt<11,1>(Offset)) {
286 return true;
287 }
288 if (MemType == MVT::i8 && isInt<11>(Offset)) {
289 return true;
290 }
291 return false;
292}
293
294
295//
296// Try to lower loads of GlobalAdresses into base+offset loads. Custom
297// lowering for GlobalAddress nodes has already turned it into a
298// CONST32.
299//
300SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl) {
Tony Linthicumb4b54152011-12-12 21:14:40 +0000301 SDValue Chain = LD->getChain();
302 SDNode* Const32 = LD->getBasePtr().getNode();
303 unsigned Opcode = 0;
304
305 if (Const32->getOpcode() == HexagonISD::CONST32 &&
306 ISD::isNormalLoad(LD)) {
307 SDValue Base = Const32->getOperand(0);
308 EVT LoadedVT = LD->getMemoryVT();
309 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
310 if (Offset != 0 && OffsetFitsS11(LoadedVT, Offset)) {
311 MVT PointerTy = TLI.getPointerTy();
312 const GlobalValue* GV =
313 cast<GlobalAddressSDNode>(Base)->getGlobal();
314 SDValue TargAddr =
315 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0);
Brendon Cahoon5262abb2012-05-14 19:35:42 +0000316 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
317 dl, PointerTy,
318 TargAddr);
Tony Linthicumb4b54152011-12-12 21:14:40 +0000319 // Figure out base + offset opcode
320 if (LoadedVT == MVT::i64) Opcode = Hexagon::LDrid_indexed;
321 else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed;
322 else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed;
323 else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed;
Sirish Pande26f61a12012-05-03 21:52:53 +0000324 else llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000325
326 // Build indexed load.
327 SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy);
328 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
329 LD->getValueType(0),
330 MVT::Other,
331 SDValue(NewBase,0),
332 TargetConstOff,
333 Chain);
334 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
335 MemOp[0] = LD->getMemOperand();
336 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
337 ReplaceUses(LD, Result);
338 return Result;
339 }
340 }
341
342 return SelectCode(LD);
343}
344
345
346SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
347 unsigned Opcode,
348 DebugLoc dl)
349{
350 SDValue Chain = LD->getChain();
351 EVT LoadedVT = LD->getMemoryVT();
352 SDValue Base = LD->getBasePtr();
353 SDValue Offset = LD->getOffset();
354 SDNode *OffsetNode = Offset.getNode();
355 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
356 SDValue N1 = LD->getOperand(1);
357 SDValue CPTmpN1_0;
358 SDValue CPTmpN1_1;
359 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
360 N1.getNode()->getValueType(0) == MVT::i32) {
361 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
362 SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32);
363 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
364 MVT::Other, Base, TargetConst,
365 Chain);
366 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, MVT::i64,
367 SDValue(Result_1, 0));
368 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
369 MemOp[0] = LD->getMemOperand();
370 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
371 const SDValue Froms[] = { SDValue(LD, 0),
372 SDValue(LD, 1),
373 SDValue(LD, 2)
374 };
375 const SDValue Tos[] = { SDValue(Result_2, 0),
376 SDValue(Result_1, 1),
377 SDValue(Result_1, 2)
378 };
379 ReplaceUses(Froms, Tos, 3);
380 return Result_2;
Sirish Pande71d56462012-05-03 16:18:50 +0000381 }
Tony Linthicumb4b54152011-12-12 21:14:40 +0000382 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
383 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
384 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
385 MVT::Other, Base, TargetConst0,
386 Chain);
387 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl,
388 MVT::i64, SDValue(Result_1, 0));
389 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl,
390 MVT::i32, Base, TargetConstVal,
391 SDValue(Result_1, 1));
392 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
393 MemOp[0] = LD->getMemOperand();
394 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
395 const SDValue Froms[] = { SDValue(LD, 0),
396 SDValue(LD, 1),
397 SDValue(LD, 2)
398 };
399 const SDValue Tos[] = { SDValue(Result_2, 0),
400 SDValue(Result_3, 0),
401 SDValue(Result_1, 1)
402 };
403 ReplaceUses(Froms, Tos, 3);
404 return Result_2;
405 }
406 return SelectCode(LD);
407}
408
409
410SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
411 unsigned Opcode,
412 DebugLoc dl)
413{
414 SDValue Chain = LD->getChain();
415 EVT LoadedVT = LD->getMemoryVT();
416 SDValue Base = LD->getBasePtr();
417 SDValue Offset = LD->getOffset();
418 SDNode *OffsetNode = Offset.getNode();
419 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
420 SDValue N1 = LD->getOperand(1);
421 SDValue CPTmpN1_0;
422 SDValue CPTmpN1_1;
423 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
424 N1.getNode()->getValueType(0) == MVT::i32) {
425 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
426 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
427 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
428 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
429 MVT::i32, MVT::Other, Base,
430 TargetConstVal, Chain);
431 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
432 TargetConst0);
433 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
434 MVT::i64, MVT::Other,
435 SDValue(Result_2,0),
436 SDValue(Result_1,0));
437 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
438 MemOp[0] = LD->getMemOperand();
439 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
440 const SDValue Froms[] = { SDValue(LD, 0),
441 SDValue(LD, 1),
442 SDValue(LD, 2)
443 };
444 const SDValue Tos[] = { SDValue(Result_3, 0),
445 SDValue(Result_1, 1),
446 SDValue(Result_1, 2)
447 };
448 ReplaceUses(Froms, Tos, 3);
449 return Result_3;
450 }
451
452 // Generate an indirect load.
453 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
454 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
455 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
456 MVT::Other,
457 Base, TargetConst0, Chain);
458 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
459 TargetConst0);
460 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
461 MVT::i64, MVT::Other,
462 SDValue(Result_2,0),
463 SDValue(Result_1,0));
464 // Add offset to base.
465 SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
466 Base, TargetConstVal,
467 SDValue(Result_1, 1));
468 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
469 MemOp[0] = LD->getMemOperand();
470 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
471 const SDValue Froms[] = { SDValue(LD, 0),
472 SDValue(LD, 1),
473 SDValue(LD, 2)
474 };
475 const SDValue Tos[] = { SDValue(Result_3, 0), // Load value.
476 SDValue(Result_4, 0), // New address.
477 SDValue(Result_1, 1)
478 };
479 ReplaceUses(Froms, Tos, 3);
480 return Result_3;
481 }
482
483 return SelectCode(LD);
484}
485
486
487SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl) {
488 SDValue Chain = LD->getChain();
489 SDValue Base = LD->getBasePtr();
490 SDValue Offset = LD->getOffset();
491 SDNode *OffsetNode = Offset.getNode();
492 // Get the constant value.
493 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
494 EVT LoadedVT = LD->getMemoryVT();
495 unsigned Opcode = 0;
496
497 // Check for zero ext loads.
498 bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD);
499
500 // Figure out the opcode.
501 if (LoadedVT == MVT::i64) {
502 if (TII->isValidAutoIncImm(LoadedVT, Val))
503 Opcode = Hexagon::POST_LDrid;
504 else
505 Opcode = Hexagon::LDrid;
506 } else if (LoadedVT == MVT::i32) {
507 if (TII->isValidAutoIncImm(LoadedVT, Val))
508 Opcode = Hexagon::POST_LDriw;
509 else
510 Opcode = Hexagon::LDriw;
511 } else if (LoadedVT == MVT::i16) {
512 if (TII->isValidAutoIncImm(LoadedVT, Val))
513 Opcode = zextval ? Hexagon::POST_LDriuh : Hexagon::POST_LDrih;
514 else
515 Opcode = zextval ? Hexagon::LDriuh : Hexagon::LDrih;
516 } else if (LoadedVT == MVT::i8) {
517 if (TII->isValidAutoIncImm(LoadedVT, Val))
518 Opcode = zextval ? Hexagon::POST_LDriub : Hexagon::POST_LDrib;
519 else
520 Opcode = zextval ? Hexagon::LDriub : Hexagon::LDrib;
521 } else
Sirish Pande26f61a12012-05-03 21:52:53 +0000522 llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000523
524 // For zero ext i64 loads, we need to add combine instructions.
525 if (LD->getValueType(0) == MVT::i64 &&
526 LD->getExtensionType() == ISD::ZEXTLOAD) {
527 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl);
528 }
529 if (LD->getValueType(0) == MVT::i64 &&
530 LD->getExtensionType() == ISD::SEXTLOAD) {
531 // Handle sign ext i64 loads.
532 return SelectIndexedLoadSignExtend64(LD, Opcode, dl);
533 }
534 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
535 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
536 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
537 LD->getValueType(0),
538 MVT::i32, MVT::Other, Base,
539 TargetConstVal, Chain);
540 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
541 MemOp[0] = LD->getMemOperand();
542 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
543 const SDValue Froms[] = { SDValue(LD, 0),
544 SDValue(LD, 1),
545 SDValue(LD, 2)
546 };
547 const SDValue Tos[] = { SDValue(Result, 0),
548 SDValue(Result, 1),
549 SDValue(Result, 2)
550 };
551 ReplaceUses(Froms, Tos, 3);
552 return Result;
553 } else {
554 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
555 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
556 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl,
557 LD->getValueType(0),
558 MVT::Other, Base, TargetConst0,
559 Chain);
560 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
561 Base, TargetConstVal,
562 SDValue(Result_1, 1));
563 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
564 MemOp[0] = LD->getMemOperand();
565 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
566 const SDValue Froms[] = { SDValue(LD, 0),
567 SDValue(LD, 1),
568 SDValue(LD, 2)
569 };
570 const SDValue Tos[] = { SDValue(Result_1, 0),
571 SDValue(Result_2, 0),
572 SDValue(Result_1, 1)
573 };
574 ReplaceUses(Froms, Tos, 3);
575 return Result_1;
576 }
Tony Linthicumb4b54152011-12-12 21:14:40 +0000577}
578
579
580SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
581 SDNode *result;
582 DebugLoc dl = N->getDebugLoc();
583 LoadSDNode *LD = cast<LoadSDNode>(N);
584 ISD::MemIndexedMode AM = LD->getAddressingMode();
585
586 // Handle indexed loads.
587 if (AM != ISD::UNINDEXED) {
588 result = SelectIndexedLoad(LD, dl);
589 } else {
590 result = SelectBaseOffsetLoad(LD, dl);
591 }
592
593 return result;
594}
595
596
597SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) {
598 SDValue Chain = ST->getChain();
599 SDValue Base = ST->getBasePtr();
600 SDValue Offset = ST->getOffset();
601 SDValue Value = ST->getValue();
602 SDNode *OffsetNode = Offset.getNode();
603 // Get the constant value.
604 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
605 EVT StoredVT = ST->getMemoryVT();
606
607 // Offset value must be within representable range
608 // and must have correct alignment properties.
609 if (TII->isValidAutoIncImm(StoredVT, Val)) {
610 SDValue Ops[] = { Value, Base,
611 CurDAG->getTargetConstant(Val, MVT::i32), Chain};
612 unsigned Opcode = 0;
613
614 // Figure out the post inc version of opcode.
615 if (StoredVT == MVT::i64) Opcode = Hexagon::POST_STdri;
616 else if (StoredVT == MVT::i32) Opcode = Hexagon::POST_STwri;
617 else if (StoredVT == MVT::i16) Opcode = Hexagon::POST_SThri;
618 else if (StoredVT == MVT::i8) Opcode = Hexagon::POST_STbri;
Sirish Pande26f61a12012-05-03 21:52:53 +0000619 else llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000620
621 // Build post increment store.
622 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
623 MVT::Other, Ops, 4);
624 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
625 MemOp[0] = ST->getMemOperand();
626 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
627
628 ReplaceUses(ST, Result);
629 ReplaceUses(SDValue(ST,1), SDValue(Result,1));
630 return Result;
631 }
632
633 // Note: Order of operands matches the def of instruction:
634 // def STrid : STInst<(outs), (ins MEMri:$addr, DoubleRegs:$src1), ...
635 // and it differs for POST_ST* for instance.
636 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value,
637 Chain};
638 unsigned Opcode = 0;
639
640 // Figure out the opcode.
641 if (StoredVT == MVT::i64) Opcode = Hexagon::STrid;
Sirish Pande26f61a12012-05-03 21:52:53 +0000642 else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed;
Tony Linthicumb4b54152011-12-12 21:14:40 +0000643 else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih;
644 else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib;
Sirish Pande26f61a12012-05-03 21:52:53 +0000645 else llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000646
647 // Build regular store.
648 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
649 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops,
650 4);
651 // Build splitted incriment instruction.
652 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
653 Base,
654 TargetConstVal,
655 SDValue(Result_1, 0));
656 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
657 MemOp[0] = ST->getMemOperand();
658 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
659
660 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0));
661 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0));
662 return Result_2;
663}
664
665
666SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST,
667 DebugLoc dl) {
668 SDValue Chain = ST->getChain();
669 SDNode* Const32 = ST->getBasePtr().getNode();
670 SDValue Value = ST->getValue();
671 unsigned Opcode = 0;
672
673 // Try to lower stores of GlobalAdresses into indexed stores. Custom
674 // lowering for GlobalAddress nodes has already turned it into a
675 // CONST32. Avoid truncating stores for the moment. Post-inc stores
676 // do the same. Don't think there's a reason for it, so will file a
677 // bug to fix.
678 if ((Const32->getOpcode() == HexagonISD::CONST32) &&
679 !(Value.getValueType() == MVT::i64 && ST->isTruncatingStore())) {
680 SDValue Base = Const32->getOperand(0);
681 if (Base.getOpcode() == ISD::TargetGlobalAddress) {
682 EVT StoredVT = ST->getMemoryVT();
683 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
684 if (Offset != 0 && OffsetFitsS11(StoredVT, Offset)) {
685 MVT PointerTy = TLI.getPointerTy();
686 const GlobalValue* GV =
687 cast<GlobalAddressSDNode>(Base)->getGlobal();
688 SDValue TargAddr =
689 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0);
Brendon Cahoon5262abb2012-05-14 19:35:42 +0000690 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
691 dl, PointerTy,
692 TargAddr);
Tony Linthicumb4b54152011-12-12 21:14:40 +0000693
694 // Figure out base + offset opcode
695 if (StoredVT == MVT::i64) Opcode = Hexagon::STrid_indexed;
696 else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed;
697 else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed;
698 else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed;
Sirish Pande26f61a12012-05-03 21:52:53 +0000699 else llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000700
701 SDValue Ops[] = {SDValue(NewBase,0),
702 CurDAG->getTargetConstant(Offset,PointerTy),
703 Value, Chain};
704 // build indexed store
705 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
706 MVT::Other, Ops, 4);
707 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
708 MemOp[0] = ST->getMemOperand();
709 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
710 ReplaceUses(ST, Result);
711 return Result;
712 }
713 }
714 }
715
716 return SelectCode(ST);
717}
718
719
720SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
721 DebugLoc dl = N->getDebugLoc();
722 StoreSDNode *ST = cast<StoreSDNode>(N);
723 ISD::MemIndexedMode AM = ST->getAddressingMode();
724
725 // Handle indexed stores.
726 if (AM != ISD::UNINDEXED) {
727 return SelectIndexedStore(ST, dl);
728 }
Sirish Pande71d56462012-05-03 16:18:50 +0000729
Tony Linthicumb4b54152011-12-12 21:14:40 +0000730 return SelectBaseOffsetStore(ST, dl);
731}
732
733SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
734 DebugLoc dl = N->getDebugLoc();
735
736 //
737 // %conv.i = sext i32 %tmp1 to i64
738 // %conv2.i = sext i32 %add to i64
739 // %mul.i = mul nsw i64 %conv2.i, %conv.i
740 //
741 // --- match with the following ---
742 //
743 // %mul.i = mpy (%tmp1, %add)
744 //
745
746 if (N->getValueType(0) == MVT::i64) {
747 // Shifting a i64 signed multiply.
748 SDValue MulOp0 = N->getOperand(0);
749 SDValue MulOp1 = N->getOperand(1);
750
751 SDValue OP0;
752 SDValue OP1;
753
754 // Handle sign_extend and sextload.
755 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
756 SDValue Sext0 = MulOp0.getOperand(0);
757 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Sirish Pande26f61a12012-05-03 21:52:53 +0000758 return SelectCode(N);
Tony Linthicumb4b54152011-12-12 21:14:40 +0000759 }
760
761 OP0 = Sext0;
762 } else if (MulOp0.getOpcode() == ISD::LOAD) {
763 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
764 if (LD->getMemoryVT() != MVT::i32 ||
765 LD->getExtensionType() != ISD::SEXTLOAD ||
766 LD->getAddressingMode() != ISD::UNINDEXED) {
Sirish Pande26f61a12012-05-03 21:52:53 +0000767 return SelectCode(N);
Tony Linthicumb4b54152011-12-12 21:14:40 +0000768 }
769
Tony Linthicumb4b54152011-12-12 21:14:40 +0000770 SDValue Chain = LD->getChain();
771 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
772 OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
773 MVT::Other,
774 LD->getBasePtr(), TargetConst0,
775 Chain), 0);
776 } else {
777 return SelectCode(N);
778 }
779
780 // Same goes for the second operand.
781 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
782 SDValue Sext1 = MulOp1.getOperand(0);
783 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
784 return SelectCode(N);
785 }
786
787 OP1 = Sext1;
788 } else if (MulOp1.getOpcode() == ISD::LOAD) {
789 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
790 if (LD->getMemoryVT() != MVT::i32 ||
791 LD->getExtensionType() != ISD::SEXTLOAD ||
792 LD->getAddressingMode() != ISD::UNINDEXED) {
793 return SelectCode(N);
794 }
795
Tony Linthicumb4b54152011-12-12 21:14:40 +0000796 SDValue Chain = LD->getChain();
797 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
798 OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
799 MVT::Other,
800 LD->getBasePtr(), TargetConst0,
801 Chain), 0);
802 } else {
803 return SelectCode(N);
804 }
805
806 // Generate a mpy instruction.
807 SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY64, dl, MVT::i64,
808 OP0, OP1);
809 ReplaceUses(N, Result);
810 return Result;
811 }
812
813 return SelectCode(N);
814}
815
816
817SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) {
818 DebugLoc dl = N->getDebugLoc();
819 SDValue N0 = N->getOperand(0);
820 if (N0.getOpcode() == ISD::SETCC) {
821 SDValue N00 = N0.getOperand(0);
822 if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) {
823 SDValue N000 = N00.getOperand(0);
824 SDValue N001 = N00.getOperand(1);
825 if (cast<VTSDNode>(N001)->getVT() == MVT::i16) {
826 SDValue N01 = N0.getOperand(1);
827 SDValue N02 = N0.getOperand(2);
828
829 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
830 // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1,
831 // IntRegs:i32:$src2)
832 // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
833 // Pattern complexity = 9 cost = 1 size = 0.
834 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) {
835 SDValue N1 = N->getOperand(1);
836 if (N01 == N1) {
837 SDValue N2 = N->getOperand(2);
838 if (N000 == N2 &&
839 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
840 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
841 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl,
842 MVT::i32, N000);
843 SDNode *Result = CurDAG->getMachineNode(Hexagon::MAXw_rr, dl,
844 MVT::i32,
845 SDValue(SextNode, 0),
846 N1);
847 ReplaceUses(N, Result);
848 return Result;
849 }
850 }
851 }
852
853 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
854 // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1,
855 // IntRegs:i32:$src2)
856 // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
857 // Pattern complexity = 9 cost = 1 size = 0.
858 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) {
859 SDValue N1 = N->getOperand(1);
860 if (N01 == N1) {
861 SDValue N2 = N->getOperand(2);
862 if (N000 == N2 &&
863 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
864 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
865 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl,
866 MVT::i32, N000);
867 SDNode *Result = CurDAG->getMachineNode(Hexagon::MINw_rr, dl,
868 MVT::i32,
869 SDValue(SextNode, 0),
870 N1);
871 ReplaceUses(N, Result);
872 return Result;
873 }
874 }
875 }
876 }
877 }
878 }
879
880 return SelectCode(N);
881}
882
883
884SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) {
885 DebugLoc dl = N->getDebugLoc();
886 SDValue Shift = N->getOperand(0);
887
888 //
889 // %conv.i = sext i32 %tmp1 to i64
890 // %conv2.i = sext i32 %add to i64
891 // %mul.i = mul nsw i64 %conv2.i, %conv.i
892 // %shr5.i = lshr i64 %mul.i, 32
893 // %conv3.i = trunc i64 %shr5.i to i32
894 //
895 // --- match with the following ---
896 //
897 // %conv3.i = mpy (%tmp1, %add)
898 //
899 // Trunc to i32.
900 if (N->getValueType(0) == MVT::i32) {
901 // Trunc from i64.
902 if (Shift.getNode()->getValueType(0) == MVT::i64) {
903 // Trunc child is logical shift right.
904 if (Shift.getOpcode() != ISD::SRL) {
905 return SelectCode(N);
906 }
907
908 SDValue ShiftOp0 = Shift.getOperand(0);
909 SDValue ShiftOp1 = Shift.getOperand(1);
910
911 // Shift by const 32
912 if (ShiftOp1.getOpcode() != ISD::Constant) {
913 return SelectCode(N);
914 }
915
916 int32_t ShiftConst =
917 cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue();
918 if (ShiftConst != 32) {
919 return SelectCode(N);
920 }
921
922 // Shifting a i64 signed multiply
923 SDValue Mul = ShiftOp0;
924 if (Mul.getOpcode() != ISD::MUL) {
925 return SelectCode(N);
926 }
927
928 SDValue MulOp0 = Mul.getOperand(0);
929 SDValue MulOp1 = Mul.getOperand(1);
930
931 SDValue OP0;
932 SDValue OP1;
933
934 // Handle sign_extend and sextload
935 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
936 SDValue Sext0 = MulOp0.getOperand(0);
937 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
938 return SelectCode(N);
939 }
940
941 OP0 = Sext0;
942 } else if (MulOp0.getOpcode() == ISD::LOAD) {
943 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
944 if (LD->getMemoryVT() != MVT::i32 ||
945 LD->getExtensionType() != ISD::SEXTLOAD ||
946 LD->getAddressingMode() != ISD::UNINDEXED) {
947 return SelectCode(N);
948 }
949
Tony Linthicumb4b54152011-12-12 21:14:40 +0000950 SDValue Chain = LD->getChain();
951 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
952 OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
953 MVT::Other,
954 LD->getBasePtr(),
955 TargetConst0, Chain), 0);
956 } else {
957 return SelectCode(N);
958 }
959
960 // Same goes for the second operand.
961 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
962 SDValue Sext1 = MulOp1.getOperand(0);
963 if (Sext1.getNode()->getValueType(0) != MVT::i32)
964 return SelectCode(N);
965
966 OP1 = Sext1;
967 } else if (MulOp1.getOpcode() == ISD::LOAD) {
968 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
969 if (LD->getMemoryVT() != MVT::i32 ||
970 LD->getExtensionType() != ISD::SEXTLOAD ||
971 LD->getAddressingMode() != ISD::UNINDEXED) {
972 return SelectCode(N);
973 }
974
Tony Linthicumb4b54152011-12-12 21:14:40 +0000975 SDValue Chain = LD->getChain();
976 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
977 OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
978 MVT::Other,
979 LD->getBasePtr(),
980 TargetConst0, Chain), 0);
981 } else {
982 return SelectCode(N);
983 }
984
985 // Generate a mpy instruction.
986 SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY, dl, MVT::i32,
987 OP0, OP1);
988 ReplaceUses(N, Result);
989 return Result;
990 }
991 }
992
993 return SelectCode(N);
994}
995
996
997SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
998 DebugLoc dl = N->getDebugLoc();
999 if (N->getValueType(0) == MVT::i32) {
1000 SDValue Shl_0 = N->getOperand(0);
1001 SDValue Shl_1 = N->getOperand(1);
1002 // RHS is const.
1003 if (Shl_1.getOpcode() == ISD::Constant) {
1004 if (Shl_0.getOpcode() == ISD::MUL) {
1005 SDValue Mul_0 = Shl_0.getOperand(0); // Val
1006 SDValue Mul_1 = Shl_0.getOperand(1); // Const
1007 // RHS of mul is const.
1008 if (Mul_1.getOpcode() == ISD::Constant) {
1009 int32_t ShlConst =
1010 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1011 int32_t MulConst =
1012 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
1013 int32_t ValConst = MulConst << ShlConst;
1014 SDValue Val = CurDAG->getTargetConstant(ValConst,
1015 MVT::i32);
1016 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
1017 if (isInt<9>(CN->getSExtValue())) {
1018 SDNode* Result =
1019 CurDAG->getMachineNode(Hexagon::MPYI_ri, dl,
1020 MVT::i32, Mul_0, Val);
1021 ReplaceUses(N, Result);
1022 return Result;
1023 }
1024
1025 }
1026 } else if (Shl_0.getOpcode() == ISD::SUB) {
1027 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
1028 SDValue Sub_1 = Shl_0.getOperand(1); // Val
1029 if (Sub_0.getOpcode() == ISD::Constant) {
1030 int32_t SubConst =
1031 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
1032 if (SubConst == 0) {
1033 if (Sub_1.getOpcode() == ISD::SHL) {
1034 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
1035 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
1036 if (Shl2_1.getOpcode() == ISD::Constant) {
1037 int32_t ShlConst =
1038 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1039 int32_t Shl2Const =
1040 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
1041 int32_t ValConst = 1 << (ShlConst+Shl2Const);
1042 SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32);
1043 if (ConstantSDNode *CN =
1044 dyn_cast<ConstantSDNode>(Val.getNode()))
1045 if (isInt<9>(CN->getSExtValue())) {
1046 SDNode* Result =
1047 CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, MVT::i32,
1048 Shl2_0, Val);
1049 ReplaceUses(N, Result);
1050 return Result;
1051 }
1052 }
1053 }
1054 }
1055 }
1056 }
1057 }
1058 }
1059 return SelectCode(N);
1060}
1061
1062
1063//
1064// If there is an zero_extend followed an intrinsic in DAG (this means - the
1065// result of the intrinsic is predicate); convert the zero_extend to
1066// transfer instruction.
1067//
1068// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
1069// converted into a MUX as predicate registers defined as 1 bit in the
1070// compiler. Architecture defines them as 8-bit registers.
1071// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
1072//
1073SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
1074 DebugLoc dl = N->getDebugLoc();
1075 SDNode *IsIntrinsic = N->getOperand(0).getNode();
1076 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
1077 unsigned ID =
1078 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
1079 if (doesIntrinsicReturnPredicate(ID)) {
1080 // Now we need to differentiate target data types.
1081 if (N->getValueType(0) == MVT::i64) {
1082 // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs).
1083 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
1084 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl,
1085 MVT::i32,
1086 SDValue(IsIntrinsic, 0));
1087 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl,
1088 MVT::i32,
1089 TargetConst0);
1090 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
1091 MVT::i64, MVT::Other,
1092 SDValue(Result_2, 0),
1093 SDValue(Result_1, 0));
1094 ReplaceUses(N, Result_3);
1095 return Result_3;
1096 }
1097 if (N->getValueType(0) == MVT::i32) {
1098 // Convert the zero_extend to Rs = Pd
1099 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl,
1100 MVT::i32,
1101 SDValue(IsIntrinsic, 0));
1102 ReplaceUses(N, RsPd);
1103 return RsPd;
1104 }
Craig Topperbc219812012-02-07 02:50:20 +00001105 llvm_unreachable("Unexpected value type");
Tony Linthicumb4b54152011-12-12 21:14:40 +00001106 }
1107 }
1108 return SelectCode(N);
1109}
1110
1111
1112//
1113// Checking for intrinsics which have predicate registers as operand(s)
1114// and lowering to the actual intrinsic.
1115//
1116SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
1117 DebugLoc dl = N->getDebugLoc();
1118 unsigned ID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
1119 unsigned IntrinsicWithPred = doesIntrinsicContainPredicate(ID);
1120
1121 // We are concerned with only those intrinsics that have predicate registers
1122 // as at least one of the operands.
1123 if (IntrinsicWithPred) {
1124 SmallVector<SDValue, 8> Ops;
1125 const MCInstrDesc &MCID = TII->get(IntrinsicWithPred);
1126 const TargetRegisterInfo *TRI = TM.getRegisterInfo();
1127
1128 // Iterate over all the operands of the intrinsics.
1129 // For PredRegs, do the transfer.
1130 // For Double/Int Regs, just preserve the value
1131 // For immediates, lower it.
1132 for (unsigned i = 1; i < N->getNumOperands(); ++i) {
1133 SDNode *Arg = N->getOperand(i).getNode();
Jakob Stoklund Olesen397fc482012-05-07 22:10:26 +00001134 const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI, *MF);
Tony Linthicumb4b54152011-12-12 21:14:40 +00001135
Craig Topper420761a2012-04-20 07:30:17 +00001136 if (RC == &Hexagon::IntRegsRegClass ||
1137 RC == &Hexagon::DoubleRegsRegClass) {
Tony Linthicumb4b54152011-12-12 21:14:40 +00001138 Ops.push_back(SDValue(Arg, 0));
Craig Topper420761a2012-04-20 07:30:17 +00001139 } else if (RC == &Hexagon::PredRegsRegClass) {
Tony Linthicumb4b54152011-12-12 21:14:40 +00001140 // Do the transfer.
1141 SDNode *PdRs = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1,
1142 SDValue(Arg, 0));
1143 Ops.push_back(SDValue(PdRs,0));
1144 } else if (RC == NULL && (dyn_cast<ConstantSDNode>(Arg) != NULL)) {
1145 // This is immediate operand. Lower it here making sure that we DO have
1146 // const SDNode for immediate value.
1147 int32_t Val = cast<ConstantSDNode>(Arg)->getSExtValue();
1148 SDValue SDVal = CurDAG->getTargetConstant(Val, MVT::i32);
1149 Ops.push_back(SDVal);
1150 } else {
Craig Topperbc219812012-02-07 02:50:20 +00001151 llvm_unreachable("Unimplemented");
Tony Linthicumb4b54152011-12-12 21:14:40 +00001152 }
1153 }
1154 EVT ReturnValueVT = N->getValueType(0);
1155 SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl,
1156 ReturnValueVT,
1157 Ops.data(), Ops.size());
1158 ReplaceUses(N, Result);
1159 return Result;
1160 }
1161 return SelectCode(N);
1162}
1163
Sirish Pande7517bbc2012-05-10 20:20:25 +00001164//
1165// Map floating point constant values.
1166//
1167SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
1168 DebugLoc dl = N->getDebugLoc();
1169 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
1170 APFloat APF = CN->getValueAPF();
1171 if (N->getValueType(0) == MVT::f32) {
1172 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
1173 CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32));
1174 }
1175 else if (N->getValueType(0) == MVT::f64) {
1176 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
1177 CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64));
1178 }
1179
1180 return SelectCode(N);
1181}
1182
Tony Linthicumb4b54152011-12-12 21:14:40 +00001183
1184//
1185// Map predicate true (encoded as -1 in LLVM) to a XOR.
1186//
1187SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
1188 DebugLoc dl = N->getDebugLoc();
1189 if (N->getValueType(0) == MVT::i1) {
1190 SDNode* Result;
1191 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
1192 if (Val == -1) {
Tony Linthicumb4b54152011-12-12 21:14:40 +00001193 // Create the IntReg = 1 node.
1194 SDNode* IntRegTFR =
1195 CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
1196 CurDAG->getTargetConstant(0, MVT::i32));
1197
1198 // Pd = IntReg
1199 SDNode* Pd = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1,
1200 SDValue(IntRegTFR, 0));
1201
1202 // not(Pd)
Sirish Pandeab7955b2012-02-15 18:52:27 +00001203 SDNode* NotPd = CurDAG->getMachineNode(Hexagon::NOT_p, dl, MVT::i1,
Tony Linthicumb4b54152011-12-12 21:14:40 +00001204 SDValue(Pd, 0));
1205
1206 // xor(not(Pd))
1207 Result = CurDAG->getMachineNode(Hexagon::XOR_pp, dl, MVT::i1,
1208 SDValue(Pd, 0), SDValue(NotPd, 0));
1209
1210 // We have just built:
1211 // Rs = Pd
1212 // Pd = xor(not(Pd), Pd)
1213
1214 ReplaceUses(N, Result);
1215 return Result;
1216 }
1217 }
1218
1219 return SelectCode(N);
1220}
1221
1222
1223//
1224// Map add followed by a asr -> asr +=.
1225//
1226SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
1227 DebugLoc dl = N->getDebugLoc();
1228 if (N->getValueType(0) != MVT::i32) {
1229 return SelectCode(N);
1230 }
1231 // Identify nodes of the form: add(asr(...)).
1232 SDNode* Src1 = N->getOperand(0).getNode();
1233 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1234 || Src1->getValueType(0) != MVT::i32) {
1235 return SelectCode(N);
1236 }
1237
1238 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1239 // Rd and Rd' are assigned to the same register
Sirish Pande71d56462012-05-03 16:18:50 +00001240 SDNode* Result = CurDAG->getMachineNode(Hexagon::ASR_ADD_rr, dl, MVT::i32,
Tony Linthicumb4b54152011-12-12 21:14:40 +00001241 N->getOperand(1),
1242 Src1->getOperand(0),
1243 Src1->getOperand(1));
1244 ReplaceUses(N, Result);
1245
1246 return Result;
1247}
1248
1249
1250SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
1251 if (N->isMachineOpcode())
1252 return NULL; // Already selected.
1253
1254
1255 switch (N->getOpcode()) {
1256 case ISD::Constant:
1257 return SelectConstant(N);
1258
Sirish Pande7517bbc2012-05-10 20:20:25 +00001259 case ISD::ConstantFP:
1260 return SelectConstantFP(N);
1261
Tony Linthicumb4b54152011-12-12 21:14:40 +00001262 case ISD::ADD:
1263 return SelectAdd(N);
1264
1265 case ISD::SHL:
1266 return SelectSHL(N);
1267
1268 case ISD::LOAD:
1269 return SelectLoad(N);
1270
1271 case ISD::STORE:
1272 return SelectStore(N);
1273
1274 case ISD::SELECT:
1275 return SelectSelect(N);
1276
1277 case ISD::TRUNCATE:
1278 return SelectTruncate(N);
1279
1280 case ISD::MUL:
1281 return SelectMul(N);
1282
1283 case ISD::ZERO_EXTEND:
1284 return SelectZeroExtend(N);
1285
1286 case ISD::INTRINSIC_WO_CHAIN:
1287 return SelectIntrinsicWOChain(N);
1288 }
1289
1290 return SelectCode(N);
1291}
1292
1293
1294//
1295// Hexagon_TODO: Five functions for ADDRri?! Surely there must be a better way
1296// to define these instructions.
1297//
1298bool HexagonDAGToDAGISel::SelectADDRri(SDValue& Addr, SDValue &Base,
1299 SDValue &Offset) {
1300 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1301 Addr.getOpcode() == ISD::TargetGlobalAddress)
1302 return false; // Direct calls.
1303
1304 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1305 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1306 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1307 return true;
1308 }
1309 Base = Addr;
1310 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1311 return true;
1312}
1313
1314
1315bool HexagonDAGToDAGISel::SelectADDRriS11_0(SDValue& Addr, SDValue &Base,
1316 SDValue &Offset) {
1317 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1318 Addr.getOpcode() == ISD::TargetGlobalAddress)
1319 return false; // Direct calls.
1320
1321 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1322 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1323 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1324 return (IsS11_0_Offset(Offset.getNode()));
1325 }
1326 Base = Addr;
1327 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1328 return (IsS11_0_Offset(Offset.getNode()));
1329}
1330
1331
1332bool HexagonDAGToDAGISel::SelectADDRriS11_1(SDValue& Addr, SDValue &Base,
1333 SDValue &Offset) {
1334 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1335 Addr.getOpcode() == ISD::TargetGlobalAddress)
1336 return false; // Direct calls.
1337
1338 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1339 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1340 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1341 return (IsS11_1_Offset(Offset.getNode()));
1342 }
1343 Base = Addr;
1344 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1345 return (IsS11_1_Offset(Offset.getNode()));
1346}
1347
1348
1349bool HexagonDAGToDAGISel::SelectADDRriS11_2(SDValue& Addr, SDValue &Base,
1350 SDValue &Offset) {
1351 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1352 Addr.getOpcode() == ISD::TargetGlobalAddress)
1353 return false; // Direct calls.
1354
1355 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1356 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1357 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1358 return (IsS11_2_Offset(Offset.getNode()));
1359 }
1360 Base = Addr;
1361 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1362 return (IsS11_2_Offset(Offset.getNode()));
1363}
1364
1365
1366bool HexagonDAGToDAGISel::SelectADDRriU6_0(SDValue& Addr, SDValue &Base,
1367 SDValue &Offset) {
1368 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1369 Addr.getOpcode() == ISD::TargetGlobalAddress)
1370 return false; // Direct calls.
1371
1372 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1373 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1374 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1375 return (IsU6_0_Offset(Offset.getNode()));
1376 }
1377 Base = Addr;
1378 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1379 return (IsU6_0_Offset(Offset.getNode()));
1380}
1381
1382
1383bool HexagonDAGToDAGISel::SelectADDRriU6_1(SDValue& Addr, SDValue &Base,
1384 SDValue &Offset) {
1385 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1386 Addr.getOpcode() == ISD::TargetGlobalAddress)
1387 return false; // Direct calls.
1388
1389 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1390 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1391 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1392 return (IsU6_1_Offset(Offset.getNode()));
1393 }
1394 Base = Addr;
1395 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1396 return (IsU6_1_Offset(Offset.getNode()));
1397}
1398
1399
1400bool HexagonDAGToDAGISel::SelectADDRriU6_2(SDValue& Addr, SDValue &Base,
1401 SDValue &Offset) {
1402 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1403 Addr.getOpcode() == ISD::TargetGlobalAddress)
1404 return false; // Direct calls.
1405
1406 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1407 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1408 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1409 return (IsU6_2_Offset(Offset.getNode()));
1410 }
1411 Base = Addr;
1412 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1413 return (IsU6_2_Offset(Offset.getNode()));
1414}
1415
1416
1417bool HexagonDAGToDAGISel::SelectMEMriS11_2(SDValue& Addr, SDValue &Base,
1418 SDValue &Offset) {
1419
1420 if (Addr.getOpcode() != ISD::ADD) {
1421 return(SelectADDRriS11_2(Addr, Base, Offset));
1422 }
1423
1424 return SelectADDRriS11_2(Addr, Base, Offset);
1425}
1426
1427
1428bool HexagonDAGToDAGISel::SelectADDRriS11_3(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_3_Offset(Offset.getNode()));
1438 }
1439 Base = Addr;
1440 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1441 return (IsS11_3_Offset(Offset.getNode()));
1442}
1443
1444bool HexagonDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1,
1445 SDValue &R2) {
1446 if (Addr.getOpcode() == ISD::FrameIndex) return false;
1447 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1448 Addr.getOpcode() == ISD::TargetGlobalAddress)
1449 return false; // Direct calls.
1450
1451 if (Addr.getOpcode() == ISD::ADD) {
1452 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
1453 if (isInt<13>(CN->getSExtValue()))
1454 return false; // Let the reg+imm pattern catch this!
1455 R1 = Addr.getOperand(0);
1456 R2 = Addr.getOperand(1);
1457 return true;
1458 }
1459
1460 R1 = Addr;
1461
1462 return true;
1463}
1464
1465
1466// Handle generic address case. It is accessed from inlined asm =m constraints,
1467// which could have any kind of pointer.
1468bool HexagonDAGToDAGISel::SelectAddr(SDNode *Op, SDValue Addr,
1469 SDValue &Base, SDValue &Offset) {
1470 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1471 Addr.getOpcode() == ISD::TargetGlobalAddress)
1472 return false; // Direct calls.
1473
1474 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1475 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1476 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1477 return true;
1478 }
1479
1480 if (Addr.getOpcode() == ISD::ADD) {
1481 Base = Addr.getOperand(0);
1482 Offset = Addr.getOperand(1);
1483 return true;
1484 }
1485
1486 Base = Addr;
1487 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1488 return true;
1489}
1490
1491
1492bool HexagonDAGToDAGISel::
1493SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
1494 std::vector<SDValue> &OutOps) {
1495 SDValue Op0, Op1;
1496
1497 switch (ConstraintCode) {
1498 case 'o': // Offsetable.
1499 case 'v': // Not offsetable.
1500 default: return true;
1501 case 'm': // Memory.
1502 if (!SelectAddr(Op.getNode(), Op, Op0, Op1))
1503 return true;
1504 break;
1505 }
1506
1507 OutOps.push_back(Op0);
1508 OutOps.push_back(Op1);
1509 return false;
1510}
Jyotsna Verma61c654c2012-11-28 20:58:14 +00001511
1512bool HexagonDAGToDAGISel::isConstExtProfitable(SDNode *N) const {
1513 unsigned UseCount = 0;
1514 for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
1515 UseCount++;
1516 }
1517
1518 return (UseCount <= 1);
1519
1520}