blob: 9981705c5f889c985808c1dd995fdff489378789 [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;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000054public:
Bill Wendlinga3cd3502013-06-19 21:36:55 +000055 explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine,
Jyotsna Vermad9225242013-02-13 21:38:46 +000056 CodeGenOpt::Level OptLevel)
Eric Christopher202f22b2015-02-02 19:22:03 +000057 : SelectionDAGISel(targetmachine, OptLevel), TM(targetmachine) {
Jyotsna Vermad9225242013-02-13 21:38:46 +000058 initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry());
Tony Linthicum1213a7a2011-12-12 21:14:40 +000059 }
60
Craig Topper906c2cd2014-04-29 07:58:16 +000061 SDNode *Select(SDNode *N) override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000062
63 // Complex Pattern Selectors.
Jyotsna Vermad9225242013-02-13 21:38:46 +000064 inline bool foldGlobalAddress(SDValue &N, SDValue &R);
65 inline bool foldGlobalAddressGP(SDValue &N, SDValue &R);
66 bool foldGlobalAddressImpl(SDValue &N, SDValue &R, bool ShouldLookForGP);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000067 bool SelectADDRri(SDValue& N, SDValue &R1, SDValue &R2);
68 bool SelectADDRriS11_0(SDValue& N, SDValue &R1, SDValue &R2);
69 bool SelectADDRriS11_1(SDValue& N, SDValue &R1, SDValue &R2);
70 bool SelectADDRriS11_2(SDValue& N, SDValue &R1, SDValue &R2);
71 bool SelectMEMriS11_2(SDValue& Addr, SDValue &Base, SDValue &Offset);
72 bool SelectADDRriS11_3(SDValue& N, SDValue &R1, SDValue &R2);
73 bool SelectADDRrr(SDValue &Addr, SDValue &Base, SDValue &Offset);
74 bool SelectADDRriU6_0(SDValue& N, SDValue &R1, SDValue &R2);
75 bool SelectADDRriU6_1(SDValue& N, SDValue &R1, SDValue &R2);
76 bool SelectADDRriU6_2(SDValue& N, SDValue &R1, SDValue &R2);
77
Colin LeMahieu987b0942015-02-04 20:38:01 +000078 // Complex Pattern Selectors.
79 inline bool SelectAddrGA(SDValue &N, SDValue &R);
Colin LeMahieu51491352015-02-04 22:36:28 +000080 inline bool SelectAddrGP(SDValue &N, SDValue &R);
Colin LeMahieu987b0942015-02-04 20:38:01 +000081 bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP);
Colin LeMahieuc7522f32015-01-14 23:07:36 +000082 bool SelectAddrFI(SDValue &N, SDValue &R);
83
Craig Topper906c2cd2014-04-29 07:58:16 +000084 const char *getPassName() const override {
Tony Linthicum1213a7a2011-12-12 21:14:40 +000085 return "Hexagon DAG->DAG Pattern Instruction Selection";
86 }
87
Eric Christopher202f22b2015-02-02 19:22:03 +000088 bool runOnMachineFunction(MachineFunction &MF) override {
89 Subtarget = &MF.getSubtarget<HexagonSubtarget>();
90 return SelectionDAGISel::runOnMachineFunction(MF);
91 }
92
Tony Linthicum1213a7a2011-12-12 21:14:40 +000093 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
94 /// inline asm expressions.
Craig Topper906c2cd2014-04-29 07:58:16 +000095 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
Daniel Sanders41c072e2015-03-12 11:00:48 +000096 unsigned ConstraintID,
Craig Topper906c2cd2014-04-29 07:58:16 +000097 std::vector<SDValue> &OutOps) override;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000098 bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset);
99
100 SDNode *SelectLoad(SDNode *N);
Andrew Trickef9de2a2013-05-25 02:42:55 +0000101 SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl);
102 SDNode *SelectIndexedLoad(LoadSDNode *LD, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000103 SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000104 SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000105 SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000106 SDLoc dl);
107 SDNode *SelectBaseOffsetStore(StoreSDNode *ST, SDLoc dl);
108 SDNode *SelectIndexedStore(StoreSDNode *ST, SDLoc dl);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000109 SDNode *SelectStore(SDNode *N);
110 SDNode *SelectSHL(SDNode *N);
111 SDNode *SelectSelect(SDNode *N);
112 SDNode *SelectTruncate(SDNode *N);
113 SDNode *SelectMul(SDNode *N);
114 SDNode *SelectZeroExtend(SDNode *N);
115 SDNode *SelectIntrinsicWOChain(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000116 SDNode *SelectIntrinsicWChain(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000117 SDNode *SelectConstant(SDNode *N);
Sirish Pande69295b82012-05-10 20:20:25 +0000118 SDNode *SelectConstantFP(SDNode *N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000119 SDNode *SelectAdd(SDNode *N);
120
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000121// XformMskToBitPosU5Imm - Returns the bit position which
122// the single bit 32 bit mask represents.
123// Used in Clr and Set bit immediate memops.
124SDValue XformMskToBitPosU5Imm(uint32_t Imm) {
125 int32_t bitPos;
126 bitPos = Log2_32(Imm);
127 assert(bitPos >= 0 && bitPos < 32 &&
128 "Constant out of range for 32 BitPos Memops");
129 return CurDAG->getTargetConstant(bitPos, MVT::i32);
130}
131
132// XformMskToBitPosU4Imm - Returns the bit position which the single bit 16 bit
133// mask represents. Used in Clr and Set bit immediate memops.
134SDValue XformMskToBitPosU4Imm(uint16_t Imm) {
135 return XformMskToBitPosU5Imm(Imm);
136}
137
138// XformMskToBitPosU3Imm - Returns the bit position which the single bit 8 bit
139// mask represents. Used in Clr and Set bit immediate memops.
140SDValue XformMskToBitPosU3Imm(uint8_t Imm) {
141 return XformMskToBitPosU5Imm(Imm);
142}
143
144// Return true if there is exactly one bit set in V, i.e., if V is one of the
145// following integers: 2^0, 2^1, ..., 2^31.
146bool ImmIsSingleBit(uint32_t v) const {
Benjamin Kramer5f6a9072015-02-12 15:35:40 +0000147 return isPowerOf2_32(v);
Jyotsna Vermafdc660b2013-03-22 18:41:34 +0000148}
149
150// XformM5ToU5Imm - Return a target constant with the specified value, of type
151// i32 where the negative literal is transformed into a positive literal for
152// use in -= memops.
153inline SDValue XformM5ToU5Imm(signed Imm) {
154 assert( (Imm >= -31 && Imm <= -1) && "Constant out of range for Memops");
155 return CurDAG->getTargetConstant( - Imm, MVT::i32);
156}
157
158
Jyotsna Verma60316252013-02-05 19:20:45 +0000159// XformU7ToU7M1Imm - Return a target constant decremented by 1, in range
160// [1..128], used in cmpb.gtu instructions.
161inline SDValue XformU7ToU7M1Imm(signed Imm) {
162 assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op");
163 return CurDAG->getTargetConstant(Imm - 1, MVT::i8);
164}
165
Jyotsna Verma89c84822013-04-23 19:15:55 +0000166// XformS8ToS8M1Imm - Return a target constant decremented by 1.
167inline SDValue XformSToSM1Imm(signed Imm) {
168 return CurDAG->getTargetConstant(Imm - 1, MVT::i32);
169}
170
171// XformU8ToU8M1Imm - Return a target constant decremented by 1.
172inline SDValue XformUToUM1Imm(unsigned Imm) {
173 assert((Imm >= 1) && "Cannot decrement unsigned int less than 1");
174 return CurDAG->getTargetConstant(Imm - 1, MVT::i32);
175}
176
Colin LeMahieu19ed07c2015-01-28 18:29:11 +0000177// XformSToSM2Imm - Return a target constant decremented by 2.
178inline SDValue XformSToSM2Imm(unsigned Imm) {
179 return CurDAG->getTargetConstant(Imm - 2, MVT::i32);
180}
181
182// XformSToSM3Imm - Return a target constant decremented by 3.
183inline SDValue XformSToSM3Imm(unsigned Imm) {
184 return CurDAG->getTargetConstant(Imm - 3, MVT::i32);
185}
186
Jyotsna Verma60316252013-02-05 19:20:45 +0000187// Include the pieces autogenerated from the target description.
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000188#include "HexagonGenDAGISel.inc"
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +0000189
190private:
191 bool isValueExtension(SDValue const &Val, unsigned FromBits, SDValue &Src);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000192};
193} // end anonymous namespace
194
195
196/// createHexagonISelDag - This pass converts a legalized DAG into a
197/// Hexagon-specific DAG, ready for instruction scheduling.
198///
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000199FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM,
Jyotsna Vermad9225242013-02-13 21:38:46 +0000200 CodeGenOpt::Level OptLevel) {
201 return new HexagonDAGToDAGISel(TM, OptLevel);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000202}
203
Jyotsna Vermad9225242013-02-13 21:38:46 +0000204static void initializePassOnce(PassRegistry &Registry) {
205 const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection";
206 PassInfo *PI = new PassInfo(Name, "hexagon-isel",
Craig Topper062a2ba2014-04-25 05:30:21 +0000207 &SelectionDAGISel::ID, nullptr, false, false);
Jyotsna Vermad9225242013-02-13 21:38:46 +0000208 Registry.registerPass(*PI, true);
209}
210
211void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) {
212 CALL_ONCE_INITIALIZATION(initializePassOnce)
213}
214
215
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000216static bool IsS11_0_Offset(SDNode * S) {
217 ConstantSDNode *N = cast<ConstantSDNode>(S);
218
219 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
220 // field.
221 int64_t v = (int64_t)N->getSExtValue();
222 return isInt<11>(v);
223}
224
225
226static bool IsS11_1_Offset(SDNode * S) {
227 ConstantSDNode *N = cast<ConstantSDNode>(S);
228
229 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
230 // field.
231 int64_t v = (int64_t)N->getSExtValue();
232 return isShiftedInt<11,1>(v);
233}
234
235
236static bool IsS11_2_Offset(SDNode * S) {
237 ConstantSDNode *N = cast<ConstantSDNode>(S);
238
239 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
240 // field.
241 int64_t v = (int64_t)N->getSExtValue();
242 return isShiftedInt<11,2>(v);
243}
244
245
246static bool IsS11_3_Offset(SDNode * S) {
247 ConstantSDNode *N = cast<ConstantSDNode>(S);
248
249 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
250 // field.
251 int64_t v = (int64_t)N->getSExtValue();
252 return isShiftedInt<11,3>(v);
253}
254
255
256static bool IsU6_0_Offset(SDNode * S) {
257 ConstantSDNode *N = cast<ConstantSDNode>(S);
258
259 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
260 // field.
261 int64_t v = (int64_t)N->getSExtValue();
262 return isUInt<6>(v);
263}
264
265
266static bool IsU6_1_Offset(SDNode * S) {
267 ConstantSDNode *N = cast<ConstantSDNode>(S);
268
269 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
270 // field.
271 int64_t v = (int64_t)N->getSExtValue();
272 return isShiftedUInt<6,1>(v);
273}
274
275
276static bool IsU6_2_Offset(SDNode * S) {
277 ConstantSDNode *N = cast<ConstantSDNode>(S);
278
279 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
280 // field.
281 int64_t v = (int64_t)N->getSExtValue();
282 return isShiftedUInt<6,2>(v);
283}
284
285
286// Intrinsics that return a a predicate.
287static unsigned doesIntrinsicReturnPredicate(unsigned ID)
288{
289 switch (ID) {
290 default:
291 return 0;
292 case Intrinsic::hexagon_C2_cmpeq:
293 case Intrinsic::hexagon_C2_cmpgt:
294 case Intrinsic::hexagon_C2_cmpgtu:
295 case Intrinsic::hexagon_C2_cmpgtup:
296 case Intrinsic::hexagon_C2_cmpgtp:
297 case Intrinsic::hexagon_C2_cmpeqp:
298 case Intrinsic::hexagon_C2_bitsset:
299 case Intrinsic::hexagon_C2_bitsclr:
300 case Intrinsic::hexagon_C2_cmpeqi:
301 case Intrinsic::hexagon_C2_cmpgti:
302 case Intrinsic::hexagon_C2_cmpgtui:
303 case Intrinsic::hexagon_C2_cmpgei:
304 case Intrinsic::hexagon_C2_cmpgeui:
305 case Intrinsic::hexagon_C2_cmplt:
306 case Intrinsic::hexagon_C2_cmpltu:
307 case Intrinsic::hexagon_C2_bitsclri:
308 case Intrinsic::hexagon_C2_and:
309 case Intrinsic::hexagon_C2_or:
310 case Intrinsic::hexagon_C2_xor:
311 case Intrinsic::hexagon_C2_andn:
312 case Intrinsic::hexagon_C2_not:
313 case Intrinsic::hexagon_C2_orn:
314 case Intrinsic::hexagon_C2_pxfer_map:
315 case Intrinsic::hexagon_C2_any8:
316 case Intrinsic::hexagon_C2_all8:
317 case Intrinsic::hexagon_A2_vcmpbeq:
318 case Intrinsic::hexagon_A2_vcmpbgtu:
319 case Intrinsic::hexagon_A2_vcmpheq:
320 case Intrinsic::hexagon_A2_vcmphgt:
321 case Intrinsic::hexagon_A2_vcmphgtu:
322 case Intrinsic::hexagon_A2_vcmpweq:
323 case Intrinsic::hexagon_A2_vcmpwgt:
324 case Intrinsic::hexagon_A2_vcmpwgtu:
325 case Intrinsic::hexagon_C2_tfrrp:
326 case Intrinsic::hexagon_S2_tstbit_i:
327 case Intrinsic::hexagon_S2_tstbit_r:
328 return 1;
329 }
330}
331
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000332
333SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
334 unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000335 SDLoc dl)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000336{
337 SDValue Chain = LD->getChain();
338 EVT LoadedVT = LD->getMemoryVT();
339 SDValue Base = LD->getBasePtr();
340 SDValue Offset = LD->getOffset();
341 SDNode *OffsetNode = Offset.getNode();
342 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
343 SDValue N1 = LD->getOperand(1);
344 SDValue CPTmpN1_0;
345 SDValue CPTmpN1_1;
Bill Wendling4a7a4082013-06-07 06:19:56 +0000346
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000347 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
348 N1.getNode()->getValueType(0) == MVT::i32) {
Eric Christopher202f22b2015-02-02 19:22:03 +0000349 const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000350 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
351 SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32);
352 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
353 MVT::Other, Base, TargetConst,
354 Chain);
Colin LeMahieueb52f692014-12-11 16:43:06 +0000355 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000356 SDValue(Result_1, 0));
357 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
358 MemOp[0] = LD->getMemOperand();
359 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
360 const SDValue Froms[] = { SDValue(LD, 0),
361 SDValue(LD, 1),
362 SDValue(LD, 2)
363 };
364 const SDValue Tos[] = { SDValue(Result_2, 0),
365 SDValue(Result_1, 1),
366 SDValue(Result_1, 2)
367 };
368 ReplaceUses(Froms, Tos, 3);
369 return Result_2;
Sirish Pandec92c3162012-05-03 16:18:50 +0000370 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000371 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
372 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
373 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
374 MVT::Other, Base, TargetConst0,
375 Chain);
Colin LeMahieueb52f692014-12-11 16:43:06 +0000376 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000377 MVT::i64, SDValue(Result_1, 0));
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000378 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000379 MVT::i32, Base, TargetConstVal,
380 SDValue(Result_1, 1));
381 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
382 MemOp[0] = LD->getMemOperand();
383 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
384 const SDValue Froms[] = { SDValue(LD, 0),
385 SDValue(LD, 1),
386 SDValue(LD, 2)
387 };
388 const SDValue Tos[] = { SDValue(Result_2, 0),
389 SDValue(Result_3, 0),
390 SDValue(Result_1, 1)
391 };
392 ReplaceUses(Froms, Tos, 3);
393 return Result_2;
394 }
395 return SelectCode(LD);
396}
397
398
399SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
400 unsigned Opcode,
Andrew Trickef9de2a2013-05-25 02:42:55 +0000401 SDLoc dl)
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000402{
403 SDValue Chain = LD->getChain();
404 EVT LoadedVT = LD->getMemoryVT();
405 SDValue Base = LD->getBasePtr();
406 SDValue Offset = LD->getOffset();
407 SDNode *OffsetNode = Offset.getNode();
408 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
409 SDValue N1 = LD->getOperand(1);
410 SDValue CPTmpN1_0;
411 SDValue CPTmpN1_1;
Bill Wendling4a7a4082013-06-07 06:19:56 +0000412
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000413 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) &&
414 N1.getNode()->getValueType(0) == MVT::i32) {
Eric Christopher202f22b2015-02-02 19:22:03 +0000415 const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000416 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
417 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
418 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
419 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
420 MVT::i32, MVT::Other, Base,
421 TargetConstVal, Chain);
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000422 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000423 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +0000424 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000425 MVT::i64, MVT::Other,
426 SDValue(Result_2,0),
427 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_3, 0),
436 SDValue(Result_1, 1),
437 SDValue(Result_1, 2)
438 };
439 ReplaceUses(Froms, Tos, 3);
440 return Result_3;
441 }
442
443 // Generate an indirect load.
444 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
445 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
446 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
447 MVT::Other,
448 Base, TargetConst0, Chain);
Colin LeMahieu4af437f2014-12-09 20:23:30 +0000449 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000450 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +0000451 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000452 MVT::i64, MVT::Other,
453 SDValue(Result_2,0),
454 SDValue(Result_1,0));
455 // Add offset to base.
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000456 SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000457 Base, TargetConstVal,
458 SDValue(Result_1, 1));
459 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
460 MemOp[0] = LD->getMemOperand();
461 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
462 const SDValue Froms[] = { SDValue(LD, 0),
463 SDValue(LD, 1),
464 SDValue(LD, 2)
465 };
466 const SDValue Tos[] = { SDValue(Result_3, 0), // Load value.
467 SDValue(Result_4, 0), // New address.
468 SDValue(Result_1, 1)
469 };
470 ReplaceUses(Froms, Tos, 3);
471 return Result_3;
472 }
473
474 return SelectCode(LD);
475}
476
477
Andrew Trickef9de2a2013-05-25 02:42:55 +0000478SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000479 SDValue Chain = LD->getChain();
480 SDValue Base = LD->getBasePtr();
481 SDValue Offset = LD->getOffset();
482 SDNode *OffsetNode = Offset.getNode();
483 // Get the constant value.
484 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
485 EVT LoadedVT = LD->getMemoryVT();
486 unsigned Opcode = 0;
487
488 // Check for zero ext loads.
489 bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD);
490
491 // Figure out the opcode.
Eric Christopher202f22b2015-02-02 19:22:03 +0000492 const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000493 if (LoadedVT == MVT::i64) {
494 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000495 Opcode = Hexagon::L2_loadrd_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000496 else
Colin LeMahieu947cd702014-12-23 20:44:59 +0000497 Opcode = Hexagon::L2_loadrd_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000498 } else if (LoadedVT == MVT::i32) {
499 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000500 Opcode = Hexagon::L2_loadri_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000501 else
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000502 Opcode = Hexagon::L2_loadri_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000503 } else if (LoadedVT == MVT::i16) {
504 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieuc83cbbf2014-12-26 19:31:46 +0000505 Opcode = zextval ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000506 else
Colin LeMahieu8e39cad2014-12-23 17:25:57 +0000507 Opcode = zextval ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000508 } else if (LoadedVT == MVT::i8) {
509 if (TII->isValidAutoIncImm(LoadedVT, Val))
Colin LeMahieufe9612e2014-12-26 19:12:11 +0000510 Opcode = zextval ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000511 else
Colin LeMahieu4b1eac42014-12-22 21:40:43 +0000512 Opcode = zextval ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000513 } else
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000514 llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000515
516 // For zero ext i64 loads, we need to add combine instructions.
517 if (LD->getValueType(0) == MVT::i64 &&
518 LD->getExtensionType() == ISD::ZEXTLOAD) {
519 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl);
520 }
521 if (LD->getValueType(0) == MVT::i64 &&
522 LD->getExtensionType() == ISD::SEXTLOAD) {
523 // Handle sign ext i64 loads.
524 return SelectIndexedLoadSignExtend64(LD, Opcode, dl);
525 }
526 if (TII->isValidAutoIncImm(LoadedVT, Val)) {
527 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
528 SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
529 LD->getValueType(0),
530 MVT::i32, MVT::Other, Base,
531 TargetConstVal, Chain);
532 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
533 MemOp[0] = LD->getMemOperand();
534 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
535 const SDValue Froms[] = { SDValue(LD, 0),
536 SDValue(LD, 1),
537 SDValue(LD, 2)
538 };
539 const SDValue Tos[] = { SDValue(Result, 0),
540 SDValue(Result, 1),
541 SDValue(Result, 2)
542 };
543 ReplaceUses(Froms, Tos, 3);
544 return Result;
545 } else {
546 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
547 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
548 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl,
549 LD->getValueType(0),
550 MVT::Other, Base, TargetConst0,
551 Chain);
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000552 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000553 Base, TargetConstVal,
554 SDValue(Result_1, 1));
555 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
556 MemOp[0] = LD->getMemOperand();
557 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
558 const SDValue Froms[] = { SDValue(LD, 0),
559 SDValue(LD, 1),
560 SDValue(LD, 2)
561 };
562 const SDValue Tos[] = { SDValue(Result_1, 0),
563 SDValue(Result_2, 0),
564 SDValue(Result_1, 1)
565 };
566 ReplaceUses(Froms, Tos, 3);
567 return Result_1;
568 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000569}
570
571
572SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
573 SDNode *result;
Andrew Trickef9de2a2013-05-25 02:42:55 +0000574 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000575 LoadSDNode *LD = cast<LoadSDNode>(N);
576 ISD::MemIndexedMode AM = LD->getAddressingMode();
577
578 // Handle indexed loads.
579 if (AM != ISD::UNINDEXED) {
580 result = SelectIndexedLoad(LD, dl);
581 } else {
Colin LeMahieu2efa2d02015-03-09 21:48:13 +0000582 result = SelectCode(LD);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000583 }
584
585 return result;
586}
587
588
Andrew Trickef9de2a2013-05-25 02:42:55 +0000589SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000590 SDValue Chain = ST->getChain();
591 SDValue Base = ST->getBasePtr();
592 SDValue Offset = ST->getOffset();
593 SDValue Value = ST->getValue();
594 SDNode *OffsetNode = Offset.getNode();
595 // Get the constant value.
596 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
597 EVT StoredVT = ST->getMemoryVT();
598
599 // Offset value must be within representable range
600 // and must have correct alignment properties.
Eric Christopher202f22b2015-02-02 19:22:03 +0000601 const HexagonInstrInfo *TII = Subtarget->getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000602 if (TII->isValidAutoIncImm(StoredVT, Val)) {
Jyotsna Vermab16a9cb2013-01-29 18:42:41 +0000603 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value,
604 Chain};
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000605 unsigned Opcode = 0;
606
607 // Figure out the post inc version of opcode.
Colin LeMahieu9a3cd3f2014-12-29 20:00:43 +0000608 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi;
609 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi;
610 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi;
Colin LeMahieu3d34afb2014-12-29 19:42:14 +0000611 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000612 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000613
614 // Build post increment store.
615 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +0000616 MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000617 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
618 MemOp[0] = ST->getMemOperand();
619 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
620
621 ReplaceUses(ST, Result);
622 ReplaceUses(SDValue(ST,1), SDValue(Result,1));
623 return Result;
624 }
625
626 // Note: Order of operands matches the def of instruction:
627 // def STrid : STInst<(outs), (ins MEMri:$addr, DoubleRegs:$src1), ...
628 // and it differs for POST_ST* for instance.
629 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value,
630 Chain};
631 unsigned Opcode = 0;
632
633 // Figure out the opcode.
Colin LeMahieubda31b42014-12-29 20:44:51 +0000634 if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io;
635 else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
636 else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
637 else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000638 else llvm_unreachable("unknown memory type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000639
640 // Build regular store.
641 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
Michael Liaob53d8962013-04-19 22:22:57 +0000642 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000643 // Build splitted incriment instruction.
Colin LeMahieuf297dbe2015-02-05 17:49:13 +0000644 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000645 Base,
646 TargetConstVal,
647 SDValue(Result_1, 0));
648 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
649 MemOp[0] = ST->getMemOperand();
650 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1);
651
652 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0));
653 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0));
654 return Result_2;
655}
656
657
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000658SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000659 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000660 StoreSDNode *ST = cast<StoreSDNode>(N);
661 ISD::MemIndexedMode AM = ST->getAddressingMode();
662
663 // Handle indexed stores.
664 if (AM != ISD::UNINDEXED) {
665 return SelectIndexedStore(ST, dl);
666 }
Sirish Pandec92c3162012-05-03 16:18:50 +0000667
Colin LeMahieu2efa2d02015-03-09 21:48:13 +0000668 return SelectCode(ST);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000669}
670
671SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000672 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000673
674 //
675 // %conv.i = sext i32 %tmp1 to i64
676 // %conv2.i = sext i32 %add to i64
677 // %mul.i = mul nsw i64 %conv2.i, %conv.i
678 //
679 // --- match with the following ---
680 //
681 // %mul.i = mpy (%tmp1, %add)
682 //
683
684 if (N->getValueType(0) == MVT::i64) {
685 // Shifting a i64 signed multiply.
686 SDValue MulOp0 = N->getOperand(0);
687 SDValue MulOp1 = N->getOperand(1);
688
689 SDValue OP0;
690 SDValue OP1;
691
692 // Handle sign_extend and sextload.
693 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
694 SDValue Sext0 = MulOp0.getOperand(0);
695 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000696 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000697 }
698
699 OP0 = Sext0;
700 } else if (MulOp0.getOpcode() == ISD::LOAD) {
701 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
702 if (LD->getMemoryVT() != MVT::i32 ||
703 LD->getExtensionType() != ISD::SEXTLOAD ||
704 LD->getAddressingMode() != ISD::UNINDEXED) {
Sirish Pandef8e5e3c2012-05-03 21:52:53 +0000705 return SelectCode(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000706 }
707
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000708 SDValue Chain = LD->getChain();
709 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000710 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000711 MVT::Other,
712 LD->getBasePtr(), TargetConst0,
713 Chain), 0);
714 } else {
715 return SelectCode(N);
716 }
717
718 // Same goes for the second operand.
719 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
720 SDValue Sext1 = MulOp1.getOperand(0);
721 if (Sext1.getNode()->getValueType(0) != MVT::i32) {
722 return SelectCode(N);
723 }
724
725 OP1 = Sext1;
726 } else if (MulOp1.getOpcode() == ISD::LOAD) {
727 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
728 if (LD->getMemoryVT() != MVT::i32 ||
729 LD->getExtensionType() != ISD::SEXTLOAD ||
730 LD->getAddressingMode() != ISD::UNINDEXED) {
731 return SelectCode(N);
732 }
733
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000734 SDValue Chain = LD->getChain();
735 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000736 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000737 MVT::Other,
738 LD->getBasePtr(), TargetConst0,
739 Chain), 0);
740 } else {
741 return SelectCode(N);
742 }
743
744 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +0000745 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl, MVT::i64,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000746 OP0, OP1);
747 ReplaceUses(N, Result);
748 return Result;
749 }
750
751 return SelectCode(N);
752}
753
754
755SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000756 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000757 SDValue N0 = N->getOperand(0);
758 if (N0.getOpcode() == ISD::SETCC) {
759 SDValue N00 = N0.getOperand(0);
760 if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) {
761 SDValue N000 = N00.getOperand(0);
762 SDValue N001 = N00.getOperand(1);
763 if (cast<VTSDNode>(N001)->getVT() == MVT::i16) {
764 SDValue N01 = N0.getOperand(1);
765 SDValue N02 = N0.getOperand(2);
766
767 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
768 // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1,
769 // IntRegs:i32:$src2)
770 // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
771 // Pattern complexity = 9 cost = 1 size = 0.
772 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) {
773 SDValue N1 = N->getOperand(1);
774 if (N01 == N1) {
775 SDValue N2 = N->getOperand(2);
776 if (N000 == N2 &&
777 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
778 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
Colin LeMahieu310991c2014-11-21 21:54:59 +0000779 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000780 MVT::i32, N000);
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000781 SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_max, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000782 MVT::i32,
783 SDValue(SextNode, 0),
784 N1);
785 ReplaceUses(N, Result);
786 return Result;
787 }
788 }
789 }
790
791 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
792 // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1,
793 // IntRegs:i32:$src2)
794 // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
795 // Pattern complexity = 9 cost = 1 size = 0.
796 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) {
797 SDValue N1 = N->getOperand(1);
798 if (N01 == N1) {
799 SDValue N2 = N->getOperand(2);
800 if (N000 == N2 &&
801 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 &&
802 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) {
Colin LeMahieu310991c2014-11-21 21:54:59 +0000803 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000804 MVT::i32, N000);
Colin LeMahieu5cf56322014-12-08 23:55:43 +0000805 SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_min, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000806 MVT::i32,
807 SDValue(SextNode, 0),
808 N1);
809 ReplaceUses(N, Result);
810 return Result;
811 }
812 }
813 }
814 }
815 }
816 }
817
818 return SelectCode(N);
819}
820
821
822SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000823 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000824 SDValue Shift = N->getOperand(0);
825
826 //
827 // %conv.i = sext i32 %tmp1 to i64
828 // %conv2.i = sext i32 %add to i64
829 // %mul.i = mul nsw i64 %conv2.i, %conv.i
830 // %shr5.i = lshr i64 %mul.i, 32
831 // %conv3.i = trunc i64 %shr5.i to i32
832 //
833 // --- match with the following ---
834 //
835 // %conv3.i = mpy (%tmp1, %add)
836 //
837 // Trunc to i32.
838 if (N->getValueType(0) == MVT::i32) {
839 // Trunc from i64.
840 if (Shift.getNode()->getValueType(0) == MVT::i64) {
841 // Trunc child is logical shift right.
842 if (Shift.getOpcode() != ISD::SRL) {
843 return SelectCode(N);
844 }
845
846 SDValue ShiftOp0 = Shift.getOperand(0);
847 SDValue ShiftOp1 = Shift.getOperand(1);
848
849 // Shift by const 32
850 if (ShiftOp1.getOpcode() != ISD::Constant) {
851 return SelectCode(N);
852 }
853
854 int32_t ShiftConst =
855 cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue();
856 if (ShiftConst != 32) {
857 return SelectCode(N);
858 }
859
860 // Shifting a i64 signed multiply
861 SDValue Mul = ShiftOp0;
862 if (Mul.getOpcode() != ISD::MUL) {
863 return SelectCode(N);
864 }
865
866 SDValue MulOp0 = Mul.getOperand(0);
867 SDValue MulOp1 = Mul.getOperand(1);
868
869 SDValue OP0;
870 SDValue OP1;
871
872 // Handle sign_extend and sextload
873 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
874 SDValue Sext0 = MulOp0.getOperand(0);
875 if (Sext0.getNode()->getValueType(0) != MVT::i32) {
876 return SelectCode(N);
877 }
878
879 OP0 = Sext0;
880 } else if (MulOp0.getOpcode() == ISD::LOAD) {
881 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
882 if (LD->getMemoryVT() != MVT::i32 ||
883 LD->getExtensionType() != ISD::SEXTLOAD ||
884 LD->getAddressingMode() != ISD::UNINDEXED) {
885 return SelectCode(N);
886 }
887
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000888 SDValue Chain = LD->getChain();
889 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000890 OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000891 MVT::Other,
892 LD->getBasePtr(),
893 TargetConst0, Chain), 0);
894 } else {
895 return SelectCode(N);
896 }
897
898 // Same goes for the second operand.
899 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
900 SDValue Sext1 = MulOp1.getOperand(0);
901 if (Sext1.getNode()->getValueType(0) != MVT::i32)
902 return SelectCode(N);
903
904 OP1 = Sext1;
905 } else if (MulOp1.getOpcode() == ISD::LOAD) {
906 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
907 if (LD->getMemoryVT() != MVT::i32 ||
908 LD->getExtensionType() != ISD::SEXTLOAD ||
909 LD->getAddressingMode() != ISD::UNINDEXED) {
910 return SelectCode(N);
911 }
912
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000913 SDValue Chain = LD->getChain();
914 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu026e88d2014-12-23 20:02:16 +0000915 OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000916 MVT::Other,
917 LD->getBasePtr(),
918 TargetConst0, Chain), 0);
919 } else {
920 return SelectCode(N);
921 }
922
923 // Generate a mpy instruction.
Colin LeMahieud9b23502014-12-16 16:10:01 +0000924 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpy_up, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000925 OP0, OP1);
926 ReplaceUses(N, Result);
927 return Result;
928 }
929 }
930
931 return SelectCode(N);
932}
933
934
935SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000936 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000937 if (N->getValueType(0) == MVT::i32) {
938 SDValue Shl_0 = N->getOperand(0);
939 SDValue Shl_1 = N->getOperand(1);
940 // RHS is const.
941 if (Shl_1.getOpcode() == ISD::Constant) {
942 if (Shl_0.getOpcode() == ISD::MUL) {
943 SDValue Mul_0 = Shl_0.getOperand(0); // Val
944 SDValue Mul_1 = Shl_0.getOperand(1); // Const
945 // RHS of mul is const.
946 if (Mul_1.getOpcode() == ISD::Constant) {
947 int32_t ShlConst =
948 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
949 int32_t MulConst =
950 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue();
951 int32_t ValConst = MulConst << ShlConst;
952 SDValue Val = CurDAG->getTargetConstant(ValConst,
953 MVT::i32);
954 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode()))
955 if (isInt<9>(CN->getSExtValue())) {
956 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +0000957 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000958 MVT::i32, Mul_0, Val);
959 ReplaceUses(N, Result);
960 return Result;
961 }
962
963 }
964 } else if (Shl_0.getOpcode() == ISD::SUB) {
965 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0
966 SDValue Sub_1 = Shl_0.getOperand(1); // Val
967 if (Sub_0.getOpcode() == ISD::Constant) {
968 int32_t SubConst =
969 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue();
970 if (SubConst == 0) {
971 if (Sub_1.getOpcode() == ISD::SHL) {
972 SDValue Shl2_0 = Sub_1.getOperand(0); // Val
973 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
974 if (Shl2_1.getOpcode() == ISD::Constant) {
975 int32_t ShlConst =
976 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue();
977 int32_t Shl2Const =
978 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue();
979 int32_t ValConst = 1 << (ShlConst+Shl2Const);
980 SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32);
981 if (ConstantSDNode *CN =
982 dyn_cast<ConstantSDNode>(Val.getNode()))
983 if (isInt<9>(CN->getSExtValue())) {
984 SDNode* Result =
Colin LeMahieud9b23502014-12-16 16:10:01 +0000985 CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000986 Shl2_0, Val);
987 ReplaceUses(N, Result);
988 return Result;
989 }
990 }
991 }
992 }
993 }
994 }
995 }
996 }
997 return SelectCode(N);
998}
999
1000
1001//
1002// If there is an zero_extend followed an intrinsic in DAG (this means - the
1003// result of the intrinsic is predicate); convert the zero_extend to
1004// transfer instruction.
1005//
1006// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
1007// converted into a MUX as predicate registers defined as 1 bit in the
1008// compiler. Architecture defines them as 8-bit registers.
1009// We want to preserve all the lower 8-bits and, not just 1 LSB bit.
1010//
1011SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001012 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001013 SDNode *IsIntrinsic = N->getOperand(0).getNode();
1014 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) {
1015 unsigned ID =
1016 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue();
1017 if (doesIntrinsicReturnPredicate(ID)) {
1018 // Now we need to differentiate target data types.
1019 if (N->getValueType(0) == MVT::i64) {
1020 // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs).
1021 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001022 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001023 MVT::i32,
1024 SDValue(IsIntrinsic, 0));
Colin LeMahieu4af437f2014-12-09 20:23:30 +00001025 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001026 MVT::i32,
1027 TargetConst0);
Colin LeMahieub580d7d2014-12-09 19:23:45 +00001028 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001029 MVT::i64, MVT::Other,
1030 SDValue(Result_2, 0),
1031 SDValue(Result_1, 0));
1032 ReplaceUses(N, Result_3);
1033 return Result_3;
1034 }
1035 if (N->getValueType(0) == MVT::i32) {
1036 // Convert the zero_extend to Rs = Pd
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001037 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001038 MVT::i32,
1039 SDValue(IsIntrinsic, 0));
1040 ReplaceUses(N, RsPd);
1041 return RsPd;
1042 }
Craig Toppere55c5562012-02-07 02:50:20 +00001043 llvm_unreachable("Unexpected value type");
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001044 }
1045 }
1046 return SelectCode(N);
1047}
1048
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001049//
1050// Checking for intrinsics which have predicate registers as operand(s)
1051// and lowering to the actual intrinsic.
1052//
1053SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001054 unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
1055 unsigned Bits;
1056 switch (IID) {
1057 case Intrinsic::hexagon_S2_vsplatrb:
1058 Bits = 8;
1059 break;
1060 case Intrinsic::hexagon_S2_vsplatrh:
1061 Bits = 16;
1062 break;
1063 default:
1064 return SelectCode(N);
1065 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001066
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001067 SDValue const &V = N->getOperand(1);
1068 SDValue U;
1069 if (isValueExtension(V, Bits, U)) {
1070 SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
1071 N->getOperand(0), U);
1072 return SelectCode(R.getNode());
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001073 }
1074 return SelectCode(N);
1075}
1076
Sirish Pande69295b82012-05-10 20:20:25 +00001077//
1078// Map floating point constant values.
1079//
1080SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001081 SDLoc dl(N);
Sirish Pande69295b82012-05-10 20:20:25 +00001082 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
1083 APFloat APF = CN->getValueAPF();
1084 if (N->getValueType(0) == MVT::f32) {
1085 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
1086 CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32));
1087 }
1088 else if (N->getValueType(0) == MVT::f64) {
1089 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
1090 CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64));
1091 }
1092
1093 return SelectCode(N);
1094}
1095
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001096
1097//
1098// Map predicate true (encoded as -1 in LLVM) to a XOR.
1099//
1100SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001101 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001102 if (N->getValueType(0) == MVT::i1) {
1103 SDNode* Result;
1104 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue();
1105 if (Val == -1) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001106 // Create the IntReg = 1 node.
1107 SDNode* IntRegTFR =
Colin LeMahieu4af437f2014-12-09 20:23:30 +00001108 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001109 CurDAG->getTargetConstant(0, MVT::i32));
1110
1111 // Pd = IntReg
Colin LeMahieu30dcb232014-12-09 18:16:49 +00001112 SDNode* Pd = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001113 SDValue(IntRegTFR, 0));
1114
1115 // not(Pd)
Colin LeMahieu5cf56322014-12-08 23:55:43 +00001116 SDNode* NotPd = CurDAG->getMachineNode(Hexagon::C2_not, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001117 SDValue(Pd, 0));
1118
1119 // xor(not(Pd))
Colin LeMahieu5cf56322014-12-08 23:55:43 +00001120 Result = CurDAG->getMachineNode(Hexagon::C2_xor, dl, MVT::i1,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001121 SDValue(Pd, 0), SDValue(NotPd, 0));
1122
1123 // We have just built:
1124 // Rs = Pd
1125 // Pd = xor(not(Pd), Pd)
1126
1127 ReplaceUses(N, Result);
1128 return Result;
1129 }
1130 }
1131
1132 return SelectCode(N);
1133}
1134
1135
1136//
1137// Map add followed by a asr -> asr +=.
1138//
1139SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001140 SDLoc dl(N);
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001141 if (N->getValueType(0) != MVT::i32) {
1142 return SelectCode(N);
1143 }
1144 // Identify nodes of the form: add(asr(...)).
1145 SDNode* Src1 = N->getOperand(0).getNode();
1146 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse()
1147 || Src1->getValueType(0) != MVT::i32) {
1148 return SelectCode(N);
1149 }
1150
1151 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1152 // Rd and Rd' are assigned to the same register
Colin LeMahieu0f850bd2014-12-19 20:29:29 +00001153 SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001154 N->getOperand(1),
1155 Src1->getOperand(0),
1156 Src1->getOperand(1));
1157 ReplaceUses(N, Result);
1158
1159 return Result;
1160}
1161
1162
1163SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
Tim Northover31d093c2013-09-22 08:21:56 +00001164 if (N->isMachineOpcode()) {
1165 N->setNodeId(-1);
Craig Topper062a2ba2014-04-25 05:30:21 +00001166 return nullptr; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00001167 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001168
1169
1170 switch (N->getOpcode()) {
1171 case ISD::Constant:
1172 return SelectConstant(N);
1173
Sirish Pande69295b82012-05-10 20:20:25 +00001174 case ISD::ConstantFP:
1175 return SelectConstantFP(N);
1176
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001177 case ISD::ADD:
1178 return SelectAdd(N);
1179
1180 case ISD::SHL:
1181 return SelectSHL(N);
1182
1183 case ISD::LOAD:
1184 return SelectLoad(N);
1185
1186 case ISD::STORE:
1187 return SelectStore(N);
1188
1189 case ISD::SELECT:
1190 return SelectSelect(N);
1191
1192 case ISD::TRUNCATE:
1193 return SelectTruncate(N);
1194
1195 case ISD::MUL:
1196 return SelectMul(N);
1197
1198 case ISD::ZERO_EXTEND:
1199 return SelectZeroExtend(N);
1200
1201 case ISD::INTRINSIC_WO_CHAIN:
1202 return SelectIntrinsicWOChain(N);
1203 }
1204
1205 return SelectCode(N);
1206}
1207
1208
1209//
1210// Hexagon_TODO: Five functions for ADDRri?! Surely there must be a better way
1211// to define these instructions.
1212//
1213bool HexagonDAGToDAGISel::SelectADDRri(SDValue& Addr, SDValue &Base,
1214 SDValue &Offset) {
1215 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1216 Addr.getOpcode() == ISD::TargetGlobalAddress)
1217 return false; // Direct calls.
1218
1219 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1220 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1221 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1222 return true;
1223 }
1224 Base = Addr;
1225 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1226 return true;
1227}
1228
1229
1230bool HexagonDAGToDAGISel::SelectADDRriS11_0(SDValue& Addr, SDValue &Base,
1231 SDValue &Offset) {
1232 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1233 Addr.getOpcode() == ISD::TargetGlobalAddress)
1234 return false; // Direct calls.
1235
1236 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1237 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1238 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1239 return (IsS11_0_Offset(Offset.getNode()));
1240 }
1241 Base = Addr;
1242 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1243 return (IsS11_0_Offset(Offset.getNode()));
1244}
1245
1246
1247bool HexagonDAGToDAGISel::SelectADDRriS11_1(SDValue& Addr, SDValue &Base,
1248 SDValue &Offset) {
1249 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1250 Addr.getOpcode() == ISD::TargetGlobalAddress)
1251 return false; // Direct calls.
1252
1253 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1254 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1255 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1256 return (IsS11_1_Offset(Offset.getNode()));
1257 }
1258 Base = Addr;
1259 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1260 return (IsS11_1_Offset(Offset.getNode()));
1261}
1262
1263
1264bool HexagonDAGToDAGISel::SelectADDRriS11_2(SDValue& Addr, SDValue &Base,
1265 SDValue &Offset) {
1266 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1267 Addr.getOpcode() == ISD::TargetGlobalAddress)
1268 return false; // Direct calls.
1269
1270 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1271 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1272 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1273 return (IsS11_2_Offset(Offset.getNode()));
1274 }
1275 Base = Addr;
1276 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1277 return (IsS11_2_Offset(Offset.getNode()));
1278}
1279
1280
1281bool HexagonDAGToDAGISel::SelectADDRriU6_0(SDValue& Addr, SDValue &Base,
1282 SDValue &Offset) {
1283 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1284 Addr.getOpcode() == ISD::TargetGlobalAddress)
1285 return false; // Direct calls.
1286
1287 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1288 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1289 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1290 return (IsU6_0_Offset(Offset.getNode()));
1291 }
1292 Base = Addr;
1293 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1294 return (IsU6_0_Offset(Offset.getNode()));
1295}
1296
1297
1298bool HexagonDAGToDAGISel::SelectADDRriU6_1(SDValue& Addr, SDValue &Base,
1299 SDValue &Offset) {
1300 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1301 Addr.getOpcode() == ISD::TargetGlobalAddress)
1302 return false; // Direct calls.
1303
1304 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1305 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1306 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1307 return (IsU6_1_Offset(Offset.getNode()));
1308 }
1309 Base = Addr;
1310 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1311 return (IsU6_1_Offset(Offset.getNode()));
1312}
1313
1314
1315bool HexagonDAGToDAGISel::SelectADDRriU6_2(SDValue& Addr, SDValue &Base,
1316 SDValue &Offset) {
1317 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1318 Addr.getOpcode() == ISD::TargetGlobalAddress)
1319 return false; // Direct calls.
1320
1321 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1322 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1323 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1324 return (IsU6_2_Offset(Offset.getNode()));
1325 }
1326 Base = Addr;
1327 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1328 return (IsU6_2_Offset(Offset.getNode()));
1329}
1330
1331
1332bool HexagonDAGToDAGISel::SelectMEMriS11_2(SDValue& Addr, SDValue &Base,
1333 SDValue &Offset) {
1334
1335 if (Addr.getOpcode() != ISD::ADD) {
1336 return(SelectADDRriS11_2(Addr, Base, Offset));
1337 }
1338
1339 return SelectADDRriS11_2(Addr, Base, Offset);
1340}
1341
1342
1343bool HexagonDAGToDAGISel::SelectADDRriS11_3(SDValue& Addr, SDValue &Base,
1344 SDValue &Offset) {
1345 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1346 Addr.getOpcode() == ISD::TargetGlobalAddress)
1347 return false; // Direct calls.
1348
1349 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1350 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1351 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1352 return (IsS11_3_Offset(Offset.getNode()));
1353 }
1354 Base = Addr;
1355 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1356 return (IsS11_3_Offset(Offset.getNode()));
1357}
1358
1359bool HexagonDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1,
1360 SDValue &R2) {
1361 if (Addr.getOpcode() == ISD::FrameIndex) return false;
1362 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1363 Addr.getOpcode() == ISD::TargetGlobalAddress)
1364 return false; // Direct calls.
1365
1366 if (Addr.getOpcode() == ISD::ADD) {
1367 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
1368 if (isInt<13>(CN->getSExtValue()))
1369 return false; // Let the reg+imm pattern catch this!
1370 R1 = Addr.getOperand(0);
1371 R2 = Addr.getOperand(1);
1372 return true;
1373 }
1374
1375 R1 = Addr;
1376
1377 return true;
1378}
1379
1380
1381// Handle generic address case. It is accessed from inlined asm =m constraints,
1382// which could have any kind of pointer.
1383bool HexagonDAGToDAGISel::SelectAddr(SDNode *Op, SDValue Addr,
1384 SDValue &Base, SDValue &Offset) {
1385 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1386 Addr.getOpcode() == ISD::TargetGlobalAddress)
1387 return false; // Direct calls.
1388
1389 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1390 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
1391 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1392 return true;
1393 }
1394
1395 if (Addr.getOpcode() == ISD::ADD) {
1396 Base = Addr.getOperand(0);
1397 Offset = Addr.getOperand(1);
1398 return true;
1399 }
1400
1401 Base = Addr;
1402 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1403 return true;
1404}
1405
1406
1407bool HexagonDAGToDAGISel::
Daniel Sanders41c072e2015-03-12 11:00:48 +00001408SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001409 std::vector<SDValue> &OutOps) {
1410 SDValue Op0, Op1;
1411
Daniel Sanders41c072e2015-03-12 11:00:48 +00001412 switch (ConstraintID) {
1413 case InlineAsm::Constraint_o: // Offsetable.
1414 case InlineAsm::Constraint_v: // Not offsetable.
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001415 default: return true;
Daniel Sanders41c072e2015-03-12 11:00:48 +00001416 case InlineAsm::Constraint_m: // Memory.
Tony Linthicum1213a7a2011-12-12 21:14:40 +00001417 if (!SelectAddr(Op.getNode(), Op, Op0, Op1))
1418 return true;
1419 break;
1420 }
1421
1422 OutOps.push_back(Op0);
1423 OutOps.push_back(Op1);
1424 return false;
1425}
Jyotsna Verma519b3852012-11-28 20:58:14 +00001426
Jyotsna Vermad9225242013-02-13 21:38:46 +00001427//===--------------------------------------------------------------------===//
Alp Tokerf907b892013-12-05 05:44:44 +00001428// Return true if the non-GP-relative global address can be folded.
Jyotsna Vermad9225242013-02-13 21:38:46 +00001429//===--------------------------------------------------------------------===//
1430inline bool HexagonDAGToDAGISel::foldGlobalAddress(SDValue &N, SDValue &R) {
1431 return foldGlobalAddressImpl(N, R, false);
1432}
1433
1434//===--------------------------------------------------------------------===//
1435// Return true if the GP-relative global address can be folded.
1436//===--------------------------------------------------------------------===//
1437inline bool HexagonDAGToDAGISel::foldGlobalAddressGP(SDValue &N, SDValue &R) {
1438 return foldGlobalAddressImpl(N, R, true);
1439}
1440
1441//===--------------------------------------------------------------------===//
1442// Fold offset of the global address if number of uses are below threshold.
1443//===--------------------------------------------------------------------===//
1444bool HexagonDAGToDAGISel::foldGlobalAddressImpl(SDValue &N, SDValue &R,
1445 bool ShouldLookForGP) {
1446 if (N.getOpcode() == ISD::ADD) {
1447 SDValue N0 = N.getOperand(0);
1448 SDValue N1 = N.getOperand(1);
1449 if ((ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32_GP)) ||
1450 (!ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32))) {
1451 ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1);
1452 GlobalAddressSDNode *GA =
1453 dyn_cast<GlobalAddressSDNode>(N0.getOperand(0));
1454
1455 if (Const && GA &&
1456 (GA->getOpcode() == ISD::TargetGlobalAddress)) {
Krzysztof Parzyszek325297c2015-03-12 00:49:13 +00001457 if (N0.getOpcode() == HexagonISD::CONST32)
1458 return false;
Jyotsna Vermad9225242013-02-13 21:38:46 +00001459 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(),
Andrew Trickef9de2a2013-05-25 02:42:55 +00001460 SDLoc(Const),
Jyotsna Vermad9225242013-02-13 21:38:46 +00001461 N.getValueType(),
1462 GA->getOffset() +
1463 (uint64_t)Const->getSExtValue());
1464 return true;
1465 }
1466 }
1467 }
1468 return false;
1469}
Colin LeMahieuc7522f32015-01-14 23:07:36 +00001470
1471bool HexagonDAGToDAGISel::SelectAddrFI(SDValue& N, SDValue &R) {
1472 if (N.getOpcode() != ISD::FrameIndex)
1473 return false;
1474 FrameIndexSDNode *FX = cast<FrameIndexSDNode>(N);
1475 R = CurDAG->getTargetFrameIndex(FX->getIndex(), MVT::i32);
1476 return true;
1477}
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001478
Colin LeMahieu987b0942015-02-04 20:38:01 +00001479inline bool HexagonDAGToDAGISel::SelectAddrGA(SDValue &N, SDValue &R) {
1480 return SelectGlobalAddress(N, R, false);
1481}
1482
Colin LeMahieu51491352015-02-04 22:36:28 +00001483inline bool HexagonDAGToDAGISel::SelectAddrGP(SDValue &N, SDValue &R) {
1484 return SelectGlobalAddress(N, R, true);
1485}
1486
Colin LeMahieu987b0942015-02-04 20:38:01 +00001487bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R,
1488 bool UseGP) {
1489 switch (N.getOpcode()) {
1490 case ISD::ADD: {
1491 SDValue N0 = N.getOperand(0);
1492 SDValue N1 = N.getOperand(1);
1493 unsigned GAOpc = N0.getOpcode();
1494 if (UseGP && GAOpc != HexagonISD::CONST32_GP)
1495 return false;
1496 if (!UseGP && GAOpc != HexagonISD::CONST32)
1497 return false;
1498 if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1)) {
1499 SDValue Addr = N0.getOperand(0);
1500 if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Addr)) {
1501 if (GA->getOpcode() == ISD::TargetGlobalAddress) {
1502 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1503 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const),
1504 N.getValueType(), NewOff);
1505 return true;
1506 }
1507 }
1508 }
1509 break;
1510 }
1511 case HexagonISD::CONST32:
1512 // The operand(0) of CONST32 is TargetGlobalAddress, which is what we
1513 // want in the instruction.
1514 if (!UseGP)
1515 R = N.getOperand(0);
1516 return !UseGP;
1517 case HexagonISD::CONST32_GP:
1518 if (UseGP)
1519 R = N.getOperand(0);
1520 return UseGP;
1521 default:
1522 return false;
1523 }
1524
1525 return false;
1526}
1527
Colin LeMahieu0ee02fc2015-01-19 20:31:18 +00001528bool HexagonDAGToDAGISel::isValueExtension(SDValue const &Val,
1529 unsigned FromBits, SDValue &Src) {
1530 unsigned Opc = Val.getOpcode();
1531 switch (Opc) {
1532 case ISD::SIGN_EXTEND:
1533 case ISD::ZERO_EXTEND:
1534 case ISD::ANY_EXTEND: {
1535 SDValue const &Op0 = Val.getOperand(0);
1536 EVT T = Op0.getValueType();
1537 if (T.isInteger() && T.getSizeInBits() == FromBits) {
1538 Src = Op0;
1539 return true;
1540 }
1541 break;
1542 }
1543 case ISD::SIGN_EXTEND_INREG:
1544 case ISD::AssertSext:
1545 case ISD::AssertZext:
1546 if (Val.getOperand(0).getValueType().isInteger()) {
1547 VTSDNode *T = cast<VTSDNode>(Val.getOperand(1));
1548 if (T->getVT().getSizeInBits() == FromBits) {
1549 Src = Val.getOperand(0);
1550 return true;
1551 }
1552 }
1553 break;
1554 case ISD::AND: {
1555 // Check if this is an AND with "FromBits" of lower bits set to 1.
1556 uint64_t FromMask = (1 << FromBits) - 1;
1557 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1558 if (C->getZExtValue() == FromMask) {
1559 Src = Val.getOperand(1);
1560 return true;
1561 }
1562 }
1563 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1564 if (C->getZExtValue() == FromMask) {
1565 Src = Val.getOperand(0);
1566 return true;
1567 }
1568 }
1569 break;
1570 }
1571 case ISD::OR:
1572 case ISD::XOR: {
1573 // OR/XOR with the lower "FromBits" bits set to 0.
1574 uint64_t FromMask = (1 << FromBits) - 1;
1575 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
1576 if ((C->getZExtValue() & FromMask) == 0) {
1577 Src = Val.getOperand(1);
1578 return true;
1579 }
1580 }
1581 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
1582 if ((C->getZExtValue() & FromMask) == 0) {
1583 Src = Val.getOperand(0);
1584 return true;
1585 }
1586 }
1587 }
1588 default:
1589 break;
1590 }
1591 return false;
1592}