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