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