blob: a5236ea1ac002a1817e16612b7bb7bd99700069f [file] [log] [blame]
Jia Liub22310f2012-02-18 12:03:15 +00001//===-- HexagonISelDAGToDAG.cpp - A dag to dag inst selector for Hexagon --===//
Tony Linthicum1213a7a2011-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
Chandler Carruthed0881b2012-12-03 16:50:05 +000014#include "Hexagon.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000015#include "HexagonISelLowering.h"
16#include "HexagonTargetMachine.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000017#include "llvm/ADT/DenseMap.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000018#include "llvm/CodeGen/SelectionDAGISel.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000019#include "llvm/IR/Intrinsics.h"
Jyotsna Vermad9225242013-02-13 21:38:46 +000020#include "llvm/Support/CommandLine.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000021#include "llvm/Support/Compiler.h"
22#include "llvm/Support/Debug.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000023using namespace llvm;
24
Chandler Carruth84e68b22014-04-22 02:41:26 +000025#define DEBUG_TYPE "hexagon-isel"
26
Jyotsna Vermad9225242013-02-13 21:38:46 +000027static
28cl::opt<unsigned>
29MaxNumOfUsesForConstExtenders("ga-max-num-uses-for-constant-extenders",
30 cl::Hidden, cl::init(2),
31 cl::desc("Maximum number of uses of a global address such that we still us a"
32 "constant extended instruction"));
Tony Linthicum1213a7a2011-12-12 21:14:40 +000033
34//===----------------------------------------------------------------------===//
35// Instruction Selector Implementation
36//===----------------------------------------------------------------------===//
37
Jyotsna Vermad9225242013-02-13 21:38:46 +000038namespace llvm {
39 void initializeHexagonDAGToDAGISelPass(PassRegistry&);
40}
41
Tony Linthicum1213a7a2011-12-12 21:14:40 +000042//===--------------------------------------------------------------------===//
43/// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine
44/// instructions for SelectionDAG operations.
45///
46namespace {
47class HexagonDAGToDAGISel : public SelectionDAGISel {
48 /// Subtarget - Keep a pointer to the Hexagon Subtarget around so that we can
49 /// make the right decision when generating code for different targets.
Eric Christopher202f22b2015-02-02 19:22:03 +000050 const HexagonSubtarget *Subtarget;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000051
52 // Keep a reference to HexagonTargetMachine.
Krzysztof Parzyszekd5007472013-05-06 18:38:37 +000053 const HexagonTargetMachine& TM;
Jyotsna Vermad9225242013-02-13 21:38:46 +000054 DenseMap<const GlobalValue *, unsigned> GlobalAddressUseCountMap;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000055public:
Bill Wendlinga3cd3502013-06-19 21:36:55 +000056 explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine,
Jyotsna Vermad9225242013-02-13 21:38:46 +000057 CodeGenOpt::Level OptLevel)
Eric Christopher202f22b2015-02-02 19:22:03 +000058 : SelectionDAGISel(targetmachine, OptLevel), TM(targetmachine) {
Jyotsna Vermad9225242013-02-13 21:38:46 +000059 initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry());
Tony Linthicum1213a7a2011-12-12 21:14:40 +000060 }
Jyotsna Vermad9225242013-02-13 21:38:46 +000061 bool hasNumUsesBelowThresGA(SDNode *N) const;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000062
Craig Topper906c2cd2014-04-29 07:58:16 +000063 SDNode *Select(SDNode *N) override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000064
65 // Complex Pattern Selectors.
Jyotsna Vermad9225242013-02-13 21:38:46 +000066 inline bool foldGlobalAddress(SDValue &N, SDValue &R);
67 inline bool foldGlobalAddressGP(SDValue &N, SDValue &R);
68 bool foldGlobalAddressImpl(SDValue &N, SDValue &R, bool ShouldLookForGP);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000069 bool SelectADDRri(SDValue& N, SDValue &R1, SDValue &R2);
70 bool SelectADDRriS11_0(SDValue& N, SDValue &R1, SDValue &R2);
71 bool SelectADDRriS11_1(SDValue& N, SDValue &R1, SDValue &R2);
72 bool SelectADDRriS11_2(SDValue& N, SDValue &R1, SDValue &R2);
73 bool SelectMEMriS11_2(SDValue& Addr, SDValue &Base, SDValue &Offset);
74 bool SelectADDRriS11_3(SDValue& N, SDValue &R1, SDValue &R2);
75 bool SelectADDRrr(SDValue &Addr, SDValue &Base, SDValue &Offset);
76 bool SelectADDRriU6_0(SDValue& N, SDValue &R1, SDValue &R2);
77 bool SelectADDRriU6_1(SDValue& N, SDValue &R1, SDValue &R2);
78 bool SelectADDRriU6_2(SDValue& N, SDValue &R1, SDValue &R2);
79
Colin LeMahieuc7522f32015-01-14 23:07:36 +000080 bool SelectAddrFI(SDValue &N, SDValue &R);
81
Craig Topper906c2cd2014-04-29 07:58:16 +000082 const char *getPassName() const override {
Tony Linthicum1213a7a2011-12-12 21:14:40 +000083 return "Hexagon DAG->DAG Pattern Instruction Selection";
84 }
85
Eric Christopher202f22b2015-02-02 19:22:03 +000086 bool runOnMachineFunction(MachineFunction &MF) override {
87 Subtarget = &MF.getSubtarget<HexagonSubtarget>();
88 return SelectionDAGISel::runOnMachineFunction(MF);
89 }
90
Tony Linthicum1213a7a2011-12-12 21:14:40 +000091 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
92 /// inline asm expressions.
Craig Topper906c2cd2014-04-29 07:58:16 +000093 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
94 char ConstraintCode,
95 std::vector<SDValue> &OutOps) override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000096 bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset);
97
98 SDNode *SelectLoad(SDNode *N);
Andrew Trickef9de2a2013-05-25 02:42:55 +000099 SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl);
100 SDNode *SelectIndexedLoad(LoadSDNode *LD, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000101 SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000102 SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000103 SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000104 SDLoc dl);
105 SDNode *SelectBaseOffsetStore(StoreSDNode *ST, SDLoc dl);
106 SDNode *SelectIndexedStore(StoreSDNode *ST, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000107 SDNode *SelectStore(SDNode *N);
108 SDNode *SelectSHL(SDNode *N);
109 SDNode *SelectSelect(SDNode *N);
110 SDNode *SelectTruncate(SDNode *N);
111 SDNode *SelectMul(SDNode *N);
112 SDNode *SelectZeroExtend(SDNode *N);
113 SDNode *SelectIntrinsicWOChain(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000114 SDNode *SelectIntrinsicWChain(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000115 SDNode *SelectConstant(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000116 SDNode *SelectConstantFP(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000117 SDNode *SelectAdd(SDNode *N);
Jyotsna Verma519b3852012-11-28 20:58:14 +0000118 bool isConstExtProfitable(SDNode *N) const;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000119
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000120// XformMskToBitPosU5Imm - Returns the bit position which
121// the single bit 32 bit mask represents.
122// Used in Clr and Set bit immediate memops.
123SDValue XformMskToBitPosU5Imm(uint32_t Imm) {
124 int32_t bitPos;
125 bitPos = Log2_32(Imm);
126 assert(bitPos >= 0 && bitPos < 32 &&
127 "Constant out of range for 32 BitPos Memops");
128 return CurDAG->getTargetConstant(bitPos, MVT::i32);
129}
130
131// XformMskToBitPosU4Imm - Returns the bit position which the single bit 16 bit
132// mask represents. Used in Clr and Set bit immediate memops.
133SDValue XformMskToBitPosU4Imm(uint16_t Imm) {
134 return XformMskToBitPosU5Imm(Imm);
135}
136
137// XformMskToBitPosU3Imm - Returns the bit position which the single bit 8 bit
138// mask represents. Used in Clr and Set bit immediate memops.
139SDValue XformMskToBitPosU3Imm(uint8_t Imm) {
140 return XformMskToBitPosU5Imm(Imm);
141}
142
143// Return true if there is exactly one bit set in V, i.e., if V is one of the
144// following integers: 2^0, 2^1, ..., 2^31.
145bool ImmIsSingleBit(uint32_t v) const {
146 uint32_t c = CountPopulation_64(v);
147 // Only return true if we counted 1 bit.
148 return c == 1;
149}
150
151// XformM5ToU5Imm - Return a target constant with the specified value, of type
152// i32 where the negative literal is transformed into a positive literal for
153// use in -= memops.
154inline SDValue XformM5ToU5Imm(signed Imm) {
155 assert( (Imm >= -31 && Imm <= -1) && "Constant out of range for Memops");
156 return CurDAG->getTargetConstant( - Imm, MVT::i32);
157}
158
159
Jyotsna Verma60316252013-02-05 19:20:45 +0000160// XformU7ToU7M1Imm - Return a target constant decremented by 1, in range
161// [1..128], used in cmpb.gtu instructions.
162inline SDValue XformU7ToU7M1Imm(signed Imm) {
163 assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op");
164 return CurDAG->getTargetConstant(Imm - 1, MVT::i8);
165}
166
Jyotsna Verma89c84822013-04-23 19:15:55 +0000167// XformS8ToS8M1Imm - Return a target constant decremented by 1.
168inline SDValue XformSToSM1Imm(signed Imm) {
169 return CurDAG->getTargetConstant(Imm - 1, MVT::i32);
170}
171
172// XformU8ToU8M1Imm - Return a target constant decremented by 1.
173inline SDValue XformUToUM1Imm(unsigned Imm) {
174 assert((Imm >= 1) && "Cannot decrement unsigned int less than 1");
175 return CurDAG->getTargetConstant(Imm - 1, MVT::i32);
176}
177
Colin LeMahieu19ed07c2015-01-28 18:29:11 +0000178// XformSToSM2Imm - Return a target constant decremented by 2.
179inline SDValue XformSToSM2Imm(unsigned Imm) {
180 return CurDAG->getTargetConstant(Imm - 2, MVT::i32);
181}
182
183// XformSToSM3Imm - Return a target constant decremented by 3.
184inline SDValue XformSToSM3Imm(unsigned Imm) {
185 return CurDAG->getTargetConstant(Imm - 3, MVT::i32);
186}
187
Jyotsna Verma60316252013-02-05 19:20:45 +0000188// Include the pieces autogenerated from the target description.
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000189#include "HexagonGenDAGISel.inc"
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +0000190
191private:
192 bool isValueExtension(SDValue const &Val, unsigned FromBits, SDValue &Src);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000193};
194} // end anonymous namespace
195
196
197/// createHexagonISelDag - This pass converts a legalized DAG into a
198/// Hexagon-specific DAG, ready for instruction scheduling.
199///
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000200FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM,
Jyotsna Vermad9225242013-02-13 21:38:46 +0000201 CodeGenOpt::Level OptLevel) {
202 return new HexagonDAGToDAGISel(TM, OptLevel);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000203}
204
Jyotsna Vermad9225242013-02-13 21:38:46 +0000205static void initializePassOnce(PassRegistry &Registry) {
206 const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection";
207 PassInfo *PI = new PassInfo(Name, "hexagon-isel",
Craig Topper062a2ba2014-04-25 05:30:21 +0000208 &SelectionDAGISel::ID, nullptr, false, false);
Jyotsna Vermad9225242013-02-13 21:38:46 +0000209 Registry.registerPass(*PI, true);
210}
211
212void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) {
213 CALL_ONCE_INITIALIZATION(initializePassOnce)
214}
215
216
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000217static bool IsS11_0_Offset(SDNode * S) {
218 ConstantSDNode *N = cast<ConstantSDNode>(S);
219
220 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
221 // field.
222 int64_t v = (int64_t)N->getSExtValue();
223 return isInt<11>(v);
224}
225
226
227static bool IsS11_1_Offset(SDNode * S) {
228 ConstantSDNode *N = cast<ConstantSDNode>(S);
229
230 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
231 // field.
232 int64_t v = (int64_t)N->getSExtValue();
233 return isShiftedInt<11,1>(v);
234}
235
236
237static bool IsS11_2_Offset(SDNode * S) {
238 ConstantSDNode *N = cast<ConstantSDNode>(S);
239
240 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
241 // field.
242 int64_t v = (int64_t)N->getSExtValue();
243 return isShiftedInt<11,2>(v);
244}
245
246
247static bool IsS11_3_Offset(SDNode * S) {
248 ConstantSDNode *N = cast<ConstantSDNode>(S);
249
250 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
251 // field.
252 int64_t v = (int64_t)N->getSExtValue();
253 return isShiftedInt<11,3>(v);
254}
255
256
257static bool IsU6_0_Offset(SDNode * S) {
258 ConstantSDNode *N = cast<ConstantSDNode>(S);
259
260 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
261 // field.
262 int64_t v = (int64_t)N->getSExtValue();
263 return isUInt<6>(v);
264}
265
266
267static bool IsU6_1_Offset(SDNode * S) {
268 ConstantSDNode *N = cast<ConstantSDNode>(S);
269
270 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
271 // field.
272 int64_t v = (int64_t)N->getSExtValue();
273 return isShiftedUInt<6,1>(v);
274}
275
276
277static bool IsU6_2_Offset(SDNode * S) {
278 ConstantSDNode *N = cast<ConstantSDNode>(S);
279
280 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
281 // field.
282 int64_t v = (int64_t)N->getSExtValue();
283 return isShiftedUInt<6,2>(v);
284}
285
286
287// Intrinsics that return a a predicate.
288static unsigned doesIntrinsicReturnPredicate(unsigned ID)
289{
290 switch (ID) {
291 default:
292 return 0;
293 case Intrinsic::hexagon_C2_cmpeq:
294 case Intrinsic::hexagon_C2_cmpgt:
295 case Intrinsic::hexagon_C2_cmpgtu:
296 case Intrinsic::hexagon_C2_cmpgtup:
297 case Intrinsic::hexagon_C2_cmpgtp:
298 case Intrinsic::hexagon_C2_cmpeqp:
299 case Intrinsic::hexagon_C2_bitsset:
300 case Intrinsic::hexagon_C2_bitsclr:
301 case Intrinsic::hexagon_C2_cmpeqi:
302 case Intrinsic::hexagon_C2_cmpgti:
303 case Intrinsic::hexagon_C2_cmpgtui:
304 case Intrinsic::hexagon_C2_cmpgei:
305 case Intrinsic::hexagon_C2_cmpgeui:
306 case Intrinsic::hexagon_C2_cmplt:
307 case Intrinsic::hexagon_C2_cmpltu:
308 case Intrinsic::hexagon_C2_bitsclri:
309 case Intrinsic::hexagon_C2_and:
310 case Intrinsic::hexagon_C2_or:
311 case Intrinsic::hexagon_C2_xor:
312 case Intrinsic::hexagon_C2_andn:
313 case Intrinsic::hexagon_C2_not:
314 case Intrinsic::hexagon_C2_orn:
315 case Intrinsic::hexagon_C2_pxfer_map:
316 case Intrinsic::hexagon_C2_any8:
317 case Intrinsic::hexagon_C2_all8:
318 case Intrinsic::hexagon_A2_vcmpbeq:
319 case Intrinsic::hexagon_A2_vcmpbgtu:
320 case Intrinsic::hexagon_A2_vcmpheq:
321 case Intrinsic::hexagon_A2_vcmphgt:
322 case Intrinsic::hexagon_A2_vcmphgtu:
323 case Intrinsic::hexagon_A2_vcmpweq:
324 case Intrinsic::hexagon_A2_vcmpwgt:
325 case Intrinsic::hexagon_A2_vcmpwgtu:
326 case Intrinsic::hexagon_C2_tfrrp:
327 case Intrinsic::hexagon_S2_tstbit_i:
328 case Intrinsic::hexagon_S2_tstbit_r:
329 return 1;
330 }
331}
332
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000333static bool OffsetFitsS11(EVT MemType, int64_t Offset) {
334 if (MemType == MVT::i64 && isShiftedInt<11,3>(Offset)) {
335 return true;
336 }
337 if (MemType == MVT::i32 && isShiftedInt<11,2>(Offset)) {
338 return true;
339 }
340 if (MemType == MVT::i16 && isShiftedInt<11,1>(Offset)) {
341 return true;
342 }
343 if (MemType == MVT::i8 && isInt<11>(Offset)) {
344 return true;
345 }
346 return false;
347}
348
349
350//
351// Try to lower loads of GlobalAdresses into base+offset loads. Custom
352// lowering for GlobalAddress nodes has already turned it into a
353// CONST32.
354//
Andrew Trickef9de2a2013-05-25 02:42:55 +0000355SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000356 SDValue Chain = LD->getChain();
357 SDNode* Const32 = LD->getBasePtr().getNode();
358 unsigned Opcode = 0;
359
360 if (Const32->getOpcode() == HexagonISD::CONST32 &&
361 ISD::isNormalLoad(LD)) {
362 SDValue Base = Const32->getOperand(0);
363 EVT LoadedVT = LD->getMemoryVT();
364 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
365 if (Offset != 0 && OffsetFitsS11(LoadedVT, Offset)) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000366 MVT PointerTy = getTargetLowering()->getPointerTy();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000367 const GlobalValue* GV =
368 cast<GlobalAddressSDNode>(Base)->getGlobal();
369 SDValue TargAddr =
370 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0);
Brendon Cahoonf6b687e2012-05-14 19:35:42 +0000371 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
372 dl, PointerTy,
373 TargAddr);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000374 // Figure out base + offset opcode
Colin LeMahieu947cd702014-12-23 20:44:59 +0000375 if (LoadedVT == MVT::i64) Opcode = Hexagon::L2_loadrd_io;
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000376 else if (LoadedVT == MVT::i32) Opcode = Hexagon::L2_loadri_io;
Colin LeMahieu8e39cad2014-12-23 17:25:57 +0000377 else if (LoadedVT == MVT::i16) Opcode = Hexagon::L2_loadrh_io;
Colin LeMahieu4b1eac42014-12-22 21:40:43 +0000378 else if (LoadedVT == MVT::i8) Opcode = Hexagon::L2_loadrb_io;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000379 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000380
381 // Build indexed load.
382 SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy);
383 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
384 LD->getValueType(0),
385 MVT::Other,
386 SDValue(NewBase,0),
387 TargetConstOff,
388 Chain);
389 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
390 MemOp[0] = LD->getMemOperand();
391 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
392 ReplaceUses(LD, Result);
393 return Result;
394 }
395 }
396
397 return SelectCode(LD);
398}
399
400
401SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
402 unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000403 SDLoc dl)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000404{
405 SDValue Chain = LD->getChain();
406 EVT LoadedVT = LD->getMemoryVT();
407 SDValue Base = LD->getBasePtr();
408 SDValue Offset = LD->getOffset();
409 SDNode *OffsetNode = Offset.getNode();
410 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
411 SDValue N1 = LD->getOperand(1);
412 SDValue CPTmpN1_0;
413 SDValue CPTmpN1_1;
Bill Wendling4a7a4082013-06-07 06:19:56 +0000414
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000415 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
416 N1.getNode()->getValueType(0) == MVT::i32) {
Eric Christopher202f22b2015-02-02 19:22:03 +0000417 const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000418 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
419 SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32);
420 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
421 MVT::Other, Base, TargetConst,
422 Chain);
Colin LeMahieueb52f692014-12-11 16:43:06 +0000423 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000424 SDValue(Result_1, 0));
425 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
426 MemOp[0] = LD->getMemOperand();
427 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
428 const SDValue Froms[] = { SDValue(LD, 0),
429 SDValue(LD, 1),
430 SDValue(LD, 2)
431 };
432 const SDValue Tos[] = { SDValue(Result_2, 0),
433 SDValue(Result_1, 1),
434 SDValue(Result_1, 2)
435 };
436 ReplaceUses(Froms, Tos, 3);
437 return Result_2;
Sirish Pandec92c3162012-05-03 16:18:50 +0000438 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000439 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
440 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
441 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
442 MVT::Other, Base, TargetConst0,
443 Chain);
Colin LeMahieueb52f692014-12-11 16:43:06 +0000444 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000445 MVT::i64, SDValue(Result_1, 0));
446 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl,
447 MVT::i32, Base, TargetConstVal,
448 SDValue(Result_1, 1));
449 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
450 MemOp[0] = LD->getMemOperand();
451 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
452 const SDValue Froms[] = { SDValue(LD, 0),
453 SDValue(LD, 1),
454 SDValue(LD, 2)
455 };
456 const SDValue Tos[] = { SDValue(Result_2, 0),
457 SDValue(Result_3, 0),
458 SDValue(Result_1, 1)
459 };
460 ReplaceUses(Froms, Tos, 3);
461 return Result_2;
462 }
463 return SelectCode(LD);
464}
465
466
467SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
468 unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000469 SDLoc dl)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000470{
471 SDValue Chain = LD->getChain();
472 EVT LoadedVT = LD->getMemoryVT();
473 SDValue Base = LD->getBasePtr();
474 SDValue Offset = LD->getOffset();
475 SDNode *OffsetNode = Offset.getNode();
476 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
477 SDValue N1 = LD->getOperand(1);
478 SDValue CPTmpN1_0;
479 SDValue CPTmpN1_1;
Bill Wendling4a7a4082013-06-07 06:19:56 +0000480
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000481 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
482 N1.getNode()->getValueType(0) == MVT::i32) {
Eric Christopher202f22b2015-02-02 19:22:03 +0000483 const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000484 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
485 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
486 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
487 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
488 MVT::i32, MVT::Other, Base,
489 TargetConstVal, Chain);
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000490 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000491 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +0000492 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000493 MVT::i64, MVT::Other,
494 SDValue(Result_2,0),
495 SDValue(Result_1,0));
496 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
497 MemOp[0] = LD->getMemOperand();
498 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
499 const SDValue Froms[] = { SDValue(LD, 0),
500 SDValue(LD, 1),
501 SDValue(LD, 2)
502 };
503 const SDValue Tos[] = { SDValue(Result_3, 0),
504 SDValue(Result_1, 1),
505 SDValue(Result_1, 2)
506 };
507 ReplaceUses(Froms, Tos, 3);
508 return Result_3;
509 }
510
511 // Generate an indirect load.
512 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
513 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
514 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
515 MVT::Other,
516 Base, TargetConst0, Chain);
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000517 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000518 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +0000519 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000520 MVT::i64, MVT::Other,
521 SDValue(Result_2,0),
522 SDValue(Result_1,0));
523 // Add offset to base.
524 SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
525 Base, TargetConstVal,
526 SDValue(Result_1, 1));
527 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
528 MemOp[0] = LD->getMemOperand();
529 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
530 const SDValue Froms[] = { SDValue(LD, 0),
531 SDValue(LD, 1),
532 SDValue(LD, 2)
533 };
534 const SDValue Tos[] = { SDValue(Result_3, 0), // Load value.
535 SDValue(Result_4, 0), // New address.
536 SDValue(Result_1, 1)
537 };
538 ReplaceUses(Froms, Tos, 3);
539 return Result_3;
540 }
541
542 return SelectCode(LD);
543}
544
545
Andrew Trickef9de2a2013-05-25 02:42:55 +0000546SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000547 SDValue Chain = LD->getChain();
548 SDValue Base = LD->getBasePtr();
549 SDValue Offset = LD->getOffset();
550 SDNode *OffsetNode = Offset.getNode();
551 // Get the constant value.
552 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
553 EVT LoadedVT = LD->getMemoryVT();
554 unsigned Opcode = 0;
555
556 // Check for zero ext loads.
557 bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD);
558
559 // Figure out the opcode.
Eric Christopher202f22b2015-02-02 19:22:03 +0000560 const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000561 if (LoadedVT == MVT::i64) {
562 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000563 Opcode = Hexagon::L2_loadrd_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000564 else
Colin LeMahieu947cd702014-12-23 20:44:59 +0000565 Opcode = Hexagon::L2_loadrd_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000566 } else if (LoadedVT == MVT::i32) {
567 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000568 Opcode = Hexagon::L2_loadri_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000569 else
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000570 Opcode = Hexagon::L2_loadri_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000571 } else if (LoadedVT == MVT::i16) {
572 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000573 Opcode = zextval ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000574 else
Colin LeMahieu8e39cad2014-12-23 17:25:57 +0000575 Opcode = zextval ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000576 } else if (LoadedVT == MVT::i8) {
577 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieufe9612e2014-12-26 19:12:11 +0000578 Opcode = zextval ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000579 else
Colin LeMahieu4b1eac42014-12-22 21:40:43 +0000580 Opcode = zextval ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000581 } else
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000582 llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000583
584 // For zero ext i64 loads, we need to add combine instructions.
585 if (LD->getValueType(0) == MVT::i64 &&
586 LD->getExtensionType() == ISD::ZEXTLOAD) {
587 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl);
588 }
589 if (LD->getValueType(0) == MVT::i64 &&
590 LD->getExtensionType() == ISD::SEXTLOAD) {
591 // Handle sign ext i64 loads.
592 return SelectIndexedLoadSignExtend64(LD, Opcode, dl);
593 }
594 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
595 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
596 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
597 LD->getValueType(0),
598 MVT::i32, MVT::Other, Base,
599 TargetConstVal, Chain);
600 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
601 MemOp[0] = LD->getMemOperand();
602 cast<MachineSDNode>(Result)->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, 0),
608 SDValue(Result, 1),
609 SDValue(Result, 2)
610 };
611 ReplaceUses(Froms, Tos, 3);
612 return Result;
613 } else {
614 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
615 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
616 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl,
617 LD->getValueType(0),
618 MVT::Other, Base, TargetConst0,
619 Chain);
620 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
621 Base, TargetConstVal,
622 SDValue(Result_1, 1));
623 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
624 MemOp[0] = LD->getMemOperand();
625 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
626 const SDValue Froms[] = { SDValue(LD, 0),
627 SDValue(LD, 1),
628 SDValue(LD, 2)
629 };
630 const SDValue Tos[] = { SDValue(Result_1, 0),
631 SDValue(Result_2, 0),
632 SDValue(Result_1, 1)
633 };
634 ReplaceUses(Froms, Tos, 3);
635 return Result_1;
636 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000637}
638
639
640SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
641 SDNode *result;
Andrew Trickef9de2a2013-05-25 02:42:55 +0000642 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000643 LoadSDNode *LD = cast<LoadSDNode>(N);
644 ISD::MemIndexedMode AM = LD->getAddressingMode();
645
646 // Handle indexed loads.
647 if (AM != ISD::UNINDEXED) {
648 result = SelectIndexedLoad(LD, dl);
649 } else {
650 result = SelectBaseOffsetLoad(LD, dl);
651 }
652
653 return result;
654}
655
656
Andrew Trickef9de2a2013-05-25 02:42:55 +0000657SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000658 SDValue Chain = ST->getChain();
659 SDValue Base = ST->getBasePtr();
660 SDValue Offset = ST->getOffset();
661 SDValue Value = ST->getValue();
662 SDNode *OffsetNode = Offset.getNode();
663 // Get the constant value.
664 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
665 EVT StoredVT = ST->getMemoryVT();
666
667 // Offset value must be within representable range
668 // and must have correct alignment properties.
Eric Christopher202f22b2015-02-02 19:22:03 +0000669 const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000670 if (TII->isValidAutoIncImm(StoredVT, Val)) {
Jyotsna Vermab16a9cb2013-01-29 18:42:41 +0000671 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value,
672 Chain};
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000673 unsigned Opcode = 0;
674
675 // Figure out the post inc version of opcode.
Colin LeMahieu9a3cd3f2014-12-29 20:00:43 +0000676 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi;
677 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi;
678 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi;
Colin LeMahieu3d34afb2014-12-29 19:42:14 +0000679 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000680 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000681
682 // Build post increment store.
683 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +0000684 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000685 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
686 MemOp[0] = ST->getMemOperand();
687 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
688
689 ReplaceUses(ST, Result);
690 ReplaceUses(SDValue(ST,1), SDValue(Result,1));
691 return Result;
692 }
693
694 // Note: Order of operands matches the def of instruction:
695 // def STrid : STInst<(outs), (ins MEMri:$addr, DoubleRegs:$src1), ...
696 // and it differs for POST_ST* for instance.
697 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value,
698 Chain};
699 unsigned Opcode = 0;
700
701 // Figure out the opcode.
Colin LeMahieubda31b42014-12-29 20:44:51 +0000702 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
703 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
704 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
705 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000706 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000707
708 // Build regular store.
709 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
Michael Liaob53d8962013-04-19 22:22:57 +0000710 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000711 // Build splitted incriment instruction.
712 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
713 Base,
714 TargetConstVal,
715 SDValue(Result_1, 0));
716 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
717 MemOp[0] = ST->getMemOperand();
718 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
719
720 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0));
721 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0));
722 return Result_2;
723}
724
725
726SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000727 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000728 SDValue Chain = ST->getChain();
729 SDNode* Const32 = ST->getBasePtr().getNode();
730 SDValue Value = ST->getValue();
731 unsigned Opcode = 0;
732
733 // Try to lower stores of GlobalAdresses into indexed stores. Custom
734 // lowering for GlobalAddress nodes has already turned it into a
735 // CONST32. Avoid truncating stores for the moment. Post-inc stores
736 // do the same. Don't think there's a reason for it, so will file a
737 // bug to fix.
738 if ((Const32->getOpcode() == HexagonISD::CONST32) &&
739 !(Value.getValueType() == MVT::i64 && ST->isTruncatingStore())) {
740 SDValue Base = Const32->getOperand(0);
741 if (Base.getOpcode() == ISD::TargetGlobalAddress) {
742 EVT StoredVT = ST->getMemoryVT();
743 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
744 if (Offset != 0 && OffsetFitsS11(StoredVT, Offset)) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000745 MVT PointerTy = getTargetLowering()->getPointerTy();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000746 const GlobalValue* GV =
747 cast<GlobalAddressSDNode>(Base)->getGlobal();
748 SDValue TargAddr =
749 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0);
Brendon Cahoonf6b687e2012-05-14 19:35:42 +0000750 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
751 dl, PointerTy,
752 TargAddr);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000753
754 // Figure out base + offset opcode
Colin LeMahieubda31b42014-12-29 20:44:51 +0000755 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
756 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
757 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
758 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000759 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000760
761 SDValue Ops[] = {SDValue(NewBase,0),
762 CurDAG->getTargetConstant(Offset,PointerTy),
763 Value, Chain};
764 // build indexed store
765 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
Michael Liaob53d8962013-04-19 22:22:57 +0000766 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000767 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
768 MemOp[0] = ST->getMemOperand();
769 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
770 ReplaceUses(ST, Result);
771 return Result;
772 }
773 }
774 }
775
776 return SelectCode(ST);
777}
778
779
780SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000781 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000782 StoreSDNode *ST = cast<StoreSDNode>(N);
783 ISD::MemIndexedMode AM = ST->getAddressingMode();
784
785 // Handle indexed stores.
786 if (AM != ISD::UNINDEXED) {
787 return SelectIndexedStore(ST, dl);
788 }
Sirish Pandec92c3162012-05-03 16:18:50 +0000789
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000790 return SelectBaseOffsetStore(ST, dl);
791}
792
793SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000794 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000795
796 //
797 // %conv.i = sext i32 %tmp1 to i64
798 // %conv2.i = sext i32 %add to i64
799 // %mul.i = mul nsw i64 %conv2.i, %conv.i
800 //
801 // --- match with the following ---
802 //
803 // %mul.i = mpy (%tmp1, %add)
804 //
805
806 if (N->getValueType(0) == MVT::i64) {
807 // Shifting a i64 signed multiply.
808 SDValue MulOp0 = N->getOperand(0);
809 SDValue MulOp1 = N->getOperand(1);
810
811 SDValue OP0;
812 SDValue OP1;
813
814 // Handle sign_extend and sextload.
815 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
816 SDValue Sext0 = MulOp0.getOperand(0);
817 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000818 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000819 }
820
821 OP0 = Sext0;
822 } else if (MulOp0.getOpcode() == ISD::LOAD) {
823 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
824 if (LD->getMemoryVT() != MVT::i32 ||
825 LD->getExtensionType() != ISD::SEXTLOAD ||
826 LD->getAddressingMode() != ISD::UNINDEXED) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000827 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000828 }
829
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000830 SDValue Chain = LD->getChain();
831 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000832 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000833 MVT::Other,
834 LD->getBasePtr(), TargetConst0,
835 Chain), 0);
836 } else {
837 return SelectCode(N);
838 }
839
840 // Same goes for the second operand.
841 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
842 SDValue Sext1 = MulOp1.getOperand(0);
843 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
844 return SelectCode(N);
845 }
846
847 OP1 = Sext1;
848 } else if (MulOp1.getOpcode() == ISD::LOAD) {
849 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
850 if (LD->getMemoryVT() != MVT::i32 ||
851 LD->getExtensionType() != ISD::SEXTLOAD ||
852 LD->getAddressingMode() != ISD::UNINDEXED) {
853 return SelectCode(N);
854 }
855
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000856 SDValue Chain = LD->getChain();
857 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000858 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000859 MVT::Other,
860 LD->getBasePtr(), TargetConst0,
861 Chain), 0);
862 } else {
863 return SelectCode(N);
864 }
865
866 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +0000867 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000868 OP0, OP1);
869 ReplaceUses(N, Result);
870 return Result;
871 }
872
873 return SelectCode(N);
874}
875
876
877SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000878 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000879 SDValue N0 = N->getOperand(0);
880 if (N0.getOpcode() == ISD::SETCC) {
881 SDValue N00 = N0.getOperand(0);
882 if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) {
883 SDValue N000 = N00.getOperand(0);
884 SDValue N001 = N00.getOperand(1);
885 if (cast<VTSDNode>(N001)->getVT() == MVT::i16) {
886 SDValue N01 = N0.getOperand(1);
887 SDValue N02 = N0.getOperand(2);
888
889 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
890 // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1,
891 // IntRegs:i32:$src2)
892 // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
893 // Pattern complexity = 9 cost = 1 size = 0.
894 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) {
895 SDValue N1 = N->getOperand(1);
896 if (N01 == N1) {
897 SDValue N2 = N->getOperand(2);
898 if (N000 == N2 &&
899 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
900 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
Colin LeMahieu310991c2014-11-21 21:54:59 +0000901 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000902 MVT::i32, N000);
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000903 SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_max, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000904 MVT::i32,
905 SDValue(SextNode, 0),
906 N1);
907 ReplaceUses(N, Result);
908 return Result;
909 }
910 }
911 }
912
913 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
914 // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1,
915 // IntRegs:i32:$src2)
916 // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
917 // Pattern complexity = 9 cost = 1 size = 0.
918 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) {
919 SDValue N1 = N->getOperand(1);
920 if (N01 == N1) {
921 SDValue N2 = N->getOperand(2);
922 if (N000 == N2 &&
923 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
924 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
Colin LeMahieu310991c2014-11-21 21:54:59 +0000925 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000926 MVT::i32, N000);
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000927 SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_min, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000928 MVT::i32,
929 SDValue(SextNode, 0),
930 N1);
931 ReplaceUses(N, Result);
932 return Result;
933 }
934 }
935 }
936 }
937 }
938 }
939
940 return SelectCode(N);
941}
942
943
944SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000945 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000946 SDValue Shift = N->getOperand(0);
947
948 //
949 // %conv.i = sext i32 %tmp1 to i64
950 // %conv2.i = sext i32 %add to i64
951 // %mul.i = mul nsw i64 %conv2.i, %conv.i
952 // %shr5.i = lshr i64 %mul.i, 32
953 // %conv3.i = trunc i64 %shr5.i to i32
954 //
955 // --- match with the following ---
956 //
957 // %conv3.i = mpy (%tmp1, %add)
958 //
959 // Trunc to i32.
960 if (N->getValueType(0) == MVT::i32) {
961 // Trunc from i64.
962 if (Shift.getNode()->getValueType(0) == MVT::i64) {
963 // Trunc child is logical shift right.
964 if (Shift.getOpcode() != ISD::SRL) {
965 return SelectCode(N);
966 }
967
968 SDValue ShiftOp0 = Shift.getOperand(0);
969 SDValue ShiftOp1 = Shift.getOperand(1);
970
971 // Shift by const 32
972 if (ShiftOp1.getOpcode() != ISD::Constant) {
973 return SelectCode(N);
974 }
975
976 int32_t ShiftConst =
977 cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue();
978 if (ShiftConst != 32) {
979 return SelectCode(N);
980 }
981
982 // Shifting a i64 signed multiply
983 SDValue Mul = ShiftOp0;
984 if (Mul.getOpcode() != ISD::MUL) {
985 return SelectCode(N);
986 }
987
988 SDValue MulOp0 = Mul.getOperand(0);
989 SDValue MulOp1 = Mul.getOperand(1);
990
991 SDValue OP0;
992 SDValue OP1;
993
994 // Handle sign_extend and sextload
995 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
996 SDValue Sext0 = MulOp0.getOperand(0);
997 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
998 return SelectCode(N);
999 }
1000
1001 OP0 = Sext0;
1002 } else if (MulOp0.getOpcode() == ISD::LOAD) {
1003 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
1004 if (LD->getMemoryVT() != MVT::i32 ||
1005 LD->getExtensionType() != ISD::SEXTLOAD ||
1006 LD->getAddressingMode() != ISD::UNINDEXED) {
1007 return SelectCode(N);
1008 }
1009
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001010 SDValue Chain = LD->getChain();
1011 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +00001012 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001013 MVT::Other,
1014 LD->getBasePtr(),
1015 TargetConst0, Chain), 0);
1016 } else {
1017 return SelectCode(N);
1018 }
1019
1020 // Same goes for the second operand.
1021 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
1022 SDValue Sext1 = MulOp1.getOperand(0);
1023 if (Sext1.getNode()->getValueType(0) != MVT::i32)
1024 return SelectCode(N);
1025
1026 OP1 = Sext1;
1027 } else if (MulOp1.getOpcode() == ISD::LOAD) {
1028 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
1029 if (LD->getMemoryVT() != MVT::i32 ||
1030 LD->getExtensionType() != ISD::SEXTLOAD ||
1031 LD->getAddressingMode() != ISD::UNINDEXED) {
1032 return SelectCode(N);
1033 }
1034
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001035 SDValue Chain = LD->getChain();
1036 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +00001037 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001038 MVT::Other,
1039 LD->getBasePtr(),
1040 TargetConst0, Chain), 0);
1041 } else {
1042 return SelectCode(N);
1043 }
1044
1045 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +00001046 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpy_up, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001047 OP0, OP1);
1048 ReplaceUses(N, Result);
1049 return Result;
1050 }
1051 }
1052
1053 return SelectCode(N);
1054}
1055
1056
1057SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001058 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001059 if (N->getValueType(0) == MVT::i32) {
1060 SDValue Shl_0 = N->getOperand(0);
1061 SDValue Shl_1 = N->getOperand(1);
1062 // RHS is const.
1063 if (Shl_1.getOpcode() == ISD::Constant) {
1064 if (Shl_0.getOpcode() == ISD::MUL) {
1065 SDValue Mul_0 = Shl_0.getOperand(0); // Val
1066 SDValue Mul_1 = Shl_0.getOperand(1); // Const
1067 // RHS of mul is const.
1068 if (Mul_1.getOpcode() == ISD::Constant) {
1069 int32_t ShlConst =
1070 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1071 int32_t MulConst =
1072 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
1073 int32_t ValConst = MulConst << ShlConst;
1074 SDValue Val = CurDAG->getTargetConstant(ValConst,
1075 MVT::i32);
1076 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
1077 if (isInt<9>(CN->getSExtValue())) {
1078 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +00001079 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001080 MVT::i32, Mul_0, Val);
1081 ReplaceUses(N, Result);
1082 return Result;
1083 }
1084
1085 }
1086 } else if (Shl_0.getOpcode() == ISD::SUB) {
1087 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
1088 SDValue Sub_1 = Shl_0.getOperand(1); // Val
1089 if (Sub_0.getOpcode() == ISD::Constant) {
1090 int32_t SubConst =
1091 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
1092 if (SubConst == 0) {
1093 if (Sub_1.getOpcode() == ISD::SHL) {
1094 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
1095 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
1096 if (Shl2_1.getOpcode() == ISD::Constant) {
1097 int32_t ShlConst =
1098 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1099 int32_t Shl2Const =
1100 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
1101 int32_t ValConst = 1 << (ShlConst+Shl2Const);
1102 SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32);
1103 if (ConstantSDNode *CN =
1104 dyn_cast<ConstantSDNode>(Val.getNode()))
1105 if (isInt<9>(CN->getSExtValue())) {
1106 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +00001107 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001108 Shl2_0, Val);
1109 ReplaceUses(N, Result);
1110 return Result;
1111 }
1112 }
1113 }
1114 }
1115 }
1116 }
1117 }
1118 }
1119 return SelectCode(N);
1120}
1121
1122
1123//
1124// If there is an zero_extend followed an intrinsic in DAG (this means - the
1125// result of the intrinsic is predicate); convert the zero_extend to
1126// transfer instruction.
1127//
1128// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
1129// converted into a MUX as predicate registers defined as 1 bit in the
1130// compiler. Architecture defines them as 8-bit registers.
1131// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
1132//
1133SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001134 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001135 SDNode *IsIntrinsic = N->getOperand(0).getNode();
1136 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
1137 unsigned ID =
1138 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
1139 if (doesIntrinsicReturnPredicate(ID)) {
1140 // Now we need to differentiate target data types.
1141 if (N->getValueType(0) == MVT::i64) {
1142 // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs).
1143 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001144 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001145 MVT::i32,
1146 SDValue(IsIntrinsic, 0));
Colin LeMahieu4af437f2014-12-09 20:23:30 +00001147 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001148 MVT::i32,
1149 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +00001150 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001151 MVT::i64, MVT::Other,
1152 SDValue(Result_2, 0),
1153 SDValue(Result_1, 0));
1154 ReplaceUses(N, Result_3);
1155 return Result_3;
1156 }
1157 if (N->getValueType(0) == MVT::i32) {
1158 // Convert the zero_extend to Rs = Pd
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001159 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001160 MVT::i32,
1161 SDValue(IsIntrinsic, 0));
1162 ReplaceUses(N, RsPd);
1163 return RsPd;
1164 }
Craig Toppere55c5562012-02-07 02:50:20 +00001165 llvm_unreachable("Unexpected value type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001166 }
1167 }
1168 return SelectCode(N);
1169}
1170
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001171//
1172// Checking for intrinsics which have predicate registers as operand(s)
1173// and lowering to the actual intrinsic.
1174//
1175SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001176 unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
1177 unsigned Bits;
1178 switch (IID) {
1179 case Intrinsic::hexagon_S2_vsplatrb:
1180 Bits = 8;
1181 break;
1182 case Intrinsic::hexagon_S2_vsplatrh:
1183 Bits = 16;
1184 break;
1185 default:
1186 return SelectCode(N);
1187 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001188
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001189 SDValue const &V = N->getOperand(1);
1190 SDValue U;
1191 if (isValueExtension(V, Bits, U)) {
1192 SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
1193 N->getOperand(0), U);
1194 return SelectCode(R.getNode());
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001195 }
1196 return SelectCode(N);
1197}
1198
Sirish Pande69295b82012-05-10 20:20:25 +00001199//
1200// Map floating point constant values.
1201//
1202SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001203 SDLoc dl(N);
Sirish Pande69295b82012-05-10 20:20:25 +00001204 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
1205 APFloat APF = CN->getValueAPF();
1206 if (N->getValueType(0) == MVT::f32) {
1207 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
1208 CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32));
1209 }
1210 else if (N->getValueType(0) == MVT::f64) {
1211 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
1212 CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64));
1213 }
1214
1215 return SelectCode(N);
1216}
1217
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001218
1219//
1220// Map predicate true (encoded as -1 in LLVM) to a XOR.
1221//
1222SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001223 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001224 if (N->getValueType(0) == MVT::i1) {
1225 SDNode* Result;
1226 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
1227 if (Val == -1) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001228 // Create the IntReg = 1 node.
1229 SDNode* IntRegTFR =
Colin LeMahieu4af437f2014-12-09 20:23:30 +00001230 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001231 CurDAG->getTargetConstant(0, MVT::i32));
1232
1233 // Pd = IntReg
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001234 SDNode* Pd = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001235 SDValue(IntRegTFR, 0));
1236
1237 // not(Pd)
Colin LeMahieu5cf56322014-12-08 23:55:43 +00001238 SDNode* NotPd = CurDAG->getMachineNode(Hexagon::C2_not, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001239 SDValue(Pd, 0));
1240
1241 // xor(not(Pd))
Colin LeMahieu5cf56322014-12-08 23:55:43 +00001242 Result = CurDAG->getMachineNode(Hexagon::C2_xor, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001243 SDValue(Pd, 0), SDValue(NotPd, 0));
1244
1245 // We have just built:
1246 // Rs = Pd
1247 // Pd = xor(not(Pd), Pd)
1248
1249 ReplaceUses(N, Result);
1250 return Result;
1251 }
1252 }
1253
1254 return SelectCode(N);
1255}
1256
1257
1258//
1259// Map add followed by a asr -> asr +=.
1260//
1261SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001262 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001263 if (N->getValueType(0) != MVT::i32) {
1264 return SelectCode(N);
1265 }
1266 // Identify nodes of the form: add(asr(...)).
1267 SDNode* Src1 = N->getOperand(0).getNode();
1268 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1269 || Src1->getValueType(0) != MVT::i32) {
1270 return SelectCode(N);
1271 }
1272
1273 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1274 // Rd and Rd' are assigned to the same register
Colin LeMahieu0f850bd2014-12-19 20:29:29 +00001275 SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001276 N->getOperand(1),
1277 Src1->getOperand(0),
1278 Src1->getOperand(1));
1279 ReplaceUses(N, Result);
1280
1281 return Result;
1282}
1283
1284
1285SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
Tim Northover31d093c2013-09-22 08:21:56 +00001286 if (N->isMachineOpcode()) {
1287 N->setNodeId(-1);
Craig Topper062a2ba2014-04-25 05:30:21 +00001288 return nullptr; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00001289 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001290
1291
1292 switch (N->getOpcode()) {
1293 case ISD::Constant:
1294 return SelectConstant(N);
1295
Sirish Pande69295b82012-05-10 20:20:25 +00001296 case ISD::ConstantFP:
1297 return SelectConstantFP(N);
1298
Tony Linthicum1213a7a2011-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 Verma519b3852012-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 Vermad9225242013-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//===--------------------------------------------------------------------===//
Alp Tokerf907b892013-12-05 05:44:44 +00001581// Return true if the non-GP-relative global address can be folded.
Jyotsna Vermad9225242013-02-13 21:38:46 +00001582//===--------------------------------------------------------------------===//
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(),
Andrew Trickef9de2a2013-05-25 02:42:55 +00001614 SDLoc(Const),
Jyotsna Vermad9225242013-02-13 21:38:46 +00001615 N.getValueType(),
1616 GA->getOffset() +
1617 (uint64_t)Const->getSExtValue());
1618 return true;
1619 }
1620 }
1621 }
1622 return false;
1623}
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001624
1625bool HexagonDAGToDAGISel::SelectAddrFI(SDValue& N, SDValue &R) {
1626 if (N.getOpcode() != ISD::FrameIndex)
1627 return false;
1628 FrameIndexSDNode *FX = cast<FrameIndexSDNode>(N);
1629 R = CurDAG->getTargetFrameIndex(FX->getIndex(), MVT::i32);
1630 return true;
1631}
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001632
1633bool HexagonDAGToDAGISel::isValueExtension(SDValue const &Val,
1634 unsigned FromBits, SDValue &Src) {
1635 unsigned Opc = Val.getOpcode();
1636 switch (Opc) {
1637 case ISD::SIGN_EXTEND:
1638 case ISD::ZERO_EXTEND:
1639 case ISD::ANY_EXTEND: {
1640 SDValue const &Op0 = Val.getOperand(0);
1641 EVT T = Op0.getValueType();
1642 if (T.isInteger() && T.getSizeInBits() == FromBits) {
1643 Src = Op0;
1644 return true;
1645 }
1646 break;
1647 }
1648 case ISD::SIGN_EXTEND_INREG:
1649 case ISD::AssertSext:
1650 case ISD::AssertZext:
1651 if (Val.getOperand(0).getValueType().isInteger()) {
1652 VTSDNode *T = cast<VTSDNode>(Val.getOperand(1));
1653 if (T->getVT().getSizeInBits() == FromBits) {
1654 Src = Val.getOperand(0);
1655 return true;
1656 }
1657 }
1658 break;
1659 case ISD::AND: {
1660 // Check if this is an AND with "FromBits" of lower bits set to 1.
1661 uint64_t FromMask = (1 << FromBits) - 1;
1662 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1663 if (C->getZExtValue() == FromMask) {
1664 Src = Val.getOperand(1);
1665 return true;
1666 }
1667 }
1668 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1669 if (C->getZExtValue() == FromMask) {
1670 Src = Val.getOperand(0);
1671 return true;
1672 }
1673 }
1674 break;
1675 }
1676 case ISD::OR:
1677 case ISD::XOR: {
1678 // OR/XOR with the lower "FromBits" bits set to 0.
1679 uint64_t FromMask = (1 << FromBits) - 1;
1680 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1681 if ((C->getZExtValue() & FromMask) == 0) {
1682 Src = Val.getOperand(1);
1683 return true;
1684 }
1685 }
1686 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1687 if ((C->getZExtValue() & FromMask) == 0) {
1688 Src = Val.getOperand(0);
1689 return true;
1690 }
1691 }
1692 }
1693 default:
1694 break;
1695 }
1696 return false;
1697}