blob: a22555d8b64ee48cb6e317bf158ab3b198c5731e [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);
Brendon Cahoon6d532d82012-05-11 19:56:59 +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 Cahoon6d532d82012-05-11 19:56:59 +0000316 SDNode* NewBase;
317 if (Subtarget.hasV4TOps())
318 NewBase = CurDAG->getMachineNode(Hexagon::TFRI_V4,
319 dl, PointerTy, TargAddr);
320 else
321 NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
322 dl, PointerTy, TargAddr);
Tony Linthicumb4b54152011-12-12 21:14:40 +0000323 // Figure out base + offset opcode
324 if (LoadedVT == MVT::i64) Opcode = Hexagon::LDrid_indexed;
325 else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed;
326 else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed;
327 else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed;
Sirish Pande26f61a12012-05-03 21:52:53 +0000328 else llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000329
330 // Build indexed load.
331 SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy);
332 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
333 LD->getValueType(0),
334 MVT::Other,
335 SDValue(NewBase,0),
336 TargetConstOff,
337 Chain);
338 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
339 MemOp[0] = LD->getMemOperand();
340 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
341 ReplaceUses(LD, Result);
342 return Result;
343 }
344 }
345
346 return SelectCode(LD);
347}
348
349
350SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
351 unsigned Opcode,
352 DebugLoc dl)
353{
354 SDValue Chain = LD->getChain();
355 EVT LoadedVT = LD->getMemoryVT();
356 SDValue Base = LD->getBasePtr();
357 SDValue Offset = LD->getOffset();
358 SDNode *OffsetNode = Offset.getNode();
359 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
360 SDValue N1 = LD->getOperand(1);
361 SDValue CPTmpN1_0;
362 SDValue CPTmpN1_1;
363 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
364 N1.getNode()->getValueType(0) == MVT::i32) {
365 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
366 SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32);
367 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
368 MVT::Other, Base, TargetConst,
369 Chain);
370 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, MVT::i64,
371 SDValue(Result_1, 0));
372 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
373 MemOp[0] = LD->getMemOperand();
374 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
375 const SDValue Froms[] = { SDValue(LD, 0),
376 SDValue(LD, 1),
377 SDValue(LD, 2)
378 };
379 const SDValue Tos[] = { SDValue(Result_2, 0),
380 SDValue(Result_1, 1),
381 SDValue(Result_1, 2)
382 };
383 ReplaceUses(Froms, Tos, 3);
384 return Result_2;
Sirish Pande71d56462012-05-03 16:18:50 +0000385 }
Tony Linthicumb4b54152011-12-12 21:14:40 +0000386 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
387 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
388 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
389 MVT::Other, Base, TargetConst0,
390 Chain);
391 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl,
392 MVT::i64, SDValue(Result_1, 0));
393 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl,
394 MVT::i32, Base, TargetConstVal,
395 SDValue(Result_1, 1));
396 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
397 MemOp[0] = LD->getMemOperand();
398 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
399 const SDValue Froms[] = { SDValue(LD, 0),
400 SDValue(LD, 1),
401 SDValue(LD, 2)
402 };
403 const SDValue Tos[] = { SDValue(Result_2, 0),
404 SDValue(Result_3, 0),
405 SDValue(Result_1, 1)
406 };
407 ReplaceUses(Froms, Tos, 3);
408 return Result_2;
409 }
410 return SelectCode(LD);
411}
412
413
414SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
415 unsigned Opcode,
416 DebugLoc dl)
417{
418 SDValue Chain = LD->getChain();
419 EVT LoadedVT = LD->getMemoryVT();
420 SDValue Base = LD->getBasePtr();
421 SDValue Offset = LD->getOffset();
422 SDNode *OffsetNode = Offset.getNode();
423 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
424 SDValue N1 = LD->getOperand(1);
425 SDValue CPTmpN1_0;
426 SDValue CPTmpN1_1;
427 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
428 N1.getNode()->getValueType(0) == MVT::i32) {
429 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
430 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
431 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
432 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
433 MVT::i32, MVT::Other, Base,
434 TargetConstVal, Chain);
435 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
436 TargetConst0);
437 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
438 MVT::i64, MVT::Other,
439 SDValue(Result_2,0),
440 SDValue(Result_1,0));
441 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
442 MemOp[0] = LD->getMemOperand();
443 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
444 const SDValue Froms[] = { SDValue(LD, 0),
445 SDValue(LD, 1),
446 SDValue(LD, 2)
447 };
448 const SDValue Tos[] = { SDValue(Result_3, 0),
449 SDValue(Result_1, 1),
450 SDValue(Result_1, 2)
451 };
452 ReplaceUses(Froms, Tos, 3);
453 return Result_3;
454 }
455
456 // Generate an indirect load.
457 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
458 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
459 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
460 MVT::Other,
461 Base, TargetConst0, Chain);
462 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
463 TargetConst0);
464 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
465 MVT::i64, MVT::Other,
466 SDValue(Result_2,0),
467 SDValue(Result_1,0));
468 // Add offset to base.
469 SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
470 Base, TargetConstVal,
471 SDValue(Result_1, 1));
472 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
473 MemOp[0] = LD->getMemOperand();
474 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
475 const SDValue Froms[] = { SDValue(LD, 0),
476 SDValue(LD, 1),
477 SDValue(LD, 2)
478 };
479 const SDValue Tos[] = { SDValue(Result_3, 0), // Load value.
480 SDValue(Result_4, 0), // New address.
481 SDValue(Result_1, 1)
482 };
483 ReplaceUses(Froms, Tos, 3);
484 return Result_3;
485 }
486
487 return SelectCode(LD);
488}
489
490
491SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl) {
492 SDValue Chain = LD->getChain();
493 SDValue Base = LD->getBasePtr();
494 SDValue Offset = LD->getOffset();
495 SDNode *OffsetNode = Offset.getNode();
496 // Get the constant value.
497 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
498 EVT LoadedVT = LD->getMemoryVT();
499 unsigned Opcode = 0;
500
501 // Check for zero ext loads.
502 bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD);
503
504 // Figure out the opcode.
505 if (LoadedVT == MVT::i64) {
506 if (TII->isValidAutoIncImm(LoadedVT, Val))
507 Opcode = Hexagon::POST_LDrid;
508 else
509 Opcode = Hexagon::LDrid;
510 } else if (LoadedVT == MVT::i32) {
511 if (TII->isValidAutoIncImm(LoadedVT, Val))
512 Opcode = Hexagon::POST_LDriw;
513 else
514 Opcode = Hexagon::LDriw;
515 } else if (LoadedVT == MVT::i16) {
516 if (TII->isValidAutoIncImm(LoadedVT, Val))
517 Opcode = zextval ? Hexagon::POST_LDriuh : Hexagon::POST_LDrih;
518 else
519 Opcode = zextval ? Hexagon::LDriuh : Hexagon::LDrih;
520 } else if (LoadedVT == MVT::i8) {
521 if (TII->isValidAutoIncImm(LoadedVT, Val))
522 Opcode = zextval ? Hexagon::POST_LDriub : Hexagon::POST_LDrib;
523 else
524 Opcode = zextval ? Hexagon::LDriub : Hexagon::LDrib;
525 } else
Sirish Pande26f61a12012-05-03 21:52:53 +0000526 llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000527
528 // For zero ext i64 loads, we need to add combine instructions.
529 if (LD->getValueType(0) == MVT::i64 &&
530 LD->getExtensionType() == ISD::ZEXTLOAD) {
531 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl);
532 }
533 if (LD->getValueType(0) == MVT::i64 &&
534 LD->getExtensionType() == ISD::SEXTLOAD) {
535 // Handle sign ext i64 loads.
536 return SelectIndexedLoadSignExtend64(LD, Opcode, dl);
537 }
538 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
539 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
540 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
541 LD->getValueType(0),
542 MVT::i32, MVT::Other, Base,
543 TargetConstVal, Chain);
544 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
545 MemOp[0] = LD->getMemOperand();
546 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
547 const SDValue Froms[] = { SDValue(LD, 0),
548 SDValue(LD, 1),
549 SDValue(LD, 2)
550 };
551 const SDValue Tos[] = { SDValue(Result, 0),
552 SDValue(Result, 1),
553 SDValue(Result, 2)
554 };
555 ReplaceUses(Froms, Tos, 3);
556 return Result;
557 } else {
558 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
559 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
560 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl,
561 LD->getValueType(0),
562 MVT::Other, Base, TargetConst0,
563 Chain);
564 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
565 Base, TargetConstVal,
566 SDValue(Result_1, 1));
567 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
568 MemOp[0] = LD->getMemOperand();
569 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
570 const SDValue Froms[] = { SDValue(LD, 0),
571 SDValue(LD, 1),
572 SDValue(LD, 2)
573 };
574 const SDValue Tos[] = { SDValue(Result_1, 0),
575 SDValue(Result_2, 0),
576 SDValue(Result_1, 1)
577 };
578 ReplaceUses(Froms, Tos, 3);
579 return Result_1;
580 }
Tony Linthicumb4b54152011-12-12 21:14:40 +0000581}
582
583
584SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
585 SDNode *result;
586 DebugLoc dl = N->getDebugLoc();
587 LoadSDNode *LD = cast<LoadSDNode>(N);
588 ISD::MemIndexedMode AM = LD->getAddressingMode();
589
590 // Handle indexed loads.
591 if (AM != ISD::UNINDEXED) {
592 result = SelectIndexedLoad(LD, dl);
593 } else {
594 result = SelectBaseOffsetLoad(LD, dl);
595 }
596
597 return result;
598}
599
600
601SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) {
602 SDValue Chain = ST->getChain();
603 SDValue Base = ST->getBasePtr();
604 SDValue Offset = ST->getOffset();
605 SDValue Value = ST->getValue();
606 SDNode *OffsetNode = Offset.getNode();
607 // Get the constant value.
608 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
609 EVT StoredVT = ST->getMemoryVT();
610
611 // Offset value must be within representable range
612 // and must have correct alignment properties.
613 if (TII->isValidAutoIncImm(StoredVT, Val)) {
614 SDValue Ops[] = { Value, Base,
615 CurDAG->getTargetConstant(Val, MVT::i32), Chain};
616 unsigned Opcode = 0;
617
618 // Figure out the post inc version of opcode.
619 if (StoredVT == MVT::i64) Opcode = Hexagon::POST_STdri;
620 else if (StoredVT == MVT::i32) Opcode = Hexagon::POST_STwri;
621 else if (StoredVT == MVT::i16) Opcode = Hexagon::POST_SThri;
622 else if (StoredVT == MVT::i8) Opcode = Hexagon::POST_STbri;
Sirish Pande26f61a12012-05-03 21:52:53 +0000623 else llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000624
625 // Build post increment store.
626 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
627 MVT::Other, Ops, 4);
628 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
629 MemOp[0] = ST->getMemOperand();
630 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
631
632 ReplaceUses(ST, Result);
633 ReplaceUses(SDValue(ST,1), SDValue(Result,1));
634 return Result;
635 }
636
637 // Note: Order of operands matches the def of instruction:
638 // def STrid : STInst<(outs), (ins MEMri:$addr, DoubleRegs:$src1), ...
639 // and it differs for POST_ST* for instance.
640 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value,
641 Chain};
642 unsigned Opcode = 0;
643
644 // Figure out the opcode.
645 if (StoredVT == MVT::i64) Opcode = Hexagon::STrid;
Sirish Pande26f61a12012-05-03 21:52:53 +0000646 else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed;
Tony Linthicumb4b54152011-12-12 21:14:40 +0000647 else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih;
648 else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib;
Sirish Pande26f61a12012-05-03 21:52:53 +0000649 else llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000650
651 // Build regular store.
652 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
653 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops,
654 4);
655 // Build splitted incriment instruction.
656 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
657 Base,
658 TargetConstVal,
659 SDValue(Result_1, 0));
660 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
661 MemOp[0] = ST->getMemOperand();
662 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
663
664 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0));
665 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0));
666 return Result_2;
667}
668
669
670SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST,
671 DebugLoc dl) {
672 SDValue Chain = ST->getChain();
673 SDNode* Const32 = ST->getBasePtr().getNode();
674 SDValue Value = ST->getValue();
675 unsigned Opcode = 0;
676
677 // Try to lower stores of GlobalAdresses into indexed stores. Custom
678 // lowering for GlobalAddress nodes has already turned it into a
679 // CONST32. Avoid truncating stores for the moment. Post-inc stores
680 // do the same. Don't think there's a reason for it, so will file a
681 // bug to fix.
682 if ((Const32->getOpcode() == HexagonISD::CONST32) &&
683 !(Value.getValueType() == MVT::i64 && ST->isTruncatingStore())) {
684 SDValue Base = Const32->getOperand(0);
685 if (Base.getOpcode() == ISD::TargetGlobalAddress) {
686 EVT StoredVT = ST->getMemoryVT();
687 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
688 if (Offset != 0 && OffsetFitsS11(StoredVT, Offset)) {
689 MVT PointerTy = TLI.getPointerTy();
690 const GlobalValue* GV =
691 cast<GlobalAddressSDNode>(Base)->getGlobal();
692 SDValue TargAddr =
693 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0);
Brendon Cahoon6d532d82012-05-11 19:56:59 +0000694 SDNode* NewBase;
695 if (Subtarget.hasV4TOps())
696 NewBase = CurDAG->getMachineNode(Hexagon::TFRI_V4,
697 dl, PointerTy, TargAddr);
698 else
699 NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
700 dl, PointerTy, TargAddr);
Tony Linthicumb4b54152011-12-12 21:14:40 +0000701
702 // Figure out base + offset opcode
703 if (StoredVT == MVT::i64) Opcode = Hexagon::STrid_indexed;
704 else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed;
705 else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed;
706 else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed;
Sirish Pande26f61a12012-05-03 21:52:53 +0000707 else llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000708
709 SDValue Ops[] = {SDValue(NewBase,0),
710 CurDAG->getTargetConstant(Offset,PointerTy),
711 Value, Chain};
712 // build indexed store
713 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
714 MVT::Other, Ops, 4);
715 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
716 MemOp[0] = ST->getMemOperand();
717 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
718 ReplaceUses(ST, Result);
719 return Result;
720 }
721 }
722 }
723
724 return SelectCode(ST);
725}
726
727
728SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
729 DebugLoc dl = N->getDebugLoc();
730 StoreSDNode *ST = cast<StoreSDNode>(N);
731 ISD::MemIndexedMode AM = ST->getAddressingMode();
732
733 // Handle indexed stores.
734 if (AM != ISD::UNINDEXED) {
735 return SelectIndexedStore(ST, dl);
736 }
Sirish Pande71d56462012-05-03 16:18:50 +0000737
Tony Linthicumb4b54152011-12-12 21:14:40 +0000738 return SelectBaseOffsetStore(ST, dl);
739}
740
741SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
742 DebugLoc dl = N->getDebugLoc();
743
744 //
745 // %conv.i = sext i32 %tmp1 to i64
746 // %conv2.i = sext i32 %add to i64
747 // %mul.i = mul nsw i64 %conv2.i, %conv.i
748 //
749 // --- match with the following ---
750 //
751 // %mul.i = mpy (%tmp1, %add)
752 //
753
754 if (N->getValueType(0) == MVT::i64) {
755 // Shifting a i64 signed multiply.
756 SDValue MulOp0 = N->getOperand(0);
757 SDValue MulOp1 = N->getOperand(1);
758
759 SDValue OP0;
760 SDValue OP1;
761
762 // Handle sign_extend and sextload.
763 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
764 SDValue Sext0 = MulOp0.getOperand(0);
765 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Sirish Pande26f61a12012-05-03 21:52:53 +0000766 return SelectCode(N);
Tony Linthicumb4b54152011-12-12 21:14:40 +0000767 }
768
769 OP0 = Sext0;
770 } else if (MulOp0.getOpcode() == ISD::LOAD) {
771 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
772 if (LD->getMemoryVT() != MVT::i32 ||
773 LD->getExtensionType() != ISD::SEXTLOAD ||
774 LD->getAddressingMode() != ISD::UNINDEXED) {
Sirish Pande26f61a12012-05-03 21:52:53 +0000775 return SelectCode(N);
Tony Linthicumb4b54152011-12-12 21:14:40 +0000776 }
777
Tony Linthicumb4b54152011-12-12 21:14:40 +0000778 SDValue Chain = LD->getChain();
779 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
780 OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
781 MVT::Other,
782 LD->getBasePtr(), TargetConst0,
783 Chain), 0);
784 } else {
785 return SelectCode(N);
786 }
787
788 // Same goes for the second operand.
789 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
790 SDValue Sext1 = MulOp1.getOperand(0);
791 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
792 return SelectCode(N);
793 }
794
795 OP1 = Sext1;
796 } else if (MulOp1.getOpcode() == ISD::LOAD) {
797 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
798 if (LD->getMemoryVT() != MVT::i32 ||
799 LD->getExtensionType() != ISD::SEXTLOAD ||
800 LD->getAddressingMode() != ISD::UNINDEXED) {
801 return SelectCode(N);
802 }
803
Tony Linthicumb4b54152011-12-12 21:14:40 +0000804 SDValue Chain = LD->getChain();
805 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
806 OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
807 MVT::Other,
808 LD->getBasePtr(), TargetConst0,
809 Chain), 0);
810 } else {
811 return SelectCode(N);
812 }
813
814 // Generate a mpy instruction.
815 SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY64, dl, MVT::i64,
816 OP0, OP1);
817 ReplaceUses(N, Result);
818 return Result;
819 }
820
821 return SelectCode(N);
822}
823
824
825SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) {
826 DebugLoc dl = N->getDebugLoc();
827 SDValue N0 = N->getOperand(0);
828 if (N0.getOpcode() == ISD::SETCC) {
829 SDValue N00 = N0.getOperand(0);
830 if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) {
831 SDValue N000 = N00.getOperand(0);
832 SDValue N001 = N00.getOperand(1);
833 if (cast<VTSDNode>(N001)->getVT() == MVT::i16) {
834 SDValue N01 = N0.getOperand(1);
835 SDValue N02 = N0.getOperand(2);
836
837 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
838 // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1,
839 // IntRegs:i32:$src2)
840 // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
841 // Pattern complexity = 9 cost = 1 size = 0.
842 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) {
843 SDValue N1 = N->getOperand(1);
844 if (N01 == N1) {
845 SDValue N2 = N->getOperand(2);
846 if (N000 == N2 &&
847 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
848 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
849 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl,
850 MVT::i32, N000);
851 SDNode *Result = CurDAG->getMachineNode(Hexagon::MAXw_rr, dl,
852 MVT::i32,
853 SDValue(SextNode, 0),
854 N1);
855 ReplaceUses(N, Result);
856 return Result;
857 }
858 }
859 }
860
861 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
862 // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1,
863 // IntRegs:i32:$src2)
864 // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
865 // Pattern complexity = 9 cost = 1 size = 0.
866 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) {
867 SDValue N1 = N->getOperand(1);
868 if (N01 == N1) {
869 SDValue N2 = N->getOperand(2);
870 if (N000 == N2 &&
871 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
872 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
873 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl,
874 MVT::i32, N000);
875 SDNode *Result = CurDAG->getMachineNode(Hexagon::MINw_rr, dl,
876 MVT::i32,
877 SDValue(SextNode, 0),
878 N1);
879 ReplaceUses(N, Result);
880 return Result;
881 }
882 }
883 }
884 }
885 }
886 }
887
888 return SelectCode(N);
889}
890
891
892SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) {
893 DebugLoc dl = N->getDebugLoc();
894 SDValue Shift = N->getOperand(0);
895
896 //
897 // %conv.i = sext i32 %tmp1 to i64
898 // %conv2.i = sext i32 %add to i64
899 // %mul.i = mul nsw i64 %conv2.i, %conv.i
900 // %shr5.i = lshr i64 %mul.i, 32
901 // %conv3.i = trunc i64 %shr5.i to i32
902 //
903 // --- match with the following ---
904 //
905 // %conv3.i = mpy (%tmp1, %add)
906 //
907 // Trunc to i32.
908 if (N->getValueType(0) == MVT::i32) {
909 // Trunc from i64.
910 if (Shift.getNode()->getValueType(0) == MVT::i64) {
911 // Trunc child is logical shift right.
912 if (Shift.getOpcode() != ISD::SRL) {
913 return SelectCode(N);
914 }
915
916 SDValue ShiftOp0 = Shift.getOperand(0);
917 SDValue ShiftOp1 = Shift.getOperand(1);
918
919 // Shift by const 32
920 if (ShiftOp1.getOpcode() != ISD::Constant) {
921 return SelectCode(N);
922 }
923
924 int32_t ShiftConst =
925 cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue();
926 if (ShiftConst != 32) {
927 return SelectCode(N);
928 }
929
930 // Shifting a i64 signed multiply
931 SDValue Mul = ShiftOp0;
932 if (Mul.getOpcode() != ISD::MUL) {
933 return SelectCode(N);
934 }
935
936 SDValue MulOp0 = Mul.getOperand(0);
937 SDValue MulOp1 = Mul.getOperand(1);
938
939 SDValue OP0;
940 SDValue OP1;
941
942 // Handle sign_extend and sextload
943 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
944 SDValue Sext0 = MulOp0.getOperand(0);
945 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
946 return SelectCode(N);
947 }
948
949 OP0 = Sext0;
950 } else if (MulOp0.getOpcode() == ISD::LOAD) {
951 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
952 if (LD->getMemoryVT() != MVT::i32 ||
953 LD->getExtensionType() != ISD::SEXTLOAD ||
954 LD->getAddressingMode() != ISD::UNINDEXED) {
955 return SelectCode(N);
956 }
957
Tony Linthicumb4b54152011-12-12 21:14:40 +0000958 SDValue Chain = LD->getChain();
959 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
960 OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
961 MVT::Other,
962 LD->getBasePtr(),
963 TargetConst0, Chain), 0);
964 } else {
965 return SelectCode(N);
966 }
967
968 // Same goes for the second operand.
969 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
970 SDValue Sext1 = MulOp1.getOperand(0);
971 if (Sext1.getNode()->getValueType(0) != MVT::i32)
972 return SelectCode(N);
973
974 OP1 = Sext1;
975 } else if (MulOp1.getOpcode() == ISD::LOAD) {
976 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
977 if (LD->getMemoryVT() != MVT::i32 ||
978 LD->getExtensionType() != ISD::SEXTLOAD ||
979 LD->getAddressingMode() != ISD::UNINDEXED) {
980 return SelectCode(N);
981 }
982
Tony Linthicumb4b54152011-12-12 21:14:40 +0000983 SDValue Chain = LD->getChain();
984 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
985 OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
986 MVT::Other,
987 LD->getBasePtr(),
988 TargetConst0, Chain), 0);
989 } else {
990 return SelectCode(N);
991 }
992
993 // Generate a mpy instruction.
994 SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY, dl, MVT::i32,
995 OP0, OP1);
996 ReplaceUses(N, Result);
997 return Result;
998 }
999 }
1000
1001 return SelectCode(N);
1002}
1003
1004
1005SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
1006 DebugLoc dl = N->getDebugLoc();
1007 if (N->getValueType(0) == MVT::i32) {
1008 SDValue Shl_0 = N->getOperand(0);
1009 SDValue Shl_1 = N->getOperand(1);
1010 // RHS is const.
1011 if (Shl_1.getOpcode() == ISD::Constant) {
1012 if (Shl_0.getOpcode() == ISD::MUL) {
1013 SDValue Mul_0 = Shl_0.getOperand(0); // Val
1014 SDValue Mul_1 = Shl_0.getOperand(1); // Const
1015 // RHS of mul is const.
1016 if (Mul_1.getOpcode() == ISD::Constant) {
1017 int32_t ShlConst =
1018 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1019 int32_t MulConst =
1020 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
1021 int32_t ValConst = MulConst << ShlConst;
1022 SDValue Val = CurDAG->getTargetConstant(ValConst,
1023 MVT::i32);
1024 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
1025 if (isInt<9>(CN->getSExtValue())) {
1026 SDNode* Result =
1027 CurDAG->getMachineNode(Hexagon::MPYI_ri, dl,
1028 MVT::i32, Mul_0, Val);
1029 ReplaceUses(N, Result);
1030 return Result;
1031 }
1032
1033 }
1034 } else if (Shl_0.getOpcode() == ISD::SUB) {
1035 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
1036 SDValue Sub_1 = Shl_0.getOperand(1); // Val
1037 if (Sub_0.getOpcode() == ISD::Constant) {
1038 int32_t SubConst =
1039 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
1040 if (SubConst == 0) {
1041 if (Sub_1.getOpcode() == ISD::SHL) {
1042 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
1043 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
1044 if (Shl2_1.getOpcode() == ISD::Constant) {
1045 int32_t ShlConst =
1046 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1047 int32_t Shl2Const =
1048 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
1049 int32_t ValConst = 1 << (ShlConst+Shl2Const);
1050 SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32);
1051 if (ConstantSDNode *CN =
1052 dyn_cast<ConstantSDNode>(Val.getNode()))
1053 if (isInt<9>(CN->getSExtValue())) {
1054 SDNode* Result =
1055 CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, MVT::i32,
1056 Shl2_0, Val);
1057 ReplaceUses(N, Result);
1058 return Result;
1059 }
1060 }
1061 }
1062 }
1063 }
1064 }
1065 }
1066 }
1067 return SelectCode(N);
1068}
1069
1070
1071//
1072// If there is an zero_extend followed an intrinsic in DAG (this means - the
1073// result of the intrinsic is predicate); convert the zero_extend to
1074// transfer instruction.
1075//
1076// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
1077// converted into a MUX as predicate registers defined as 1 bit in the
1078// compiler. Architecture defines them as 8-bit registers.
1079// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
1080//
1081SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
1082 DebugLoc dl = N->getDebugLoc();
1083 SDNode *IsIntrinsic = N->getOperand(0).getNode();
1084 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
1085 unsigned ID =
1086 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
1087 if (doesIntrinsicReturnPredicate(ID)) {
1088 // Now we need to differentiate target data types.
1089 if (N->getValueType(0) == MVT::i64) {
1090 // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs).
1091 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
1092 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl,
1093 MVT::i32,
1094 SDValue(IsIntrinsic, 0));
1095 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl,
1096 MVT::i32,
1097 TargetConst0);
1098 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
1099 MVT::i64, MVT::Other,
1100 SDValue(Result_2, 0),
1101 SDValue(Result_1, 0));
1102 ReplaceUses(N, Result_3);
1103 return Result_3;
1104 }
1105 if (N->getValueType(0) == MVT::i32) {
1106 // Convert the zero_extend to Rs = Pd
1107 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl,
1108 MVT::i32,
1109 SDValue(IsIntrinsic, 0));
1110 ReplaceUses(N, RsPd);
1111 return RsPd;
1112 }
Craig Topperbc219812012-02-07 02:50:20 +00001113 llvm_unreachable("Unexpected value type");
Tony Linthicumb4b54152011-12-12 21:14:40 +00001114 }
1115 }
1116 return SelectCode(N);
1117}
1118
1119
1120//
1121// Checking for intrinsics which have predicate registers as operand(s)
1122// and lowering to the actual intrinsic.
1123//
1124SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
1125 DebugLoc dl = N->getDebugLoc();
1126 unsigned ID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
1127 unsigned IntrinsicWithPred = doesIntrinsicContainPredicate(ID);
1128
1129 // We are concerned with only those intrinsics that have predicate registers
1130 // as at least one of the operands.
1131 if (IntrinsicWithPred) {
1132 SmallVector<SDValue, 8> Ops;
1133 const MCInstrDesc &MCID = TII->get(IntrinsicWithPred);
1134 const TargetRegisterInfo *TRI = TM.getRegisterInfo();
1135
1136 // Iterate over all the operands of the intrinsics.
1137 // For PredRegs, do the transfer.
1138 // For Double/Int Regs, just preserve the value
1139 // For immediates, lower it.
1140 for (unsigned i = 1; i < N->getNumOperands(); ++i) {
1141 SDNode *Arg = N->getOperand(i).getNode();
Jakob Stoklund Olesen397fc482012-05-07 22:10:26 +00001142 const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI, *MF);
Tony Linthicumb4b54152011-12-12 21:14:40 +00001143
Craig Topper420761a2012-04-20 07:30:17 +00001144 if (RC == &Hexagon::IntRegsRegClass ||
1145 RC == &Hexagon::DoubleRegsRegClass) {
Tony Linthicumb4b54152011-12-12 21:14:40 +00001146 Ops.push_back(SDValue(Arg, 0));
Craig Topper420761a2012-04-20 07:30:17 +00001147 } else if (RC == &Hexagon::PredRegsRegClass) {
Tony Linthicumb4b54152011-12-12 21:14:40 +00001148 // Do the transfer.
1149 SDNode *PdRs = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1,
1150 SDValue(Arg, 0));
1151 Ops.push_back(SDValue(PdRs,0));
1152 } else if (RC == NULL && (dyn_cast<ConstantSDNode>(Arg) != NULL)) {
1153 // This is immediate operand. Lower it here making sure that we DO have
1154 // const SDNode for immediate value.
1155 int32_t Val = cast<ConstantSDNode>(Arg)->getSExtValue();
1156 SDValue SDVal = CurDAG->getTargetConstant(Val, MVT::i32);
1157 Ops.push_back(SDVal);
1158 } else {
Craig Topperbc219812012-02-07 02:50:20 +00001159 llvm_unreachable("Unimplemented");
Tony Linthicumb4b54152011-12-12 21:14:40 +00001160 }
1161 }
1162 EVT ReturnValueVT = N->getValueType(0);
1163 SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl,
1164 ReturnValueVT,
1165 Ops.data(), Ops.size());
1166 ReplaceUses(N, Result);
1167 return Result;
1168 }
1169 return SelectCode(N);
1170}
1171
Sirish Pande7517bbc2012-05-10 20:20:25 +00001172//
1173// Map floating point constant values.
1174//
1175SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
1176 DebugLoc dl = N->getDebugLoc();
1177 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
1178 APFloat APF = CN->getValueAPF();
1179 if (N->getValueType(0) == MVT::f32) {
1180 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
1181 CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32));
1182 }
1183 else if (N->getValueType(0) == MVT::f64) {
1184 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
1185 CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64));
1186 }
1187
1188 return SelectCode(N);
1189}
1190
Tony Linthicumb4b54152011-12-12 21:14:40 +00001191
1192//
1193// Map predicate true (encoded as -1 in LLVM) to a XOR.
1194//
1195SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
1196 DebugLoc dl = N->getDebugLoc();
1197 if (N->getValueType(0) == MVT::i1) {
1198 SDNode* Result;
1199 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
1200 if (Val == -1) {
Tony Linthicumb4b54152011-12-12 21:14:40 +00001201 // Create the IntReg = 1 node.
1202 SDNode* IntRegTFR =
1203 CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
1204 CurDAG->getTargetConstant(0, MVT::i32));
1205
1206 // Pd = IntReg
1207 SDNode* Pd = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1,
1208 SDValue(IntRegTFR, 0));
1209
1210 // not(Pd)
Sirish Pandeab7955b2012-02-15 18:52:27 +00001211 SDNode* NotPd = CurDAG->getMachineNode(Hexagon::NOT_p, dl, MVT::i1,
Tony Linthicumb4b54152011-12-12 21:14:40 +00001212 SDValue(Pd, 0));
1213
1214 // xor(not(Pd))
1215 Result = CurDAG->getMachineNode(Hexagon::XOR_pp, dl, MVT::i1,
1216 SDValue(Pd, 0), SDValue(NotPd, 0));
1217
1218 // We have just built:
1219 // Rs = Pd
1220 // Pd = xor(not(Pd), Pd)
1221
1222 ReplaceUses(N, Result);
1223 return Result;
1224 }
1225 }
1226
1227 return SelectCode(N);
1228}
1229
1230
1231//
1232// Map add followed by a asr -> asr +=.
1233//
1234SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
1235 DebugLoc dl = N->getDebugLoc();
1236 if (N->getValueType(0) != MVT::i32) {
1237 return SelectCode(N);
1238 }
1239 // Identify nodes of the form: add(asr(...)).
1240 SDNode* Src1 = N->getOperand(0).getNode();
1241 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1242 || Src1->getValueType(0) != MVT::i32) {
1243 return SelectCode(N);
1244 }
1245
1246 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1247 // Rd and Rd' are assigned to the same register
Sirish Pande71d56462012-05-03 16:18:50 +00001248 SDNode* Result = CurDAG->getMachineNode(Hexagon::ASR_ADD_rr, dl, MVT::i32,
Tony Linthicumb4b54152011-12-12 21:14:40 +00001249 N->getOperand(1),
1250 Src1->getOperand(0),
1251 Src1->getOperand(1));
1252 ReplaceUses(N, Result);
1253
1254 return Result;
1255}
1256
1257
1258SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
1259 if (N->isMachineOpcode())
1260 return NULL; // Already selected.
1261
1262
1263 switch (N->getOpcode()) {
1264 case ISD::Constant:
1265 return SelectConstant(N);
1266
Sirish Pande7517bbc2012-05-10 20:20:25 +00001267 case ISD::ConstantFP:
1268 return SelectConstantFP(N);
1269
Tony Linthicumb4b54152011-12-12 21:14:40 +00001270 case ISD::ADD:
1271 return SelectAdd(N);
1272
1273 case ISD::SHL:
1274 return SelectSHL(N);
1275
1276 case ISD::LOAD:
1277 return SelectLoad(N);
1278
1279 case ISD::STORE:
1280 return SelectStore(N);
1281
1282 case ISD::SELECT:
1283 return SelectSelect(N);
1284
1285 case ISD::TRUNCATE:
1286 return SelectTruncate(N);
1287
1288 case ISD::MUL:
1289 return SelectMul(N);
1290
1291 case ISD::ZERO_EXTEND:
1292 return SelectZeroExtend(N);
1293
1294 case ISD::INTRINSIC_WO_CHAIN:
1295 return SelectIntrinsicWOChain(N);
1296 }
1297
1298 return SelectCode(N);
1299}
1300
1301
1302//
1303// Hexagon_TODO: Five functions for ADDRri?! Surely there must be a better way
1304// to define these instructions.
1305//
1306bool HexagonDAGToDAGISel::SelectADDRri(SDValue& Addr, SDValue &Base,
1307 SDValue &Offset) {
1308 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1309 Addr.getOpcode() == ISD::TargetGlobalAddress)
1310 return false; // Direct calls.
1311
1312 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1313 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1314 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1315 return true;
1316 }
1317 Base = Addr;
1318 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1319 return true;
1320}
1321
1322
1323bool HexagonDAGToDAGISel::SelectADDRriS11_0(SDValue& Addr, SDValue &Base,
1324 SDValue &Offset) {
1325 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1326 Addr.getOpcode() == ISD::TargetGlobalAddress)
1327 return false; // Direct calls.
1328
1329 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1330 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1331 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1332 return (IsS11_0_Offset(Offset.getNode()));
1333 }
1334 Base = Addr;
1335 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1336 return (IsS11_0_Offset(Offset.getNode()));
1337}
1338
1339
1340bool HexagonDAGToDAGISel::SelectADDRriS11_1(SDValue& Addr, SDValue &Base,
1341 SDValue &Offset) {
1342 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1343 Addr.getOpcode() == ISD::TargetGlobalAddress)
1344 return false; // Direct calls.
1345
1346 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1347 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1348 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1349 return (IsS11_1_Offset(Offset.getNode()));
1350 }
1351 Base = Addr;
1352 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1353 return (IsS11_1_Offset(Offset.getNode()));
1354}
1355
1356
1357bool HexagonDAGToDAGISel::SelectADDRriS11_2(SDValue& Addr, SDValue &Base,
1358 SDValue &Offset) {
1359 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1360 Addr.getOpcode() == ISD::TargetGlobalAddress)
1361 return false; // Direct calls.
1362
1363 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1364 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1365 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1366 return (IsS11_2_Offset(Offset.getNode()));
1367 }
1368 Base = Addr;
1369 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1370 return (IsS11_2_Offset(Offset.getNode()));
1371}
1372
1373
1374bool HexagonDAGToDAGISel::SelectADDRriU6_0(SDValue& Addr, SDValue &Base,
1375 SDValue &Offset) {
1376 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1377 Addr.getOpcode() == ISD::TargetGlobalAddress)
1378 return false; // Direct calls.
1379
1380 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1381 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1382 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1383 return (IsU6_0_Offset(Offset.getNode()));
1384 }
1385 Base = Addr;
1386 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1387 return (IsU6_0_Offset(Offset.getNode()));
1388}
1389
1390
1391bool HexagonDAGToDAGISel::SelectADDRriU6_1(SDValue& Addr, SDValue &Base,
1392 SDValue &Offset) {
1393 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1394 Addr.getOpcode() == ISD::TargetGlobalAddress)
1395 return false; // Direct calls.
1396
1397 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1398 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1399 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1400 return (IsU6_1_Offset(Offset.getNode()));
1401 }
1402 Base = Addr;
1403 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1404 return (IsU6_1_Offset(Offset.getNode()));
1405}
1406
1407
1408bool HexagonDAGToDAGISel::SelectADDRriU6_2(SDValue& Addr, SDValue &Base,
1409 SDValue &Offset) {
1410 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1411 Addr.getOpcode() == ISD::TargetGlobalAddress)
1412 return false; // Direct calls.
1413
1414 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1415 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1416 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1417 return (IsU6_2_Offset(Offset.getNode()));
1418 }
1419 Base = Addr;
1420 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1421 return (IsU6_2_Offset(Offset.getNode()));
1422}
1423
1424
1425bool HexagonDAGToDAGISel::SelectMEMriS11_2(SDValue& Addr, SDValue &Base,
1426 SDValue &Offset) {
1427
1428 if (Addr.getOpcode() != ISD::ADD) {
1429 return(SelectADDRriS11_2(Addr, Base, Offset));
1430 }
1431
1432 return SelectADDRriS11_2(Addr, Base, Offset);
1433}
1434
1435
1436bool HexagonDAGToDAGISel::SelectADDRriS11_3(SDValue& Addr, SDValue &Base,
1437 SDValue &Offset) {
1438 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1439 Addr.getOpcode() == ISD::TargetGlobalAddress)
1440 return false; // Direct calls.
1441
1442 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1443 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1444 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1445 return (IsS11_3_Offset(Offset.getNode()));
1446 }
1447 Base = Addr;
1448 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1449 return (IsS11_3_Offset(Offset.getNode()));
1450}
1451
1452bool HexagonDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1,
1453 SDValue &R2) {
1454 if (Addr.getOpcode() == ISD::FrameIndex) return false;
1455 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1456 Addr.getOpcode() == ISD::TargetGlobalAddress)
1457 return false; // Direct calls.
1458
1459 if (Addr.getOpcode() == ISD::ADD) {
1460 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
1461 if (isInt<13>(CN->getSExtValue()))
1462 return false; // Let the reg+imm pattern catch this!
1463 R1 = Addr.getOperand(0);
1464 R2 = Addr.getOperand(1);
1465 return true;
1466 }
1467
1468 R1 = Addr;
1469
1470 return true;
1471}
1472
1473
1474// Handle generic address case. It is accessed from inlined asm =m constraints,
1475// which could have any kind of pointer.
1476bool HexagonDAGToDAGISel::SelectAddr(SDNode *Op, SDValue Addr,
1477 SDValue &Base, SDValue &Offset) {
1478 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1479 Addr.getOpcode() == ISD::TargetGlobalAddress)
1480 return false; // Direct calls.
1481
1482 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1483 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1484 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1485 return true;
1486 }
1487
1488 if (Addr.getOpcode() == ISD::ADD) {
1489 Base = Addr.getOperand(0);
1490 Offset = Addr.getOperand(1);
1491 return true;
1492 }
1493
1494 Base = Addr;
1495 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1496 return true;
1497}
1498
1499
1500bool HexagonDAGToDAGISel::
1501SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
1502 std::vector<SDValue> &OutOps) {
1503 SDValue Op0, Op1;
1504
1505 switch (ConstraintCode) {
1506 case 'o': // Offsetable.
1507 case 'v': // Not offsetable.
1508 default: return true;
1509 case 'm': // Memory.
1510 if (!SelectAddr(Op.getNode(), Op, Op0, Op1))
1511 return true;
1512 break;
1513 }
1514
1515 OutOps.push_back(Op0);
1516 OutOps.push_back(Op1);
1517 return false;
1518}
Brendon Cahoon6d532d82012-05-11 19:56:59 +00001519
1520bool HexagonDAGToDAGISel::isConstExtProfitable(SDNode *N) const {
1521 unsigned UseCount = 0;
1522 for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
1523 UseCount++;
1524 }
1525
1526 return (UseCount <= 1);
1527
1528}