blob: 381032b8e9506610bfc1c11407473f52776801ce [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"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000015#include "Hexagon.h"
Tony Linthicumb4b54152011-12-12 21:14:40 +000016#include "HexagonISelLowering.h"
17#include "HexagonTargetMachine.h"
Tony Linthicumb4b54152011-12-12 21:14:40 +000018#include "llvm/CodeGen/SelectionDAGISel.h"
Chandler Carruth0b8c9a82013-01-02 11:36:10 +000019#include "llvm/IR/Intrinsics.h"
Tony Linthicumb4b54152011-12-12 21:14:40 +000020#include "llvm/Support/Compiler.h"
21#include "llvm/Support/Debug.h"
22
23using namespace llvm;
24
25
26//===----------------------------------------------------------------------===//
27// Instruction Selector Implementation
28//===----------------------------------------------------------------------===//
29
30//===--------------------------------------------------------------------===//
31/// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine
32/// instructions for SelectionDAG operations.
33///
34namespace {
35class HexagonDAGToDAGISel : public SelectionDAGISel {
36 /// Subtarget - Keep a pointer to the Hexagon Subtarget around so that we can
37 /// make the right decision when generating code for different targets.
38 const HexagonSubtarget &Subtarget;
39
40 // Keep a reference to HexagonTargetMachine.
41 HexagonTargetMachine& TM;
42 const HexagonInstrInfo *TII;
43
44public:
45 explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine)
46 : SelectionDAGISel(targetmachine),
47 Subtarget(targetmachine.getSubtarget<HexagonSubtarget>()),
48 TM(targetmachine),
49 TII(static_cast<const HexagonInstrInfo*>(TM.getInstrInfo())) {
50
51 }
52
53 SDNode *Select(SDNode *N);
54
55 // Complex Pattern Selectors.
56 bool SelectADDRri(SDValue& N, SDValue &R1, SDValue &R2);
57 bool SelectADDRriS11_0(SDValue& N, SDValue &R1, SDValue &R2);
58 bool SelectADDRriS11_1(SDValue& N, SDValue &R1, SDValue &R2);
59 bool SelectADDRriS11_2(SDValue& N, SDValue &R1, SDValue &R2);
60 bool SelectMEMriS11_2(SDValue& Addr, SDValue &Base, SDValue &Offset);
61 bool SelectADDRriS11_3(SDValue& N, SDValue &R1, SDValue &R2);
62 bool SelectADDRrr(SDValue &Addr, SDValue &Base, SDValue &Offset);
63 bool SelectADDRriU6_0(SDValue& N, SDValue &R1, SDValue &R2);
64 bool SelectADDRriU6_1(SDValue& N, SDValue &R1, SDValue &R2);
65 bool SelectADDRriU6_2(SDValue& N, SDValue &R1, SDValue &R2);
66
67 virtual const char *getPassName() const {
68 return "Hexagon DAG->DAG Pattern Instruction Selection";
69 }
70
71 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
72 /// inline asm expressions.
73 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
74 char ConstraintCode,
75 std::vector<SDValue> &OutOps);
76 bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset);
77
78 SDNode *SelectLoad(SDNode *N);
79 SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl);
80 SDNode *SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl);
81 SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode,
82 DebugLoc dl);
83 SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode,
84 DebugLoc dl);
85 SDNode *SelectBaseOffsetStore(StoreSDNode *ST, DebugLoc dl);
86 SDNode *SelectIndexedStore(StoreSDNode *ST, DebugLoc dl);
87 SDNode *SelectStore(SDNode *N);
88 SDNode *SelectSHL(SDNode *N);
89 SDNode *SelectSelect(SDNode *N);
90 SDNode *SelectTruncate(SDNode *N);
91 SDNode *SelectMul(SDNode *N);
92 SDNode *SelectZeroExtend(SDNode *N);
93 SDNode *SelectIntrinsicWOChain(SDNode *N);
Sirish Pande7517bbc2012-05-10 20:20:25 +000094 SDNode *SelectIntrinsicWChain(SDNode *N);
Tony Linthicumb4b54152011-12-12 21:14:40 +000095 SDNode *SelectConstant(SDNode *N);
Sirish Pande7517bbc2012-05-10 20:20:25 +000096 SDNode *SelectConstantFP(SDNode *N);
Tony Linthicumb4b54152011-12-12 21:14:40 +000097 SDNode *SelectAdd(SDNode *N);
Jyotsna Verma61c654c2012-11-28 20:58:14 +000098 bool isConstExtProfitable(SDNode *N) const;
Tony Linthicumb4b54152011-12-12 21:14:40 +000099
100 // Include the pieces autogenerated from the target description.
101#include "HexagonGenDAGISel.inc"
102};
103} // end anonymous namespace
104
105
106/// createHexagonISelDag - This pass converts a legalized DAG into a
107/// Hexagon-specific DAG, ready for instruction scheduling.
108///
109FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM) {
110 return new HexagonDAGToDAGISel(TM);
111}
112
113static bool IsS11_0_Offset(SDNode * S) {
114 ConstantSDNode *N = cast<ConstantSDNode>(S);
115
116 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
117 // field.
118 int64_t v = (int64_t)N->getSExtValue();
119 return isInt<11>(v);
120}
121
122
123static bool IsS11_1_Offset(SDNode * S) {
124 ConstantSDNode *N = cast<ConstantSDNode>(S);
125
126 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
127 // field.
128 int64_t v = (int64_t)N->getSExtValue();
129 return isShiftedInt<11,1>(v);
130}
131
132
133static bool IsS11_2_Offset(SDNode * S) {
134 ConstantSDNode *N = cast<ConstantSDNode>(S);
135
136 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
137 // field.
138 int64_t v = (int64_t)N->getSExtValue();
139 return isShiftedInt<11,2>(v);
140}
141
142
143static bool IsS11_3_Offset(SDNode * S) {
144 ConstantSDNode *N = cast<ConstantSDNode>(S);
145
146 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
147 // field.
148 int64_t v = (int64_t)N->getSExtValue();
149 return isShiftedInt<11,3>(v);
150}
151
152
153static bool IsU6_0_Offset(SDNode * S) {
154 ConstantSDNode *N = cast<ConstantSDNode>(S);
155
156 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
157 // field.
158 int64_t v = (int64_t)N->getSExtValue();
159 return isUInt<6>(v);
160}
161
162
163static bool IsU6_1_Offset(SDNode * S) {
164 ConstantSDNode *N = cast<ConstantSDNode>(S);
165
166 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
167 // field.
168 int64_t v = (int64_t)N->getSExtValue();
169 return isShiftedUInt<6,1>(v);
170}
171
172
173static bool IsU6_2_Offset(SDNode * S) {
174 ConstantSDNode *N = cast<ConstantSDNode>(S);
175
176 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
177 // field.
178 int64_t v = (int64_t)N->getSExtValue();
179 return isShiftedUInt<6,2>(v);
180}
181
182
183// Intrinsics that return a a predicate.
184static unsigned doesIntrinsicReturnPredicate(unsigned ID)
185{
186 switch (ID) {
187 default:
188 return 0;
189 case Intrinsic::hexagon_C2_cmpeq:
190 case Intrinsic::hexagon_C2_cmpgt:
191 case Intrinsic::hexagon_C2_cmpgtu:
192 case Intrinsic::hexagon_C2_cmpgtup:
193 case Intrinsic::hexagon_C2_cmpgtp:
194 case Intrinsic::hexagon_C2_cmpeqp:
195 case Intrinsic::hexagon_C2_bitsset:
196 case Intrinsic::hexagon_C2_bitsclr:
197 case Intrinsic::hexagon_C2_cmpeqi:
198 case Intrinsic::hexagon_C2_cmpgti:
199 case Intrinsic::hexagon_C2_cmpgtui:
200 case Intrinsic::hexagon_C2_cmpgei:
201 case Intrinsic::hexagon_C2_cmpgeui:
202 case Intrinsic::hexagon_C2_cmplt:
203 case Intrinsic::hexagon_C2_cmpltu:
204 case Intrinsic::hexagon_C2_bitsclri:
205 case Intrinsic::hexagon_C2_and:
206 case Intrinsic::hexagon_C2_or:
207 case Intrinsic::hexagon_C2_xor:
208 case Intrinsic::hexagon_C2_andn:
209 case Intrinsic::hexagon_C2_not:
210 case Intrinsic::hexagon_C2_orn:
211 case Intrinsic::hexagon_C2_pxfer_map:
212 case Intrinsic::hexagon_C2_any8:
213 case Intrinsic::hexagon_C2_all8:
214 case Intrinsic::hexagon_A2_vcmpbeq:
215 case Intrinsic::hexagon_A2_vcmpbgtu:
216 case Intrinsic::hexagon_A2_vcmpheq:
217 case Intrinsic::hexagon_A2_vcmphgt:
218 case Intrinsic::hexagon_A2_vcmphgtu:
219 case Intrinsic::hexagon_A2_vcmpweq:
220 case Intrinsic::hexagon_A2_vcmpwgt:
221 case Intrinsic::hexagon_A2_vcmpwgtu:
222 case Intrinsic::hexagon_C2_tfrrp:
223 case Intrinsic::hexagon_S2_tstbit_i:
224 case Intrinsic::hexagon_S2_tstbit_r:
225 return 1;
226 }
227}
228
229
230// Intrinsics that have predicate operands.
231static unsigned doesIntrinsicContainPredicate(unsigned ID)
232{
233 switch (ID) {
234 default:
235 return 0;
236 case Intrinsic::hexagon_C2_tfrpr:
237 return Hexagon::TFR_RsPd;
238 case Intrinsic::hexagon_C2_and:
239 return Hexagon::AND_pp;
240 case Intrinsic::hexagon_C2_xor:
241 return Hexagon::XOR_pp;
242 case Intrinsic::hexagon_C2_or:
243 return Hexagon::OR_pp;
244 case Intrinsic::hexagon_C2_not:
Sirish Pandeab7955b2012-02-15 18:52:27 +0000245 return Hexagon::NOT_p;
Tony Linthicumb4b54152011-12-12 21:14:40 +0000246 case Intrinsic::hexagon_C2_any8:
247 return Hexagon::ANY_pp;
248 case Intrinsic::hexagon_C2_all8:
249 return Hexagon::ALL_pp;
250 case Intrinsic::hexagon_C2_vitpack:
251 return Hexagon::VITPACK_pp;
252 case Intrinsic::hexagon_C2_mask:
253 return Hexagon::MASK_p;
254 case Intrinsic::hexagon_C2_mux:
255 return Hexagon::MUX_rr;
256
257 // Mapping hexagon_C2_muxir to MUX_pri. This is pretty weird - but
258 // that's how it's mapped in q6protos.h.
259 case Intrinsic::hexagon_C2_muxir:
260 return Hexagon::MUX_ri;
261
262 // Mapping hexagon_C2_muxri to MUX_pir. This is pretty weird - but
263 // that's how it's mapped in q6protos.h.
264 case Intrinsic::hexagon_C2_muxri:
265 return Hexagon::MUX_ir;
266
267 case Intrinsic::hexagon_C2_muxii:
268 return Hexagon::MUX_ii;
269 case Intrinsic::hexagon_C2_vmux:
270 return Hexagon::VMUX_prr64;
271 case Intrinsic::hexagon_S2_valignrb:
272 return Hexagon::VALIGN_rrp;
273 case Intrinsic::hexagon_S2_vsplicerb:
274 return Hexagon::VSPLICE_rrp;
275 }
276}
277
278
279static bool OffsetFitsS11(EVT MemType, int64_t Offset) {
280 if (MemType == MVT::i64 && isShiftedInt<11,3>(Offset)) {
281 return true;
282 }
283 if (MemType == MVT::i32 && isShiftedInt<11,2>(Offset)) {
284 return true;
285 }
286 if (MemType == MVT::i16 && isShiftedInt<11,1>(Offset)) {
287 return true;
288 }
289 if (MemType == MVT::i8 && isInt<11>(Offset)) {
290 return true;
291 }
292 return false;
293}
294
295
296//
297// Try to lower loads of GlobalAdresses into base+offset loads. Custom
298// lowering for GlobalAddress nodes has already turned it into a
299// CONST32.
300//
301SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl) {
Tony Linthicumb4b54152011-12-12 21:14:40 +0000302 SDValue Chain = LD->getChain();
303 SDNode* Const32 = LD->getBasePtr().getNode();
304 unsigned Opcode = 0;
305
306 if (Const32->getOpcode() == HexagonISD::CONST32 &&
307 ISD::isNormalLoad(LD)) {
308 SDValue Base = Const32->getOperand(0);
309 EVT LoadedVT = LD->getMemoryVT();
310 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
311 if (Offset != 0 && OffsetFitsS11(LoadedVT, Offset)) {
312 MVT PointerTy = TLI.getPointerTy();
313 const GlobalValue* GV =
314 cast<GlobalAddressSDNode>(Base)->getGlobal();
315 SDValue TargAddr =
316 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0);
Brendon Cahoon5262abb2012-05-14 19:35:42 +0000317 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
318 dl, PointerTy,
319 TargAddr);
Tony Linthicumb4b54152011-12-12 21:14:40 +0000320 // Figure out base + offset opcode
321 if (LoadedVT == MVT::i64) Opcode = Hexagon::LDrid_indexed;
322 else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed;
323 else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed;
324 else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed;
Sirish Pande26f61a12012-05-03 21:52:53 +0000325 else llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000326
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 Pande71d56462012-05-03 16:18:50 +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
Sirish Pande26f61a12012-05-03 21:52:53 +0000523 llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000524
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)) {
Jyotsna Verma9c3846c2013-01-29 18:42:41 +0000611 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value,
612 Chain};
Tony Linthicumb4b54152011-12-12 21:14:40 +0000613 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;
Sirish Pande26f61a12012-05-03 21:52:53 +0000620 else llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000621
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 Pande26f61a12012-05-03 21:52:53 +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;
Sirish Pande26f61a12012-05-03 21:52:53 +0000646 else llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000647
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);
Brendon Cahoon5262abb2012-05-14 19:35:42 +0000691 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
692 dl, PointerTy,
693 TargAddr);
Tony Linthicumb4b54152011-12-12 21:14:40 +0000694
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 Pande26f61a12012-05-03 21:52:53 +0000700 else llvm_unreachable("unknown memory type");
Tony Linthicumb4b54152011-12-12 21:14:40 +0000701
702 SDValue Ops[] = {SDValue(NewBase,0),
703 CurDAG->getTargetConstant(Offset,PointerTy),
704 Value, Chain};
705 // build indexed store
706 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
707 MVT::Other, Ops, 4);
708 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
709 MemOp[0] = ST->getMemOperand();
710 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
711 ReplaceUses(ST, Result);
712 return Result;
713 }
714 }
715 }
716
717 return SelectCode(ST);
718}
719
720
721SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
722 DebugLoc dl = N->getDebugLoc();
723 StoreSDNode *ST = cast<StoreSDNode>(N);
724 ISD::MemIndexedMode AM = ST->getAddressingMode();
725
726 // Handle indexed stores.
727 if (AM != ISD::UNINDEXED) {
728 return SelectIndexedStore(ST, dl);
729 }
Sirish Pande71d56462012-05-03 16:18:50 +0000730
Tony Linthicumb4b54152011-12-12 21:14:40 +0000731 return SelectBaseOffsetStore(ST, dl);
732}
733
734SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
735 DebugLoc dl = N->getDebugLoc();
736
737 //
738 // %conv.i = sext i32 %tmp1 to i64
739 // %conv2.i = sext i32 %add to i64
740 // %mul.i = mul nsw i64 %conv2.i, %conv.i
741 //
742 // --- match with the following ---
743 //
744 // %mul.i = mpy (%tmp1, %add)
745 //
746
747 if (N->getValueType(0) == MVT::i64) {
748 // Shifting a i64 signed multiply.
749 SDValue MulOp0 = N->getOperand(0);
750 SDValue MulOp1 = N->getOperand(1);
751
752 SDValue OP0;
753 SDValue OP1;
754
755 // Handle sign_extend and sextload.
756 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
757 SDValue Sext0 = MulOp0.getOperand(0);
758 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Sirish Pande26f61a12012-05-03 21:52:53 +0000759 return SelectCode(N);
Tony Linthicumb4b54152011-12-12 21:14:40 +0000760 }
761
762 OP0 = Sext0;
763 } else if (MulOp0.getOpcode() == ISD::LOAD) {
764 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
765 if (LD->getMemoryVT() != MVT::i32 ||
766 LD->getExtensionType() != ISD::SEXTLOAD ||
767 LD->getAddressingMode() != ISD::UNINDEXED) {
Sirish Pande26f61a12012-05-03 21:52:53 +0000768 return SelectCode(N);
Tony Linthicumb4b54152011-12-12 21:14:40 +0000769 }
770
Tony Linthicumb4b54152011-12-12 21:14:40 +0000771 SDValue Chain = LD->getChain();
772 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
773 OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
774 MVT::Other,
775 LD->getBasePtr(), TargetConst0,
776 Chain), 0);
777 } else {
778 return SelectCode(N);
779 }
780
781 // Same goes for the second operand.
782 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
783 SDValue Sext1 = MulOp1.getOperand(0);
784 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
785 return SelectCode(N);
786 }
787
788 OP1 = Sext1;
789 } else if (MulOp1.getOpcode() == ISD::LOAD) {
790 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
791 if (LD->getMemoryVT() != MVT::i32 ||
792 LD->getExtensionType() != ISD::SEXTLOAD ||
793 LD->getAddressingMode() != ISD::UNINDEXED) {
794 return SelectCode(N);
795 }
796
Tony Linthicumb4b54152011-12-12 21:14:40 +0000797 SDValue Chain = LD->getChain();
798 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
799 OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
800 MVT::Other,
801 LD->getBasePtr(), TargetConst0,
802 Chain), 0);
803 } else {
804 return SelectCode(N);
805 }
806
807 // Generate a mpy instruction.
808 SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY64, dl, MVT::i64,
809 OP0, OP1);
810 ReplaceUses(N, Result);
811 return Result;
812 }
813
814 return SelectCode(N);
815}
816
817
818SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) {
819 DebugLoc dl = N->getDebugLoc();
820 SDValue N0 = N->getOperand(0);
821 if (N0.getOpcode() == ISD::SETCC) {
822 SDValue N00 = N0.getOperand(0);
823 if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) {
824 SDValue N000 = N00.getOperand(0);
825 SDValue N001 = N00.getOperand(1);
826 if (cast<VTSDNode>(N001)->getVT() == MVT::i16) {
827 SDValue N01 = N0.getOperand(1);
828 SDValue N02 = N0.getOperand(2);
829
830 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
831 // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1,
832 // IntRegs:i32:$src2)
833 // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
834 // Pattern complexity = 9 cost = 1 size = 0.
835 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) {
836 SDValue N1 = N->getOperand(1);
837 if (N01 == N1) {
838 SDValue N2 = N->getOperand(2);
839 if (N000 == N2 &&
840 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
841 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
842 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl,
843 MVT::i32, N000);
844 SDNode *Result = CurDAG->getMachineNode(Hexagon::MAXw_rr, dl,
845 MVT::i32,
846 SDValue(SextNode, 0),
847 N1);
848 ReplaceUses(N, Result);
849 return Result;
850 }
851 }
852 }
853
854 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
855 // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1,
856 // IntRegs:i32:$src2)
857 // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
858 // Pattern complexity = 9 cost = 1 size = 0.
859 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) {
860 SDValue N1 = N->getOperand(1);
861 if (N01 == N1) {
862 SDValue N2 = N->getOperand(2);
863 if (N000 == N2 &&
864 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
865 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
866 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl,
867 MVT::i32, N000);
868 SDNode *Result = CurDAG->getMachineNode(Hexagon::MINw_rr, dl,
869 MVT::i32,
870 SDValue(SextNode, 0),
871 N1);
872 ReplaceUses(N, Result);
873 return Result;
874 }
875 }
876 }
877 }
878 }
879 }
880
881 return SelectCode(N);
882}
883
884
885SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) {
886 DebugLoc dl = N->getDebugLoc();
887 SDValue Shift = N->getOperand(0);
888
889 //
890 // %conv.i = sext i32 %tmp1 to i64
891 // %conv2.i = sext i32 %add to i64
892 // %mul.i = mul nsw i64 %conv2.i, %conv.i
893 // %shr5.i = lshr i64 %mul.i, 32
894 // %conv3.i = trunc i64 %shr5.i to i32
895 //
896 // --- match with the following ---
897 //
898 // %conv3.i = mpy (%tmp1, %add)
899 //
900 // Trunc to i32.
901 if (N->getValueType(0) == MVT::i32) {
902 // Trunc from i64.
903 if (Shift.getNode()->getValueType(0) == MVT::i64) {
904 // Trunc child is logical shift right.
905 if (Shift.getOpcode() != ISD::SRL) {
906 return SelectCode(N);
907 }
908
909 SDValue ShiftOp0 = Shift.getOperand(0);
910 SDValue ShiftOp1 = Shift.getOperand(1);
911
912 // Shift by const 32
913 if (ShiftOp1.getOpcode() != ISD::Constant) {
914 return SelectCode(N);
915 }
916
917 int32_t ShiftConst =
918 cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue();
919 if (ShiftConst != 32) {
920 return SelectCode(N);
921 }
922
923 // Shifting a i64 signed multiply
924 SDValue Mul = ShiftOp0;
925 if (Mul.getOpcode() != ISD::MUL) {
926 return SelectCode(N);
927 }
928
929 SDValue MulOp0 = Mul.getOperand(0);
930 SDValue MulOp1 = Mul.getOperand(1);
931
932 SDValue OP0;
933 SDValue OP1;
934
935 // Handle sign_extend and sextload
936 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
937 SDValue Sext0 = MulOp0.getOperand(0);
938 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
939 return SelectCode(N);
940 }
941
942 OP0 = Sext0;
943 } else if (MulOp0.getOpcode() == ISD::LOAD) {
944 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
945 if (LD->getMemoryVT() != MVT::i32 ||
946 LD->getExtensionType() != ISD::SEXTLOAD ||
947 LD->getAddressingMode() != ISD::UNINDEXED) {
948 return SelectCode(N);
949 }
950
Tony Linthicumb4b54152011-12-12 21:14:40 +0000951 SDValue Chain = LD->getChain();
952 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
953 OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
954 MVT::Other,
955 LD->getBasePtr(),
956 TargetConst0, Chain), 0);
957 } else {
958 return SelectCode(N);
959 }
960
961 // Same goes for the second operand.
962 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
963 SDValue Sext1 = MulOp1.getOperand(0);
964 if (Sext1.getNode()->getValueType(0) != MVT::i32)
965 return SelectCode(N);
966
967 OP1 = Sext1;
968 } else if (MulOp1.getOpcode() == ISD::LOAD) {
969 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
970 if (LD->getMemoryVT() != MVT::i32 ||
971 LD->getExtensionType() != ISD::SEXTLOAD ||
972 LD->getAddressingMode() != ISD::UNINDEXED) {
973 return SelectCode(N);
974 }
975
Tony Linthicumb4b54152011-12-12 21:14:40 +0000976 SDValue Chain = LD->getChain();
977 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
978 OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32,
979 MVT::Other,
980 LD->getBasePtr(),
981 TargetConst0, Chain), 0);
982 } else {
983 return SelectCode(N);
984 }
985
986 // Generate a mpy instruction.
987 SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY, dl, MVT::i32,
988 OP0, OP1);
989 ReplaceUses(N, Result);
990 return Result;
991 }
992 }
993
994 return SelectCode(N);
995}
996
997
998SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
999 DebugLoc dl = N->getDebugLoc();
1000 if (N->getValueType(0) == MVT::i32) {
1001 SDValue Shl_0 = N->getOperand(0);
1002 SDValue Shl_1 = N->getOperand(1);
1003 // RHS is const.
1004 if (Shl_1.getOpcode() == ISD::Constant) {
1005 if (Shl_0.getOpcode() == ISD::MUL) {
1006 SDValue Mul_0 = Shl_0.getOperand(0); // Val
1007 SDValue Mul_1 = Shl_0.getOperand(1); // Const
1008 // RHS of mul is const.
1009 if (Mul_1.getOpcode() == ISD::Constant) {
1010 int32_t ShlConst =
1011 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1012 int32_t MulConst =
1013 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
1014 int32_t ValConst = MulConst << ShlConst;
1015 SDValue Val = CurDAG->getTargetConstant(ValConst,
1016 MVT::i32);
1017 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
1018 if (isInt<9>(CN->getSExtValue())) {
1019 SDNode* Result =
1020 CurDAG->getMachineNode(Hexagon::MPYI_ri, dl,
1021 MVT::i32, Mul_0, Val);
1022 ReplaceUses(N, Result);
1023 return Result;
1024 }
1025
1026 }
1027 } else if (Shl_0.getOpcode() == ISD::SUB) {
1028 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
1029 SDValue Sub_1 = Shl_0.getOperand(1); // Val
1030 if (Sub_0.getOpcode() == ISD::Constant) {
1031 int32_t SubConst =
1032 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
1033 if (SubConst == 0) {
1034 if (Sub_1.getOpcode() == ISD::SHL) {
1035 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
1036 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
1037 if (Shl2_1.getOpcode() == ISD::Constant) {
1038 int32_t ShlConst =
1039 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1040 int32_t Shl2Const =
1041 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
1042 int32_t ValConst = 1 << (ShlConst+Shl2Const);
1043 SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32);
1044 if (ConstantSDNode *CN =
1045 dyn_cast<ConstantSDNode>(Val.getNode()))
1046 if (isInt<9>(CN->getSExtValue())) {
1047 SDNode* Result =
1048 CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, MVT::i32,
1049 Shl2_0, Val);
1050 ReplaceUses(N, Result);
1051 return Result;
1052 }
1053 }
1054 }
1055 }
1056 }
1057 }
1058 }
1059 }
1060 return SelectCode(N);
1061}
1062
1063
1064//
1065// If there is an zero_extend followed an intrinsic in DAG (this means - the
1066// result of the intrinsic is predicate); convert the zero_extend to
1067// transfer instruction.
1068//
1069// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
1070// converted into a MUX as predicate registers defined as 1 bit in the
1071// compiler. Architecture defines them as 8-bit registers.
1072// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
1073//
1074SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
1075 DebugLoc dl = N->getDebugLoc();
1076 SDNode *IsIntrinsic = N->getOperand(0).getNode();
1077 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
1078 unsigned ID =
1079 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
1080 if (doesIntrinsicReturnPredicate(ID)) {
1081 // Now we need to differentiate target data types.
1082 if (N->getValueType(0) == MVT::i64) {
1083 // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs).
1084 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
1085 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl,
1086 MVT::i32,
1087 SDValue(IsIntrinsic, 0));
1088 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl,
1089 MVT::i32,
1090 TargetConst0);
1091 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl,
1092 MVT::i64, MVT::Other,
1093 SDValue(Result_2, 0),
1094 SDValue(Result_1, 0));
1095 ReplaceUses(N, Result_3);
1096 return Result_3;
1097 }
1098 if (N->getValueType(0) == MVT::i32) {
1099 // Convert the zero_extend to Rs = Pd
1100 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl,
1101 MVT::i32,
1102 SDValue(IsIntrinsic, 0));
1103 ReplaceUses(N, RsPd);
1104 return RsPd;
1105 }
Craig Topperbc219812012-02-07 02:50:20 +00001106 llvm_unreachable("Unexpected value type");
Tony Linthicumb4b54152011-12-12 21:14:40 +00001107 }
1108 }
1109 return SelectCode(N);
1110}
1111
1112
1113//
1114// Checking for intrinsics which have predicate registers as operand(s)
1115// and lowering to the actual intrinsic.
1116//
1117SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
1118 DebugLoc dl = N->getDebugLoc();
1119 unsigned ID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
1120 unsigned IntrinsicWithPred = doesIntrinsicContainPredicate(ID);
1121
1122 // We are concerned with only those intrinsics that have predicate registers
1123 // as at least one of the operands.
1124 if (IntrinsicWithPred) {
1125 SmallVector<SDValue, 8> Ops;
1126 const MCInstrDesc &MCID = TII->get(IntrinsicWithPred);
1127 const TargetRegisterInfo *TRI = TM.getRegisterInfo();
1128
1129 // Iterate over all the operands of the intrinsics.
1130 // For PredRegs, do the transfer.
1131 // For Double/Int Regs, just preserve the value
1132 // For immediates, lower it.
1133 for (unsigned i = 1; i < N->getNumOperands(); ++i) {
1134 SDNode *Arg = N->getOperand(i).getNode();
Jakob Stoklund Olesen397fc482012-05-07 22:10:26 +00001135 const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI, *MF);
Tony Linthicumb4b54152011-12-12 21:14:40 +00001136
Craig Topper420761a2012-04-20 07:30:17 +00001137 if (RC == &Hexagon::IntRegsRegClass ||
1138 RC == &Hexagon::DoubleRegsRegClass) {
Tony Linthicumb4b54152011-12-12 21:14:40 +00001139 Ops.push_back(SDValue(Arg, 0));
Craig Topper420761a2012-04-20 07:30:17 +00001140 } else if (RC == &Hexagon::PredRegsRegClass) {
Tony Linthicumb4b54152011-12-12 21:14:40 +00001141 // Do the transfer.
1142 SDNode *PdRs = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1,
1143 SDValue(Arg, 0));
1144 Ops.push_back(SDValue(PdRs,0));
1145 } else if (RC == NULL && (dyn_cast<ConstantSDNode>(Arg) != NULL)) {
1146 // This is immediate operand. Lower it here making sure that we DO have
1147 // const SDNode for immediate value.
1148 int32_t Val = cast<ConstantSDNode>(Arg)->getSExtValue();
1149 SDValue SDVal = CurDAG->getTargetConstant(Val, MVT::i32);
1150 Ops.push_back(SDVal);
1151 } else {
Craig Topperbc219812012-02-07 02:50:20 +00001152 llvm_unreachable("Unimplemented");
Tony Linthicumb4b54152011-12-12 21:14:40 +00001153 }
1154 }
1155 EVT ReturnValueVT = N->getValueType(0);
1156 SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl,
1157 ReturnValueVT,
1158 Ops.data(), Ops.size());
1159 ReplaceUses(N, Result);
1160 return Result;
1161 }
1162 return SelectCode(N);
1163}
1164
Sirish Pande7517bbc2012-05-10 20:20:25 +00001165//
1166// Map floating point constant values.
1167//
1168SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
1169 DebugLoc dl = N->getDebugLoc();
1170 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
1171 APFloat APF = CN->getValueAPF();
1172 if (N->getValueType(0) == MVT::f32) {
1173 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
1174 CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32));
1175 }
1176 else if (N->getValueType(0) == MVT::f64) {
1177 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
1178 CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64));
1179 }
1180
1181 return SelectCode(N);
1182}
1183
Tony Linthicumb4b54152011-12-12 21:14:40 +00001184
1185//
1186// Map predicate true (encoded as -1 in LLVM) to a XOR.
1187//
1188SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
1189 DebugLoc dl = N->getDebugLoc();
1190 if (N->getValueType(0) == MVT::i1) {
1191 SDNode* Result;
1192 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
1193 if (Val == -1) {
Tony Linthicumb4b54152011-12-12 21:14:40 +00001194 // Create the IntReg = 1 node.
1195 SDNode* IntRegTFR =
1196 CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
1197 CurDAG->getTargetConstant(0, MVT::i32));
1198
1199 // Pd = IntReg
1200 SDNode* Pd = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1,
1201 SDValue(IntRegTFR, 0));
1202
1203 // not(Pd)
Sirish Pandeab7955b2012-02-15 18:52:27 +00001204 SDNode* NotPd = CurDAG->getMachineNode(Hexagon::NOT_p, dl, MVT::i1,
Tony Linthicumb4b54152011-12-12 21:14:40 +00001205 SDValue(Pd, 0));
1206
1207 // xor(not(Pd))
1208 Result = CurDAG->getMachineNode(Hexagon::XOR_pp, dl, MVT::i1,
1209 SDValue(Pd, 0), SDValue(NotPd, 0));
1210
1211 // We have just built:
1212 // Rs = Pd
1213 // Pd = xor(not(Pd), Pd)
1214
1215 ReplaceUses(N, Result);
1216 return Result;
1217 }
1218 }
1219
1220 return SelectCode(N);
1221}
1222
1223
1224//
1225// Map add followed by a asr -> asr +=.
1226//
1227SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
1228 DebugLoc dl = N->getDebugLoc();
1229 if (N->getValueType(0) != MVT::i32) {
1230 return SelectCode(N);
1231 }
1232 // Identify nodes of the form: add(asr(...)).
1233 SDNode* Src1 = N->getOperand(0).getNode();
1234 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1235 || Src1->getValueType(0) != MVT::i32) {
1236 return SelectCode(N);
1237 }
1238
1239 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1240 // Rd and Rd' are assigned to the same register
Sirish Pande71d56462012-05-03 16:18:50 +00001241 SDNode* Result = CurDAG->getMachineNode(Hexagon::ASR_ADD_rr, dl, MVT::i32,
Tony Linthicumb4b54152011-12-12 21:14:40 +00001242 N->getOperand(1),
1243 Src1->getOperand(0),
1244 Src1->getOperand(1));
1245 ReplaceUses(N, Result);
1246
1247 return Result;
1248}
1249
1250
1251SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
1252 if (N->isMachineOpcode())
1253 return NULL; // Already selected.
1254
1255
1256 switch (N->getOpcode()) {
1257 case ISD::Constant:
1258 return SelectConstant(N);
1259
Sirish Pande7517bbc2012-05-10 20:20:25 +00001260 case ISD::ConstantFP:
1261 return SelectConstantFP(N);
1262
Tony Linthicumb4b54152011-12-12 21:14:40 +00001263 case ISD::ADD:
1264 return SelectAdd(N);
1265
1266 case ISD::SHL:
1267 return SelectSHL(N);
1268
1269 case ISD::LOAD:
1270 return SelectLoad(N);
1271
1272 case ISD::STORE:
1273 return SelectStore(N);
1274
1275 case ISD::SELECT:
1276 return SelectSelect(N);
1277
1278 case ISD::TRUNCATE:
1279 return SelectTruncate(N);
1280
1281 case ISD::MUL:
1282 return SelectMul(N);
1283
1284 case ISD::ZERO_EXTEND:
1285 return SelectZeroExtend(N);
1286
1287 case ISD::INTRINSIC_WO_CHAIN:
1288 return SelectIntrinsicWOChain(N);
1289 }
1290
1291 return SelectCode(N);
1292}
1293
1294
1295//
1296// Hexagon_TODO: Five functions for ADDRri?! Surely there must be a better way
1297// to define these instructions.
1298//
1299bool HexagonDAGToDAGISel::SelectADDRri(SDValue& Addr, SDValue &Base,
1300 SDValue &Offset) {
1301 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1302 Addr.getOpcode() == ISD::TargetGlobalAddress)
1303 return false; // Direct calls.
1304
1305 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1306 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1307 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1308 return true;
1309 }
1310 Base = Addr;
1311 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1312 return true;
1313}
1314
1315
1316bool HexagonDAGToDAGISel::SelectADDRriS11_0(SDValue& Addr, SDValue &Base,
1317 SDValue &Offset) {
1318 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1319 Addr.getOpcode() == ISD::TargetGlobalAddress)
1320 return false; // Direct calls.
1321
1322 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1323 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1324 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1325 return (IsS11_0_Offset(Offset.getNode()));
1326 }
1327 Base = Addr;
1328 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1329 return (IsS11_0_Offset(Offset.getNode()));
1330}
1331
1332
1333bool HexagonDAGToDAGISel::SelectADDRriS11_1(SDValue& Addr, SDValue &Base,
1334 SDValue &Offset) {
1335 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1336 Addr.getOpcode() == ISD::TargetGlobalAddress)
1337 return false; // Direct calls.
1338
1339 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1340 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1341 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1342 return (IsS11_1_Offset(Offset.getNode()));
1343 }
1344 Base = Addr;
1345 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1346 return (IsS11_1_Offset(Offset.getNode()));
1347}
1348
1349
1350bool HexagonDAGToDAGISel::SelectADDRriS11_2(SDValue& Addr, SDValue &Base,
1351 SDValue &Offset) {
1352 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1353 Addr.getOpcode() == ISD::TargetGlobalAddress)
1354 return false; // Direct calls.
1355
1356 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1357 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1358 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1359 return (IsS11_2_Offset(Offset.getNode()));
1360 }
1361 Base = Addr;
1362 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1363 return (IsS11_2_Offset(Offset.getNode()));
1364}
1365
1366
1367bool HexagonDAGToDAGISel::SelectADDRriU6_0(SDValue& Addr, SDValue &Base,
1368 SDValue &Offset) {
1369 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1370 Addr.getOpcode() == ISD::TargetGlobalAddress)
1371 return false; // Direct calls.
1372
1373 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1374 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1375 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1376 return (IsU6_0_Offset(Offset.getNode()));
1377 }
1378 Base = Addr;
1379 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1380 return (IsU6_0_Offset(Offset.getNode()));
1381}
1382
1383
1384bool HexagonDAGToDAGISel::SelectADDRriU6_1(SDValue& Addr, SDValue &Base,
1385 SDValue &Offset) {
1386 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1387 Addr.getOpcode() == ISD::TargetGlobalAddress)
1388 return false; // Direct calls.
1389
1390 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1391 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1392 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1393 return (IsU6_1_Offset(Offset.getNode()));
1394 }
1395 Base = Addr;
1396 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1397 return (IsU6_1_Offset(Offset.getNode()));
1398}
1399
1400
1401bool HexagonDAGToDAGISel::SelectADDRriU6_2(SDValue& Addr, SDValue &Base,
1402 SDValue &Offset) {
1403 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1404 Addr.getOpcode() == ISD::TargetGlobalAddress)
1405 return false; // Direct calls.
1406
1407 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1408 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1409 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1410 return (IsU6_2_Offset(Offset.getNode()));
1411 }
1412 Base = Addr;
1413 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1414 return (IsU6_2_Offset(Offset.getNode()));
1415}
1416
1417
1418bool HexagonDAGToDAGISel::SelectMEMriS11_2(SDValue& Addr, SDValue &Base,
1419 SDValue &Offset) {
1420
1421 if (Addr.getOpcode() != ISD::ADD) {
1422 return(SelectADDRriS11_2(Addr, Base, Offset));
1423 }
1424
1425 return SelectADDRriS11_2(Addr, Base, Offset);
1426}
1427
1428
1429bool HexagonDAGToDAGISel::SelectADDRriS11_3(SDValue& Addr, SDValue &Base,
1430 SDValue &Offset) {
1431 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1432 Addr.getOpcode() == ISD::TargetGlobalAddress)
1433 return false; // Direct calls.
1434
1435 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1436 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1437 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1438 return (IsS11_3_Offset(Offset.getNode()));
1439 }
1440 Base = Addr;
1441 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1442 return (IsS11_3_Offset(Offset.getNode()));
1443}
1444
1445bool HexagonDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1,
1446 SDValue &R2) {
1447 if (Addr.getOpcode() == ISD::FrameIndex) return false;
1448 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1449 Addr.getOpcode() == ISD::TargetGlobalAddress)
1450 return false; // Direct calls.
1451
1452 if (Addr.getOpcode() == ISD::ADD) {
1453 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
1454 if (isInt<13>(CN->getSExtValue()))
1455 return false; // Let the reg+imm pattern catch this!
1456 R1 = Addr.getOperand(0);
1457 R2 = Addr.getOperand(1);
1458 return true;
1459 }
1460
1461 R1 = Addr;
1462
1463 return true;
1464}
1465
1466
1467// Handle generic address case. It is accessed from inlined asm =m constraints,
1468// which could have any kind of pointer.
1469bool HexagonDAGToDAGISel::SelectAddr(SDNode *Op, SDValue Addr,
1470 SDValue &Base, SDValue &Offset) {
1471 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1472 Addr.getOpcode() == ISD::TargetGlobalAddress)
1473 return false; // Direct calls.
1474
1475 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1476 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1477 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1478 return true;
1479 }
1480
1481 if (Addr.getOpcode() == ISD::ADD) {
1482 Base = Addr.getOperand(0);
1483 Offset = Addr.getOperand(1);
1484 return true;
1485 }
1486
1487 Base = Addr;
1488 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1489 return true;
1490}
1491
1492
1493bool HexagonDAGToDAGISel::
1494SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
1495 std::vector<SDValue> &OutOps) {
1496 SDValue Op0, Op1;
1497
1498 switch (ConstraintCode) {
1499 case 'o': // Offsetable.
1500 case 'v': // Not offsetable.
1501 default: return true;
1502 case 'm': // Memory.
1503 if (!SelectAddr(Op.getNode(), Op, Op0, Op1))
1504 return true;
1505 break;
1506 }
1507
1508 OutOps.push_back(Op0);
1509 OutOps.push_back(Op1);
1510 return false;
1511}
Jyotsna Verma61c654c2012-11-28 20:58:14 +00001512
1513bool HexagonDAGToDAGISel::isConstExtProfitable(SDNode *N) const {
1514 unsigned UseCount = 0;
1515 for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
1516 UseCount++;
1517 }
1518
1519 return (UseCount <= 1);
1520
1521}