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