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