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