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