blob: 05f63928b882d1d5bf61fdf03a656982c3e8efb0 [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 LeMahieu987b0942015-02-04 20:38:01 +000080 // Complex Pattern Selectors.
81 inline bool SelectAddrGA(SDValue &N, SDValue &R);
82 bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP);
Colin LeMahieuc7522f32015-01-14 23:07:36 +000083 bool SelectAddrFI(SDValue &N, SDValue &R);
84
Craig Topper906c2cd2014-04-29 07:58:16 +000085 const char *getPassName() const override {
Tony Linthicum1213a7a2011-12-12 21:14:40 +000086 return "Hexagon DAG->DAG Pattern Instruction Selection";
87 }
88
Eric Christopher202f22b2015-02-02 19:22:03 +000089 bool runOnMachineFunction(MachineFunction &MF) override {
90 Subtarget = &MF.getSubtarget<HexagonSubtarget>();
91 return SelectionDAGISel::runOnMachineFunction(MF);
92 }
93
Tony Linthicum1213a7a2011-12-12 21:14:40 +000094 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
95 /// inline asm expressions.
Craig Topper906c2cd2014-04-29 07:58:16 +000096 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
97 char ConstraintCode,
98 std::vector<SDValue> &OutOps) override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000099 bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset);
100
101 SDNode *SelectLoad(SDNode *N);
Andrew Trickef9de2a2013-05-25 02:42:55 +0000102 SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl);
103 SDNode *SelectIndexedLoad(LoadSDNode *LD, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000104 SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000105 SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000106 SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000107 SDLoc dl);
108 SDNode *SelectBaseOffsetStore(StoreSDNode *ST, SDLoc dl);
109 SDNode *SelectIndexedStore(StoreSDNode *ST, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000110 SDNode *SelectStore(SDNode *N);
111 SDNode *SelectSHL(SDNode *N);
112 SDNode *SelectSelect(SDNode *N);
113 SDNode *SelectTruncate(SDNode *N);
114 SDNode *SelectMul(SDNode *N);
115 SDNode *SelectZeroExtend(SDNode *N);
116 SDNode *SelectIntrinsicWOChain(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000117 SDNode *SelectIntrinsicWChain(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000118 SDNode *SelectConstant(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000119 SDNode *SelectConstantFP(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000120 SDNode *SelectAdd(SDNode *N);
Jyotsna Verma519b3852012-11-28 20:58:14 +0000121 bool isConstExtProfitable(SDNode *N) const;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000122
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000123// XformMskToBitPosU5Imm - Returns the bit position which
124// the single bit 32 bit mask represents.
125// Used in Clr and Set bit immediate memops.
126SDValue XformMskToBitPosU5Imm(uint32_t Imm) {
127 int32_t bitPos;
128 bitPos = Log2_32(Imm);
129 assert(bitPos >= 0 && bitPos < 32 &&
130 "Constant out of range for 32 BitPos Memops");
131 return CurDAG->getTargetConstant(bitPos, MVT::i32);
132}
133
134// XformMskToBitPosU4Imm - Returns the bit position which the single bit 16 bit
135// mask represents. Used in Clr and Set bit immediate memops.
136SDValue XformMskToBitPosU4Imm(uint16_t Imm) {
137 return XformMskToBitPosU5Imm(Imm);
138}
139
140// XformMskToBitPosU3Imm - Returns the bit position which the single bit 8 bit
141// mask represents. Used in Clr and Set bit immediate memops.
142SDValue XformMskToBitPosU3Imm(uint8_t Imm) {
143 return XformMskToBitPosU5Imm(Imm);
144}
145
146// Return true if there is exactly one bit set in V, i.e., if V is one of the
147// following integers: 2^0, 2^1, ..., 2^31.
148bool ImmIsSingleBit(uint32_t v) const {
149 uint32_t c = CountPopulation_64(v);
150 // Only return true if we counted 1 bit.
151 return c == 1;
152}
153
154// XformM5ToU5Imm - Return a target constant with the specified value, of type
155// i32 where the negative literal is transformed into a positive literal for
156// use in -= memops.
157inline SDValue XformM5ToU5Imm(signed Imm) {
158 assert( (Imm >= -31 && Imm <= -1) && "Constant out of range for Memops");
159 return CurDAG->getTargetConstant( - Imm, MVT::i32);
160}
161
162
Jyotsna Verma60316252013-02-05 19:20:45 +0000163// XformU7ToU7M1Imm - Return a target constant decremented by 1, in range
164// [1..128], used in cmpb.gtu instructions.
165inline SDValue XformU7ToU7M1Imm(signed Imm) {
166 assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op");
167 return CurDAG->getTargetConstant(Imm - 1, MVT::i8);
168}
169
Jyotsna Verma89c84822013-04-23 19:15:55 +0000170// XformS8ToS8M1Imm - Return a target constant decremented by 1.
171inline SDValue XformSToSM1Imm(signed Imm) {
172 return CurDAG->getTargetConstant(Imm - 1, MVT::i32);
173}
174
175// XformU8ToU8M1Imm - Return a target constant decremented by 1.
176inline SDValue XformUToUM1Imm(unsigned Imm) {
177 assert((Imm >= 1) && "Cannot decrement unsigned int less than 1");
178 return CurDAG->getTargetConstant(Imm - 1, MVT::i32);
179}
180
Colin LeMahieu19ed07c2015-01-28 18:29:11 +0000181// XformSToSM2Imm - Return a target constant decremented by 2.
182inline SDValue XformSToSM2Imm(unsigned Imm) {
183 return CurDAG->getTargetConstant(Imm - 2, MVT::i32);
184}
185
186// XformSToSM3Imm - Return a target constant decremented by 3.
187inline SDValue XformSToSM3Imm(unsigned Imm) {
188 return CurDAG->getTargetConstant(Imm - 3, MVT::i32);
189}
190
Jyotsna Verma60316252013-02-05 19:20:45 +0000191// Include the pieces autogenerated from the target description.
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000192#include "HexagonGenDAGISel.inc"
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +0000193
194private:
195 bool isValueExtension(SDValue const &Val, unsigned FromBits, SDValue &Src);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000196};
197} // end anonymous namespace
198
199
200/// createHexagonISelDag - This pass converts a legalized DAG into a
201/// Hexagon-specific DAG, ready for instruction scheduling.
202///
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000203FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM,
Jyotsna Vermad9225242013-02-13 21:38:46 +0000204 CodeGenOpt::Level OptLevel) {
205 return new HexagonDAGToDAGISel(TM, OptLevel);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000206}
207
Jyotsna Vermad9225242013-02-13 21:38:46 +0000208static void initializePassOnce(PassRegistry &Registry) {
209 const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection";
210 PassInfo *PI = new PassInfo(Name, "hexagon-isel",
Craig Topper062a2ba2014-04-25 05:30:21 +0000211 &SelectionDAGISel::ID, nullptr, false, false);
Jyotsna Vermad9225242013-02-13 21:38:46 +0000212 Registry.registerPass(*PI, true);
213}
214
215void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) {
216 CALL_ONCE_INITIALIZATION(initializePassOnce)
217}
218
219
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000220static bool IsS11_0_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 isInt<11>(v);
227}
228
229
230static bool IsS11_1_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,1>(v);
237}
238
239
240static bool IsS11_2_Offset(SDNode * S) {
241 ConstantSDNode *N = cast<ConstantSDNode>(S);
242
243 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
244 // field.
245 int64_t v = (int64_t)N->getSExtValue();
246 return isShiftedInt<11,2>(v);
247}
248
249
250static bool IsS11_3_Offset(SDNode * S) {
251 ConstantSDNode *N = cast<ConstantSDNode>(S);
252
253 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
254 // field.
255 int64_t v = (int64_t)N->getSExtValue();
256 return isShiftedInt<11,3>(v);
257}
258
259
260static bool IsU6_0_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 isUInt<6>(v);
267}
268
269
270static bool IsU6_1_Offset(SDNode * S) {
271 ConstantSDNode *N = cast<ConstantSDNode>(S);
272
273 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
274 // field.
275 int64_t v = (int64_t)N->getSExtValue();
276 return isShiftedUInt<6,1>(v);
277}
278
279
280static bool IsU6_2_Offset(SDNode * S) {
281 ConstantSDNode *N = cast<ConstantSDNode>(S);
282
283 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
284 // field.
285 int64_t v = (int64_t)N->getSExtValue();
286 return isShiftedUInt<6,2>(v);
287}
288
289
290// Intrinsics that return a a predicate.
291static unsigned doesIntrinsicReturnPredicate(unsigned ID)
292{
293 switch (ID) {
294 default:
295 return 0;
296 case Intrinsic::hexagon_C2_cmpeq:
297 case Intrinsic::hexagon_C2_cmpgt:
298 case Intrinsic::hexagon_C2_cmpgtu:
299 case Intrinsic::hexagon_C2_cmpgtup:
300 case Intrinsic::hexagon_C2_cmpgtp:
301 case Intrinsic::hexagon_C2_cmpeqp:
302 case Intrinsic::hexagon_C2_bitsset:
303 case Intrinsic::hexagon_C2_bitsclr:
304 case Intrinsic::hexagon_C2_cmpeqi:
305 case Intrinsic::hexagon_C2_cmpgti:
306 case Intrinsic::hexagon_C2_cmpgtui:
307 case Intrinsic::hexagon_C2_cmpgei:
308 case Intrinsic::hexagon_C2_cmpgeui:
309 case Intrinsic::hexagon_C2_cmplt:
310 case Intrinsic::hexagon_C2_cmpltu:
311 case Intrinsic::hexagon_C2_bitsclri:
312 case Intrinsic::hexagon_C2_and:
313 case Intrinsic::hexagon_C2_or:
314 case Intrinsic::hexagon_C2_xor:
315 case Intrinsic::hexagon_C2_andn:
316 case Intrinsic::hexagon_C2_not:
317 case Intrinsic::hexagon_C2_orn:
318 case Intrinsic::hexagon_C2_pxfer_map:
319 case Intrinsic::hexagon_C2_any8:
320 case Intrinsic::hexagon_C2_all8:
321 case Intrinsic::hexagon_A2_vcmpbeq:
322 case Intrinsic::hexagon_A2_vcmpbgtu:
323 case Intrinsic::hexagon_A2_vcmpheq:
324 case Intrinsic::hexagon_A2_vcmphgt:
325 case Intrinsic::hexagon_A2_vcmphgtu:
326 case Intrinsic::hexagon_A2_vcmpweq:
327 case Intrinsic::hexagon_A2_vcmpwgt:
328 case Intrinsic::hexagon_A2_vcmpwgtu:
329 case Intrinsic::hexagon_C2_tfrrp:
330 case Intrinsic::hexagon_S2_tstbit_i:
331 case Intrinsic::hexagon_S2_tstbit_r:
332 return 1;
333 }
334}
335
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000336static bool OffsetFitsS11(EVT MemType, int64_t Offset) {
337 if (MemType == MVT::i64 && isShiftedInt<11,3>(Offset)) {
338 return true;
339 }
340 if (MemType == MVT::i32 && isShiftedInt<11,2>(Offset)) {
341 return true;
342 }
343 if (MemType == MVT::i16 && isShiftedInt<11,1>(Offset)) {
344 return true;
345 }
346 if (MemType == MVT::i8 && isInt<11>(Offset)) {
347 return true;
348 }
349 return false;
350}
351
352
353//
354// Try to lower loads of GlobalAdresses into base+offset loads. Custom
355// lowering for GlobalAddress nodes has already turned it into a
356// CONST32.
357//
Andrew Trickef9de2a2013-05-25 02:42:55 +0000358SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000359 SDValue Chain = LD->getChain();
360 SDNode* Const32 = LD->getBasePtr().getNode();
361 unsigned Opcode = 0;
362
363 if (Const32->getOpcode() == HexagonISD::CONST32 &&
364 ISD::isNormalLoad(LD)) {
365 SDValue Base = Const32->getOperand(0);
366 EVT LoadedVT = LD->getMemoryVT();
367 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
368 if (Offset != 0 && OffsetFitsS11(LoadedVT, Offset)) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000369 MVT PointerTy = getTargetLowering()->getPointerTy();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000370 const GlobalValue* GV =
371 cast<GlobalAddressSDNode>(Base)->getGlobal();
372 SDValue TargAddr =
373 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0);
Brendon Cahoonf6b687e2012-05-14 19:35:42 +0000374 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
375 dl, PointerTy,
376 TargAddr);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000377 // Figure out base + offset opcode
Colin LeMahieu947cd702014-12-23 20:44:59 +0000378 if (LoadedVT == MVT::i64) Opcode = Hexagon::L2_loadrd_io;
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000379 else if (LoadedVT == MVT::i32) Opcode = Hexagon::L2_loadri_io;
Colin LeMahieu8e39cad2014-12-23 17:25:57 +0000380 else if (LoadedVT == MVT::i16) Opcode = Hexagon::L2_loadrh_io;
Colin LeMahieu4b1eac42014-12-22 21:40:43 +0000381 else if (LoadedVT == MVT::i8) Opcode = Hexagon::L2_loadrb_io;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000382 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000383
384 // Build indexed load.
385 SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy);
386 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
387 LD->getValueType(0),
388 MVT::Other,
389 SDValue(NewBase,0),
390 TargetConstOff,
391 Chain);
392 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
393 MemOp[0] = LD->getMemOperand();
394 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
395 ReplaceUses(LD, Result);
396 return Result;
397 }
398 }
399
400 return SelectCode(LD);
401}
402
403
404SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
405 unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000406 SDLoc dl)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000407{
408 SDValue Chain = LD->getChain();
409 EVT LoadedVT = LD->getMemoryVT();
410 SDValue Base = LD->getBasePtr();
411 SDValue Offset = LD->getOffset();
412 SDNode *OffsetNode = Offset.getNode();
413 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
414 SDValue N1 = LD->getOperand(1);
415 SDValue CPTmpN1_0;
416 SDValue CPTmpN1_1;
Bill Wendling4a7a4082013-06-07 06:19:56 +0000417
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000418 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
419 N1.getNode()->getValueType(0) == MVT::i32) {
Eric Christopher202f22b2015-02-02 19:22:03 +0000420 const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000421 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
422 SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32);
423 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
424 MVT::Other, Base, TargetConst,
425 Chain);
Colin LeMahieueb52f692014-12-11 16:43:06 +0000426 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000427 SDValue(Result_1, 0));
428 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
429 MemOp[0] = LD->getMemOperand();
430 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
431 const SDValue Froms[] = { SDValue(LD, 0),
432 SDValue(LD, 1),
433 SDValue(LD, 2)
434 };
435 const SDValue Tos[] = { SDValue(Result_2, 0),
436 SDValue(Result_1, 1),
437 SDValue(Result_1, 2)
438 };
439 ReplaceUses(Froms, Tos, 3);
440 return Result_2;
Sirish Pandec92c3162012-05-03 16:18:50 +0000441 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000442 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
443 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
444 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
445 MVT::Other, Base, TargetConst0,
446 Chain);
Colin LeMahieueb52f692014-12-11 16:43:06 +0000447 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000448 MVT::i64, SDValue(Result_1, 0));
449 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl,
450 MVT::i32, Base, TargetConstVal,
451 SDValue(Result_1, 1));
452 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
453 MemOp[0] = LD->getMemOperand();
454 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
455 const SDValue Froms[] = { SDValue(LD, 0),
456 SDValue(LD, 1),
457 SDValue(LD, 2)
458 };
459 const SDValue Tos[] = { SDValue(Result_2, 0),
460 SDValue(Result_3, 0),
461 SDValue(Result_1, 1)
462 };
463 ReplaceUses(Froms, Tos, 3);
464 return Result_2;
465 }
466 return SelectCode(LD);
467}
468
469
470SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
471 unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000472 SDLoc dl)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000473{
474 SDValue Chain = LD->getChain();
475 EVT LoadedVT = LD->getMemoryVT();
476 SDValue Base = LD->getBasePtr();
477 SDValue Offset = LD->getOffset();
478 SDNode *OffsetNode = Offset.getNode();
479 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
480 SDValue N1 = LD->getOperand(1);
481 SDValue CPTmpN1_0;
482 SDValue CPTmpN1_1;
Bill Wendling4a7a4082013-06-07 06:19:56 +0000483
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000484 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
485 N1.getNode()->getValueType(0) == MVT::i32) {
Eric Christopher202f22b2015-02-02 19:22:03 +0000486 const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000487 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
488 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
489 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
490 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
491 MVT::i32, MVT::Other, Base,
492 TargetConstVal, Chain);
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000493 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000494 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +0000495 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000496 MVT::i64, MVT::Other,
497 SDValue(Result_2,0),
498 SDValue(Result_1,0));
499 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
500 MemOp[0] = LD->getMemOperand();
501 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
502 const SDValue Froms[] = { SDValue(LD, 0),
503 SDValue(LD, 1),
504 SDValue(LD, 2)
505 };
506 const SDValue Tos[] = { SDValue(Result_3, 0),
507 SDValue(Result_1, 1),
508 SDValue(Result_1, 2)
509 };
510 ReplaceUses(Froms, Tos, 3);
511 return Result_3;
512 }
513
514 // Generate an indirect load.
515 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
516 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
517 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
518 MVT::Other,
519 Base, TargetConst0, Chain);
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000520 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000521 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +0000522 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000523 MVT::i64, MVT::Other,
524 SDValue(Result_2,0),
525 SDValue(Result_1,0));
526 // Add offset to base.
527 SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
528 Base, TargetConstVal,
529 SDValue(Result_1, 1));
530 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
531 MemOp[0] = LD->getMemOperand();
532 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
533 const SDValue Froms[] = { SDValue(LD, 0),
534 SDValue(LD, 1),
535 SDValue(LD, 2)
536 };
537 const SDValue Tos[] = { SDValue(Result_3, 0), // Load value.
538 SDValue(Result_4, 0), // New address.
539 SDValue(Result_1, 1)
540 };
541 ReplaceUses(Froms, Tos, 3);
542 return Result_3;
543 }
544
545 return SelectCode(LD);
546}
547
548
Andrew Trickef9de2a2013-05-25 02:42:55 +0000549SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000550 SDValue Chain = LD->getChain();
551 SDValue Base = LD->getBasePtr();
552 SDValue Offset = LD->getOffset();
553 SDNode *OffsetNode = Offset.getNode();
554 // Get the constant value.
555 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
556 EVT LoadedVT = LD->getMemoryVT();
557 unsigned Opcode = 0;
558
559 // Check for zero ext loads.
560 bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD);
561
562 // Figure out the opcode.
Eric Christopher202f22b2015-02-02 19:22:03 +0000563 const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000564 if (LoadedVT == MVT::i64) {
565 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000566 Opcode = Hexagon::L2_loadrd_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000567 else
Colin LeMahieu947cd702014-12-23 20:44:59 +0000568 Opcode = Hexagon::L2_loadrd_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000569 } else if (LoadedVT == MVT::i32) {
570 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000571 Opcode = Hexagon::L2_loadri_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000572 else
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000573 Opcode = Hexagon::L2_loadri_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000574 } else if (LoadedVT == MVT::i16) {
575 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000576 Opcode = zextval ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000577 else
Colin LeMahieu8e39cad2014-12-23 17:25:57 +0000578 Opcode = zextval ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000579 } else if (LoadedVT == MVT::i8) {
580 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieufe9612e2014-12-26 19:12:11 +0000581 Opcode = zextval ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000582 else
Colin LeMahieu4b1eac42014-12-22 21:40:43 +0000583 Opcode = zextval ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000584 } else
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000585 llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000586
587 // For zero ext i64 loads, we need to add combine instructions.
588 if (LD->getValueType(0) == MVT::i64 &&
589 LD->getExtensionType() == ISD::ZEXTLOAD) {
590 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl);
591 }
592 if (LD->getValueType(0) == MVT::i64 &&
593 LD->getExtensionType() == ISD::SEXTLOAD) {
594 // Handle sign ext i64 loads.
595 return SelectIndexedLoadSignExtend64(LD, Opcode, dl);
596 }
597 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
598 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
599 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
600 LD->getValueType(0),
601 MVT::i32, MVT::Other, Base,
602 TargetConstVal, Chain);
603 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
604 MemOp[0] = LD->getMemOperand();
605 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
606 const SDValue Froms[] = { SDValue(LD, 0),
607 SDValue(LD, 1),
608 SDValue(LD, 2)
609 };
610 const SDValue Tos[] = { SDValue(Result, 0),
611 SDValue(Result, 1),
612 SDValue(Result, 2)
613 };
614 ReplaceUses(Froms, Tos, 3);
615 return Result;
616 } else {
617 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
618 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
619 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl,
620 LD->getValueType(0),
621 MVT::Other, Base, TargetConst0,
622 Chain);
623 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
624 Base, TargetConstVal,
625 SDValue(Result_1, 1));
626 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
627 MemOp[0] = LD->getMemOperand();
628 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
629 const SDValue Froms[] = { SDValue(LD, 0),
630 SDValue(LD, 1),
631 SDValue(LD, 2)
632 };
633 const SDValue Tos[] = { SDValue(Result_1, 0),
634 SDValue(Result_2, 0),
635 SDValue(Result_1, 1)
636 };
637 ReplaceUses(Froms, Tos, 3);
638 return Result_1;
639 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000640}
641
642
643SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
644 SDNode *result;
Andrew Trickef9de2a2013-05-25 02:42:55 +0000645 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000646 LoadSDNode *LD = cast<LoadSDNode>(N);
647 ISD::MemIndexedMode AM = LD->getAddressingMode();
648
649 // Handle indexed loads.
650 if (AM != ISD::UNINDEXED) {
651 result = SelectIndexedLoad(LD, dl);
652 } else {
653 result = SelectBaseOffsetLoad(LD, dl);
654 }
655
656 return result;
657}
658
659
Andrew Trickef9de2a2013-05-25 02:42:55 +0000660SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000661 SDValue Chain = ST->getChain();
662 SDValue Base = ST->getBasePtr();
663 SDValue Offset = ST->getOffset();
664 SDValue Value = ST->getValue();
665 SDNode *OffsetNode = Offset.getNode();
666 // Get the constant value.
667 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
668 EVT StoredVT = ST->getMemoryVT();
669
670 // Offset value must be within representable range
671 // and must have correct alignment properties.
Eric Christopher202f22b2015-02-02 19:22:03 +0000672 const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000673 if (TII->isValidAutoIncImm(StoredVT, Val)) {
Jyotsna Vermab16a9cb2013-01-29 18:42:41 +0000674 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value,
675 Chain};
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000676 unsigned Opcode = 0;
677
678 // Figure out the post inc version of opcode.
Colin LeMahieu9a3cd3f2014-12-29 20:00:43 +0000679 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi;
680 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi;
681 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi;
Colin LeMahieu3d34afb2014-12-29 19:42:14 +0000682 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000683 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000684
685 // Build post increment store.
686 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +0000687 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000688 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
689 MemOp[0] = ST->getMemOperand();
690 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
691
692 ReplaceUses(ST, Result);
693 ReplaceUses(SDValue(ST,1), SDValue(Result,1));
694 return Result;
695 }
696
697 // Note: Order of operands matches the def of instruction:
698 // def STrid : STInst<(outs), (ins MEMri:$addr, DoubleRegs:$src1), ...
699 // and it differs for POST_ST* for instance.
700 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value,
701 Chain};
702 unsigned Opcode = 0;
703
704 // Figure out the opcode.
Colin LeMahieubda31b42014-12-29 20:44:51 +0000705 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
706 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
707 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
708 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000709 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000710
711 // Build regular store.
712 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
Michael Liaob53d8962013-04-19 22:22:57 +0000713 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000714 // Build splitted incriment instruction.
715 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32,
716 Base,
717 TargetConstVal,
718 SDValue(Result_1, 0));
719 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
720 MemOp[0] = ST->getMemOperand();
721 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
722
723 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0));
724 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0));
725 return Result_2;
726}
727
728
729SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000730 SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000731 SDValue Chain = ST->getChain();
732 SDNode* Const32 = ST->getBasePtr().getNode();
733 SDValue Value = ST->getValue();
734 unsigned Opcode = 0;
735
736 // Try to lower stores of GlobalAdresses into indexed stores. Custom
737 // lowering for GlobalAddress nodes has already turned it into a
738 // CONST32. Avoid truncating stores for the moment. Post-inc stores
739 // do the same. Don't think there's a reason for it, so will file a
740 // bug to fix.
741 if ((Const32->getOpcode() == HexagonISD::CONST32) &&
742 !(Value.getValueType() == MVT::i64 && ST->isTruncatingStore())) {
743 SDValue Base = Const32->getOperand(0);
744 if (Base.getOpcode() == ISD::TargetGlobalAddress) {
745 EVT StoredVT = ST->getMemoryVT();
746 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset();
747 if (Offset != 0 && OffsetFitsS11(StoredVT, Offset)) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000748 MVT PointerTy = getTargetLowering()->getPointerTy();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000749 const GlobalValue* GV =
750 cast<GlobalAddressSDNode>(Base)->getGlobal();
751 SDValue TargAddr =
752 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0);
Brendon Cahoonf6b687e2012-05-14 19:35:42 +0000753 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set,
754 dl, PointerTy,
755 TargAddr);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000756
757 // Figure out base + offset opcode
Colin LeMahieubda31b42014-12-29 20:44:51 +0000758 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
759 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
760 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
761 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000762 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000763
764 SDValue Ops[] = {SDValue(NewBase,0),
765 CurDAG->getTargetConstant(Offset,PointerTy),
766 Value, Chain};
767 // build indexed store
768 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
Michael Liaob53d8962013-04-19 22:22:57 +0000769 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000770 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
771 MemOp[0] = ST->getMemOperand();
772 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
773 ReplaceUses(ST, Result);
774 return Result;
775 }
776 }
777 }
778
779 return SelectCode(ST);
780}
781
782
783SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000784 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000785 StoreSDNode *ST = cast<StoreSDNode>(N);
786 ISD::MemIndexedMode AM = ST->getAddressingMode();
787
788 // Handle indexed stores.
789 if (AM != ISD::UNINDEXED) {
790 return SelectIndexedStore(ST, dl);
791 }
Sirish Pandec92c3162012-05-03 16:18:50 +0000792
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000793 return SelectBaseOffsetStore(ST, dl);
794}
795
796SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000797 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000798
799 //
800 // %conv.i = sext i32 %tmp1 to i64
801 // %conv2.i = sext i32 %add to i64
802 // %mul.i = mul nsw i64 %conv2.i, %conv.i
803 //
804 // --- match with the following ---
805 //
806 // %mul.i = mpy (%tmp1, %add)
807 //
808
809 if (N->getValueType(0) == MVT::i64) {
810 // Shifting a i64 signed multiply.
811 SDValue MulOp0 = N->getOperand(0);
812 SDValue MulOp1 = N->getOperand(1);
813
814 SDValue OP0;
815 SDValue OP1;
816
817 // Handle sign_extend and sextload.
818 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
819 SDValue Sext0 = MulOp0.getOperand(0);
820 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000821 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000822 }
823
824 OP0 = Sext0;
825 } else if (MulOp0.getOpcode() == ISD::LOAD) {
826 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
827 if (LD->getMemoryVT() != MVT::i32 ||
828 LD->getExtensionType() != ISD::SEXTLOAD ||
829 LD->getAddressingMode() != ISD::UNINDEXED) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000830 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000831 }
832
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000833 SDValue Chain = LD->getChain();
834 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000835 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000836 MVT::Other,
837 LD->getBasePtr(), TargetConst0,
838 Chain), 0);
839 } else {
840 return SelectCode(N);
841 }
842
843 // Same goes for the second operand.
844 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
845 SDValue Sext1 = MulOp1.getOperand(0);
846 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
847 return SelectCode(N);
848 }
849
850 OP1 = Sext1;
851 } else if (MulOp1.getOpcode() == ISD::LOAD) {
852 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
853 if (LD->getMemoryVT() != MVT::i32 ||
854 LD->getExtensionType() != ISD::SEXTLOAD ||
855 LD->getAddressingMode() != ISD::UNINDEXED) {
856 return SelectCode(N);
857 }
858
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000859 SDValue Chain = LD->getChain();
860 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000861 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000862 MVT::Other,
863 LD->getBasePtr(), TargetConst0,
864 Chain), 0);
865 } else {
866 return SelectCode(N);
867 }
868
869 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +0000870 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000871 OP0, OP1);
872 ReplaceUses(N, Result);
873 return Result;
874 }
875
876 return SelectCode(N);
877}
878
879
880SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000881 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000882 SDValue N0 = N->getOperand(0);
883 if (N0.getOpcode() == ISD::SETCC) {
884 SDValue N00 = N0.getOperand(0);
885 if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) {
886 SDValue N000 = N00.getOperand(0);
887 SDValue N001 = N00.getOperand(1);
888 if (cast<VTSDNode>(N001)->getVT() == MVT::i16) {
889 SDValue N01 = N0.getOperand(1);
890 SDValue N02 = N0.getOperand(2);
891
892 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
893 // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1,
894 // IntRegs:i32:$src2)
895 // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
896 // Pattern complexity = 9 cost = 1 size = 0.
897 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) {
898 SDValue N1 = N->getOperand(1);
899 if (N01 == N1) {
900 SDValue N2 = N->getOperand(2);
901 if (N000 == N2 &&
902 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
903 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
Colin LeMahieu310991c2014-11-21 21:54:59 +0000904 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000905 MVT::i32, N000);
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000906 SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_max, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000907 MVT::i32,
908 SDValue(SextNode, 0),
909 N1);
910 ReplaceUses(N, Result);
911 return Result;
912 }
913 }
914 }
915
916 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
917 // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1,
918 // IntRegs:i32:$src2)
919 // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
920 // Pattern complexity = 9 cost = 1 size = 0.
921 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) {
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) {
Colin LeMahieu310991c2014-11-21 21:54:59 +0000928 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000929 MVT::i32, N000);
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000930 SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_min, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000931 MVT::i32,
932 SDValue(SextNode, 0),
933 N1);
934 ReplaceUses(N, Result);
935 return Result;
936 }
937 }
938 }
939 }
940 }
941 }
942
943 return SelectCode(N);
944}
945
946
947SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000948 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000949 SDValue Shift = N->getOperand(0);
950
951 //
952 // %conv.i = sext i32 %tmp1 to i64
953 // %conv2.i = sext i32 %add to i64
954 // %mul.i = mul nsw i64 %conv2.i, %conv.i
955 // %shr5.i = lshr i64 %mul.i, 32
956 // %conv3.i = trunc i64 %shr5.i to i32
957 //
958 // --- match with the following ---
959 //
960 // %conv3.i = mpy (%tmp1, %add)
961 //
962 // Trunc to i32.
963 if (N->getValueType(0) == MVT::i32) {
964 // Trunc from i64.
965 if (Shift.getNode()->getValueType(0) == MVT::i64) {
966 // Trunc child is logical shift right.
967 if (Shift.getOpcode() != ISD::SRL) {
968 return SelectCode(N);
969 }
970
971 SDValue ShiftOp0 = Shift.getOperand(0);
972 SDValue ShiftOp1 = Shift.getOperand(1);
973
974 // Shift by const 32
975 if (ShiftOp1.getOpcode() != ISD::Constant) {
976 return SelectCode(N);
977 }
978
979 int32_t ShiftConst =
980 cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue();
981 if (ShiftConst != 32) {
982 return SelectCode(N);
983 }
984
985 // Shifting a i64 signed multiply
986 SDValue Mul = ShiftOp0;
987 if (Mul.getOpcode() != ISD::MUL) {
988 return SelectCode(N);
989 }
990
991 SDValue MulOp0 = Mul.getOperand(0);
992 SDValue MulOp1 = Mul.getOperand(1);
993
994 SDValue OP0;
995 SDValue OP1;
996
997 // Handle sign_extend and sextload
998 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
999 SDValue Sext0 = MulOp0.getOperand(0);
1000 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
1001 return SelectCode(N);
1002 }
1003
1004 OP0 = Sext0;
1005 } else if (MulOp0.getOpcode() == ISD::LOAD) {
1006 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
1007 if (LD->getMemoryVT() != MVT::i32 ||
1008 LD->getExtensionType() != ISD::SEXTLOAD ||
1009 LD->getAddressingMode() != ISD::UNINDEXED) {
1010 return SelectCode(N);
1011 }
1012
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001013 SDValue Chain = LD->getChain();
1014 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +00001015 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001016 MVT::Other,
1017 LD->getBasePtr(),
1018 TargetConst0, Chain), 0);
1019 } else {
1020 return SelectCode(N);
1021 }
1022
1023 // Same goes for the second operand.
1024 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
1025 SDValue Sext1 = MulOp1.getOperand(0);
1026 if (Sext1.getNode()->getValueType(0) != MVT::i32)
1027 return SelectCode(N);
1028
1029 OP1 = Sext1;
1030 } else if (MulOp1.getOpcode() == ISD::LOAD) {
1031 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
1032 if (LD->getMemoryVT() != MVT::i32 ||
1033 LD->getExtensionType() != ISD::SEXTLOAD ||
1034 LD->getAddressingMode() != ISD::UNINDEXED) {
1035 return SelectCode(N);
1036 }
1037
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001038 SDValue Chain = LD->getChain();
1039 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +00001040 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001041 MVT::Other,
1042 LD->getBasePtr(),
1043 TargetConst0, Chain), 0);
1044 } else {
1045 return SelectCode(N);
1046 }
1047
1048 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +00001049 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpy_up, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001050 OP0, OP1);
1051 ReplaceUses(N, Result);
1052 return Result;
1053 }
1054 }
1055
1056 return SelectCode(N);
1057}
1058
1059
1060SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001061 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001062 if (N->getValueType(0) == MVT::i32) {
1063 SDValue Shl_0 = N->getOperand(0);
1064 SDValue Shl_1 = N->getOperand(1);
1065 // RHS is const.
1066 if (Shl_1.getOpcode() == ISD::Constant) {
1067 if (Shl_0.getOpcode() == ISD::MUL) {
1068 SDValue Mul_0 = Shl_0.getOperand(0); // Val
1069 SDValue Mul_1 = Shl_0.getOperand(1); // Const
1070 // RHS of mul is const.
1071 if (Mul_1.getOpcode() == ISD::Constant) {
1072 int32_t ShlConst =
1073 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1074 int32_t MulConst =
1075 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
1076 int32_t ValConst = MulConst << ShlConst;
1077 SDValue Val = CurDAG->getTargetConstant(ValConst,
1078 MVT::i32);
1079 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
1080 if (isInt<9>(CN->getSExtValue())) {
1081 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +00001082 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001083 MVT::i32, Mul_0, Val);
1084 ReplaceUses(N, Result);
1085 return Result;
1086 }
1087
1088 }
1089 } else if (Shl_0.getOpcode() == ISD::SUB) {
1090 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
1091 SDValue Sub_1 = Shl_0.getOperand(1); // Val
1092 if (Sub_0.getOpcode() == ISD::Constant) {
1093 int32_t SubConst =
1094 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
1095 if (SubConst == 0) {
1096 if (Sub_1.getOpcode() == ISD::SHL) {
1097 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
1098 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
1099 if (Shl2_1.getOpcode() == ISD::Constant) {
1100 int32_t ShlConst =
1101 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
1102 int32_t Shl2Const =
1103 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
1104 int32_t ValConst = 1 << (ShlConst+Shl2Const);
1105 SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32);
1106 if (ConstantSDNode *CN =
1107 dyn_cast<ConstantSDNode>(Val.getNode()))
1108 if (isInt<9>(CN->getSExtValue())) {
1109 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +00001110 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001111 Shl2_0, Val);
1112 ReplaceUses(N, Result);
1113 return Result;
1114 }
1115 }
1116 }
1117 }
1118 }
1119 }
1120 }
1121 }
1122 return SelectCode(N);
1123}
1124
1125
1126//
1127// If there is an zero_extend followed an intrinsic in DAG (this means - the
1128// result of the intrinsic is predicate); convert the zero_extend to
1129// transfer instruction.
1130//
1131// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
1132// converted into a MUX as predicate registers defined as 1 bit in the
1133// compiler. Architecture defines them as 8-bit registers.
1134// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
1135//
1136SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001137 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001138 SDNode *IsIntrinsic = N->getOperand(0).getNode();
1139 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
1140 unsigned ID =
1141 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
1142 if (doesIntrinsicReturnPredicate(ID)) {
1143 // Now we need to differentiate target data types.
1144 if (N->getValueType(0) == MVT::i64) {
1145 // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs).
1146 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001147 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001148 MVT::i32,
1149 SDValue(IsIntrinsic, 0));
Colin LeMahieu4af437f2014-12-09 20:23:30 +00001150 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001151 MVT::i32,
1152 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +00001153 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001154 MVT::i64, MVT::Other,
1155 SDValue(Result_2, 0),
1156 SDValue(Result_1, 0));
1157 ReplaceUses(N, Result_3);
1158 return Result_3;
1159 }
1160 if (N->getValueType(0) == MVT::i32) {
1161 // Convert the zero_extend to Rs = Pd
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001162 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001163 MVT::i32,
1164 SDValue(IsIntrinsic, 0));
1165 ReplaceUses(N, RsPd);
1166 return RsPd;
1167 }
Craig Toppere55c5562012-02-07 02:50:20 +00001168 llvm_unreachable("Unexpected value type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001169 }
1170 }
1171 return SelectCode(N);
1172}
1173
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001174//
1175// Checking for intrinsics which have predicate registers as operand(s)
1176// and lowering to the actual intrinsic.
1177//
1178SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001179 unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
1180 unsigned Bits;
1181 switch (IID) {
1182 case Intrinsic::hexagon_S2_vsplatrb:
1183 Bits = 8;
1184 break;
1185 case Intrinsic::hexagon_S2_vsplatrh:
1186 Bits = 16;
1187 break;
1188 default:
1189 return SelectCode(N);
1190 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001191
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001192 SDValue const &V = N->getOperand(1);
1193 SDValue U;
1194 if (isValueExtension(V, Bits, U)) {
1195 SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
1196 N->getOperand(0), U);
1197 return SelectCode(R.getNode());
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001198 }
1199 return SelectCode(N);
1200}
1201
Sirish Pande69295b82012-05-10 20:20:25 +00001202//
1203// Map floating point constant values.
1204//
1205SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001206 SDLoc dl(N);
Sirish Pande69295b82012-05-10 20:20:25 +00001207 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
1208 APFloat APF = CN->getValueAPF();
1209 if (N->getValueType(0) == MVT::f32) {
1210 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
1211 CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32));
1212 }
1213 else if (N->getValueType(0) == MVT::f64) {
1214 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
1215 CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64));
1216 }
1217
1218 return SelectCode(N);
1219}
1220
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001221
1222//
1223// Map predicate true (encoded as -1 in LLVM) to a XOR.
1224//
1225SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001226 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001227 if (N->getValueType(0) == MVT::i1) {
1228 SDNode* Result;
1229 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
1230 if (Val == -1) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001231 // Create the IntReg = 1 node.
1232 SDNode* IntRegTFR =
Colin LeMahieu4af437f2014-12-09 20:23:30 +00001233 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001234 CurDAG->getTargetConstant(0, MVT::i32));
1235
1236 // Pd = IntReg
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001237 SDNode* Pd = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001238 SDValue(IntRegTFR, 0));
1239
1240 // not(Pd)
Colin LeMahieu5cf56322014-12-08 23:55:43 +00001241 SDNode* NotPd = CurDAG->getMachineNode(Hexagon::C2_not, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001242 SDValue(Pd, 0));
1243
1244 // xor(not(Pd))
Colin LeMahieu5cf56322014-12-08 23:55:43 +00001245 Result = CurDAG->getMachineNode(Hexagon::C2_xor, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001246 SDValue(Pd, 0), SDValue(NotPd, 0));
1247
1248 // We have just built:
1249 // Rs = Pd
1250 // Pd = xor(not(Pd), Pd)
1251
1252 ReplaceUses(N, Result);
1253 return Result;
1254 }
1255 }
1256
1257 return SelectCode(N);
1258}
1259
1260
1261//
1262// Map add followed by a asr -> asr +=.
1263//
1264SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001265 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001266 if (N->getValueType(0) != MVT::i32) {
1267 return SelectCode(N);
1268 }
1269 // Identify nodes of the form: add(asr(...)).
1270 SDNode* Src1 = N->getOperand(0).getNode();
1271 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1272 || Src1->getValueType(0) != MVT::i32) {
1273 return SelectCode(N);
1274 }
1275
1276 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1277 // Rd and Rd' are assigned to the same register
Colin LeMahieu0f850bd2014-12-19 20:29:29 +00001278 SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001279 N->getOperand(1),
1280 Src1->getOperand(0),
1281 Src1->getOperand(1));
1282 ReplaceUses(N, Result);
1283
1284 return Result;
1285}
1286
1287
1288SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
Tim Northover31d093c2013-09-22 08:21:56 +00001289 if (N->isMachineOpcode()) {
1290 N->setNodeId(-1);
Craig Topper062a2ba2014-04-25 05:30:21 +00001291 return nullptr; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00001292 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001293
1294
1295 switch (N->getOpcode()) {
1296 case ISD::Constant:
1297 return SelectConstant(N);
1298
Sirish Pande69295b82012-05-10 20:20:25 +00001299 case ISD::ConstantFP:
1300 return SelectConstantFP(N);
1301
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001302 case ISD::ADD:
1303 return SelectAdd(N);
1304
1305 case ISD::SHL:
1306 return SelectSHL(N);
1307
1308 case ISD::LOAD:
1309 return SelectLoad(N);
1310
1311 case ISD::STORE:
1312 return SelectStore(N);
1313
1314 case ISD::SELECT:
1315 return SelectSelect(N);
1316
1317 case ISD::TRUNCATE:
1318 return SelectTruncate(N);
1319
1320 case ISD::MUL:
1321 return SelectMul(N);
1322
1323 case ISD::ZERO_EXTEND:
1324 return SelectZeroExtend(N);
1325
1326 case ISD::INTRINSIC_WO_CHAIN:
1327 return SelectIntrinsicWOChain(N);
1328 }
1329
1330 return SelectCode(N);
1331}
1332
1333
1334//
1335// Hexagon_TODO: Five functions for ADDRri?! Surely there must be a better way
1336// to define these instructions.
1337//
1338bool HexagonDAGToDAGISel::SelectADDRri(SDValue& Addr, SDValue &Base,
1339 SDValue &Offset) {
1340 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1341 Addr.getOpcode() == ISD::TargetGlobalAddress)
1342 return false; // Direct calls.
1343
1344 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1345 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1346 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1347 return true;
1348 }
1349 Base = Addr;
1350 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1351 return true;
1352}
1353
1354
1355bool HexagonDAGToDAGISel::SelectADDRriS11_0(SDValue& Addr, SDValue &Base,
1356 SDValue &Offset) {
1357 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1358 Addr.getOpcode() == ISD::TargetGlobalAddress)
1359 return false; // Direct calls.
1360
1361 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1362 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1363 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1364 return (IsS11_0_Offset(Offset.getNode()));
1365 }
1366 Base = Addr;
1367 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1368 return (IsS11_0_Offset(Offset.getNode()));
1369}
1370
1371
1372bool HexagonDAGToDAGISel::SelectADDRriS11_1(SDValue& Addr, SDValue &Base,
1373 SDValue &Offset) {
1374 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1375 Addr.getOpcode() == ISD::TargetGlobalAddress)
1376 return false; // Direct calls.
1377
1378 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1379 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1380 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1381 return (IsS11_1_Offset(Offset.getNode()));
1382 }
1383 Base = Addr;
1384 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1385 return (IsS11_1_Offset(Offset.getNode()));
1386}
1387
1388
1389bool HexagonDAGToDAGISel::SelectADDRriS11_2(SDValue& Addr, SDValue &Base,
1390 SDValue &Offset) {
1391 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1392 Addr.getOpcode() == ISD::TargetGlobalAddress)
1393 return false; // Direct calls.
1394
1395 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1396 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1397 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1398 return (IsS11_2_Offset(Offset.getNode()));
1399 }
1400 Base = Addr;
1401 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1402 return (IsS11_2_Offset(Offset.getNode()));
1403}
1404
1405
1406bool HexagonDAGToDAGISel::SelectADDRriU6_0(SDValue& Addr, SDValue &Base,
1407 SDValue &Offset) {
1408 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1409 Addr.getOpcode() == ISD::TargetGlobalAddress)
1410 return false; // Direct calls.
1411
1412 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1413 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1414 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1415 return (IsU6_0_Offset(Offset.getNode()));
1416 }
1417 Base = Addr;
1418 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1419 return (IsU6_0_Offset(Offset.getNode()));
1420}
1421
1422
1423bool HexagonDAGToDAGISel::SelectADDRriU6_1(SDValue& Addr, SDValue &Base,
1424 SDValue &Offset) {
1425 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1426 Addr.getOpcode() == ISD::TargetGlobalAddress)
1427 return false; // Direct calls.
1428
1429 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1430 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1431 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1432 return (IsU6_1_Offset(Offset.getNode()));
1433 }
1434 Base = Addr;
1435 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1436 return (IsU6_1_Offset(Offset.getNode()));
1437}
1438
1439
1440bool HexagonDAGToDAGISel::SelectADDRriU6_2(SDValue& Addr, SDValue &Base,
1441 SDValue &Offset) {
1442 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1443 Addr.getOpcode() == ISD::TargetGlobalAddress)
1444 return false; // Direct calls.
1445
1446 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1447 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1448 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1449 return (IsU6_2_Offset(Offset.getNode()));
1450 }
1451 Base = Addr;
1452 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1453 return (IsU6_2_Offset(Offset.getNode()));
1454}
1455
1456
1457bool HexagonDAGToDAGISel::SelectMEMriS11_2(SDValue& Addr, SDValue &Base,
1458 SDValue &Offset) {
1459
1460 if (Addr.getOpcode() != ISD::ADD) {
1461 return(SelectADDRriS11_2(Addr, Base, Offset));
1462 }
1463
1464 return SelectADDRriS11_2(Addr, Base, Offset);
1465}
1466
1467
1468bool HexagonDAGToDAGISel::SelectADDRriS11_3(SDValue& Addr, SDValue &Base,
1469 SDValue &Offset) {
1470 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1471 Addr.getOpcode() == ISD::TargetGlobalAddress)
1472 return false; // Direct calls.
1473
1474 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1475 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1476 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1477 return (IsS11_3_Offset(Offset.getNode()));
1478 }
1479 Base = Addr;
1480 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1481 return (IsS11_3_Offset(Offset.getNode()));
1482}
1483
1484bool HexagonDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1,
1485 SDValue &R2) {
1486 if (Addr.getOpcode() == ISD::FrameIndex) return false;
1487 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1488 Addr.getOpcode() == ISD::TargetGlobalAddress)
1489 return false; // Direct calls.
1490
1491 if (Addr.getOpcode() == ISD::ADD) {
1492 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
1493 if (isInt<13>(CN->getSExtValue()))
1494 return false; // Let the reg+imm pattern catch this!
1495 R1 = Addr.getOperand(0);
1496 R2 = Addr.getOperand(1);
1497 return true;
1498 }
1499
1500 R1 = Addr;
1501
1502 return true;
1503}
1504
1505
1506// Handle generic address case. It is accessed from inlined asm =m constraints,
1507// which could have any kind of pointer.
1508bool HexagonDAGToDAGISel::SelectAddr(SDNode *Op, SDValue Addr,
1509 SDValue &Base, SDValue &Offset) {
1510 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1511 Addr.getOpcode() == ISD::TargetGlobalAddress)
1512 return false; // Direct calls.
1513
1514 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1515 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1516 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1517 return true;
1518 }
1519
1520 if (Addr.getOpcode() == ISD::ADD) {
1521 Base = Addr.getOperand(0);
1522 Offset = Addr.getOperand(1);
1523 return true;
1524 }
1525
1526 Base = Addr;
1527 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1528 return true;
1529}
1530
1531
1532bool HexagonDAGToDAGISel::
1533SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
1534 std::vector<SDValue> &OutOps) {
1535 SDValue Op0, Op1;
1536
1537 switch (ConstraintCode) {
1538 case 'o': // Offsetable.
1539 case 'v': // Not offsetable.
1540 default: return true;
1541 case 'm': // Memory.
1542 if (!SelectAddr(Op.getNode(), Op, Op0, Op1))
1543 return true;
1544 break;
1545 }
1546
1547 OutOps.push_back(Op0);
1548 OutOps.push_back(Op1);
1549 return false;
1550}
Jyotsna Verma519b3852012-11-28 20:58:14 +00001551
1552bool HexagonDAGToDAGISel::isConstExtProfitable(SDNode *N) const {
1553 unsigned UseCount = 0;
1554 for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
1555 UseCount++;
1556 }
1557
1558 return (UseCount <= 1);
1559
1560}
Jyotsna Vermad9225242013-02-13 21:38:46 +00001561
1562//===--------------------------------------------------------------------===//
1563// Return 'true' if use count of the global address is below threshold.
1564//===--------------------------------------------------------------------===//
1565bool HexagonDAGToDAGISel::hasNumUsesBelowThresGA(SDNode *N) const {
1566 assert(N->getOpcode() == ISD::TargetGlobalAddress &&
1567 "Expecting a target global address");
1568
1569 // Always try to fold the address.
1570 if (TM.getOptLevel() == CodeGenOpt::Aggressive)
1571 return true;
1572
1573 GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N);
1574 DenseMap<const GlobalValue *, unsigned>::const_iterator GI =
1575 GlobalAddressUseCountMap.find(GA->getGlobal());
1576
1577 if (GI == GlobalAddressUseCountMap.end())
1578 return false;
1579
1580 return GI->second <= MaxNumOfUsesForConstExtenders;
1581}
1582
1583//===--------------------------------------------------------------------===//
Alp Tokerf907b892013-12-05 05:44:44 +00001584// Return true if the non-GP-relative global address can be folded.
Jyotsna Vermad9225242013-02-13 21:38:46 +00001585//===--------------------------------------------------------------------===//
1586inline bool HexagonDAGToDAGISel::foldGlobalAddress(SDValue &N, SDValue &R) {
1587 return foldGlobalAddressImpl(N, R, false);
1588}
1589
1590//===--------------------------------------------------------------------===//
1591// Return true if the GP-relative global address can be folded.
1592//===--------------------------------------------------------------------===//
1593inline bool HexagonDAGToDAGISel::foldGlobalAddressGP(SDValue &N, SDValue &R) {
1594 return foldGlobalAddressImpl(N, R, true);
1595}
1596
1597//===--------------------------------------------------------------------===//
1598// Fold offset of the global address if number of uses are below threshold.
1599//===--------------------------------------------------------------------===//
1600bool HexagonDAGToDAGISel::foldGlobalAddressImpl(SDValue &N, SDValue &R,
1601 bool ShouldLookForGP) {
1602 if (N.getOpcode() == ISD::ADD) {
1603 SDValue N0 = N.getOperand(0);
1604 SDValue N1 = N.getOperand(1);
1605 if ((ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32_GP)) ||
1606 (!ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32))) {
1607 ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1);
1608 GlobalAddressSDNode *GA =
1609 dyn_cast<GlobalAddressSDNode>(N0.getOperand(0));
1610
1611 if (Const && GA &&
1612 (GA->getOpcode() == ISD::TargetGlobalAddress)) {
1613 if ((N0.getOpcode() == HexagonISD::CONST32) &&
1614 !hasNumUsesBelowThresGA(GA))
1615 return false;
1616 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(),
Andrew Trickef9de2a2013-05-25 02:42:55 +00001617 SDLoc(Const),
Jyotsna Vermad9225242013-02-13 21:38:46 +00001618 N.getValueType(),
1619 GA->getOffset() +
1620 (uint64_t)Const->getSExtValue());
1621 return true;
1622 }
1623 }
1624 }
1625 return false;
1626}
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001627
1628bool HexagonDAGToDAGISel::SelectAddrFI(SDValue& N, SDValue &R) {
1629 if (N.getOpcode() != ISD::FrameIndex)
1630 return false;
1631 FrameIndexSDNode *FX = cast<FrameIndexSDNode>(N);
1632 R = CurDAG->getTargetFrameIndex(FX->getIndex(), MVT::i32);
1633 return true;
1634}
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001635
Colin LeMahieu987b0942015-02-04 20:38:01 +00001636inline bool HexagonDAGToDAGISel::SelectAddrGA(SDValue &N, SDValue &R) {
1637 return SelectGlobalAddress(N, R, false);
1638}
1639
1640bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R,
1641 bool UseGP) {
1642 switch (N.getOpcode()) {
1643 case ISD::ADD: {
1644 SDValue N0 = N.getOperand(0);
1645 SDValue N1 = N.getOperand(1);
1646 unsigned GAOpc = N0.getOpcode();
1647 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1648 return false;
1649 if (!UseGP && GAOpc != HexagonISD::CONST32)
1650 return false;
1651 if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1)) {
1652 SDValue Addr = N0.getOperand(0);
1653 if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Addr)) {
1654 if (GA->getOpcode() == ISD::TargetGlobalAddress) {
1655 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1656 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const),
1657 N.getValueType(), NewOff);
1658 return true;
1659 }
1660 }
1661 }
1662 break;
1663 }
1664 case HexagonISD::CONST32:
1665 // The operand(0) of CONST32 is TargetGlobalAddress, which is what we
1666 // want in the instruction.
1667 if (!UseGP)
1668 R = N.getOperand(0);
1669 return !UseGP;
1670 case HexagonISD::CONST32_GP:
1671 if (UseGP)
1672 R = N.getOperand(0);
1673 return UseGP;
1674 default:
1675 return false;
1676 }
1677
1678 return false;
1679}
1680
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001681bool HexagonDAGToDAGISel::isValueExtension(SDValue const &Val,
1682 unsigned FromBits, SDValue &Src) {
1683 unsigned Opc = Val.getOpcode();
1684 switch (Opc) {
1685 case ISD::SIGN_EXTEND:
1686 case ISD::ZERO_EXTEND:
1687 case ISD::ANY_EXTEND: {
1688 SDValue const &Op0 = Val.getOperand(0);
1689 EVT T = Op0.getValueType();
1690 if (T.isInteger() && T.getSizeInBits() == FromBits) {
1691 Src = Op0;
1692 return true;
1693 }
1694 break;
1695 }
1696 case ISD::SIGN_EXTEND_INREG:
1697 case ISD::AssertSext:
1698 case ISD::AssertZext:
1699 if (Val.getOperand(0).getValueType().isInteger()) {
1700 VTSDNode *T = cast<VTSDNode>(Val.getOperand(1));
1701 if (T->getVT().getSizeInBits() == FromBits) {
1702 Src = Val.getOperand(0);
1703 return true;
1704 }
1705 }
1706 break;
1707 case ISD::AND: {
1708 // Check if this is an AND with "FromBits" of lower bits set to 1.
1709 uint64_t FromMask = (1 << FromBits) - 1;
1710 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1711 if (C->getZExtValue() == FromMask) {
1712 Src = Val.getOperand(1);
1713 return true;
1714 }
1715 }
1716 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1717 if (C->getZExtValue() == FromMask) {
1718 Src = Val.getOperand(0);
1719 return true;
1720 }
1721 }
1722 break;
1723 }
1724 case ISD::OR:
1725 case ISD::XOR: {
1726 // OR/XOR with the lower "FromBits" bits set to 0.
1727 uint64_t FromMask = (1 << FromBits) - 1;
1728 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1729 if ((C->getZExtValue() & FromMask) == 0) {
1730 Src = Val.getOperand(1);
1731 return true;
1732 }
1733 }
1734 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1735 if ((C->getZExtValue() & FromMask) == 0) {
1736 Src = Val.getOperand(0);
1737 return true;
1738 }
1739 }
1740 }
1741 default:
1742 break;
1743 }
1744 return false;
1745}