blob: 939bed77bd649f164ae6f56c27f51babd40255e2 [file] [log] [blame]
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00001//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the ARM target.
11//
12//===----------------------------------------------------------------------===//
13
Dale Johannesen51e28e62010-06-03 21:09:53 +000014#define DEBUG_TYPE "arm-isel"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000015#include "ARM.h"
Evan Cheng48575f62010-12-05 22:04:16 +000016#include "ARMBaseInstrInfo.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000017#include "ARMTargetMachine.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000018#include "MCTargetDesc/ARMAddressingModes.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000019#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineFunction.h"
21#include "llvm/CodeGen/MachineInstrBuilder.h"
22#include "llvm/CodeGen/SelectionDAG.h"
23#include "llvm/CodeGen/SelectionDAGISel.h"
Chandler Carruth0b8c9a82013-01-02 11:36:10 +000024#include "llvm/IR/CallingConv.h"
25#include "llvm/IR/Constants.h"
26#include "llvm/IR/DerivedTypes.h"
27#include "llvm/IR/Function.h"
28#include "llvm/IR/Intrinsics.h"
29#include "llvm/IR/LLVMContext.h"
Evan Cheng94cc6d32010-05-04 20:39:49 +000030#include "llvm/Support/CommandLine.h"
Chris Lattner3d62d782008-02-03 05:43:57 +000031#include "llvm/Support/Compiler.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000032#include "llvm/Support/Debug.h"
Torok Edwindac237e2009-07-08 20:53:28 +000033#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Support/raw_ostream.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000035#include "llvm/Target/TargetLowering.h"
36#include "llvm/Target/TargetOptions.h"
Torok Edwindac237e2009-07-08 20:53:28 +000037
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000038using namespace llvm;
39
Evan Chenga2c519b2010-07-30 23:33:54 +000040static cl::opt<bool>
41DisableShifterOp("disable-shifter-op", cl::Hidden,
42 cl::desc("Disable isel of shifter-op"),
43 cl::init(false));
44
Evan Cheng48575f62010-12-05 22:04:16 +000045static cl::opt<bool>
46CheckVMLxHazard("check-vmlx-hazard", cl::Hidden,
47 cl::desc("Check fp vmla / vmls hazard at isel time"),
Bob Wilson84c5eed2011-04-19 18:11:57 +000048 cl::init(true));
Evan Cheng48575f62010-12-05 22:04:16 +000049
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000050//===--------------------------------------------------------------------===//
51/// ARMDAGToDAGISel - ARM specific code to select ARM machine
52/// instructions for SelectionDAG operations.
53///
54namespace {
Jim Grosbach82891622010-09-29 19:03:54 +000055
56enum AddrMode2Type {
57 AM2_BASE, // Simple AM2 (+-imm12)
58 AM2_SHOP // Shifter-op AM2
59};
60
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000061class ARMDAGToDAGISel : public SelectionDAGISel {
Anton Korobeynikovd49ea772009-06-26 21:28:53 +000062 ARMBaseTargetMachine &TM;
Evan Cheng48575f62010-12-05 22:04:16 +000063 const ARMBaseInstrInfo *TII;
Evan Cheng3f7eb8e2008-09-18 07:24:33 +000064
Evan Chenga8e29892007-01-19 07:51:42 +000065 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
66 /// make the right decision when generating code for different targets.
67 const ARMSubtarget *Subtarget;
68
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000069public:
Bob Wilson522ce972009-09-28 14:30:20 +000070 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm,
71 CodeGenOpt::Level OptLevel)
72 : SelectionDAGISel(tm, OptLevel), TM(tm),
Evan Cheng48575f62010-12-05 22:04:16 +000073 TII(static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo())),
74 Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000075 }
76
Evan Chenga8e29892007-01-19 07:51:42 +000077 virtual const char *getPassName() const {
78 return "ARM Instruction Selection";
Anton Korobeynikov52237112009-06-17 18:13:58 +000079 }
80
Evan Cheng733c6b12012-12-19 20:16:09 +000081 virtual void PreprocessISelDAG();
82
Bob Wilsonaf4a8912009-10-08 18:51:31 +000083 /// getI32Imm - Return a target constant of type i32 with the specified
84 /// value.
Anton Korobeynikov52237112009-06-17 18:13:58 +000085 inline SDValue getI32Imm(unsigned Imm) {
Owen Anderson825b72b2009-08-11 20:47:22 +000086 return CurDAG->getTargetConstant(Imm, MVT::i32);
Anton Korobeynikov52237112009-06-17 18:13:58 +000087 }
88
Dan Gohmaneeb3a002010-01-05 01:24:18 +000089 SDNode *Select(SDNode *N);
Evan Cheng014bf212010-02-15 19:41:07 +000090
Evan Cheng48575f62010-12-05 22:04:16 +000091
92 bool hasNoVMLxHazardUse(SDNode *N) const;
Evan Chengf40deed2010-10-27 23:41:30 +000093 bool isShifterOpProfitable(const SDValue &Shift,
94 ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt);
Owen Anderson92a20222011-07-21 18:54:16 +000095 bool SelectRegShifterOperand(SDValue N, SDValue &A,
96 SDValue &B, SDValue &C,
97 bool CheckProfitability = true);
98 bool SelectImmShifterOperand(SDValue N, SDValue &A,
Owen Anderson152d4a42011-07-21 23:38:37 +000099 SDValue &B, bool CheckProfitability = true);
100 bool SelectShiftRegShifterOperand(SDValue N, SDValue &A,
Owen Anderson099e5552011-03-18 19:46:58 +0000101 SDValue &B, SDValue &C) {
102 // Don't apply the profitability check
Owen Anderson152d4a42011-07-21 23:38:37 +0000103 return SelectRegShifterOperand(N, A, B, C, false);
104 }
105 bool SelectShiftImmShifterOperand(SDValue N, SDValue &A,
106 SDValue &B) {
107 // Don't apply the profitability check
108 return SelectImmShifterOperand(N, A, B, false);
Owen Anderson099e5552011-03-18 19:46:58 +0000109 }
110
Jim Grosbach3e556122010-10-26 22:37:02 +0000111 bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
112 bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);
113
Jim Grosbach82891622010-09-29 19:03:54 +0000114 AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base,
115 SDValue &Offset, SDValue &Opc);
116 bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset,
117 SDValue &Opc) {
118 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE;
119 }
120
121 bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset,
122 SDValue &Opc) {
123 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP;
124 }
125
126 bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset,
127 SDValue &Opc) {
128 SelectAddrMode2Worker(N, Base, Offset, Opc);
Jim Grosbach3e556122010-10-26 22:37:02 +0000129// return SelectAddrMode2ShOp(N, Base, Offset, Opc);
Jim Grosbach82891622010-09-29 19:03:54 +0000130 // This always matches one way or another.
131 return true;
132 }
133
Owen Anderson793e7962011-07-26 20:54:26 +0000134 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
135 SDValue &Offset, SDValue &Opc);
136 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000137 SDValue &Offset, SDValue &Opc);
Owen Andersonc4e16de2011-08-29 20:16:50 +0000138 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
139 SDValue &Offset, SDValue &Opc);
Jim Grosbach19dec202011-08-05 20:35:44 +0000140 bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
Chris Lattner52a261b2010-09-21 20:31:19 +0000141 bool SelectAddrMode3(SDValue N, SDValue &Base,
Dan Gohman475871a2008-07-27 21:46:04 +0000142 SDValue &Offset, SDValue &Opc);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000143 bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000144 SDValue &Offset, SDValue &Opc);
Chris Lattner52a261b2010-09-21 20:31:19 +0000145 bool SelectAddrMode5(SDValue N, SDValue &Base,
Dan Gohman475871a2008-07-27 21:46:04 +0000146 SDValue &Offset);
Bob Wilson665814b2010-11-01 23:40:51 +0000147 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
Bob Wilsonda525062011-02-25 06:42:42 +0000148 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000149
Evan Cheng5de5d4b2011-01-17 08:03:18 +0000150 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
Evan Chenga8e29892007-01-19 07:51:42 +0000151
Bill Wendlingf4caf692010-12-14 03:36:38 +0000152 // Thumb Addressing Modes:
Chris Lattner52a261b2010-09-21 20:31:19 +0000153 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
Bill Wendlingf4caf692010-12-14 03:36:38 +0000154 bool SelectThumbAddrModeRI(SDValue N, SDValue &Base, SDValue &Offset,
155 unsigned Scale);
156 bool SelectThumbAddrModeRI5S1(SDValue N, SDValue &Base, SDValue &Offset);
157 bool SelectThumbAddrModeRI5S2(SDValue N, SDValue &Base, SDValue &Offset);
158 bool SelectThumbAddrModeRI5S4(SDValue N, SDValue &Base, SDValue &Offset);
159 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
160 SDValue &OffImm);
161 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
162 SDValue &OffImm);
163 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
164 SDValue &OffImm);
165 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
166 SDValue &OffImm);
Chris Lattner52a261b2010-09-21 20:31:19 +0000167 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Chenga8e29892007-01-19 07:51:42 +0000168
Bill Wendlingf4caf692010-12-14 03:36:38 +0000169 // Thumb 2 Addressing Modes:
Chris Lattner52a261b2010-09-21 20:31:19 +0000170 bool SelectT2ShifterOperandReg(SDValue N,
Evan Cheng9cb9e672009-06-27 02:26:13 +0000171 SDValue &BaseReg, SDValue &Opc);
Chris Lattner52a261b2010-09-21 20:31:19 +0000172 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
173 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
Evan Cheng055b0312009-06-29 07:51:04 +0000174 SDValue &OffImm);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000175 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Chenge88d5ce2009-07-02 07:28:31 +0000176 SDValue &OffImm);
Chris Lattner52a261b2010-09-21 20:31:19 +0000177 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
Evan Cheng055b0312009-06-29 07:51:04 +0000178 SDValue &OffReg, SDValue &ShImm);
179
Evan Cheng875a6ac2010-11-12 22:42:47 +0000180 inline bool is_so_imm(unsigned Imm) const {
181 return ARM_AM::getSOImmVal(Imm) != -1;
182 }
183
184 inline bool is_so_imm_not(unsigned Imm) const {
185 return ARM_AM::getSOImmVal(~Imm) != -1;
186 }
187
188 inline bool is_t2_so_imm(unsigned Imm) const {
189 return ARM_AM::getT2SOImmVal(Imm) != -1;
190 }
191
192 inline bool is_t2_so_imm_not(unsigned Imm) const {
193 return ARM_AM::getT2SOImmVal(~Imm) != -1;
194 }
195
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000196 // Include the pieces autogenerated from the target description.
197#include "ARMGenDAGISel.inc"
Bob Wilson224c2442009-05-19 05:53:42 +0000198
199private:
Evan Chenge88d5ce2009-07-02 07:28:31 +0000200 /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
201 /// ARM.
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000202 SDNode *SelectARMIndexedLoad(SDNode *N);
203 SDNode *SelectT2IndexedLoad(SDNode *N);
Evan Chenge88d5ce2009-07-02 07:28:31 +0000204
Bob Wilson621f1952010-03-23 05:25:43 +0000205 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
206 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson3e36f132009-10-14 17:28:52 +0000207 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson621f1952010-03-23 05:25:43 +0000208 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson1c3ef902011-02-07 17:43:21 +0000209 SDNode *SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +0000210 const uint16_t *DOpcodes,
211 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilson3e36f132009-10-14 17:28:52 +0000212
Bob Wilson24f995d2009-10-14 18:32:29 +0000213 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilson11d98992010-03-23 06:20:33 +0000214 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson24f995d2009-10-14 18:32:29 +0000215 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilson11d98992010-03-23 06:20:33 +0000216 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson1c3ef902011-02-07 17:43:21 +0000217 SDNode *SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +0000218 const uint16_t *DOpcodes,
219 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilson24f995d2009-10-14 18:32:29 +0000220
Bob Wilson96493442009-10-14 16:46:45 +0000221 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilsona7c397c2009-10-14 16:19:03 +0000222 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson8466fa12010-09-13 23:01:35 +0000223 /// load/store of D registers and Q registers.
Bob Wilson1c3ef902011-02-07 17:43:21 +0000224 SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad,
225 bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +0000226 const uint16_t *DOpcodes, const uint16_t *QOpcodes);
Bob Wilsona7c397c2009-10-14 16:19:03 +0000227
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +0000228 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
229 /// should be 2, 3 or 4. The opcode array specifies the instructions used
230 /// for loading D registers. (Q registers are not supported.)
Bob Wilson1c3ef902011-02-07 17:43:21 +0000231 SDNode *SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +0000232 const uint16_t *Opcodes);
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +0000233
Bob Wilson78dfbc32010-07-07 00:08:54 +0000234 /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2,
235 /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be
236 /// generated to force the table registers to be consecutive.
237 SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc);
Bob Wilsond491d6e2010-07-06 23:36:25 +0000238
Sandeep Patel4e1ed882009-10-13 20:25:58 +0000239 /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
Jim Grosbach3a1287b2010-04-22 23:24:18 +0000240 SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel47eedaa2009-10-13 18:59:48 +0000241
Evan Cheng07ba9062009-11-19 21:45:22 +0000242 /// SelectCMOVOp - Select CMOV instructions for ARM.
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000243 SDNode *SelectCMOVOp(SDNode *N);
244 SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +0000245 ARMCC::CondCodes CCVal, SDValue CCR,
246 SDValue InFlag);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000247 SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +0000248 ARMCC::CondCodes CCVal, SDValue CCR,
249 SDValue InFlag);
Jim Grosbacha4257162010-10-07 00:53:56 +0000250 SDNode *SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +0000251 ARMCC::CondCodes CCVal, SDValue CCR,
252 SDValue InFlag);
Jim Grosbach3bbdcea2010-10-07 00:42:42 +0000253 SDNode *SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +0000254 ARMCC::CondCodes CCVal, SDValue CCR,
255 SDValue InFlag);
Evan Cheng07ba9062009-11-19 21:45:22 +0000256
Bill Wendlingef2c86f2011-10-10 22:59:55 +0000257 // Select special operations if node forms integer ABS pattern
258 SDNode *SelectABSOp(SDNode *N);
259
Evan Chengde8aa4e2010-05-05 18:28:36 +0000260 SDNode *SelectConcatVector(SDNode *N);
261
Eli Friedman2bdffe42011-08-31 00:31:29 +0000262 SDNode *SelectAtomic64(SDNode *Node, unsigned Opc);
263
Evan Chengaf4550f2009-07-02 01:23:32 +0000264 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
265 /// inline asm expressions.
266 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
267 char ConstraintCode,
268 std::vector<SDValue> &OutOps);
Bob Wilson3bf12ab2009-10-06 22:01:59 +0000269
Weiming Zhao8b149cb2012-11-17 00:23:35 +0000270 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhaoe56764b2012-11-16 21:55:34 +0000271 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao8b149cb2012-11-17 00:23:35 +0000272 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
273 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
274 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Cheng603afbf2010-05-10 17:34:18 +0000275
Bob Wilson40cbe7d2010-06-04 00:04:02 +0000276 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao8b149cb2012-11-17 00:23:35 +0000277 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
278 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
279 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilson665814b2010-11-01 23:40:51 +0000280
281 // Get the alignment operand for a NEON VLD or VST instruction.
282 SDValue GetVLDSTAlign(SDValue Align, unsigned NumVecs, bool is64BitVector);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000283};
Evan Chenga8e29892007-01-19 07:51:42 +0000284}
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000285
Sandeep Patel47eedaa2009-10-13 18:59:48 +0000286/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
287/// operand. If so Imm will receive the 32-bit value.
288static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
289 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
290 Imm = cast<ConstantSDNode>(N)->getZExtValue();
291 return true;
292 }
293 return false;
294}
295
296// isInt32Immediate - This method tests to see if a constant operand.
297// If so Imm will receive the 32 bit value.
298static bool isInt32Immediate(SDValue N, unsigned &Imm) {
299 return isInt32Immediate(N.getNode(), Imm);
300}
301
302// isOpcWithIntImmediate - This method tests to see if the node is a specific
303// opcode and that it has a immediate integer right operand.
304// If so Imm will receive the 32 bit value.
305static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
306 return N->getOpcode() == Opc &&
307 isInt32Immediate(N->getOperand(1).getNode(), Imm);
308}
309
Daniel Dunbarec91d522011-01-19 15:12:16 +0000310/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenkoc5252da2012-09-14 14:57:36 +0000311/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbarec91d522011-01-19 15:12:16 +0000312///
313/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen11ebe3d2011-09-23 22:10:33 +0000314static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbarec91d522011-01-19 15:12:16 +0000315 int RangeMin, int RangeMax,
316 int &ScaledConstant) {
Jakob Stoklund Olesen11ebe3d2011-09-23 22:10:33 +0000317 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbarec91d522011-01-19 15:12:16 +0000318
319 // Check that this is a constant.
320 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
321 if (!C)
322 return false;
323
324 ScaledConstant = (int) C->getZExtValue();
325 if ((ScaledConstant % Scale) != 0)
326 return false;
327
328 ScaledConstant /= Scale;
329 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
330}
331
Evan Cheng733c6b12012-12-19 20:16:09 +0000332void ARMDAGToDAGISel::PreprocessISelDAG() {
333 if (!Subtarget->hasV6T2Ops())
334 return;
335
336 bool isThumb2 = Subtarget->isThumb();
337 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
338 E = CurDAG->allnodes_end(); I != E; ) {
339 SDNode *N = I++; // Preincrement iterator to avoid invalidation issues.
340
341 if (N->getOpcode() != ISD::ADD)
342 continue;
343
344 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
345 // leading zeros, followed by consecutive set bits, followed by 1 or 2
346 // trailing zeros, e.g. 1020.
347 // Transform the expression to
348 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
349 // of trailing zeros of c2. The left shift would be folded as an shifter
350 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
351 // node (UBFX).
352
353 SDValue N0 = N->getOperand(0);
354 SDValue N1 = N->getOperand(1);
355 unsigned And_imm = 0;
356 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
357 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
358 std::swap(N0, N1);
359 }
360 if (!And_imm)
361 continue;
362
363 // Check if the AND mask is an immediate of the form: 000.....1111111100
364 unsigned TZ = CountTrailingZeros_32(And_imm);
365 if (TZ != 1 && TZ != 2)
366 // Be conservative here. Shifter operands aren't always free. e.g. On
367 // Swift, left shifter operand of 1 / 2 for free but others are not.
368 // e.g.
369 // ubfx r3, r1, #16, #8
370 // ldr.w r3, [r0, r3, lsl #2]
371 // vs.
372 // mov.w r9, #1020
373 // and.w r2, r9, r1, lsr #14
374 // ldr r2, [r0, r2]
375 continue;
376 And_imm >>= TZ;
377 if (And_imm & (And_imm + 1))
378 continue;
379
380 // Look for (and (srl X, c1), c2).
381 SDValue Srl = N1.getOperand(0);
382 unsigned Srl_imm = 0;
383 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
384 (Srl_imm <= 2))
385 continue;
386
387 // Make sure first operand is not a shifter operand which would prevent
388 // folding of the left shift.
389 SDValue CPTmp0;
390 SDValue CPTmp1;
391 SDValue CPTmp2;
392 if (isThumb2) {
393 if (SelectT2ShifterOperandReg(N0, CPTmp0, CPTmp1))
394 continue;
395 } else {
396 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
397 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
398 continue;
399 }
400
401 // Now make the transformation.
402 Srl = CurDAG->getNode(ISD::SRL, Srl.getDebugLoc(), MVT::i32,
403 Srl.getOperand(0),
404 CurDAG->getConstant(Srl_imm+TZ, MVT::i32));
405 N1 = CurDAG->getNode(ISD::AND, N1.getDebugLoc(), MVT::i32,
406 Srl, CurDAG->getConstant(And_imm, MVT::i32));
407 N1 = CurDAG->getNode(ISD::SHL, N1.getDebugLoc(), MVT::i32,
408 N1, CurDAG->getConstant(TZ, MVT::i32));
409 CurDAG->UpdateNodeOperands(N, N0, N1);
410 }
411}
412
Evan Cheng48575f62010-12-05 22:04:16 +0000413/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
414/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
415/// least on current ARM implementations) which should be avoidded.
416bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
417 if (OptLevel == CodeGenOpt::None)
418 return true;
419
420 if (!CheckVMLxHazard)
421 return true;
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000422
423 if (!Subtarget->isCortexA8() && !Subtarget->isLikeA9() &&
424 !Subtarget->isSwift())
Evan Cheng48575f62010-12-05 22:04:16 +0000425 return true;
426
427 if (!N->hasOneUse())
428 return false;
429
430 SDNode *Use = *N->use_begin();
431 if (Use->getOpcode() == ISD::CopyToReg)
432 return true;
433 if (Use->isMachineOpcode()) {
Evan Chenge837dea2011-06-28 19:10:37 +0000434 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
435 if (MCID.mayStore())
Evan Cheng48575f62010-12-05 22:04:16 +0000436 return true;
Evan Chenge837dea2011-06-28 19:10:37 +0000437 unsigned Opcode = MCID.getOpcode();
Evan Cheng48575f62010-12-05 22:04:16 +0000438 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
439 return true;
440 // vmlx feeding into another vmlx. We actually want to unfold
441 // the use later in the MLxExpansion pass. e.g.
442 // vmla
443 // vmla (stall 8 cycles)
444 //
445 // vmul (5 cycles)
446 // vadd (5 cycles)
447 // vmla
448 // This adds up to about 18 - 19 cycles.
449 //
450 // vmla
451 // vmul (stall 4 cycles)
452 // vadd adds up to about 14 cycles.
453 return TII->isFpMLxInstruction(Opcode);
454 }
455
456 return false;
457}
Sandeep Patel47eedaa2009-10-13 18:59:48 +0000458
Evan Chengf40deed2010-10-27 23:41:30 +0000459bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
460 ARM_AM::ShiftOpc ShOpcVal,
461 unsigned ShAmt) {
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000462 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Chengf40deed2010-10-27 23:41:30 +0000463 return true;
464 if (Shift.hasOneUse())
465 return true;
466 // R << 2 is free.
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000467 return ShOpcVal == ARM_AM::lsl &&
468 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Chengf40deed2010-10-27 23:41:30 +0000469}
470
Owen Anderson92a20222011-07-21 18:54:16 +0000471bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Cheng055b0312009-06-29 07:51:04 +0000472 SDValue &BaseReg,
Owen Anderson099e5552011-03-18 19:46:58 +0000473 SDValue &Opc,
474 bool CheckProfitability) {
Evan Chenga2c519b2010-07-30 23:33:54 +0000475 if (DisableShifterOp)
476 return false;
477
Evan Chengee04a6d2011-07-20 23:34:39 +0000478 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng055b0312009-06-29 07:51:04 +0000479
480 // Don't match base register only case. That is matched to a separate
481 // lower complexity pattern with explicit register operand.
482 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbach764ab522009-08-11 15:33:49 +0000483
Evan Cheng055b0312009-06-29 07:51:04 +0000484 BaseReg = N.getOperand(0);
485 unsigned ShImmVal = 0;
Owen Anderson92a20222011-07-21 18:54:16 +0000486 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
487 if (!RHS) return false;
Owen Anderson92a20222011-07-21 18:54:16 +0000488 ShImmVal = RHS->getZExtValue() & 31;
Evan Chengf40deed2010-10-27 23:41:30 +0000489 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
490 MVT::i32);
491 return true;
492}
493
Owen Anderson92a20222011-07-21 18:54:16 +0000494bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
495 SDValue &BaseReg,
496 SDValue &ShReg,
497 SDValue &Opc,
498 bool CheckProfitability) {
499 if (DisableShifterOp)
500 return false;
501
502 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
503
504 // Don't match base register only case. That is matched to a separate
505 // lower complexity pattern with explicit register operand.
506 if (ShOpcVal == ARM_AM::no_shift) return false;
507
508 BaseReg = N.getOperand(0);
509 unsigned ShImmVal = 0;
510 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
511 if (RHS) return false;
512
513 ShReg = N.getOperand(1);
514 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
515 return false;
516 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
517 MVT::i32);
518 return true;
519}
520
521
Jim Grosbach3e556122010-10-26 22:37:02 +0000522bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
523 SDValue &Base,
524 SDValue &OffImm) {
525 // Match simple R + imm12 operands.
526
527 // Base only.
Chris Lattner0a9481f2011-02-13 22:25:43 +0000528 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
529 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach3e556122010-10-26 22:37:02 +0000530 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner0a9481f2011-02-13 22:25:43 +0000531 // Match frame index.
Jim Grosbach3e556122010-10-26 22:37:02 +0000532 int FI = cast<FrameIndexSDNode>(N)->getIndex();
533 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
534 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
535 return true;
Chris Lattner0a9481f2011-02-13 22:25:43 +0000536 }
Owen Anderson099e5552011-03-18 19:46:58 +0000537
Chris Lattner0a9481f2011-02-13 22:25:43 +0000538 if (N.getOpcode() == ARMISD::Wrapper &&
539 !(Subtarget->useMovt() &&
540 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Jim Grosbach3e556122010-10-26 22:37:02 +0000541 Base = N.getOperand(0);
542 } else
543 Base = N;
544 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
545 return true;
546 }
547
548 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
549 int RHSC = (int)RHS->getZExtValue();
550 if (N.getOpcode() == ISD::SUB)
551 RHSC = -RHSC;
552
553 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
554 Base = N.getOperand(0);
555 if (Base.getOpcode() == ISD::FrameIndex) {
556 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
557 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
558 }
559 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
560 return true;
561 }
562 }
563
564 // Base only.
565 Base = N;
566 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
567 return true;
568}
569
570
571
572bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
573 SDValue &Opc) {
Evan Chengf40deed2010-10-27 23:41:30 +0000574 if (N.getOpcode() == ISD::MUL &&
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000575 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach3e556122010-10-26 22:37:02 +0000576 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
577 // X * [3,5,9] -> X + X * [2,4,8] etc.
578 int RHSC = (int)RHS->getZExtValue();
579 if (RHSC & 1) {
580 RHSC = RHSC & ~1;
581 ARM_AM::AddrOpc AddSub = ARM_AM::add;
582 if (RHSC < 0) {
583 AddSub = ARM_AM::sub;
584 RHSC = - RHSC;
585 }
586 if (isPowerOf2_32(RHSC)) {
587 unsigned ShAmt = Log2_32(RHSC);
588 Base = Offset = N.getOperand(0);
589 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
590 ARM_AM::lsl),
591 MVT::i32);
592 return true;
593 }
594 }
595 }
596 }
597
Chris Lattner0a9481f2011-02-13 22:25:43 +0000598 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
599 // ISD::OR that is equivalent to an ISD::ADD.
600 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach3e556122010-10-26 22:37:02 +0000601 return false;
602
603 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner0a9481f2011-02-13 22:25:43 +0000604 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbarec91d522011-01-19 15:12:16 +0000605 int RHSC;
606 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
607 -0x1000+1, 0x1000, RHSC)) // 12 bits.
608 return false;
Jim Grosbach3e556122010-10-26 22:37:02 +0000609 }
610
611 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner0a9481f2011-02-13 22:25:43 +0000612 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chengee04a6d2011-07-20 23:34:39 +0000613 ARM_AM::ShiftOpc ShOpcVal =
614 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach3e556122010-10-26 22:37:02 +0000615 unsigned ShAmt = 0;
616
617 Base = N.getOperand(0);
618 Offset = N.getOperand(1);
619
620 if (ShOpcVal != ARM_AM::no_shift) {
621 // Check to see if the RHS of the shift is a constant, if not, we can't fold
622 // it.
623 if (ConstantSDNode *Sh =
624 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
625 ShAmt = Sh->getZExtValue();
Evan Chengf40deed2010-10-27 23:41:30 +0000626 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
627 Offset = N.getOperand(1).getOperand(0);
628 else {
629 ShAmt = 0;
630 ShOpcVal = ARM_AM::no_shift;
631 }
Jim Grosbach3e556122010-10-26 22:37:02 +0000632 } else {
633 ShOpcVal = ARM_AM::no_shift;
634 }
635 }
636
637 // Try matching (R shl C) + (R).
Chris Lattner0a9481f2011-02-13 22:25:43 +0000638 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000639 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
640 N.getOperand(0).hasOneUse())) {
Evan Chengee04a6d2011-07-20 23:34:39 +0000641 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach3e556122010-10-26 22:37:02 +0000642 if (ShOpcVal != ARM_AM::no_shift) {
643 // Check to see if the RHS of the shift is a constant, if not, we can't
644 // fold it.
645 if (ConstantSDNode *Sh =
646 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
647 ShAmt = Sh->getZExtValue();
Cameron Zwarich8f8aa812011-10-05 23:39:02 +0000648 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Chengf40deed2010-10-27 23:41:30 +0000649 Offset = N.getOperand(0).getOperand(0);
650 Base = N.getOperand(1);
651 } else {
652 ShAmt = 0;
653 ShOpcVal = ARM_AM::no_shift;
654 }
Jim Grosbach3e556122010-10-26 22:37:02 +0000655 } else {
656 ShOpcVal = ARM_AM::no_shift;
657 }
658 }
659 }
660
661 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
662 MVT::i32);
663 return true;
664}
665
666
Jim Grosbach3e556122010-10-26 22:37:02 +0000667//-----
668
Jim Grosbach82891622010-09-29 19:03:54 +0000669AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
670 SDValue &Base,
671 SDValue &Offset,
672 SDValue &Opc) {
Evan Chengf40deed2010-10-27 23:41:30 +0000673 if (N.getOpcode() == ISD::MUL &&
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000674 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Chenga13fd102007-03-13 21:05:54 +0000675 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
676 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000677 int RHSC = (int)RHS->getZExtValue();
Evan Chenga13fd102007-03-13 21:05:54 +0000678 if (RHSC & 1) {
679 RHSC = RHSC & ~1;
680 ARM_AM::AddrOpc AddSub = ARM_AM::add;
681 if (RHSC < 0) {
682 AddSub = ARM_AM::sub;
683 RHSC = - RHSC;
684 }
685 if (isPowerOf2_32(RHSC)) {
686 unsigned ShAmt = Log2_32(RHSC);
687 Base = Offset = N.getOperand(0);
688 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
689 ARM_AM::lsl),
Owen Anderson825b72b2009-08-11 20:47:22 +0000690 MVT::i32);
Jim Grosbach82891622010-09-29 19:03:54 +0000691 return AM2_SHOP;
Evan Chenga13fd102007-03-13 21:05:54 +0000692 }
693 }
694 }
695 }
696
Chris Lattner0a9481f2011-02-13 22:25:43 +0000697 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
698 // ISD::OR that is equivalent to an ADD.
699 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Chenga8e29892007-01-19 07:51:42 +0000700 Base = N;
701 if (N.getOpcode() == ISD::FrameIndex) {
702 int FI = cast<FrameIndexSDNode>(N)->getIndex();
703 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000704 } else if (N.getOpcode() == ARMISD::Wrapper &&
705 !(Subtarget->useMovt() &&
706 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Chenga8e29892007-01-19 07:51:42 +0000707 Base = N.getOperand(0);
708 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000709 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000710 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
711 ARM_AM::no_shift),
Owen Anderson825b72b2009-08-11 20:47:22 +0000712 MVT::i32);
Jim Grosbach82891622010-09-29 19:03:54 +0000713 return AM2_BASE;
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000714 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000715
Evan Chenga8e29892007-01-19 07:51:42 +0000716 // Match simple R +/- imm12 operands.
Chris Lattner0a9481f2011-02-13 22:25:43 +0000717 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbarec91d522011-01-19 15:12:16 +0000718 int RHSC;
719 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
720 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
721 Base = N.getOperand(0);
722 if (Base.getOpcode() == ISD::FrameIndex) {
723 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
724 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000725 }
Daniel Dunbarec91d522011-01-19 15:12:16 +0000726 Offset = CurDAG->getRegister(0, MVT::i32);
727
728 ARM_AM::AddrOpc AddSub = ARM_AM::add;
729 if (RHSC < 0) {
730 AddSub = ARM_AM::sub;
731 RHSC = - RHSC;
732 }
733 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
734 ARM_AM::no_shift),
735 MVT::i32);
736 return AM2_BASE;
Evan Chenga8e29892007-01-19 07:51:42 +0000737 }
Jim Grosbachbe912322010-09-29 17:32:29 +0000738 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000739
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000740 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Chengf40deed2010-10-27 23:41:30 +0000741 // Compute R +/- (R << N) and reuse it.
742 Base = N;
743 Offset = CurDAG->getRegister(0, MVT::i32);
744 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
745 ARM_AM::no_shift),
746 MVT::i32);
747 return AM2_BASE;
748 }
749
Johnny Chen6a3b5ee2009-10-27 17:25:15 +0000750 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner0a9481f2011-02-13 22:25:43 +0000751 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chengee04a6d2011-07-20 23:34:39 +0000752 ARM_AM::ShiftOpc ShOpcVal =
753 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Chenga8e29892007-01-19 07:51:42 +0000754 unsigned ShAmt = 0;
Jim Grosbach764ab522009-08-11 15:33:49 +0000755
Evan Chenga8e29892007-01-19 07:51:42 +0000756 Base = N.getOperand(0);
757 Offset = N.getOperand(1);
Jim Grosbach764ab522009-08-11 15:33:49 +0000758
Evan Chenga8e29892007-01-19 07:51:42 +0000759 if (ShOpcVal != ARM_AM::no_shift) {
760 // Check to see if the RHS of the shift is a constant, if not, we can't fold
761 // it.
762 if (ConstantSDNode *Sh =
763 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000764 ShAmt = Sh->getZExtValue();
Evan Chengf40deed2010-10-27 23:41:30 +0000765 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
766 Offset = N.getOperand(1).getOperand(0);
767 else {
768 ShAmt = 0;
769 ShOpcVal = ARM_AM::no_shift;
770 }
Evan Chenga8e29892007-01-19 07:51:42 +0000771 } else {
772 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000773 }
774 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000775
Evan Chenga8e29892007-01-19 07:51:42 +0000776 // Try matching (R shl C) + (R).
Chris Lattner0a9481f2011-02-13 22:25:43 +0000777 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000778 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
779 N.getOperand(0).hasOneUse())) {
Evan Chengee04a6d2011-07-20 23:34:39 +0000780 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Chenga8e29892007-01-19 07:51:42 +0000781 if (ShOpcVal != ARM_AM::no_shift) {
782 // Check to see if the RHS of the shift is a constant, if not, we can't
783 // fold it.
784 if (ConstantSDNode *Sh =
785 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000786 ShAmt = Sh->getZExtValue();
Cameron Zwarich8f8aa812011-10-05 23:39:02 +0000787 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Chengf40deed2010-10-27 23:41:30 +0000788 Offset = N.getOperand(0).getOperand(0);
789 Base = N.getOperand(1);
790 } else {
791 ShAmt = 0;
792 ShOpcVal = ARM_AM::no_shift;
793 }
Evan Chenga8e29892007-01-19 07:51:42 +0000794 } else {
795 ShOpcVal = ARM_AM::no_shift;
796 }
797 }
798 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000799
Evan Chenga8e29892007-01-19 07:51:42 +0000800 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson825b72b2009-08-11 20:47:22 +0000801 MVT::i32);
Jim Grosbach82891622010-09-29 19:03:54 +0000802 return AM2_SHOP;
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000803}
804
Owen Anderson793e7962011-07-26 20:54:26 +0000805bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000806 SDValue &Offset, SDValue &Opc) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000807 unsigned Opcode = Op->getOpcode();
Evan Chenga8e29892007-01-19 07:51:42 +0000808 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
809 ? cast<LoadSDNode>(Op)->getAddressingMode()
810 : cast<StoreSDNode>(Op)->getAddressingMode();
811 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
812 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbarec91d522011-01-19 15:12:16 +0000813 int Val;
Owen Anderson793e7962011-07-26 20:54:26 +0000814 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
815 return false;
Evan Chenga8e29892007-01-19 07:51:42 +0000816
817 Offset = N;
Evan Chengee04a6d2011-07-20 23:34:39 +0000818 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chenga8e29892007-01-19 07:51:42 +0000819 unsigned ShAmt = 0;
820 if (ShOpcVal != ARM_AM::no_shift) {
821 // Check to see if the RHS of the shift is a constant, if not, we can't fold
822 // it.
823 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000824 ShAmt = Sh->getZExtValue();
Evan Chengf40deed2010-10-27 23:41:30 +0000825 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
826 Offset = N.getOperand(0);
827 else {
828 ShAmt = 0;
829 ShOpcVal = ARM_AM::no_shift;
830 }
Evan Chenga8e29892007-01-19 07:51:42 +0000831 } else {
832 ShOpcVal = ARM_AM::no_shift;
833 }
834 }
835
836 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson825b72b2009-08-11 20:47:22 +0000837 MVT::i32);
Rafael Espindola32bd5f42006-10-17 18:04:53 +0000838 return true;
839}
840
Owen Andersonc4e16de2011-08-29 20:16:50 +0000841bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
842 SDValue &Offset, SDValue &Opc) {
Owen Andersond84192f2011-08-31 20:00:11 +0000843 unsigned Opcode = Op->getOpcode();
844 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
845 ? cast<LoadSDNode>(Op)->getAddressingMode()
846 : cast<StoreSDNode>(Op)->getAddressingMode();
847 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
848 ? ARM_AM::add : ARM_AM::sub;
Owen Andersonc4e16de2011-08-29 20:16:50 +0000849 int Val;
850 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Andersond84192f2011-08-31 20:00:11 +0000851 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Andersonc4e16de2011-08-29 20:16:50 +0000852 Offset = CurDAG->getRegister(0, MVT::i32);
853 Opc = CurDAG->getTargetConstant(Val, MVT::i32);
854 return true;
855 }
856
857 return false;
858}
859
860
Owen Anderson793e7962011-07-26 20:54:26 +0000861bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
862 SDValue &Offset, SDValue &Opc) {
863 unsigned Opcode = Op->getOpcode();
864 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
865 ? cast<LoadSDNode>(Op)->getAddressingMode()
866 : cast<StoreSDNode>(Op)->getAddressingMode();
867 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
868 ? ARM_AM::add : ARM_AM::sub;
869 int Val;
870 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
871 Offset = CurDAG->getRegister(0, MVT::i32);
872 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
873 ARM_AM::no_shift),
874 MVT::i32);
875 return true;
876 }
877
878 return false;
879}
880
Jim Grosbach19dec202011-08-05 20:35:44 +0000881bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
882 Base = N;
883 return true;
884}
Evan Chenga8e29892007-01-19 07:51:42 +0000885
Chris Lattner52a261b2010-09-21 20:31:19 +0000886bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000887 SDValue &Base, SDValue &Offset,
888 SDValue &Opc) {
Evan Chenga8e29892007-01-19 07:51:42 +0000889 if (N.getOpcode() == ISD::SUB) {
890 // X - C is canonicalize to X + -C, no need to handle it here.
891 Base = N.getOperand(0);
892 Offset = N.getOperand(1);
Owen Anderson825b72b2009-08-11 20:47:22 +0000893 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000894 return true;
895 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000896
Chris Lattner0a9481f2011-02-13 22:25:43 +0000897 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Chenga8e29892007-01-19 07:51:42 +0000898 Base = N;
899 if (N.getOpcode() == ISD::FrameIndex) {
900 int FI = cast<FrameIndexSDNode>(N)->getIndex();
901 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
902 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000903 Offset = CurDAG->getRegister(0, MVT::i32);
904 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000905 return true;
906 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000907
Evan Chenga8e29892007-01-19 07:51:42 +0000908 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbarec91d522011-01-19 15:12:16 +0000909 int RHSC;
910 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
911 -256 + 1, 256, RHSC)) { // 8 bits.
912 Base = N.getOperand(0);
913 if (Base.getOpcode() == ISD::FrameIndex) {
914 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
915 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Evan Chenga8e29892007-01-19 07:51:42 +0000916 }
Daniel Dunbarec91d522011-01-19 15:12:16 +0000917 Offset = CurDAG->getRegister(0, MVT::i32);
918
919 ARM_AM::AddrOpc AddSub = ARM_AM::add;
920 if (RHSC < 0) {
921 AddSub = ARM_AM::sub;
Chris Lattner0a9481f2011-02-13 22:25:43 +0000922 RHSC = -RHSC;
Daniel Dunbarec91d522011-01-19 15:12:16 +0000923 }
924 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32);
925 return true;
Evan Chenga8e29892007-01-19 07:51:42 +0000926 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000927
Evan Chenga8e29892007-01-19 07:51:42 +0000928 Base = N.getOperand(0);
929 Offset = N.getOperand(1);
Owen Anderson825b72b2009-08-11 20:47:22 +0000930 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000931 return true;
932}
933
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000934bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000935 SDValue &Offset, SDValue &Opc) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000936 unsigned Opcode = Op->getOpcode();
Evan Chenga8e29892007-01-19 07:51:42 +0000937 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
938 ? cast<LoadSDNode>(Op)->getAddressingMode()
939 : cast<StoreSDNode>(Op)->getAddressingMode();
940 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
941 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbarec91d522011-01-19 15:12:16 +0000942 int Val;
943 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
944 Offset = CurDAG->getRegister(0, MVT::i32);
945 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32);
946 return true;
Evan Chenga8e29892007-01-19 07:51:42 +0000947 }
948
949 Offset = N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000950 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000951 return true;
952}
953
Jim Grosbach3ab56582010-10-21 19:38:40 +0000954bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000955 SDValue &Base, SDValue &Offset) {
Chris Lattner0a9481f2011-02-13 22:25:43 +0000956 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Chenga8e29892007-01-19 07:51:42 +0000957 Base = N;
958 if (N.getOpcode() == ISD::FrameIndex) {
959 int FI = cast<FrameIndexSDNode>(N)->getIndex();
960 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000961 } else if (N.getOpcode() == ARMISD::Wrapper &&
962 !(Subtarget->useMovt() &&
963 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Chenga8e29892007-01-19 07:51:42 +0000964 Base = N.getOperand(0);
965 }
966 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson825b72b2009-08-11 20:47:22 +0000967 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000968 return true;
969 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000970
Evan Chenga8e29892007-01-19 07:51:42 +0000971 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbarec91d522011-01-19 15:12:16 +0000972 int RHSC;
973 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
974 -256 + 1, 256, RHSC)) {
975 Base = N.getOperand(0);
976 if (Base.getOpcode() == ISD::FrameIndex) {
977 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
978 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Evan Chenga8e29892007-01-19 07:51:42 +0000979 }
Daniel Dunbarec91d522011-01-19 15:12:16 +0000980
981 ARM_AM::AddrOpc AddSub = ARM_AM::add;
982 if (RHSC < 0) {
983 AddSub = ARM_AM::sub;
Chris Lattner0a9481f2011-02-13 22:25:43 +0000984 RHSC = -RHSC;
Daniel Dunbarec91d522011-01-19 15:12:16 +0000985 }
986 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
987 MVT::i32);
988 return true;
Evan Chenga8e29892007-01-19 07:51:42 +0000989 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000990
Evan Chenga8e29892007-01-19 07:51:42 +0000991 Base = N;
992 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson825b72b2009-08-11 20:47:22 +0000993 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000994 return true;
995}
996
Bob Wilson665814b2010-11-01 23:40:51 +0000997bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
998 SDValue &Align) {
Bob Wilson8b024a52009-07-01 23:16:05 +0000999 Addr = N;
Bob Wilson665814b2010-11-01 23:40:51 +00001000
1001 unsigned Alignment = 0;
1002 if (LSBaseSDNode *LSN = dyn_cast<LSBaseSDNode>(Parent)) {
1003 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
1004 // The maximum alignment is equal to the memory size being referenced.
1005 unsigned LSNAlign = LSN->getAlignment();
1006 unsigned MemSize = LSN->getMemoryVT().getSizeInBits() / 8;
Jakob Stoklund Olesenb0117ee2011-10-27 22:39:16 +00001007 if (LSNAlign >= MemSize && MemSize > 1)
Bob Wilson665814b2010-11-01 23:40:51 +00001008 Alignment = MemSize;
1009 } else {
1010 // All other uses of addrmode6 are for intrinsics. For now just record
1011 // the raw alignment value; it will be refined later based on the legal
1012 // alignment operands for the intrinsic.
1013 Alignment = cast<MemIntrinsicSDNode>(Parent)->getAlignment();
1014 }
1015
1016 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilson8b024a52009-07-01 23:16:05 +00001017 return true;
1018}
1019
Bob Wilsonda525062011-02-25 06:42:42 +00001020bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1021 SDValue &Offset) {
1022 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1023 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1024 if (AM != ISD::POST_INC)
1025 return false;
1026 Offset = N;
1027 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1028 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1029 Offset = CurDAG->getRegister(0, MVT::i32);
1030 }
1031 return true;
1032}
1033
Chris Lattner52a261b2010-09-21 20:31:19 +00001034bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Chengbba9f5f2009-08-14 19:01:37 +00001035 SDValue &Offset, SDValue &Label) {
Evan Chenga8e29892007-01-19 07:51:42 +00001036 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1037 Offset = N.getOperand(0);
Dan Gohman475871a2008-07-27 21:46:04 +00001038 SDValue N1 = N.getOperand(1);
Evan Cheng9fe20092011-01-20 08:34:58 +00001039 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
1040 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +00001041 return true;
1042 }
Bill Wendlingf4caf692010-12-14 03:36:38 +00001043
Evan Chenga8e29892007-01-19 07:51:42 +00001044 return false;
1045}
1046
Bill Wendlingf4caf692010-12-14 03:36:38 +00001047
1048//===----------------------------------------------------------------------===//
1049// Thumb Addressing Modes
1050//===----------------------------------------------------------------------===//
1051
Chris Lattner52a261b2010-09-21 20:31:19 +00001052bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +00001053 SDValue &Base, SDValue &Offset){
Chris Lattner0a9481f2011-02-13 22:25:43 +00001054 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng2f297df2009-07-11 07:08:13 +00001055 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmane368b462010-06-18 14:22:04 +00001056 if (!NC || !NC->isNullValue())
Evan Cheng2f297df2009-07-11 07:08:13 +00001057 return false;
1058
1059 Base = Offset = N;
Evan Chengc38f2bc2007-01-23 22:59:13 +00001060 return true;
1061 }
1062
Evan Chenga8e29892007-01-19 07:51:42 +00001063 Base = N.getOperand(0);
1064 Offset = N.getOperand(1);
1065 return true;
1066}
1067
Evan Cheng79d43262007-01-24 02:21:22 +00001068bool
Bill Wendlingf4caf692010-12-14 03:36:38 +00001069ARMDAGToDAGISel::SelectThumbAddrModeRI(SDValue N, SDValue &Base,
1070 SDValue &Offset, unsigned Scale) {
Evan Cheng79d43262007-01-24 02:21:22 +00001071 if (Scale == 4) {
Dan Gohman475871a2008-07-27 21:46:04 +00001072 SDValue TmpBase, TmpOffImm;
Chris Lattner52a261b2010-09-21 20:31:19 +00001073 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
Evan Cheng79d43262007-01-24 02:21:22 +00001074 return false; // We want to select tLDRspi / tSTRspi instead.
Bill Wendlingf4caf692010-12-14 03:36:38 +00001075
Evan Cheng012f2d92007-01-24 08:53:17 +00001076 if (N.getOpcode() == ARMISD::Wrapper &&
1077 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1078 return false; // We want to select tLDRpci instead.
Evan Cheng79d43262007-01-24 02:21:22 +00001079 }
1080
Chris Lattner0a9481f2011-02-13 22:25:43 +00001081 if (!CurDAG->isBaseWithConstantOffset(N))
Bill Wendlingbc4224b2010-12-15 01:03:19 +00001082 return false;
Evan Chenga8e29892007-01-19 07:51:42 +00001083
Evan Chengad0e4652007-02-06 00:22:06 +00001084 // Thumb does not have [sp, r] address mode.
1085 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1086 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1087 if ((LHSR && LHSR->getReg() == ARM::SP) ||
Bill Wendlingbc4224b2010-12-15 01:03:19 +00001088 (RHSR && RHSR->getReg() == ARM::SP))
1089 return false;
Bill Wendlingf4caf692010-12-14 03:36:38 +00001090
Daniel Dunbarec91d522011-01-19 15:12:16 +00001091 // FIXME: Why do we explicitly check for a match here and then return false?
1092 // Presumably to allow something else to match, but shouldn't this be
1093 // documented?
1094 int RHSC;
1095 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC))
1096 return false;
Bill Wendlingf4caf692010-12-14 03:36:38 +00001097
1098 Base = N.getOperand(0);
1099 Offset = N.getOperand(1);
1100 return true;
1101}
1102
1103bool
1104ARMDAGToDAGISel::SelectThumbAddrModeRI5S1(SDValue N,
1105 SDValue &Base,
1106 SDValue &Offset) {
1107 return SelectThumbAddrModeRI(N, Base, Offset, 1);
1108}
1109
1110bool
1111ARMDAGToDAGISel::SelectThumbAddrModeRI5S2(SDValue N,
1112 SDValue &Base,
1113 SDValue &Offset) {
1114 return SelectThumbAddrModeRI(N, Base, Offset, 2);
1115}
1116
1117bool
1118ARMDAGToDAGISel::SelectThumbAddrModeRI5S4(SDValue N,
1119 SDValue &Base,
1120 SDValue &Offset) {
1121 return SelectThumbAddrModeRI(N, Base, Offset, 4);
1122}
1123
1124bool
1125ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1126 SDValue &Base, SDValue &OffImm) {
1127 if (Scale == 4) {
1128 SDValue TmpBase, TmpOffImm;
1129 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
1130 return false; // We want to select tLDRspi / tSTRspi instead.
1131
1132 if (N.getOpcode() == ARMISD::Wrapper &&
1133 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1134 return false; // We want to select tLDRpci instead.
1135 }
1136
Chris Lattner0a9481f2011-02-13 22:25:43 +00001137 if (!CurDAG->isBaseWithConstantOffset(N)) {
Bill Wendlingf4caf692010-12-14 03:36:38 +00001138 if (N.getOpcode() == ARMISD::Wrapper &&
1139 !(Subtarget->useMovt() &&
1140 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
1141 Base = N.getOperand(0);
1142 } else {
1143 Base = N;
1144 }
1145
Owen Anderson825b72b2009-08-11 20:47:22 +00001146 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chengad0e4652007-02-06 00:22:06 +00001147 return true;
1148 }
1149
Bill Wendlingbc4224b2010-12-15 01:03:19 +00001150 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1151 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1152 if ((LHSR && LHSR->getReg() == ARM::SP) ||
1153 (RHSR && RHSR->getReg() == ARM::SP)) {
1154 ConstantSDNode *LHS = dyn_cast<ConstantSDNode>(N.getOperand(0));
1155 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1156 unsigned LHSC = LHS ? LHS->getZExtValue() : 0;
1157 unsigned RHSC = RHS ? RHS->getZExtValue() : 0;
1158
1159 // Thumb does not have [sp, #imm5] address mode for non-zero imm5.
1160 if (LHSC != 0 || RHSC != 0) return false;
1161
1162 Base = N;
1163 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
1164 return true;
1165 }
1166
Evan Chenga8e29892007-01-19 07:51:42 +00001167 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbarec91d522011-01-19 15:12:16 +00001168 int RHSC;
1169 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1170 Base = N.getOperand(0);
1171 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1172 return true;
Evan Chenga8e29892007-01-19 07:51:42 +00001173 }
1174
Evan Chengc38f2bc2007-01-23 22:59:13 +00001175 Base = N.getOperand(0);
Owen Anderson825b72b2009-08-11 20:47:22 +00001176 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chengc38f2bc2007-01-23 22:59:13 +00001177 return true;
Evan Chenga8e29892007-01-19 07:51:42 +00001178}
1179
Bill Wendlingf4caf692010-12-14 03:36:38 +00001180bool
1181ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1182 SDValue &OffImm) {
1183 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Chenga8e29892007-01-19 07:51:42 +00001184}
1185
Bill Wendlingf4caf692010-12-14 03:36:38 +00001186bool
1187ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1188 SDValue &OffImm) {
1189 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Chenga8e29892007-01-19 07:51:42 +00001190}
1191
Bill Wendlingf4caf692010-12-14 03:36:38 +00001192bool
1193ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1194 SDValue &OffImm) {
1195 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Chenga8e29892007-01-19 07:51:42 +00001196}
1197
Chris Lattner52a261b2010-09-21 20:31:19 +00001198bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1199 SDValue &Base, SDValue &OffImm) {
Evan Chenga8e29892007-01-19 07:51:42 +00001200 if (N.getOpcode() == ISD::FrameIndex) {
1201 int FI = cast<FrameIndexSDNode>(N)->getIndex();
1202 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Owen Anderson825b72b2009-08-11 20:47:22 +00001203 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +00001204 return true;
1205 }
Evan Cheng79d43262007-01-24 02:21:22 +00001206
Chris Lattner0a9481f2011-02-13 22:25:43 +00001207 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Chengad0e4652007-02-06 00:22:06 +00001208 return false;
1209
1210 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Cheng8c1a73a2007-02-06 09:11:20 +00001211 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1212 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng79d43262007-01-24 02:21:22 +00001213 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbarec91d522011-01-19 15:12:16 +00001214 int RHSC;
1215 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1216 Base = N.getOperand(0);
1217 if (Base.getOpcode() == ISD::FrameIndex) {
1218 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1219 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Evan Cheng79d43262007-01-24 02:21:22 +00001220 }
Daniel Dunbarec91d522011-01-19 15:12:16 +00001221 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1222 return true;
Evan Cheng79d43262007-01-24 02:21:22 +00001223 }
1224 }
Jim Grosbach764ab522009-08-11 15:33:49 +00001225
Evan Chenga8e29892007-01-19 07:51:42 +00001226 return false;
1227}
1228
Bill Wendlingf4caf692010-12-14 03:36:38 +00001229
1230//===----------------------------------------------------------------------===//
1231// Thumb 2 Addressing Modes
1232//===----------------------------------------------------------------------===//
1233
1234
Chris Lattner52a261b2010-09-21 20:31:19 +00001235bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg,
Evan Cheng9cb9e672009-06-27 02:26:13 +00001236 SDValue &Opc) {
Evan Chenga2c519b2010-07-30 23:33:54 +00001237 if (DisableShifterOp)
1238 return false;
1239
Evan Chengee04a6d2011-07-20 23:34:39 +00001240 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng9cb9e672009-06-27 02:26:13 +00001241
1242 // Don't match base register only case. That is matched to a separate
1243 // lower complexity pattern with explicit register operand.
1244 if (ShOpcVal == ARM_AM::no_shift) return false;
1245
1246 BaseReg = N.getOperand(0);
1247 unsigned ShImmVal = 0;
1248 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1249 ShImmVal = RHS->getZExtValue() & 31;
1250 Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
1251 return true;
1252 }
1253
1254 return false;
1255}
1256
Chris Lattner52a261b2010-09-21 20:31:19 +00001257bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Cheng055b0312009-06-29 07:51:04 +00001258 SDValue &Base, SDValue &OffImm) {
1259 // Match simple R + imm12 operands.
David Goodwin31e7eba2009-07-20 15:55:39 +00001260
Evan Cheng3a214252009-08-11 08:52:18 +00001261 // Base only.
Chris Lattner0a9481f2011-02-13 22:25:43 +00001262 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1263 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin31e7eba2009-07-20 15:55:39 +00001264 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner0a9481f2011-02-13 22:25:43 +00001265 // Match frame index.
David Goodwin31e7eba2009-07-20 15:55:39 +00001266 int FI = cast<FrameIndexSDNode>(N)->getIndex();
1267 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Owen Anderson825b72b2009-08-11 20:47:22 +00001268 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
David Goodwin31e7eba2009-07-20 15:55:39 +00001269 return true;
Chris Lattner0a9481f2011-02-13 22:25:43 +00001270 }
Owen Anderson099e5552011-03-18 19:46:58 +00001271
Chris Lattner0a9481f2011-02-13 22:25:43 +00001272 if (N.getOpcode() == ARMISD::Wrapper &&
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +00001273 !(Subtarget->useMovt() &&
1274 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Cheng3a214252009-08-11 08:52:18 +00001275 Base = N.getOperand(0);
1276 if (Base.getOpcode() == ISD::TargetConstantPool)
1277 return false; // We want to select t2LDRpci instead.
1278 } else
1279 Base = N;
Owen Anderson825b72b2009-08-11 20:47:22 +00001280 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng3a214252009-08-11 08:52:18 +00001281 return true;
David Goodwin31e7eba2009-07-20 15:55:39 +00001282 }
Evan Cheng055b0312009-06-29 07:51:04 +00001283
1284 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner52a261b2010-09-21 20:31:19 +00001285 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng3a214252009-08-11 08:52:18 +00001286 // Let t2LDRi8 handle (R - imm8).
1287 return false;
1288
Evan Cheng055b0312009-06-29 07:51:04 +00001289 int RHSC = (int)RHS->getZExtValue();
David Goodwind8c95b52009-07-30 18:56:48 +00001290 if (N.getOpcode() == ISD::SUB)
1291 RHSC = -RHSC;
1292
1293 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Cheng055b0312009-06-29 07:51:04 +00001294 Base = N.getOperand(0);
David Goodwind8c95b52009-07-30 18:56:48 +00001295 if (Base.getOpcode() == ISD::FrameIndex) {
1296 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1297 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
1298 }
Owen Anderson825b72b2009-08-11 20:47:22 +00001299 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
Evan Cheng055b0312009-06-29 07:51:04 +00001300 return true;
1301 }
1302 }
1303
Evan Cheng3a214252009-08-11 08:52:18 +00001304 // Base only.
1305 Base = N;
Owen Anderson825b72b2009-08-11 20:47:22 +00001306 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng3a214252009-08-11 08:52:18 +00001307 return true;
Evan Cheng055b0312009-06-29 07:51:04 +00001308}
1309
Chris Lattner52a261b2010-09-21 20:31:19 +00001310bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Cheng055b0312009-06-29 07:51:04 +00001311 SDValue &Base, SDValue &OffImm) {
David Goodwind8c95b52009-07-30 18:56:48 +00001312 // Match simple R - imm8 operands.
Chris Lattner0a9481f2011-02-13 22:25:43 +00001313 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1314 !CurDAG->isBaseWithConstantOffset(N))
1315 return false;
Owen Anderson099e5552011-03-18 19:46:58 +00001316
Chris Lattner0a9481f2011-02-13 22:25:43 +00001317 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1318 int RHSC = (int)RHS->getSExtValue();
1319 if (N.getOpcode() == ISD::SUB)
1320 RHSC = -RHSC;
Jim Grosbach764ab522009-08-11 15:33:49 +00001321
Chris Lattner0a9481f2011-02-13 22:25:43 +00001322 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1323 Base = N.getOperand(0);
1324 if (Base.getOpcode() == ISD::FrameIndex) {
1325 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1326 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Evan Cheng055b0312009-06-29 07:51:04 +00001327 }
Chris Lattner0a9481f2011-02-13 22:25:43 +00001328 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1329 return true;
Evan Cheng055b0312009-06-29 07:51:04 +00001330 }
1331 }
1332
1333 return false;
1334}
1335
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001336bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Chenge88d5ce2009-07-02 07:28:31 +00001337 SDValue &OffImm){
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001338 unsigned Opcode = Op->getOpcode();
Evan Chenge88d5ce2009-07-02 07:28:31 +00001339 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1340 ? cast<LoadSDNode>(Op)->getAddressingMode()
1341 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbarec91d522011-01-19 15:12:16 +00001342 int RHSC;
1343 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1344 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
1345 ? CurDAG->getTargetConstant(RHSC, MVT::i32)
1346 : CurDAG->getTargetConstant(-RHSC, MVT::i32);
1347 return true;
Evan Chenge88d5ce2009-07-02 07:28:31 +00001348 }
1349
1350 return false;
1351}
1352
Chris Lattner52a261b2010-09-21 20:31:19 +00001353bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Cheng055b0312009-06-29 07:51:04 +00001354 SDValue &Base,
1355 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng3a214252009-08-11 08:52:18 +00001356 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner0a9481f2011-02-13 22:25:43 +00001357 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng3a214252009-08-11 08:52:18 +00001358 return false;
Evan Cheng055b0312009-06-29 07:51:04 +00001359
Evan Cheng3a214252009-08-11 08:52:18 +00001360 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1361 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1362 int RHSC = (int)RHS->getZExtValue();
1363 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1364 return false;
1365 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwind8c95b52009-07-30 18:56:48 +00001366 return false;
1367 }
1368
Evan Cheng055b0312009-06-29 07:51:04 +00001369 // Look for (R + R) or (R + (R << [1,2,3])).
1370 unsigned ShAmt = 0;
1371 Base = N.getOperand(0);
1372 OffReg = N.getOperand(1);
1373
1374 // Swap if it is ((R << c) + R).
Evan Chengee04a6d2011-07-20 23:34:39 +00001375 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Cheng055b0312009-06-29 07:51:04 +00001376 if (ShOpcVal != ARM_AM::lsl) {
Evan Chengee04a6d2011-07-20 23:34:39 +00001377 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Cheng055b0312009-06-29 07:51:04 +00001378 if (ShOpcVal == ARM_AM::lsl)
1379 std::swap(Base, OffReg);
Jim Grosbach764ab522009-08-11 15:33:49 +00001380 }
1381
Evan Cheng055b0312009-06-29 07:51:04 +00001382 if (ShOpcVal == ARM_AM::lsl) {
1383 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1384 // it.
1385 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1386 ShAmt = Sh->getZExtValue();
Evan Chengf40deed2010-10-27 23:41:30 +00001387 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1388 OffReg = OffReg.getOperand(0);
1389 else {
Evan Cheng055b0312009-06-29 07:51:04 +00001390 ShAmt = 0;
1391 ShOpcVal = ARM_AM::no_shift;
Evan Chengf40deed2010-10-27 23:41:30 +00001392 }
Evan Cheng055b0312009-06-29 07:51:04 +00001393 } else {
1394 ShOpcVal = ARM_AM::no_shift;
1395 }
David Goodwin7ecc8502009-07-15 15:50:19 +00001396 }
Jim Grosbach764ab522009-08-11 15:33:49 +00001397
Owen Anderson825b72b2009-08-11 20:47:22 +00001398 ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32);
Evan Cheng055b0312009-06-29 07:51:04 +00001399
1400 return true;
1401}
1402
1403//===--------------------------------------------------------------------===//
1404
Evan Chengee568cf2007-07-05 07:15:27 +00001405/// getAL - Returns a ARMCC::AL immediate node.
Dan Gohman475871a2008-07-27 21:46:04 +00001406static inline SDValue getAL(SelectionDAG *CurDAG) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001407 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);
Evan Cheng44bec522007-05-15 01:29:07 +00001408}
1409
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001410SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
1411 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengaf4550f2009-07-02 01:23:32 +00001412 ISD::MemIndexedMode AM = LD->getAddressingMode();
1413 if (AM == ISD::UNINDEXED)
1414 return NULL;
1415
Owen Andersone50ed302009-08-10 22:56:29 +00001416 EVT LoadedVT = LD->getMemoryVT();
Evan Chengaf4550f2009-07-02 01:23:32 +00001417 SDValue Offset, AMOpc;
1418 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1419 unsigned Opcode = 0;
1420 bool Match = false;
Owen Andersonc4e16de2011-08-29 20:16:50 +00001421 if (LoadedVT == MVT::i32 && isPre &&
1422 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1423 Opcode = ARM::LDR_PRE_IMM;
1424 Match = true;
1425 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson793e7962011-07-26 20:54:26 +00001426 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Andersonc4e16de2011-08-29 20:16:50 +00001427 Opcode = ARM::LDR_POST_IMM;
Evan Chengaf4550f2009-07-02 01:23:32 +00001428 Match = true;
Owen Anderson793e7962011-07-26 20:54:26 +00001429 } else if (LoadedVT == MVT::i32 &&
1430 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson9ab0f252011-08-26 20:43:14 +00001431 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson793e7962011-07-26 20:54:26 +00001432 Match = true;
1433
Owen Anderson825b72b2009-08-11 20:47:22 +00001434 } else if (LoadedVT == MVT::i16 &&
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001435 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengaf4550f2009-07-02 01:23:32 +00001436 Match = true;
1437 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1438 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1439 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson825b72b2009-08-11 20:47:22 +00001440 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengaf4550f2009-07-02 01:23:32 +00001441 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001442 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengaf4550f2009-07-02 01:23:32 +00001443 Match = true;
1444 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1445 }
1446 } else {
Owen Andersonc4e16de2011-08-29 20:16:50 +00001447 if (isPre &&
1448 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengaf4550f2009-07-02 01:23:32 +00001449 Match = true;
Owen Andersonc4e16de2011-08-29 20:16:50 +00001450 Opcode = ARM::LDRB_PRE_IMM;
1451 } else if (!isPre &&
1452 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1453 Match = true;
1454 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson793e7962011-07-26 20:54:26 +00001455 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1456 Match = true;
Owen Anderson9ab0f252011-08-26 20:43:14 +00001457 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengaf4550f2009-07-02 01:23:32 +00001458 }
1459 }
1460 }
1461
1462 if (Match) {
Owen Anderson2b568fb2011-08-26 21:12:37 +00001463 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1464 SDValue Chain = LD->getChain();
1465 SDValue Base = LD->getBasePtr();
1466 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG),
1467 CurDAG->getRegister(0, MVT::i32), Chain };
Jim Grosbachb04546f2011-09-13 20:30:37 +00001468 return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32,
1469 MVT::i32, MVT::Other, Ops, 5);
Owen Anderson2b568fb2011-08-26 21:12:37 +00001470 } else {
1471 SDValue Chain = LD->getChain();
1472 SDValue Base = LD->getBasePtr();
1473 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG),
1474 CurDAG->getRegister(0, MVT::i32), Chain };
Jim Grosbachb04546f2011-09-13 20:30:37 +00001475 return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32,
1476 MVT::i32, MVT::Other, Ops, 6);
Owen Anderson2b568fb2011-08-26 21:12:37 +00001477 }
Evan Chengaf4550f2009-07-02 01:23:32 +00001478 }
1479
1480 return NULL;
1481}
1482
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001483SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
1484 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chenge88d5ce2009-07-02 07:28:31 +00001485 ISD::MemIndexedMode AM = LD->getAddressingMode();
1486 if (AM == ISD::UNINDEXED)
1487 return NULL;
1488
Owen Andersone50ed302009-08-10 22:56:29 +00001489 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng4fbb9962009-07-02 23:16:11 +00001490 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Chenge88d5ce2009-07-02 07:28:31 +00001491 SDValue Offset;
1492 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1493 unsigned Opcode = 0;
1494 bool Match = false;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001495 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001496 switch (LoadedVT.getSimpleVT().SimpleTy) {
1497 case MVT::i32:
Evan Chenge88d5ce2009-07-02 07:28:31 +00001498 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1499 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001500 case MVT::i16:
Evan Cheng4fbb9962009-07-02 23:16:11 +00001501 if (isSExtLd)
1502 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1503 else
1504 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Chenge88d5ce2009-07-02 07:28:31 +00001505 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001506 case MVT::i8:
1507 case MVT::i1:
Evan Cheng4fbb9962009-07-02 23:16:11 +00001508 if (isSExtLd)
1509 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1510 else
1511 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Chenge88d5ce2009-07-02 07:28:31 +00001512 break;
1513 default:
1514 return NULL;
1515 }
1516 Match = true;
1517 }
1518
1519 if (Match) {
1520 SDValue Chain = LD->getChain();
1521 SDValue Base = LD->getBasePtr();
1522 SDValue Ops[]= { Base, Offset, getAL(CurDAG),
Owen Anderson825b72b2009-08-11 20:47:22 +00001523 CurDAG->getRegister(0, MVT::i32), Chain };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001524 return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32,
Dan Gohman602b0c82009-09-25 18:54:59 +00001525 MVT::Other, Ops, 5);
Evan Chenge88d5ce2009-07-02 07:28:31 +00001526 }
1527
1528 return NULL;
1529}
1530
Weiming Zhaoe56764b2012-11-16 21:55:34 +00001531/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1532SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
1533 DebugLoc dl = V0.getNode()->getDebugLoc();
1534 SDValue RegClass =
1535 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, MVT::i32);
1536 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32);
1537 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32);
1538 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1539 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 5);
1540}
1541
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001542/// \brief Form a D register from a pair of S registers.
1543SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001544 DebugLoc dl = V0.getNode()->getDebugLoc();
Owen Anderson1300f302011-06-16 18:17:13 +00001545 SDValue RegClass =
1546 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, MVT::i32);
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001547 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1548 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
Owen Anderson1300f302011-06-16 18:17:13 +00001549 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1550 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 5);
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001551}
1552
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001553/// \brief Form a quad register from a pair of D registers.
1554SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Bob Wilson3bf12ab2009-10-06 22:01:59 +00001555 DebugLoc dl = V0.getNode()->getDebugLoc();
Owen Anderson1300f302011-06-16 18:17:13 +00001556 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, MVT::i32);
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001557 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1558 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
Owen Anderson1300f302011-06-16 18:17:13 +00001559 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1560 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 5);
Bob Wilson3bf12ab2009-10-06 22:01:59 +00001561}
1562
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001563/// \brief Form 4 consecutive D registers from a pair of Q registers.
1564SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Evan Cheng603afbf2010-05-10 17:34:18 +00001565 DebugLoc dl = V0.getNode()->getDebugLoc();
Owen Anderson1300f302011-06-16 18:17:13 +00001566 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001567 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1568 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
Owen Anderson1300f302011-06-16 18:17:13 +00001569 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1570 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 5);
Evan Cheng603afbf2010-05-10 17:34:18 +00001571}
1572
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001573/// \brief Form 4 consecutive S registers.
1574SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001575 SDValue V2, SDValue V3) {
1576 DebugLoc dl = V0.getNode()->getDebugLoc();
Owen Anderson1300f302011-06-16 18:17:13 +00001577 SDValue RegClass =
1578 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, MVT::i32);
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001579 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1580 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
1581 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, MVT::i32);
1582 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, MVT::i32);
Owen Anderson1300f302011-06-16 18:17:13 +00001583 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1584 V2, SubReg2, V3, SubReg3 };
1585 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 9);
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001586}
1587
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001588/// \brief Form 4 consecutive D registers.
1589SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng603afbf2010-05-10 17:34:18 +00001590 SDValue V2, SDValue V3) {
1591 DebugLoc dl = V0.getNode()->getDebugLoc();
Owen Anderson1300f302011-06-16 18:17:13 +00001592 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001593 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1594 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
1595 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32);
1596 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32);
Owen Anderson1300f302011-06-16 18:17:13 +00001597 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1598 V2, SubReg2, V3, SubReg3 };
1599 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 9);
Evan Cheng603afbf2010-05-10 17:34:18 +00001600}
1601
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001602/// \brief Form 4 consecutive Q registers.
1603SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng8f6de382010-05-16 03:27:48 +00001604 SDValue V2, SDValue V3) {
1605 DebugLoc dl = V0.getNode()->getDebugLoc();
Owen Anderson1300f302011-06-16 18:17:13 +00001606 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001607 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1608 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
1609 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32);
1610 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32);
Owen Anderson1300f302011-06-16 18:17:13 +00001611 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1612 V2, SubReg2, V3, SubReg3 };
1613 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 9);
Evan Cheng8f6de382010-05-16 03:27:48 +00001614}
1615
Bob Wilson2a6e6162010-09-23 23:42:37 +00001616/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1617/// of a NEON VLD or VST instruction. The supported values depend on the
1618/// number of registers being loaded.
Bob Wilson665814b2010-11-01 23:40:51 +00001619SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, unsigned NumVecs,
1620 bool is64BitVector) {
Bob Wilson2a6e6162010-09-23 23:42:37 +00001621 unsigned NumRegs = NumVecs;
1622 if (!is64BitVector && NumVecs < 3)
1623 NumRegs *= 2;
1624
Bob Wilson665814b2010-11-01 23:40:51 +00001625 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson2a6e6162010-09-23 23:42:37 +00001626 if (Alignment >= 32 && NumRegs == 4)
Bob Wilson665814b2010-11-01 23:40:51 +00001627 Alignment = 32;
1628 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1629 Alignment = 16;
1630 else if (Alignment >= 8)
1631 Alignment = 8;
1632 else
1633 Alignment = 0;
1634
1635 return CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilson2a6e6162010-09-23 23:42:37 +00001636}
1637
Jim Grosbach10b90a92011-10-24 21:45:13 +00001638// Get the register stride update opcode of a VLD/VST instruction that
1639// is otherwise equivalent to the given fixed stride updating instruction.
1640static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
1641 switch (Opc) {
1642 default: break;
1643 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1644 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1645 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1646 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1647 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1648 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1649 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1650 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jim Grosbach4334e032011-10-31 21:50:31 +00001651
1652 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1653 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1654 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1655 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1656 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1657 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1658 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1659 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbachd5ca2012011-11-29 22:38:04 +00001660 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach4c7edb32011-11-29 22:58:48 +00001661 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbacha4e3c7f2011-12-09 21:28:25 +00001662
Jim Grosbach28f08c92012-03-05 19:33:30 +00001663 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1664 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1665 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbacha4e3c7f2011-12-09 21:28:25 +00001666 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1667 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1668 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1669
Jim Grosbach28f08c92012-03-05 19:33:30 +00001670 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1671 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1672 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbachbb3a2e42011-12-14 21:32:11 +00001673 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1674 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1675 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbache6949b12011-12-21 19:40:55 +00001676
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001677 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1678 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1679 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach10b90a92011-10-24 21:45:13 +00001680 }
1681 return Opc; // If not one we handle, return it unchanged.
1682}
1683
Bob Wilson1c3ef902011-02-07 17:43:21 +00001684SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +00001685 const uint16_t *DOpcodes,
1686 const uint16_t *QOpcodes0,
1687 const uint16_t *QOpcodes1) {
Bob Wilson621f1952010-03-23 05:25:43 +00001688 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Bob Wilson3e36f132009-10-14 17:28:52 +00001689 DebugLoc dl = N->getDebugLoc();
1690
Bob Wilson226036e2010-03-20 22:13:40 +00001691 SDValue MemAddr, Align;
Bob Wilson1c3ef902011-02-07 17:43:21 +00001692 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1693 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilson3e36f132009-10-14 17:28:52 +00001694 return NULL;
1695
1696 SDValue Chain = N->getOperand(0);
1697 EVT VT = N->getValueType(0);
1698 bool is64BitVector = VT.is64BitVector();
Bob Wilson665814b2010-11-01 23:40:51 +00001699 Align = GetVLDSTAlign(Align, NumVecs, is64BitVector);
Bob Wilson40ff01a2010-09-23 21:43:54 +00001700
Bob Wilson3e36f132009-10-14 17:28:52 +00001701 unsigned OpcodeIndex;
1702 switch (VT.getSimpleVT().SimpleTy) {
1703 default: llvm_unreachable("unhandled vld type");
1704 // Double-register operations:
1705 case MVT::v8i8: OpcodeIndex = 0; break;
1706 case MVT::v4i16: OpcodeIndex = 1; break;
1707 case MVT::v2f32:
1708 case MVT::v2i32: OpcodeIndex = 2; break;
1709 case MVT::v1i64: OpcodeIndex = 3; break;
1710 // Quad-register operations:
1711 case MVT::v16i8: OpcodeIndex = 0; break;
1712 case MVT::v8i16: OpcodeIndex = 1; break;
1713 case MVT::v4f32:
1714 case MVT::v4i32: OpcodeIndex = 2; break;
Bob Wilson621f1952010-03-23 05:25:43 +00001715 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilson11d98992010-03-23 06:20:33 +00001716 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson621f1952010-03-23 05:25:43 +00001717 break;
Bob Wilson3e36f132009-10-14 17:28:52 +00001718 }
1719
Bob Wilsonf5721912010-09-03 18:16:02 +00001720 EVT ResTy;
1721 if (NumVecs == 1)
1722 ResTy = VT;
1723 else {
1724 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1725 if (!is64BitVector)
1726 ResTyElts *= 2;
1727 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1728 }
Bob Wilson1c3ef902011-02-07 17:43:21 +00001729 std::vector<EVT> ResTys;
1730 ResTys.push_back(ResTy);
1731 if (isUpdating)
1732 ResTys.push_back(MVT::i32);
1733 ResTys.push_back(MVT::Other);
Bob Wilsonf5721912010-09-03 18:16:02 +00001734
Evan Cheng47b7b9f2010-04-16 05:46:06 +00001735 SDValue Pred = getAL(CurDAG);
Bob Wilson226036e2010-03-20 22:13:40 +00001736 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson1c3ef902011-02-07 17:43:21 +00001737 SDNode *VLd;
1738 SmallVector<SDValue, 7> Ops;
Evan Chenge9e2ba02010-05-10 21:26:24 +00001739
Bob Wilson1c3ef902011-02-07 17:43:21 +00001740 // Double registers and VLD1/VLD2 quad registers are directly supported.
1741 if (is64BitVector || NumVecs <= 2) {
1742 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1743 QOpcodes0[OpcodeIndex]);
1744 Ops.push_back(MemAddr);
1745 Ops.push_back(Align);
1746 if (isUpdating) {
1747 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbacha4e3c7f2011-12-09 21:28:25 +00001748 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach10b90a92011-10-24 21:45:13 +00001749 // case entirely when the rest are updated to that form, too.
Jim Grosbacha4e3c7f2011-12-09 21:28:25 +00001750 if ((NumVecs == 1 || NumVecs == 2) && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach10b90a92011-10-24 21:45:13 +00001751 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jim Grosbacha4e3c7f2011-12-09 21:28:25 +00001752 // We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach4334e032011-10-31 21:50:31 +00001753 // check for that explicitly too. Horribly hacky, but temporary.
Jim Grosbach28f08c92012-03-05 19:33:30 +00001754 if ((NumVecs != 1 && NumVecs != 2 && Opc != ARM::VLD1q64wb_fixed) ||
Jim Grosbach4334e032011-10-31 21:50:31 +00001755 !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach10b90a92011-10-24 21:45:13 +00001756 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Evan Chenge9e2ba02010-05-10 21:26:24 +00001757 }
Bob Wilson1c3ef902011-02-07 17:43:21 +00001758 Ops.push_back(Pred);
1759 Ops.push_back(Reg0);
1760 Ops.push_back(Chain);
1761 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size());
Bob Wilsonffde0802010-09-02 16:00:54 +00001762
Bob Wilson3e36f132009-10-14 17:28:52 +00001763 } else {
1764 // Otherwise, quad registers are loaded with two separate instructions,
1765 // where one loads the even registers and the other loads the odd registers.
Bob Wilsonf5721912010-09-03 18:16:02 +00001766 EVT AddrTy = MemAddr.getValueType();
Bob Wilson3e36f132009-10-14 17:28:52 +00001767
Bob Wilson1c3ef902011-02-07 17:43:21 +00001768 // Load the even subregs. This is always an updating load, so that it
1769 // provides the address to the second load for the odd subregs.
Bob Wilsonf5721912010-09-03 18:16:02 +00001770 SDValue ImplDef =
1771 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1772 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilson7de68142011-02-07 17:43:15 +00001773 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
1774 ResTy, AddrTy, MVT::Other, OpsA, 7);
Bob Wilsonf5721912010-09-03 18:16:02 +00001775 Chain = SDValue(VLdA, 2);
Bob Wilson3e36f132009-10-14 17:28:52 +00001776
Bob Wilson24f995d2009-10-14 18:32:29 +00001777 // Load the odd subregs.
Bob Wilson1c3ef902011-02-07 17:43:21 +00001778 Ops.push_back(SDValue(VLdA, 1));
1779 Ops.push_back(Align);
1780 if (isUpdating) {
1781 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1782 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1783 "only constant post-increment update allowed for VLD3/4");
1784 (void)Inc;
1785 Ops.push_back(Reg0);
1786 }
1787 Ops.push_back(SDValue(VLdA, 0));
1788 Ops.push_back(Pred);
1789 Ops.push_back(Reg0);
1790 Ops.push_back(Chain);
1791 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
1792 Ops.data(), Ops.size());
Bob Wilsonf5721912010-09-03 18:16:02 +00001793 }
Bob Wilson3e36f132009-10-14 17:28:52 +00001794
Evan Chengb58a3402011-04-19 00:04:03 +00001795 // Transfer memoperands.
1796 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1797 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1798 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1799
Bob Wilson1c3ef902011-02-07 17:43:21 +00001800 if (NumVecs == 1)
1801 return VLd;
1802
1803 // Extract out the subregisters.
1804 SDValue SuperReg = SDValue(VLd, 0);
1805 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
1806 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
1807 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1808 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1809 ReplaceUses(SDValue(N, Vec),
1810 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1811 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1812 if (isUpdating)
1813 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Bob Wilson3e36f132009-10-14 17:28:52 +00001814 return NULL;
1815}
1816
Bob Wilson1c3ef902011-02-07 17:43:21 +00001817SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +00001818 const uint16_t *DOpcodes,
1819 const uint16_t *QOpcodes0,
1820 const uint16_t *QOpcodes1) {
Bob Wilsond491d6e2010-07-06 23:36:25 +00001821 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Bob Wilson24f995d2009-10-14 18:32:29 +00001822 DebugLoc dl = N->getDebugLoc();
1823
Bob Wilson226036e2010-03-20 22:13:40 +00001824 SDValue MemAddr, Align;
Bob Wilson1c3ef902011-02-07 17:43:21 +00001825 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1826 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1827 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilson24f995d2009-10-14 18:32:29 +00001828 return NULL;
1829
Evan Chengb58a3402011-04-19 00:04:03 +00001830 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1831 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1832
Bob Wilson24f995d2009-10-14 18:32:29 +00001833 SDValue Chain = N->getOperand(0);
Bob Wilson1c3ef902011-02-07 17:43:21 +00001834 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson24f995d2009-10-14 18:32:29 +00001835 bool is64BitVector = VT.is64BitVector();
Bob Wilson665814b2010-11-01 23:40:51 +00001836 Align = GetVLDSTAlign(Align, NumVecs, is64BitVector);
Bob Wilson2a6e6162010-09-23 23:42:37 +00001837
Bob Wilson24f995d2009-10-14 18:32:29 +00001838 unsigned OpcodeIndex;
1839 switch (VT.getSimpleVT().SimpleTy) {
1840 default: llvm_unreachable("unhandled vst type");
1841 // Double-register operations:
1842 case MVT::v8i8: OpcodeIndex = 0; break;
1843 case MVT::v4i16: OpcodeIndex = 1; break;
1844 case MVT::v2f32:
1845 case MVT::v2i32: OpcodeIndex = 2; break;
1846 case MVT::v1i64: OpcodeIndex = 3; break;
1847 // Quad-register operations:
1848 case MVT::v16i8: OpcodeIndex = 0; break;
1849 case MVT::v8i16: OpcodeIndex = 1; break;
1850 case MVT::v4f32:
1851 case MVT::v4i32: OpcodeIndex = 2; break;
Bob Wilson11d98992010-03-23 06:20:33 +00001852 case MVT::v2i64: OpcodeIndex = 3;
1853 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
1854 break;
Bob Wilson24f995d2009-10-14 18:32:29 +00001855 }
1856
Bob Wilson1c3ef902011-02-07 17:43:21 +00001857 std::vector<EVT> ResTys;
1858 if (isUpdating)
1859 ResTys.push_back(MVT::i32);
1860 ResTys.push_back(MVT::Other);
1861
Evan Cheng47b7b9f2010-04-16 05:46:06 +00001862 SDValue Pred = getAL(CurDAG);
Bob Wilson226036e2010-03-20 22:13:40 +00001863 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson1c3ef902011-02-07 17:43:21 +00001864 SmallVector<SDValue, 7> Ops;
Evan Chengac0869d2009-11-21 06:21:52 +00001865
Bob Wilson1c3ef902011-02-07 17:43:21 +00001866 // Double registers and VST1/VST2 quad registers are directly supported.
1867 if (is64BitVector || NumVecs <= 2) {
Bob Wilson7de68142011-02-07 17:43:15 +00001868 SDValue SrcReg;
Bob Wilsone5ce4f62010-08-28 05:12:57 +00001869 if (NumVecs == 1) {
Bob Wilson1c3ef902011-02-07 17:43:21 +00001870 SrcReg = N->getOperand(Vec0Idx);
1871 } else if (is64BitVector) {
Evan Cheng0ce537a2010-05-11 01:19:40 +00001872 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson1c3ef902011-02-07 17:43:21 +00001873 SDValue V0 = N->getOperand(Vec0Idx + 0);
1874 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Cheng0ce537a2010-05-11 01:19:40 +00001875 if (NumVecs == 2)
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001876 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Cheng0ce537a2010-05-11 01:19:40 +00001877 else {
Bob Wilson1c3ef902011-02-07 17:43:21 +00001878 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson7de68142011-02-07 17:43:15 +00001879 // If it's a vst3, form a quad D-register and leave the last part as
Evan Cheng0ce537a2010-05-11 01:19:40 +00001880 // an undef.
1881 SDValue V3 = (NumVecs == 3)
1882 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson1c3ef902011-02-07 17:43:21 +00001883 : N->getOperand(Vec0Idx + 3);
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001884 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Cheng0ce537a2010-05-11 01:19:40 +00001885 }
Bob Wilsone5ce4f62010-08-28 05:12:57 +00001886 } else {
1887 // Form a QQ register.
Bob Wilson1c3ef902011-02-07 17:43:21 +00001888 SDValue Q0 = N->getOperand(Vec0Idx);
1889 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001890 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilson24f995d2009-10-14 18:32:29 +00001891 }
Bob Wilson1c3ef902011-02-07 17:43:21 +00001892
1893 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1894 QOpcodes0[OpcodeIndex]);
1895 Ops.push_back(MemAddr);
1896 Ops.push_back(Align);
1897 if (isUpdating) {
1898 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachbb3a2e42011-12-14 21:32:11 +00001899 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach4334e032011-10-31 21:50:31 +00001900 // case entirely when the rest are updated to that form, too.
Jim Grosbachbb3a2e42011-12-14 21:32:11 +00001901 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach4334e032011-10-31 21:50:31 +00001902 Opc = getVLDSTRegisterUpdateOpcode(Opc);
1903 // We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
1904 // check for that explicitly too. Horribly hacky, but temporary.
Jim Grosbach28f08c92012-03-05 19:33:30 +00001905 if ((NumVecs > 2 && Opc != ARM::VST1q64wb_fixed) ||
Jim Grosbach4334e032011-10-31 21:50:31 +00001906 !isa<ConstantSDNode>(Inc.getNode()))
1907 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Bob Wilson1c3ef902011-02-07 17:43:21 +00001908 }
1909 Ops.push_back(SrcReg);
1910 Ops.push_back(Pred);
1911 Ops.push_back(Reg0);
1912 Ops.push_back(Chain);
Evan Chengb58a3402011-04-19 00:04:03 +00001913 SDNode *VSt =
1914 CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size());
1915
1916 // Transfer memoperands.
1917 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
1918
1919 return VSt;
Bob Wilson24f995d2009-10-14 18:32:29 +00001920 }
1921
1922 // Otherwise, quad registers are stored with two separate instructions,
1923 // where one stores the even registers and the other stores the odd registers.
Evan Cheng7189fd02010-05-15 07:53:37 +00001924
Bob Wilson07f6e802010-06-16 21:34:01 +00001925 // Form the QQQQ REG_SEQUENCE.
Bob Wilson1c3ef902011-02-07 17:43:21 +00001926 SDValue V0 = N->getOperand(Vec0Idx + 0);
1927 SDValue V1 = N->getOperand(Vec0Idx + 1);
1928 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsone5ce4f62010-08-28 05:12:57 +00001929 SDValue V3 = (NumVecs == 3)
1930 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson1c3ef902011-02-07 17:43:21 +00001931 : N->getOperand(Vec0Idx + 3);
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001932 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson07f6e802010-06-16 21:34:01 +00001933
Bob Wilson1c3ef902011-02-07 17:43:21 +00001934 // Store the even D registers. This is always an updating store, so that it
1935 // provides the address to the second store for the odd subregs.
Bob Wilson7de68142011-02-07 17:43:15 +00001936 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
1937 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
1938 MemAddr.getValueType(),
1939 MVT::Other, OpsA, 7);
Evan Chengb58a3402011-04-19 00:04:03 +00001940 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson07f6e802010-06-16 21:34:01 +00001941 Chain = SDValue(VStA, 1);
1942
1943 // Store the odd D registers.
Bob Wilson1c3ef902011-02-07 17:43:21 +00001944 Ops.push_back(SDValue(VStA, 0));
1945 Ops.push_back(Align);
1946 if (isUpdating) {
1947 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1948 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1949 "only constant post-increment update allowed for VST3/4");
1950 (void)Inc;
1951 Ops.push_back(Reg0);
1952 }
1953 Ops.push_back(RegSeq);
1954 Ops.push_back(Pred);
1955 Ops.push_back(Reg0);
1956 Ops.push_back(Chain);
Evan Chengb58a3402011-04-19 00:04:03 +00001957 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
1958 Ops.data(), Ops.size());
1959 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
1960 return VStB;
Bob Wilson24f995d2009-10-14 18:32:29 +00001961}
1962
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001963SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
Bob Wilson1c3ef902011-02-07 17:43:21 +00001964 bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +00001965 const uint16_t *DOpcodes,
1966 const uint16_t *QOpcodes) {
Bob Wilson96493442009-10-14 16:46:45 +00001967 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Bob Wilsona7c397c2009-10-14 16:19:03 +00001968 DebugLoc dl = N->getDebugLoc();
1969
Bob Wilson226036e2010-03-20 22:13:40 +00001970 SDValue MemAddr, Align;
Bob Wilson1c3ef902011-02-07 17:43:21 +00001971 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1972 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1973 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilsona7c397c2009-10-14 16:19:03 +00001974 return NULL;
1975
Evan Chengb58a3402011-04-19 00:04:03 +00001976 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1977 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1978
Bob Wilsona7c397c2009-10-14 16:19:03 +00001979 SDValue Chain = N->getOperand(0);
1980 unsigned Lane =
Bob Wilson1c3ef902011-02-07 17:43:21 +00001981 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
1982 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsona7c397c2009-10-14 16:19:03 +00001983 bool is64BitVector = VT.is64BitVector();
1984
Bob Wilson665814b2010-11-01 23:40:51 +00001985 unsigned Alignment = 0;
Bob Wilson3454ed92010-10-19 00:16:32 +00001986 if (NumVecs != 3) {
Bob Wilson665814b2010-11-01 23:40:51 +00001987 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson3454ed92010-10-19 00:16:32 +00001988 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
1989 if (Alignment > NumBytes)
1990 Alignment = NumBytes;
Bob Wilsona92bac62010-12-10 19:37:42 +00001991 if (Alignment < 8 && Alignment < NumBytes)
1992 Alignment = 0;
Bob Wilson3454ed92010-10-19 00:16:32 +00001993 // Alignment must be a power of two; make sure of that.
1994 Alignment = (Alignment & -Alignment);
Bob Wilson665814b2010-11-01 23:40:51 +00001995 if (Alignment == 1)
1996 Alignment = 0;
Bob Wilson3454ed92010-10-19 00:16:32 +00001997 }
Bob Wilson665814b2010-11-01 23:40:51 +00001998 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilson3454ed92010-10-19 00:16:32 +00001999
Bob Wilsona7c397c2009-10-14 16:19:03 +00002000 unsigned OpcodeIndex;
2001 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson96493442009-10-14 16:46:45 +00002002 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilsona7c397c2009-10-14 16:19:03 +00002003 // Double-register operations:
2004 case MVT::v8i8: OpcodeIndex = 0; break;
2005 case MVT::v4i16: OpcodeIndex = 1; break;
2006 case MVT::v2f32:
2007 case MVT::v2i32: OpcodeIndex = 2; break;
2008 // Quad-register operations:
2009 case MVT::v8i16: OpcodeIndex = 0; break;
2010 case MVT::v4f32:
2011 case MVT::v4i32: OpcodeIndex = 1; break;
2012 }
2013
Bob Wilson1c3ef902011-02-07 17:43:21 +00002014 std::vector<EVT> ResTys;
2015 if (IsLoad) {
2016 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2017 if (!is64BitVector)
2018 ResTyElts *= 2;
2019 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2020 MVT::i64, ResTyElts));
2021 }
2022 if (isUpdating)
2023 ResTys.push_back(MVT::i32);
2024 ResTys.push_back(MVT::Other);
2025
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002026 SDValue Pred = getAL(CurDAG);
Bob Wilson226036e2010-03-20 22:13:40 +00002027 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengac0869d2009-11-21 06:21:52 +00002028
Bob Wilson1c3ef902011-02-07 17:43:21 +00002029 SmallVector<SDValue, 8> Ops;
Bob Wilsona7c397c2009-10-14 16:19:03 +00002030 Ops.push_back(MemAddr);
Jim Grosbach8a5ec862009-11-07 21:25:39 +00002031 Ops.push_back(Align);
Bob Wilson1c3ef902011-02-07 17:43:21 +00002032 if (isUpdating) {
2033 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2034 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
2035 }
Bob Wilson07f6e802010-06-16 21:34:01 +00002036
Bob Wilson8466fa12010-09-13 23:01:35 +00002037 SDValue SuperReg;
Bob Wilson1c3ef902011-02-07 17:43:21 +00002038 SDValue V0 = N->getOperand(Vec0Idx + 0);
2039 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilson8466fa12010-09-13 23:01:35 +00002040 if (NumVecs == 2) {
2041 if (is64BitVector)
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002042 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilson8466fa12010-09-13 23:01:35 +00002043 else
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002044 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilsona7c397c2009-10-14 16:19:03 +00002045 } else {
Bob Wilson1c3ef902011-02-07 17:43:21 +00002046 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson8466fa12010-09-13 23:01:35 +00002047 SDValue V3 = (NumVecs == 3)
Bob Wilson1c3ef902011-02-07 17:43:21 +00002048 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2049 : N->getOperand(Vec0Idx + 3);
Bob Wilson8466fa12010-09-13 23:01:35 +00002050 if (is64BitVector)
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002051 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilson8466fa12010-09-13 23:01:35 +00002052 else
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002053 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilsona7c397c2009-10-14 16:19:03 +00002054 }
Bob Wilson8466fa12010-09-13 23:01:35 +00002055 Ops.push_back(SuperReg);
Bob Wilsona7c397c2009-10-14 16:19:03 +00002056 Ops.push_back(getI32Imm(Lane));
Evan Chengac0869d2009-11-21 06:21:52 +00002057 Ops.push_back(Pred);
Bob Wilson226036e2010-03-20 22:13:40 +00002058 Ops.push_back(Reg0);
Bob Wilsona7c397c2009-10-14 16:19:03 +00002059 Ops.push_back(Chain);
2060
Bob Wilson1c3ef902011-02-07 17:43:21 +00002061 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2062 QOpcodes[OpcodeIndex]);
2063 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys,
2064 Ops.data(), Ops.size());
Evan Chengb58a3402011-04-19 00:04:03 +00002065 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson96493442009-10-14 16:46:45 +00002066 if (!IsLoad)
Bob Wilson1c3ef902011-02-07 17:43:21 +00002067 return VLdLn;
Evan Cheng7092c2b2010-05-15 01:36:29 +00002068
Bob Wilson8466fa12010-09-13 23:01:35 +00002069 // Extract the subregisters.
Bob Wilson1c3ef902011-02-07 17:43:21 +00002070 SuperReg = SDValue(VLdLn, 0);
2071 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
2072 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
2073 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson07f6e802010-06-16 21:34:01 +00002074 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2075 ReplaceUses(SDValue(N, Vec),
Bob Wilson1c3ef902011-02-07 17:43:21 +00002076 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2077 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2078 if (isUpdating)
2079 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Bob Wilsona7c397c2009-10-14 16:19:03 +00002080 return NULL;
2081}
2082
Bob Wilson1c3ef902011-02-07 17:43:21 +00002083SDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating,
Craig Topper51f50c12012-05-24 05:17:00 +00002084 unsigned NumVecs,
2085 const uint16_t *Opcodes) {
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002086 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
2087 DebugLoc dl = N->getDebugLoc();
2088
2089 SDValue MemAddr, Align;
2090 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
2091 return NULL;
2092
Evan Chengb58a3402011-04-19 00:04:03 +00002093 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2094 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2095
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002096 SDValue Chain = N->getOperand(0);
2097 EVT VT = N->getValueType(0);
2098
2099 unsigned Alignment = 0;
2100 if (NumVecs != 3) {
2101 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2102 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2103 if (Alignment > NumBytes)
2104 Alignment = NumBytes;
Bob Wilsona92bac62010-12-10 19:37:42 +00002105 if (Alignment < 8 && Alignment < NumBytes)
2106 Alignment = 0;
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002107 // Alignment must be a power of two; make sure of that.
2108 Alignment = (Alignment & -Alignment);
2109 if (Alignment == 1)
2110 Alignment = 0;
2111 }
2112 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
2113
2114 unsigned OpcodeIndex;
2115 switch (VT.getSimpleVT().SimpleTy) {
2116 default: llvm_unreachable("unhandled vld-dup type");
2117 case MVT::v8i8: OpcodeIndex = 0; break;
2118 case MVT::v4i16: OpcodeIndex = 1; break;
2119 case MVT::v2f32:
2120 case MVT::v2i32: OpcodeIndex = 2; break;
2121 }
2122
2123 SDValue Pred = getAL(CurDAG);
2124 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2125 SDValue SuperReg;
2126 unsigned Opc = Opcodes[OpcodeIndex];
Bob Wilson1c3ef902011-02-07 17:43:21 +00002127 SmallVector<SDValue, 6> Ops;
2128 Ops.push_back(MemAddr);
2129 Ops.push_back(Align);
2130 if (isUpdating) {
Jim Grosbache6949b12011-12-21 19:40:55 +00002131 // fixed-stride update instructions don't have an explicit writeback
2132 // operand. It's implicit in the opcode itself.
Bob Wilson1c3ef902011-02-07 17:43:21 +00002133 SDValue Inc = N->getOperand(2);
Jim Grosbache6949b12011-12-21 19:40:55 +00002134 if (!isa<ConstantSDNode>(Inc.getNode()))
2135 Ops.push_back(Inc);
2136 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2137 else if (NumVecs > 2)
2138 Ops.push_back(Reg0);
Bob Wilson1c3ef902011-02-07 17:43:21 +00002139 }
2140 Ops.push_back(Pred);
2141 Ops.push_back(Reg0);
2142 Ops.push_back(Chain);
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002143
2144 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson1c3ef902011-02-07 17:43:21 +00002145 std::vector<EVT> ResTys;
Evan Chengb58a3402011-04-19 00:04:03 +00002146 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson1c3ef902011-02-07 17:43:21 +00002147 if (isUpdating)
2148 ResTys.push_back(MVT::i32);
2149 ResTys.push_back(MVT::Other);
2150 SDNode *VLdDup =
2151 CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size());
Evan Chengb58a3402011-04-19 00:04:03 +00002152 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002153 SuperReg = SDValue(VLdDup, 0);
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002154
2155 // Extract the subregisters.
2156 assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
2157 unsigned SubIdx = ARM::dsub_0;
2158 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2159 ReplaceUses(SDValue(N, Vec),
2160 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Bob Wilson1c3ef902011-02-07 17:43:21 +00002161 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2162 if (isUpdating)
2163 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002164 return NULL;
2165}
2166
Bob Wilson78dfbc32010-07-07 00:08:54 +00002167SDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2168 unsigned Opc) {
Bob Wilsond491d6e2010-07-06 23:36:25 +00002169 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
2170 DebugLoc dl = N->getDebugLoc();
2171 EVT VT = N->getValueType(0);
Bob Wilson78dfbc32010-07-07 00:08:54 +00002172 unsigned FirstTblReg = IsExt ? 2 : 1;
Bob Wilsond491d6e2010-07-06 23:36:25 +00002173
2174 // Form a REG_SEQUENCE to force register allocation.
2175 SDValue RegSeq;
Bob Wilson78dfbc32010-07-07 00:08:54 +00002176 SDValue V0 = N->getOperand(FirstTblReg + 0);
2177 SDValue V1 = N->getOperand(FirstTblReg + 1);
Bob Wilsond491d6e2010-07-06 23:36:25 +00002178 if (NumVecs == 2)
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002179 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bob Wilsond491d6e2010-07-06 23:36:25 +00002180 else {
Bob Wilson78dfbc32010-07-07 00:08:54 +00002181 SDValue V2 = N->getOperand(FirstTblReg + 2);
Jim Grosbach3ab56582010-10-21 19:38:40 +00002182 // If it's a vtbl3, form a quad D-register and leave the last part as
Bob Wilsond491d6e2010-07-06 23:36:25 +00002183 // an undef.
2184 SDValue V3 = (NumVecs == 3)
2185 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson78dfbc32010-07-07 00:08:54 +00002186 : N->getOperand(FirstTblReg + 3);
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002187 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond491d6e2010-07-06 23:36:25 +00002188 }
2189
Bob Wilson78dfbc32010-07-07 00:08:54 +00002190 SmallVector<SDValue, 6> Ops;
2191 if (IsExt)
2192 Ops.push_back(N->getOperand(1));
Bob Wilsonbd916c52010-09-13 23:55:10 +00002193 Ops.push_back(RegSeq);
Bob Wilson78dfbc32010-07-07 00:08:54 +00002194 Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
Bob Wilsond491d6e2010-07-06 23:36:25 +00002195 Ops.push_back(getAL(CurDAG)); // predicate
2196 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
Bob Wilson78dfbc32010-07-07 00:08:54 +00002197 return CurDAG->getMachineNode(Opc, dl, VT, Ops.data(), Ops.size());
Bob Wilsond491d6e2010-07-06 23:36:25 +00002198}
2199
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002200SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002201 bool isSigned) {
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002202 if (!Subtarget->hasV6T2Ops())
2203 return NULL;
Bob Wilson96493442009-10-14 16:46:45 +00002204
Evan Cheng733c6b12012-12-19 20:16:09 +00002205 unsigned Opc = isSigned
2206 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002207 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
2208
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002209 // For unsigned extracts, check for a shift right and mask
2210 unsigned And_imm = 0;
2211 if (N->getOpcode() == ISD::AND) {
2212 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2213
Sylvestre Ledru94c22712012-09-27 10:14:43 +00002214 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002215 if (And_imm & (And_imm + 1))
2216 return NULL;
2217
2218 unsigned Srl_imm = 0;
2219 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2220 Srl_imm)) {
2221 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2222
Jim Grosbachfb8989e2011-07-27 21:09:25 +00002223 // Note: The width operand is encoded as width-1.
2224 unsigned Width = CountTrailingOnes_32(And_imm) - 1;
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002225 unsigned LSB = Srl_imm;
Evan Cheng733c6b12012-12-19 20:16:09 +00002226
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002227 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng733c6b12012-12-19 20:16:09 +00002228
2229 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2230 // It's cheaper to use a right shift to extract the top bits.
2231 if (Subtarget->isThumb()) {
2232 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2233 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2234 CurDAG->getTargetConstant(LSB, MVT::i32),
2235 getAL(CurDAG), Reg0, Reg0 };
2236 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
2237 }
2238
2239 // ARM models shift instructions as MOVsi with shifter operand.
2240 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2241 SDValue ShOpc =
2242 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB),
2243 MVT::i32);
2244 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
2245 getAL(CurDAG), Reg0, Reg0 };
2246 return CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops, 5);
2247 }
2248
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002249 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2250 CurDAG->getTargetConstant(LSB, MVT::i32),
2251 CurDAG->getTargetConstant(Width, MVT::i32),
2252 getAL(CurDAG), Reg0 };
2253 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
2254 }
2255 }
2256 return NULL;
2257 }
2258
2259 // Otherwise, we're looking for a shift of a shift
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002260 unsigned Shl_imm = 0;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002261 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002262 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2263 unsigned Srl_imm = 0;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002264 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002265 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbachfb8989e2011-07-27 21:09:25 +00002266 // Note: The width operand is encoded as width-1.
2267 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002268 int LSB = Srl_imm - Shl_imm;
Evan Cheng8000c6c2009-10-22 00:40:00 +00002269 if (LSB < 0)
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002270 return NULL;
2271 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002272 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002273 CurDAG->getTargetConstant(LSB, MVT::i32),
2274 CurDAG->getTargetConstant(Width, MVT::i32),
2275 getAL(CurDAG), Reg0 };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002276 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002277 }
2278 }
2279 return NULL;
2280}
2281
Evan Cheng9ef48352009-11-20 00:54:03 +00002282SDNode *ARMDAGToDAGISel::
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002283SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002284 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
2285 SDValue CPTmp0;
2286 SDValue CPTmp1;
Chris Lattner52a261b2010-09-21 20:31:19 +00002287 if (SelectT2ShifterOperandReg(TrueVal, CPTmp0, CPTmp1)) {
Evan Cheng9ef48352009-11-20 00:54:03 +00002288 unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue();
2289 unsigned SOShOp = ARM_AM::getSORegShOp(SOVal);
2290 unsigned Opc = 0;
2291 switch (SOShOp) {
2292 case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break;
2293 case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break;
2294 case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break;
2295 case ARM_AM::ror: Opc = ARM::t2MOVCCror; break;
2296 default:
2297 llvm_unreachable("Unknown so_reg opcode!");
Evan Cheng9ef48352009-11-20 00:54:03 +00002298 }
2299 SDValue SOShImm =
2300 CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32);
2301 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2302 SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002303 return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6);
Evan Cheng9ef48352009-11-20 00:54:03 +00002304 }
2305 return 0;
2306}
2307
2308SDNode *ARMDAGToDAGISel::
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002309SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002310 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
2311 SDValue CPTmp0;
2312 SDValue CPTmp1;
2313 SDValue CPTmp2;
Owen Anderson152d4a42011-07-21 23:38:37 +00002314 if (SelectImmShifterOperand(TrueVal, CPTmp0, CPTmp2)) {
Evan Cheng9ef48352009-11-20 00:54:03 +00002315 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
Owen Andersone0a03142011-07-22 18:30:30 +00002316 SDValue Ops[] = { FalseVal, CPTmp0, CPTmp2, CC, CCR, InFlag };
2317 return CurDAG->SelectNodeTo(N, ARM::MOVCCsi, MVT::i32, Ops, 6);
Owen Anderson92a20222011-07-21 18:54:16 +00002318 }
2319
2320 if (SelectRegShifterOperand(TrueVal, CPTmp0, CPTmp1, CPTmp2)) {
2321 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2322 SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag };
2323 return CurDAG->SelectNodeTo(N, ARM::MOVCCsr, MVT::i32, Ops, 7);
Evan Cheng9ef48352009-11-20 00:54:03 +00002324 }
2325 return 0;
2326}
2327
2328SDNode *ARMDAGToDAGISel::
Jim Grosbacha4257162010-10-07 00:53:56 +00002329SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng6b194912010-11-17 20:56:30 +00002330 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
Evan Cheng9ef48352009-11-20 00:54:03 +00002331 ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal);
Evan Chengff96b632010-11-19 23:01:16 +00002332 if (!T)
Evan Cheng9ef48352009-11-20 00:54:03 +00002333 return 0;
2334
Evan Cheng63f35442010-11-13 02:25:14 +00002335 unsigned Opc = 0;
Jim Grosbacha4257162010-10-07 00:53:56 +00002336 unsigned TrueImm = T->getZExtValue();
Evan Cheng6b194912010-11-17 20:56:30 +00002337 if (is_t2_so_imm(TrueImm)) {
2338 Opc = ARM::t2MOVCCi;
2339 } else if (TrueImm <= 0xffff) {
2340 Opc = ARM::t2MOVCCi16;
Evan Cheng63f35442010-11-13 02:25:14 +00002341 } else if (is_t2_so_imm_not(TrueImm)) {
2342 TrueImm = ~TrueImm;
2343 Opc = ARM::t2MVNCCi;
Evan Cheng6b194912010-11-17 20:56:30 +00002344 } else if (TrueVal.getNode()->hasOneUse() && Subtarget->hasV6T2Ops()) {
Evan Cheng63f35442010-11-13 02:25:14 +00002345 // Large immediate.
2346 Opc = ARM::t2MOVCCi32imm;
2347 }
2348
2349 if (Opc) {
Evan Cheng875a6ac2010-11-12 22:42:47 +00002350 SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32);
Evan Cheng9ef48352009-11-20 00:54:03 +00002351 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2352 SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
Evan Cheng63f35442010-11-13 02:25:14 +00002353 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Cheng9ef48352009-11-20 00:54:03 +00002354 }
Evan Cheng63f35442010-11-13 02:25:14 +00002355
Evan Cheng9ef48352009-11-20 00:54:03 +00002356 return 0;
2357}
2358
2359SDNode *ARMDAGToDAGISel::
Jim Grosbach3bbdcea2010-10-07 00:42:42 +00002360SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng6b194912010-11-17 20:56:30 +00002361 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
Evan Cheng9ef48352009-11-20 00:54:03 +00002362 ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal);
2363 if (!T)
2364 return 0;
2365
Evan Cheng63f35442010-11-13 02:25:14 +00002366 unsigned Opc = 0;
Jim Grosbach3bbdcea2010-10-07 00:42:42 +00002367 unsigned TrueImm = T->getZExtValue();
Evan Cheng875a6ac2010-11-12 22:42:47 +00002368 bool isSoImm = is_so_imm(TrueImm);
Evan Cheng6b194912010-11-17 20:56:30 +00002369 if (isSoImm) {
2370 Opc = ARM::MOVCCi;
2371 } else if (Subtarget->hasV6T2Ops() && TrueImm <= 0xffff) {
2372 Opc = ARM::MOVCCi16;
Evan Cheng63f35442010-11-13 02:25:14 +00002373 } else if (is_so_imm_not(TrueImm)) {
2374 TrueImm = ~TrueImm;
2375 Opc = ARM::MVNCCi;
Evan Cheng6b194912010-11-17 20:56:30 +00002376 } else if (TrueVal.getNode()->hasOneUse() &&
2377 (Subtarget->hasV6T2Ops() || ARM_AM::isSOImmTwoPartVal(TrueImm))) {
Evan Cheng63f35442010-11-13 02:25:14 +00002378 // Large immediate.
2379 Opc = ARM::MOVCCi32imm;
2380 }
2381
2382 if (Opc) {
Jim Grosbach3bbdcea2010-10-07 00:42:42 +00002383 SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32);
Evan Cheng9ef48352009-11-20 00:54:03 +00002384 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2385 SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
Evan Cheng63f35442010-11-13 02:25:14 +00002386 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Cheng9ef48352009-11-20 00:54:03 +00002387 }
Andrew Trick6e8f4c42010-12-24 04:28:06 +00002388
Evan Cheng9ef48352009-11-20 00:54:03 +00002389 return 0;
2390}
2391
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002392SDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) {
2393 EVT VT = N->getValueType(0);
2394 SDValue FalseVal = N->getOperand(0);
2395 SDValue TrueVal = N->getOperand(1);
2396 SDValue CC = N->getOperand(2);
2397 SDValue CCR = N->getOperand(3);
2398 SDValue InFlag = N->getOperand(4);
Evan Cheng9ef48352009-11-20 00:54:03 +00002399 assert(CC.getOpcode() == ISD::Constant);
2400 assert(CCR.getOpcode() == ISD::Register);
2401 ARMCC::CondCodes CCVal =
2402 (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue();
Evan Cheng07ba9062009-11-19 21:45:22 +00002403
2404 if (!Subtarget->isThumb1Only() && VT == MVT::i32) {
2405 // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
2406 // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
2407 // Pattern complexity = 18 cost = 1 size = 0
Evan Cheng07ba9062009-11-19 21:45:22 +00002408 if (Subtarget->isThumb()) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002409 SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002410 CCVal, CCR, InFlag);
2411 if (!Res)
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002412 Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002413 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2414 if (Res)
2415 return Res;
Evan Cheng07ba9062009-11-19 21:45:22 +00002416 } else {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002417 SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002418 CCVal, CCR, InFlag);
2419 if (!Res)
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002420 Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002421 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2422 if (Res)
2423 return Res;
Evan Cheng07ba9062009-11-19 21:45:22 +00002424 }
2425
2426 // Pattern: (ARMcmov:i32 GPR:i32:$false,
Jakob Stoklund Olesen00d3dda2010-08-17 20:39:04 +00002427 // (imm:i32)<<P:Pred_so_imm>>:$true,
Evan Cheng07ba9062009-11-19 21:45:22 +00002428 // (imm:i32):$cc)
2429 // Emits: (MOVCCi:i32 GPR:i32:$false,
2430 // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc)
2431 // Pattern complexity = 10 cost = 1 size = 0
Evan Cheng9ef48352009-11-20 00:54:03 +00002432 if (Subtarget->isThumb()) {
Jim Grosbacha4257162010-10-07 00:53:56 +00002433 SDNode *Res = SelectT2CMOVImmOp(N, FalseVal, TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002434 CCVal, CCR, InFlag);
2435 if (!Res)
Jim Grosbacha4257162010-10-07 00:53:56 +00002436 Res = SelectT2CMOVImmOp(N, TrueVal, FalseVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002437 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2438 if (Res)
2439 return Res;
2440 } else {
Jim Grosbach3bbdcea2010-10-07 00:42:42 +00002441 SDNode *Res = SelectARMCMOVImmOp(N, FalseVal, TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002442 CCVal, CCR, InFlag);
2443 if (!Res)
Jim Grosbach3bbdcea2010-10-07 00:42:42 +00002444 Res = SelectARMCMOVImmOp(N, TrueVal, FalseVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002445 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2446 if (Res)
2447 return Res;
Evan Cheng07ba9062009-11-19 21:45:22 +00002448 }
2449 }
2450
2451 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2452 // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2453 // Pattern complexity = 6 cost = 1 size = 0
2454 //
2455 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2456 // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2457 // Pattern complexity = 6 cost = 11 size = 0
2458 //
Jim Grosbach3c5edaa2011-03-11 23:15:02 +00002459 // Also VMOVScc and VMOVDcc.
Evan Cheng9ef48352009-11-20 00:54:03 +00002460 SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32);
2461 SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag };
Evan Cheng07ba9062009-11-19 21:45:22 +00002462 unsigned Opc = 0;
2463 switch (VT.getSimpleVT().SimpleTy) {
Craig Topperbc219812012-02-07 02:50:20 +00002464 default: llvm_unreachable("Illegal conditional move type!");
Evan Cheng07ba9062009-11-19 21:45:22 +00002465 case MVT::i32:
2466 Opc = Subtarget->isThumb()
2467 ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo)
2468 : ARM::MOVCCr;
2469 break;
2470 case MVT::f32:
2471 Opc = ARM::VMOVScc;
2472 break;
2473 case MVT::f64:
2474 Opc = ARM::VMOVDcc;
2475 break;
2476 }
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002477 return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5);
Evan Cheng07ba9062009-11-19 21:45:22 +00002478}
2479
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002480/// Target-specific DAG combining for ISD::XOR.
2481/// Target-independent combining lowers SELECT_CC nodes of the form
2482/// select_cc setg[ge] X, 0, X, -X
2483/// select_cc setgt X, -1, X, -X
2484/// select_cc setl[te] X, 0, -X, X
2485/// select_cc setlt X, 1, -X, X
2486/// which represent Integer ABS into:
2487/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2488/// ARM instruction selection detects the latter and matches it to
2489/// ARM::ABS or ARM::t2ABS machine node.
2490SDNode *ARMDAGToDAGISel::SelectABSOp(SDNode *N){
2491 SDValue XORSrc0 = N->getOperand(0);
2492 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002493 EVT VT = N->getValueType(0);
2494
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002495 if (Subtarget->isThumb1Only())
2496 return NULL;
2497
Jim Grosbach27690282012-08-01 20:33:00 +00002498 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002499 return NULL;
2500
2501 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2502 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2503 SDValue SRASrc0 = XORSrc1.getOperand(0);
2504 SDValue SRASrc1 = XORSrc1.getOperand(1);
2505 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2506 EVT XType = SRASrc0.getValueType();
2507 unsigned Size = XType.getSizeInBits() - 1;
2508
Jim Grosbach27690282012-08-01 20:33:00 +00002509 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
2510 XType.isInteger() && SRAConstant != NULL &&
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002511 Size == SRAConstant->getZExtValue()) {
Jim Grosbach27690282012-08-01 20:33:00 +00002512 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002513 return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2514 }
2515
2516 return NULL;
2517}
2518
Evan Chengde8aa4e2010-05-05 18:28:36 +00002519SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
2520 // The only time a CONCAT_VECTORS operation can have legal types is when
2521 // two 64-bit vectors are concatenated to a 128-bit vector.
2522 EVT VT = N->getValueType(0);
2523 if (!VT.is128BitVector() || N->getNumOperands() != 2)
2524 llvm_unreachable("unexpected CONCAT_VECTORS");
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002525 return createDRegPairNode(VT, N->getOperand(0), N->getOperand(1));
Evan Chengde8aa4e2010-05-05 18:28:36 +00002526}
2527
Eli Friedman2bdffe42011-08-31 00:31:29 +00002528SDNode *ARMDAGToDAGISel::SelectAtomic64(SDNode *Node, unsigned Opc) {
Eli Friedman4d3f3292011-08-31 17:52:22 +00002529 SmallVector<SDValue, 6> Ops;
2530 Ops.push_back(Node->getOperand(1)); // Ptr
2531 Ops.push_back(Node->getOperand(2)); // Low part of Val1
2532 Ops.push_back(Node->getOperand(3)); // High part of Val1
Owen Andersond84192f2011-08-31 20:00:11 +00002533 if (Opc == ARM::ATOMCMPXCHG6432) {
Eli Friedman4d3f3292011-08-31 17:52:22 +00002534 Ops.push_back(Node->getOperand(4)); // Low part of Val2
2535 Ops.push_back(Node->getOperand(5)); // High part of Val2
2536 }
2537 Ops.push_back(Node->getOperand(0)); // Chain
Eli Friedman2bdffe42011-08-31 00:31:29 +00002538 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2539 MemOp[0] = cast<MemSDNode>(Node)->getMemOperand();
Eli Friedman2bdffe42011-08-31 00:31:29 +00002540 SDNode *ResNode = CurDAG->getMachineNode(Opc, Node->getDebugLoc(),
Eli Friedman4d3f3292011-08-31 17:52:22 +00002541 MVT::i32, MVT::i32, MVT::Other,
2542 Ops.data() ,Ops.size());
Eli Friedman2bdffe42011-08-31 00:31:29 +00002543 cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp + 1);
2544 return ResNode;
2545}
2546
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002547SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
Dale Johannesened2eee62009-02-06 01:31:28 +00002548 DebugLoc dl = N->getDebugLoc();
Evan Chenga8e29892007-01-19 07:51:42 +00002549
Dan Gohmane8be6c62008-07-17 19:10:17 +00002550 if (N->isMachineOpcode())
Evan Chenga8e29892007-01-19 07:51:42 +00002551 return NULL; // Already selected.
Rafael Espindola337c4ad62006-06-12 12:28:08 +00002552
2553 switch (N->getOpcode()) {
Evan Chenga8e29892007-01-19 07:51:42 +00002554 default: break;
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002555 case ISD::XOR: {
2556 // Select special operations if XOR node forms integer ABS pattern
2557 SDNode *ResNode = SelectABSOp(N);
2558 if (ResNode)
2559 return ResNode;
2560 // Other cases are autogenerated.
2561 break;
2562 }
Evan Chenga8e29892007-01-19 07:51:42 +00002563 case ISD::Constant: {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002564 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +00002565 bool UseCP = true;
Anton Korobeynikov6a2fa322009-09-27 23:52:58 +00002566 if (Subtarget->hasThumb2())
2567 // Thumb2-aware targets have the MOVT instruction, so all immediates can
2568 // be done with MOV + MOVT, at worst.
2569 UseCP = 0;
2570 else {
2571 if (Subtarget->isThumb()) {
Bob Wilsone64e3cf2009-06-22 17:29:13 +00002572 UseCP = (Val > 255 && // MOV
2573 ~Val > 255 && // MOV + MVN
2574 !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL
Anton Korobeynikov6a2fa322009-09-27 23:52:58 +00002575 } else
2576 UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV
2577 ARM_AM::getSOImmVal(~Val) == -1 && // MVN
2578 !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs.
2579 }
2580
Evan Chenga8e29892007-01-19 07:51:42 +00002581 if (UseCP) {
Dan Gohman475871a2008-07-27 21:46:04 +00002582 SDValue CPIdx =
Owen Anderson1d0be152009-08-13 21:58:54 +00002583 CurDAG->getTargetConstantPool(ConstantInt::get(
2584 Type::getInt32Ty(*CurDAG->getContext()), Val),
Evan Chenga8e29892007-01-19 07:51:42 +00002585 TLI.getPointerTy());
Evan Cheng012f2d92007-01-24 08:53:17 +00002586
2587 SDNode *ResNode;
Evan Cheng446c4282009-07-11 06:43:01 +00002588 if (Subtarget->isThumb1Only()) {
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002589 SDValue Pred = getAL(CurDAG);
Owen Anderson825b72b2009-08-11 20:47:22 +00002590 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Cheng446c4282009-07-11 06:43:01 +00002591 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbach3e333632010-12-15 23:52:36 +00002592 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Dan Gohman602b0c82009-09-25 18:54:59 +00002593 Ops, 4);
Evan Cheng446c4282009-07-11 06:43:01 +00002594 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00002595 SDValue Ops[] = {
Jim Grosbach764ab522009-08-11 15:33:49 +00002596 CPIdx,
Owen Anderson825b72b2009-08-11 20:47:22 +00002597 CurDAG->getTargetConstant(0, MVT::i32),
Evan Chengee568cf2007-07-05 07:15:27 +00002598 getAL(CurDAG),
Owen Anderson825b72b2009-08-11 20:47:22 +00002599 CurDAG->getRegister(0, MVT::i32),
Evan Cheng012f2d92007-01-24 08:53:17 +00002600 CurDAG->getEntryNode()
2601 };
Dan Gohman602b0c82009-09-25 18:54:59 +00002602 ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
Jim Grosbach3e556122010-10-26 22:37:02 +00002603 Ops, 5);
Evan Cheng012f2d92007-01-24 08:53:17 +00002604 }
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002605 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
Evan Chenga8e29892007-01-19 07:51:42 +00002606 return NULL;
2607 }
Jim Grosbach764ab522009-08-11 15:33:49 +00002608
Evan Chenga8e29892007-01-19 07:51:42 +00002609 // Other cases are autogenerated.
Rafael Espindola337c4ad62006-06-12 12:28:08 +00002610 break;
Evan Chenga8e29892007-01-19 07:51:42 +00002611 }
Rafael Espindolaf819a492006-11-09 13:58:55 +00002612 case ISD::FrameIndex: {
Evan Chenga8e29892007-01-19 07:51:42 +00002613 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindolaf819a492006-11-09 13:58:55 +00002614 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Dan Gohman475871a2008-07-27 21:46:04 +00002615 SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
David Goodwinf1daf7d2009-07-08 23:10:31 +00002616 if (Subtarget->isThumb1Only()) {
Jim Grosbach5b815842011-08-24 17:46:13 +00002617 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
2618 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2619 return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, Ops, 4);
Jim Grosbach30eae3c2009-04-07 20:34:09 +00002620 } else {
David Goodwin419c6152009-07-14 18:48:51 +00002621 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2622 ARM::t2ADDri : ARM::ADDri);
Owen Anderson825b72b2009-08-11 20:47:22 +00002623 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
2624 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2625 CurDAG->getRegister(0, MVT::i32) };
2626 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Chengee568cf2007-07-05 07:15:27 +00002627 }
Evan Chenga8e29892007-01-19 07:51:42 +00002628 }
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002629 case ISD::SRL:
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002630 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002631 return I;
2632 break;
2633 case ISD::SRA:
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002634 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true))
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002635 return I;
2636 break;
Evan Chenga8e29892007-01-19 07:51:42 +00002637 case ISD::MUL:
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002638 if (Subtarget->isThumb1Only())
Evan Cheng79d43262007-01-24 02:21:22 +00002639 break;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002640 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002641 unsigned RHSV = C->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +00002642 if (!RHSV) break;
2643 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Chengaf9e7a72009-07-21 00:31:12 +00002644 unsigned ShImm = Log2_32(RHSV-1);
2645 if (ShImm >= 32)
2646 break;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002647 SDValue V = N->getOperand(0);
Evan Chengaf9e7a72009-07-21 00:31:12 +00002648 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson825b72b2009-08-11 20:47:22 +00002649 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
2650 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng78dd9db2009-07-22 18:08:05 +00002651 if (Subtarget->isThumb()) {
Evan Chengaf9e7a72009-07-21 00:31:12 +00002652 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson825b72b2009-08-11 20:47:22 +00002653 return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6);
Evan Chengaf9e7a72009-07-21 00:31:12 +00002654 } else {
2655 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson92a20222011-07-21 18:54:16 +00002656 return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops, 7);
Evan Chengaf9e7a72009-07-21 00:31:12 +00002657 }
Evan Chenga8e29892007-01-19 07:51:42 +00002658 }
2659 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Chengaf9e7a72009-07-21 00:31:12 +00002660 unsigned ShImm = Log2_32(RHSV+1);
2661 if (ShImm >= 32)
2662 break;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002663 SDValue V = N->getOperand(0);
Evan Chengaf9e7a72009-07-21 00:31:12 +00002664 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson825b72b2009-08-11 20:47:22 +00002665 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
2666 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng78dd9db2009-07-22 18:08:05 +00002667 if (Subtarget->isThumb()) {
Bob Wilson13ef8402010-05-28 00:27:15 +00002668 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
2669 return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 6);
Evan Chengaf9e7a72009-07-21 00:31:12 +00002670 } else {
2671 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson92a20222011-07-21 18:54:16 +00002672 return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops, 7);
Evan Chengaf9e7a72009-07-21 00:31:12 +00002673 }
Evan Chenga8e29892007-01-19 07:51:42 +00002674 }
2675 }
2676 break;
Evan Cheng20956592009-10-21 08:15:52 +00002677 case ISD::AND: {
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002678 // Check for unsigned bitfield extract
2679 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
2680 return I;
2681
Evan Cheng20956592009-10-21 08:15:52 +00002682 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2683 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2684 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2685 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2686 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002687 EVT VT = N->getValueType(0);
Evan Cheng20956592009-10-21 08:15:52 +00002688 if (VT != MVT::i32)
2689 break;
2690 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2691 ? ARM::t2MOVTi16
2692 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2693 if (!Opc)
2694 break;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002695 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
Evan Cheng20956592009-10-21 08:15:52 +00002696 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
2697 if (!N1C)
2698 break;
2699 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2700 SDValue N2 = N0.getOperand(1);
2701 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2702 if (!N2C)
2703 break;
2704 unsigned N1CVal = N1C->getZExtValue();
2705 unsigned N2CVal = N2C->getZExtValue();
2706 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2707 (N1CVal & 0xffffU) == 0xffffU &&
2708 (N2CVal & 0xffffU) == 0x0U) {
2709 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
2710 MVT::i32);
2711 SDValue Ops[] = { N0.getOperand(0), Imm16,
2712 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2713 return CurDAG->getMachineNode(Opc, dl, VT, Ops, 4);
2714 }
2715 }
2716 break;
2717 }
Jim Grosbache5165492009-11-09 00:11:35 +00002718 case ARMISD::VMOVRRD:
2719 return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002720 N->getOperand(0), getAL(CurDAG),
Dan Gohman602b0c82009-09-25 18:54:59 +00002721 CurDAG->getRegister(0, MVT::i32));
Dan Gohman525178c2007-10-08 18:33:35 +00002722 case ISD::UMUL_LOHI: {
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002723 if (Subtarget->isThumb1Only())
2724 break;
2725 if (Subtarget->isThumb()) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002726 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00002727 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2728 CurDAG->getRegister(0, MVT::i32) };
Jim Grosbach18f30e62010-06-02 21:53:11 +00002729 return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32,Ops,4);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002730 } else {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002731 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00002732 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2733 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov4d728602011-01-01 20:38:38 +00002734 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2735 ARM::UMULL : ARM::UMULLv5,
2736 dl, MVT::i32, MVT::i32, Ops, 5);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002737 }
Evan Chengee568cf2007-07-05 07:15:27 +00002738 }
Dan Gohman525178c2007-10-08 18:33:35 +00002739 case ISD::SMUL_LOHI: {
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002740 if (Subtarget->isThumb1Only())
2741 break;
2742 if (Subtarget->isThumb()) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002743 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00002744 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
Jim Grosbach18f30e62010-06-02 21:53:11 +00002745 return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32,Ops,4);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002746 } else {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002747 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00002748 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2749 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov4d728602011-01-01 20:38:38 +00002750 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2751 ARM::SMULL : ARM::SMULLv5,
2752 dl, MVT::i32, MVT::i32, Ops, 5);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002753 }
Evan Chengee568cf2007-07-05 07:15:27 +00002754 }
Arnold Schwaighofer67514e92012-09-04 14:37:49 +00002755 case ARMISD::UMLAL:{
2756 if (Subtarget->isThumb()) {
2757 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2758 N->getOperand(3), getAL(CurDAG),
2759 CurDAG->getRegister(0, MVT::i32)};
2760 return CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops, 6);
2761 }else{
2762 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2763 N->getOperand(3), getAL(CurDAG),
2764 CurDAG->getRegister(0, MVT::i32),
2765 CurDAG->getRegister(0, MVT::i32) };
2766 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2767 ARM::UMLAL : ARM::UMLALv5,
2768 dl, MVT::i32, MVT::i32, Ops, 7);
2769 }
2770 }
2771 case ARMISD::SMLAL:{
2772 if (Subtarget->isThumb()) {
2773 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2774 N->getOperand(3), getAL(CurDAG),
2775 CurDAG->getRegister(0, MVT::i32)};
2776 return CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops, 6);
2777 }else{
2778 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2779 N->getOperand(3), getAL(CurDAG),
2780 CurDAG->getRegister(0, MVT::i32),
2781 CurDAG->getRegister(0, MVT::i32) };
2782 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2783 ARM::SMLAL : ARM::SMLALv5,
2784 dl, MVT::i32, MVT::i32, Ops, 7);
2785 }
2786 }
Evan Chenga8e29892007-01-19 07:51:42 +00002787 case ISD::LOAD: {
Evan Chenge88d5ce2009-07-02 07:28:31 +00002788 SDNode *ResNode = 0;
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002789 if (Subtarget->isThumb() && Subtarget->hasThumb2())
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002790 ResNode = SelectT2IndexedLoad(N);
Evan Chenge88d5ce2009-07-02 07:28:31 +00002791 else
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002792 ResNode = SelectARMIndexedLoad(N);
Evan Chengaf4550f2009-07-02 01:23:32 +00002793 if (ResNode)
2794 return ResNode;
Evan Chenga8e29892007-01-19 07:51:42 +00002795 // Other cases are autogenerated.
Rafael Espindolaf819a492006-11-09 13:58:55 +00002796 break;
Rafael Espindola337c4ad62006-06-12 12:28:08 +00002797 }
Evan Chengee568cf2007-07-05 07:15:27 +00002798 case ARMISD::BRCOND: {
2799 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2800 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2801 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00002802
Evan Chengee568cf2007-07-05 07:15:27 +00002803 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2804 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2805 // Pattern complexity = 6 cost = 1 size = 0
2806
David Goodwin5e47a9a2009-06-30 18:04:13 +00002807 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2808 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2809 // Pattern complexity = 6 cost = 1 size = 0
2810
Jim Grosbach764ab522009-08-11 15:33:49 +00002811 unsigned Opc = Subtarget->isThumb() ?
David Goodwin5e47a9a2009-06-30 18:04:13 +00002812 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002813 SDValue Chain = N->getOperand(0);
2814 SDValue N1 = N->getOperand(1);
2815 SDValue N2 = N->getOperand(2);
2816 SDValue N3 = N->getOperand(3);
2817 SDValue InFlag = N->getOperand(4);
Evan Chengee568cf2007-07-05 07:15:27 +00002818 assert(N1.getOpcode() == ISD::BasicBlock);
2819 assert(N2.getOpcode() == ISD::Constant);
2820 assert(N3.getOpcode() == ISD::Register);
2821
Dan Gohman475871a2008-07-27 21:46:04 +00002822 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002823 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00002824 MVT::i32);
Dan Gohman475871a2008-07-27 21:46:04 +00002825 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman602b0c82009-09-25 18:54:59 +00002826 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Chris Lattnerf1b4eaf2010-12-21 02:38:05 +00002827 MVT::Glue, Ops, 5);
Dan Gohman475871a2008-07-27 21:46:04 +00002828 Chain = SDValue(ResNode, 0);
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002829 if (N->getNumValues() == 2) {
Dan Gohman475871a2008-07-27 21:46:04 +00002830 InFlag = SDValue(ResNode, 1);
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002831 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnera47b9bc2008-02-03 03:20:59 +00002832 }
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002833 ReplaceUses(SDValue(N, 0),
Evan Chenged54de42009-11-19 08:16:50 +00002834 SDValue(Chain.getNode(), Chain.getResNo()));
Evan Chengee568cf2007-07-05 07:15:27 +00002835 return NULL;
2836 }
Evan Cheng07ba9062009-11-19 21:45:22 +00002837 case ARMISD::CMOV:
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002838 return SelectCMOVOp(N);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002839 case ARMISD::VZIP: {
2840 unsigned Opc = 0;
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002841 EVT VT = N->getValueType(0);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002842 switch (VT.getSimpleVT().SimpleTy) {
2843 default: return NULL;
2844 case MVT::v8i8: Opc = ARM::VZIPd8; break;
2845 case MVT::v4i16: Opc = ARM::VZIPd16; break;
2846 case MVT::v2f32:
Jim Grosbach6073b302012-04-11 16:53:25 +00002847 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2848 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002849 case MVT::v16i8: Opc = ARM::VZIPq8; break;
2850 case MVT::v8i16: Opc = ARM::VZIPq16; break;
2851 case MVT::v4f32:
2852 case MVT::v4i32: Opc = ARM::VZIPq32; break;
2853 }
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002854 SDValue Pred = getAL(CurDAG);
Evan Chengac0869d2009-11-21 06:21:52 +00002855 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2856 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
2857 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4);
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002858 }
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002859 case ARMISD::VUZP: {
2860 unsigned Opc = 0;
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002861 EVT VT = N->getValueType(0);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002862 switch (VT.getSimpleVT().SimpleTy) {
2863 default: return NULL;
2864 case MVT::v8i8: Opc = ARM::VUZPd8; break;
2865 case MVT::v4i16: Opc = ARM::VUZPd16; break;
2866 case MVT::v2f32:
Jim Grosbach18355472012-04-11 17:40:18 +00002867 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2868 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002869 case MVT::v16i8: Opc = ARM::VUZPq8; break;
2870 case MVT::v8i16: Opc = ARM::VUZPq16; break;
2871 case MVT::v4f32:
2872 case MVT::v4i32: Opc = ARM::VUZPq32; break;
2873 }
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002874 SDValue Pred = getAL(CurDAG);
Evan Chengac0869d2009-11-21 06:21:52 +00002875 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2876 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
2877 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4);
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002878 }
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002879 case ARMISD::VTRN: {
2880 unsigned Opc = 0;
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002881 EVT VT = N->getValueType(0);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002882 switch (VT.getSimpleVT().SimpleTy) {
2883 default: return NULL;
2884 case MVT::v8i8: Opc = ARM::VTRNd8; break;
2885 case MVT::v4i16: Opc = ARM::VTRNd16; break;
2886 case MVT::v2f32:
2887 case MVT::v2i32: Opc = ARM::VTRNd32; break;
2888 case MVT::v16i8: Opc = ARM::VTRNq8; break;
2889 case MVT::v8i16: Opc = ARM::VTRNq16; break;
2890 case MVT::v4f32:
2891 case MVT::v4i32: Opc = ARM::VTRNq32; break;
2892 }
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002893 SDValue Pred = getAL(CurDAG);
Evan Chengac0869d2009-11-21 06:21:52 +00002894 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2895 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
2896 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4);
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002897 }
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002898 case ARMISD::BUILD_VECTOR: {
2899 EVT VecVT = N->getValueType(0);
2900 EVT EltVT = VecVT.getVectorElementType();
2901 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sandscdfad362010-11-03 12:17:33 +00002902 if (EltVT == MVT::f64) {
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002903 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002904 return createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002905 }
Duncan Sandscdfad362010-11-03 12:17:33 +00002906 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002907 if (NumElts == 2)
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002908 return createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002909 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002910 return createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002911 N->getOperand(2), N->getOperand(3));
2912 }
Bob Wilson31fb12f2009-08-26 17:39:53 +00002913
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002914 case ARMISD::VLD2DUP: {
Craig Topper51f50c12012-05-24 05:17:00 +00002915 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
2916 ARM::VLD2DUPd32 };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002917 return SelectVLDDup(N, false, 2, Opcodes);
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002918 }
2919
Bob Wilson86c6d802010-11-29 19:35:29 +00002920 case ARMISD::VLD3DUP: {
Craig Topper51f50c12012-05-24 05:17:00 +00002921 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
2922 ARM::VLD3DUPd16Pseudo,
2923 ARM::VLD3DUPd32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002924 return SelectVLDDup(N, false, 3, Opcodes);
Bob Wilson86c6d802010-11-29 19:35:29 +00002925 }
2926
Bob Wilson6c4c9822010-11-30 00:00:35 +00002927 case ARMISD::VLD4DUP: {
Craig Topper51f50c12012-05-24 05:17:00 +00002928 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
2929 ARM::VLD4DUPd16Pseudo,
2930 ARM::VLD4DUPd32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002931 return SelectVLDDup(N, false, 4, Opcodes);
2932 }
2933
2934 case ARMISD::VLD2DUP_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002935 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
2936 ARM::VLD2DUPd16wb_fixed,
2937 ARM::VLD2DUPd32wb_fixed };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002938 return SelectVLDDup(N, true, 2, Opcodes);
2939 }
2940
2941 case ARMISD::VLD3DUP_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002942 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
2943 ARM::VLD3DUPd16Pseudo_UPD,
2944 ARM::VLD3DUPd32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002945 return SelectVLDDup(N, true, 3, Opcodes);
2946 }
2947
2948 case ARMISD::VLD4DUP_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002949 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
2950 ARM::VLD4DUPd16Pseudo_UPD,
2951 ARM::VLD4DUPd32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002952 return SelectVLDDup(N, true, 4, Opcodes);
2953 }
2954
2955 case ARMISD::VLD1_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002956 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
2957 ARM::VLD1d16wb_fixed,
2958 ARM::VLD1d32wb_fixed,
2959 ARM::VLD1d64wb_fixed };
2960 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
2961 ARM::VLD1q16wb_fixed,
2962 ARM::VLD1q32wb_fixed,
2963 ARM::VLD1q64wb_fixed };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002964 return SelectVLD(N, true, 1, DOpcodes, QOpcodes, 0);
2965 }
2966
2967 case ARMISD::VLD2_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002968 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
2969 ARM::VLD2d16wb_fixed,
2970 ARM::VLD2d32wb_fixed,
2971 ARM::VLD1q64wb_fixed};
2972 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
2973 ARM::VLD2q16PseudoWB_fixed,
2974 ARM::VLD2q32PseudoWB_fixed };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002975 return SelectVLD(N, true, 2, DOpcodes, QOpcodes, 0);
2976 }
2977
2978 case ARMISD::VLD3_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002979 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
2980 ARM::VLD3d16Pseudo_UPD,
2981 ARM::VLD3d32Pseudo_UPD,
2982 ARM::VLD1q64wb_fixed};
2983 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
2984 ARM::VLD3q16Pseudo_UPD,
2985 ARM::VLD3q32Pseudo_UPD };
2986 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
2987 ARM::VLD3q16oddPseudo_UPD,
2988 ARM::VLD3q32oddPseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002989 return SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
2990 }
2991
2992 case ARMISD::VLD4_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002993 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
2994 ARM::VLD4d16Pseudo_UPD,
2995 ARM::VLD4d32Pseudo_UPD,
2996 ARM::VLD1q64wb_fixed};
2997 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
2998 ARM::VLD4q16Pseudo_UPD,
2999 ARM::VLD4q32Pseudo_UPD };
3000 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3001 ARM::VLD4q16oddPseudo_UPD,
3002 ARM::VLD4q32oddPseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003003 return SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3004 }
3005
3006 case ARMISD::VLD2LN_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00003007 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3008 ARM::VLD2LNd16Pseudo_UPD,
3009 ARM::VLD2LNd32Pseudo_UPD };
3010 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3011 ARM::VLD2LNq32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003012 return SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3013 }
3014
3015 case ARMISD::VLD3LN_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00003016 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3017 ARM::VLD3LNd16Pseudo_UPD,
3018 ARM::VLD3LNd32Pseudo_UPD };
3019 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3020 ARM::VLD3LNq32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003021 return SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3022 }
3023
3024 case ARMISD::VLD4LN_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00003025 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3026 ARM::VLD4LNd16Pseudo_UPD,
3027 ARM::VLD4LNd32Pseudo_UPD };
3028 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3029 ARM::VLD4LNq32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003030 return SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3031 }
3032
3033 case ARMISD::VST1_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00003034 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3035 ARM::VST1d16wb_fixed,
3036 ARM::VST1d32wb_fixed,
3037 ARM::VST1d64wb_fixed };
3038 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3039 ARM::VST1q16wb_fixed,
3040 ARM::VST1q32wb_fixed,
3041 ARM::VST1q64wb_fixed };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003042 return SelectVST(N, true, 1, DOpcodes, QOpcodes, 0);
3043 }
3044
3045 case ARMISD::VST2_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00003046 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3047 ARM::VST2d16wb_fixed,
3048 ARM::VST2d32wb_fixed,
3049 ARM::VST1q64wb_fixed};
3050 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3051 ARM::VST2q16PseudoWB_fixed,
3052 ARM::VST2q32PseudoWB_fixed };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003053 return SelectVST(N, true, 2, DOpcodes, QOpcodes, 0);
3054 }
3055
3056 case ARMISD::VST3_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00003057 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3058 ARM::VST3d16Pseudo_UPD,
3059 ARM::VST3d32Pseudo_UPD,
3060 ARM::VST1d64TPseudoWB_fixed};
3061 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3062 ARM::VST3q16Pseudo_UPD,
3063 ARM::VST3q32Pseudo_UPD };
3064 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3065 ARM::VST3q16oddPseudo_UPD,
3066 ARM::VST3q32oddPseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003067 return SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3068 }
3069
3070 case ARMISD::VST4_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00003071 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3072 ARM::VST4d16Pseudo_UPD,
3073 ARM::VST4d32Pseudo_UPD,
3074 ARM::VST1d64QPseudoWB_fixed};
3075 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3076 ARM::VST4q16Pseudo_UPD,
3077 ARM::VST4q32Pseudo_UPD };
3078 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3079 ARM::VST4q16oddPseudo_UPD,
3080 ARM::VST4q32oddPseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003081 return SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3082 }
3083
3084 case ARMISD::VST2LN_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00003085 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3086 ARM::VST2LNd16Pseudo_UPD,
3087 ARM::VST2LNd32Pseudo_UPD };
3088 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3089 ARM::VST2LNq32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003090 return SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3091 }
3092
3093 case ARMISD::VST3LN_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00003094 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3095 ARM::VST3LNd16Pseudo_UPD,
3096 ARM::VST3LNd32Pseudo_UPD };
3097 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3098 ARM::VST3LNq32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003099 return SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3100 }
3101
3102 case ARMISD::VST4LN_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00003103 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3104 ARM::VST4LNd16Pseudo_UPD,
3105 ARM::VST4LNd32Pseudo_UPD };
3106 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3107 ARM::VST4LNq32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003108 return SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
Bob Wilson6c4c9822010-11-30 00:00:35 +00003109 }
3110
Bob Wilson31fb12f2009-08-26 17:39:53 +00003111 case ISD::INTRINSIC_VOID:
3112 case ISD::INTRINSIC_W_CHAIN: {
3113 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilson31fb12f2009-08-26 17:39:53 +00003114 switch (IntNo) {
3115 default:
Bob Wilson429009b2010-05-06 16:05:26 +00003116 break;
Bob Wilson31fb12f2009-08-26 17:39:53 +00003117
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003118 case Intrinsic::arm_ldrexd: {
3119 SDValue MemAddr = N->getOperand(2);
3120 DebugLoc dl = N->getDebugLoc();
3121 SDValue Chain = N->getOperand(0);
3122
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003123 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3124 unsigned NewOpc = isThumb ? ARM::t2LDREXD :ARM::LDREXD;
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003125
3126 // arm_ldrexd returns a i64 value in {i32, i32}
3127 std::vector<EVT> ResTys;
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003128 if (isThumb) {
3129 ResTys.push_back(MVT::i32);
3130 ResTys.push_back(MVT::i32);
3131 } else
3132 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003133 ResTys.push_back(MVT::Other);
3134
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003135 // Place arguments in the right order.
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003136 SmallVector<SDValue, 7> Ops;
3137 Ops.push_back(MemAddr);
3138 Ops.push_back(getAL(CurDAG));
3139 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3140 Ops.push_back(Chain);
3141 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops.data(),
3142 Ops.size());
3143 // Transfer memoperands.
3144 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3145 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3146 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3147
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003148 // Remap uses.
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003149 SDValue Glue = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003150 if (!SDValue(N, 0).use_empty()) {
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003151 SDValue Result;
3152 if (isThumb)
3153 Result = SDValue(Ld, 0);
3154 else {
3155 SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32);
3156 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
3157 dl, MVT::i32, MVT::Glue, SDValue(Ld, 0), SubRegIdx, Glue);
3158 Result = SDValue(ResNode,0);
3159 Glue = Result.getValue(1);
3160 }
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003161 ReplaceUses(SDValue(N, 0), Result);
3162 }
3163 if (!SDValue(N, 1).use_empty()) {
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003164 SDValue Result;
3165 if (isThumb)
3166 Result = SDValue(Ld, 1);
3167 else {
3168 SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32);
3169 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
3170 dl, MVT::i32, MVT::Glue, SDValue(Ld, 0), SubRegIdx, Glue);
3171 Result = SDValue(ResNode,0);
3172 Glue = Result.getValue(1);
3173 }
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003174 ReplaceUses(SDValue(N, 1), Result);
3175 }
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003176 ReplaceUses(SDValue(N, 2), Glue);
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003177 return NULL;
3178 }
3179
3180 case Intrinsic::arm_strexd: {
3181 DebugLoc dl = N->getDebugLoc();
3182 SDValue Chain = N->getOperand(0);
3183 SDValue Val0 = N->getOperand(2);
3184 SDValue Val1 = N->getOperand(3);
3185 SDValue MemAddr = N->getOperand(4);
3186
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003187 // Store exclusive double return a i32 value which is the return status
3188 // of the issued store.
3189 std::vector<EVT> ResTys;
3190 ResTys.push_back(MVT::i32);
3191 ResTys.push_back(MVT::Other);
3192
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003193 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3194 // Place arguments in the right order.
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003195 SmallVector<SDValue, 7> Ops;
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003196 if (isThumb) {
3197 Ops.push_back(Val0);
3198 Ops.push_back(Val1);
3199 } else
3200 // arm_strexd uses GPRPair.
3201 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003202 Ops.push_back(MemAddr);
3203 Ops.push_back(getAL(CurDAG));
3204 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3205 Ops.push_back(Chain);
3206
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003207 unsigned NewOpc = isThumb ? ARM::t2STREXD : ARM::STREXD;
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003208
3209 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops.data(),
3210 Ops.size());
3211 // Transfer memoperands.
3212 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3213 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3214 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3215
3216 return St;
3217 }
3218
Bob Wilson621f1952010-03-23 05:25:43 +00003219 case Intrinsic::arm_neon_vld1: {
Craig Topper51f50c12012-05-24 05:17:00 +00003220 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3221 ARM::VLD1d32, ARM::VLD1d64 };
3222 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3223 ARM::VLD1q32, ARM::VLD1q64};
Bob Wilson1c3ef902011-02-07 17:43:21 +00003224 return SelectVLD(N, false, 1, DOpcodes, QOpcodes, 0);
Bob Wilson621f1952010-03-23 05:25:43 +00003225 }
3226
Bob Wilson31fb12f2009-08-26 17:39:53 +00003227 case Intrinsic::arm_neon_vld2: {
Craig Topper51f50c12012-05-24 05:17:00 +00003228 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3229 ARM::VLD2d32, ARM::VLD1q64 };
3230 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3231 ARM::VLD2q32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003232 return SelectVLD(N, false, 2, DOpcodes, QOpcodes, 0);
Bob Wilson31fb12f2009-08-26 17:39:53 +00003233 }
3234
3235 case Intrinsic::arm_neon_vld3: {
Craig Topper51f50c12012-05-24 05:17:00 +00003236 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3237 ARM::VLD3d16Pseudo,
3238 ARM::VLD3d32Pseudo,
3239 ARM::VLD1d64TPseudo };
3240 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3241 ARM::VLD3q16Pseudo_UPD,
3242 ARM::VLD3q32Pseudo_UPD };
3243 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3244 ARM::VLD3q16oddPseudo,
3245 ARM::VLD3q32oddPseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003246 return SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson31fb12f2009-08-26 17:39:53 +00003247 }
3248
3249 case Intrinsic::arm_neon_vld4: {
Craig Topper51f50c12012-05-24 05:17:00 +00003250 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3251 ARM::VLD4d16Pseudo,
3252 ARM::VLD4d32Pseudo,
3253 ARM::VLD1d64QPseudo };
3254 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3255 ARM::VLD4q16Pseudo_UPD,
3256 ARM::VLD4q32Pseudo_UPD };
3257 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3258 ARM::VLD4q16oddPseudo,
3259 ARM::VLD4q32oddPseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003260 return SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson31fb12f2009-08-26 17:39:53 +00003261 }
3262
Bob Wilson243fcc52009-09-01 04:26:28 +00003263 case Intrinsic::arm_neon_vld2lane: {
Craig Topper51f50c12012-05-24 05:17:00 +00003264 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3265 ARM::VLD2LNd16Pseudo,
3266 ARM::VLD2LNd32Pseudo };
3267 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3268 ARM::VLD2LNq32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003269 return SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
Bob Wilson243fcc52009-09-01 04:26:28 +00003270 }
3271
3272 case Intrinsic::arm_neon_vld3lane: {
Craig Topper51f50c12012-05-24 05:17:00 +00003273 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3274 ARM::VLD3LNd16Pseudo,
3275 ARM::VLD3LNd32Pseudo };
3276 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3277 ARM::VLD3LNq32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003278 return SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
Bob Wilson243fcc52009-09-01 04:26:28 +00003279 }
3280
3281 case Intrinsic::arm_neon_vld4lane: {
Craig Topper51f50c12012-05-24 05:17:00 +00003282 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3283 ARM::VLD4LNd16Pseudo,
3284 ARM::VLD4LNd32Pseudo };
3285 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3286 ARM::VLD4LNq32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003287 return SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
Bob Wilson243fcc52009-09-01 04:26:28 +00003288 }
3289
Bob Wilson11d98992010-03-23 06:20:33 +00003290 case Intrinsic::arm_neon_vst1: {
Craig Topper51f50c12012-05-24 05:17:00 +00003291 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3292 ARM::VST1d32, ARM::VST1d64 };
3293 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3294 ARM::VST1q32, ARM::VST1q64 };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003295 return SelectVST(N, false, 1, DOpcodes, QOpcodes, 0);
Bob Wilson11d98992010-03-23 06:20:33 +00003296 }
3297
Bob Wilson31fb12f2009-08-26 17:39:53 +00003298 case Intrinsic::arm_neon_vst2: {
Craig Topper51f50c12012-05-24 05:17:00 +00003299 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3300 ARM::VST2d32, ARM::VST1q64 };
3301 static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3302 ARM::VST2q32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003303 return SelectVST(N, false, 2, DOpcodes, QOpcodes, 0);
Bob Wilson31fb12f2009-08-26 17:39:53 +00003304 }
3305
3306 case Intrinsic::arm_neon_vst3: {
Craig Topper51f50c12012-05-24 05:17:00 +00003307 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3308 ARM::VST3d16Pseudo,
3309 ARM::VST3d32Pseudo,
3310 ARM::VST1d64TPseudo };
3311 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3312 ARM::VST3q16Pseudo_UPD,
3313 ARM::VST3q32Pseudo_UPD };
3314 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3315 ARM::VST3q16oddPseudo,
3316 ARM::VST3q32oddPseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003317 return SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson31fb12f2009-08-26 17:39:53 +00003318 }
3319
3320 case Intrinsic::arm_neon_vst4: {
Craig Topper51f50c12012-05-24 05:17:00 +00003321 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3322 ARM::VST4d16Pseudo,
3323 ARM::VST4d32Pseudo,
3324 ARM::VST1d64QPseudo };
3325 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3326 ARM::VST4q16Pseudo_UPD,
3327 ARM::VST4q32Pseudo_UPD };
3328 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3329 ARM::VST4q16oddPseudo,
3330 ARM::VST4q32oddPseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003331 return SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson31fb12f2009-08-26 17:39:53 +00003332 }
Bob Wilson8a3198b2009-09-01 18:51:56 +00003333
3334 case Intrinsic::arm_neon_vst2lane: {
Craig Topper51f50c12012-05-24 05:17:00 +00003335 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3336 ARM::VST2LNd16Pseudo,
3337 ARM::VST2LNd32Pseudo };
3338 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3339 ARM::VST2LNq32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003340 return SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
Bob Wilson8a3198b2009-09-01 18:51:56 +00003341 }
3342
3343 case Intrinsic::arm_neon_vst3lane: {
Craig Topper51f50c12012-05-24 05:17:00 +00003344 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3345 ARM::VST3LNd16Pseudo,
3346 ARM::VST3LNd32Pseudo };
3347 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3348 ARM::VST3LNq32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003349 return SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
Bob Wilson8a3198b2009-09-01 18:51:56 +00003350 }
3351
3352 case Intrinsic::arm_neon_vst4lane: {
Craig Topper51f50c12012-05-24 05:17:00 +00003353 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3354 ARM::VST4LNd16Pseudo,
3355 ARM::VST4LNd32Pseudo };
3356 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3357 ARM::VST4LNq32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003358 return SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
Bob Wilson8a3198b2009-09-01 18:51:56 +00003359 }
Bob Wilson31fb12f2009-08-26 17:39:53 +00003360 }
Bob Wilson429009b2010-05-06 16:05:26 +00003361 break;
Bob Wilson31fb12f2009-08-26 17:39:53 +00003362 }
Evan Chengde8aa4e2010-05-05 18:28:36 +00003363
Bob Wilsond491d6e2010-07-06 23:36:25 +00003364 case ISD::INTRINSIC_WO_CHAIN: {
3365 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3366 switch (IntNo) {
3367 default:
3368 break;
3369
3370 case Intrinsic::arm_neon_vtbl2:
Jim Grosbach28f08c92012-03-05 19:33:30 +00003371 return SelectVTBL(N, false, 2, ARM::VTBL2);
Bob Wilsond491d6e2010-07-06 23:36:25 +00003372 case Intrinsic::arm_neon_vtbl3:
Bob Wilsonbd916c52010-09-13 23:55:10 +00003373 return SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
Bob Wilsond491d6e2010-07-06 23:36:25 +00003374 case Intrinsic::arm_neon_vtbl4:
Bob Wilsonbd916c52010-09-13 23:55:10 +00003375 return SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
Bob Wilson78dfbc32010-07-07 00:08:54 +00003376
3377 case Intrinsic::arm_neon_vtbx2:
Jim Grosbach28f08c92012-03-05 19:33:30 +00003378 return SelectVTBL(N, true, 2, ARM::VTBX2);
Bob Wilson78dfbc32010-07-07 00:08:54 +00003379 case Intrinsic::arm_neon_vtbx3:
Bob Wilsonbd916c52010-09-13 23:55:10 +00003380 return SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
Bob Wilson78dfbc32010-07-07 00:08:54 +00003381 case Intrinsic::arm_neon_vtbx4:
Bob Wilsonbd916c52010-09-13 23:55:10 +00003382 return SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
Bob Wilsond491d6e2010-07-06 23:36:25 +00003383 }
3384 break;
3385 }
3386
Bill Wendling69a05a72011-03-14 23:02:38 +00003387 case ARMISD::VTBL1: {
3388 DebugLoc dl = N->getDebugLoc();
3389 EVT VT = N->getValueType(0);
3390 SmallVector<SDValue, 6> Ops;
3391
3392 Ops.push_back(N->getOperand(0));
3393 Ops.push_back(N->getOperand(1));
3394 Ops.push_back(getAL(CurDAG)); // Predicate
3395 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
3396 return CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops.data(), Ops.size());
3397 }
3398 case ARMISD::VTBL2: {
3399 DebugLoc dl = N->getDebugLoc();
3400 EVT VT = N->getValueType(0);
3401
3402 // Form a REG_SEQUENCE to force register allocation.
3403 SDValue V0 = N->getOperand(0);
3404 SDValue V1 = N->getOperand(1);
Weiming Zhao8b149cb2012-11-17 00:23:35 +00003405 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendling69a05a72011-03-14 23:02:38 +00003406
3407 SmallVector<SDValue, 6> Ops;
3408 Ops.push_back(RegSeq);
3409 Ops.push_back(N->getOperand(2));
3410 Ops.push_back(getAL(CurDAG)); // Predicate
3411 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Jim Grosbach28f08c92012-03-05 19:33:30 +00003412 return CurDAG->getMachineNode(ARM::VTBL2, dl, VT,
Bill Wendling69a05a72011-03-14 23:02:38 +00003413 Ops.data(), Ops.size());
3414 }
3415
Bob Wilson429009b2010-05-06 16:05:26 +00003416 case ISD::CONCAT_VECTORS:
Evan Chengde8aa4e2010-05-05 18:28:36 +00003417 return SelectConcatVector(N);
Eli Friedman2bdffe42011-08-31 00:31:29 +00003418
3419 case ARMISD::ATOMOR64_DAG:
3420 return SelectAtomic64(N, ARM::ATOMOR6432);
3421 case ARMISD::ATOMXOR64_DAG:
3422 return SelectAtomic64(N, ARM::ATOMXOR6432);
3423 case ARMISD::ATOMADD64_DAG:
3424 return SelectAtomic64(N, ARM::ATOMADD6432);
3425 case ARMISD::ATOMSUB64_DAG:
3426 return SelectAtomic64(N, ARM::ATOMSUB6432);
3427 case ARMISD::ATOMNAND64_DAG:
3428 return SelectAtomic64(N, ARM::ATOMNAND6432);
3429 case ARMISD::ATOMAND64_DAG:
3430 return SelectAtomic64(N, ARM::ATOMAND6432);
3431 case ARMISD::ATOMSWAP64_DAG:
3432 return SelectAtomic64(N, ARM::ATOMSWAP6432);
Eli Friedman4d3f3292011-08-31 17:52:22 +00003433 case ARMISD::ATOMCMPXCHG64_DAG:
3434 return SelectAtomic64(N, ARM::ATOMCMPXCHG6432);
Silviu Baranga35b3df62012-11-29 14:41:25 +00003435
3436 case ARMISD::ATOMMIN64_DAG:
3437 return SelectAtomic64(N, ARM::ATOMMIN6432);
3438 case ARMISD::ATOMUMIN64_DAG:
3439 return SelectAtomic64(N, ARM::ATOMUMIN6432);
3440 case ARMISD::ATOMMAX64_DAG:
3441 return SelectAtomic64(N, ARM::ATOMMAX6432);
3442 case ARMISD::ATOMUMAX64_DAG:
3443 return SelectAtomic64(N, ARM::ATOMUMAX6432);
Evan Chengde8aa4e2010-05-05 18:28:36 +00003444 }
Evan Chenge5ad88e2008-12-10 21:54:21 +00003445
Dan Gohmaneeb3a002010-01-05 01:24:18 +00003446 return SelectCode(N);
Evan Chenga8e29892007-01-19 07:51:42 +00003447}
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00003448
Bob Wilson224c2442009-05-19 05:53:42 +00003449bool ARMDAGToDAGISel::
3450SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
3451 std::vector<SDValue> &OutOps) {
3452 assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
Bob Wilson765cc0b2009-10-13 20:50:28 +00003453 // Require the address to be in a register. That is safe for all ARM
3454 // variants and it is hard to do anything much smarter without knowing
3455 // how the operand is used.
3456 OutOps.push_back(Op);
Bob Wilson224c2442009-05-19 05:53:42 +00003457 return false;
3458}
3459
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00003460/// createARMISelDag - This pass converts a legalized DAG into a
3461/// ARM-specific DAG, ready for instruction scheduling.
3462///
Bob Wilson522ce972009-09-28 14:30:20 +00003463FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
3464 CodeGenOpt::Level OptLevel) {
3465 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00003466}