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