blob: fd5aac977b9951d284620bbd94f99d323a6209bd [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
14#include "ARM.h"
Evan Chenge5ad88e2008-12-10 21:54:21 +000015#include "ARMAddressingModes.h"
16#include "ARMConstantPoolValue.h"
Evan Chenga8e29892007-01-19 07:51:42 +000017#include "ARMISelLowering.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000018#include "ARMTargetMachine.h"
Rafael Espindola84b19be2006-07-16 01:02:57 +000019#include "llvm/CallingConv.h"
Evan Chenga8e29892007-01-19 07:51:42 +000020#include "llvm/Constants.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000021#include "llvm/DerivedTypes.h"
22#include "llvm/Function.h"
23#include "llvm/Intrinsics.h"
Owen Anderson9adc0ab2009-07-14 23:09:55 +000024#include "llvm/LLVMContext.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000025#include "llvm/CodeGen/MachineFrameInfo.h"
26#include "llvm/CodeGen/MachineFunction.h"
27#include "llvm/CodeGen/MachineInstrBuilder.h"
28#include "llvm/CodeGen/SelectionDAG.h"
29#include "llvm/CodeGen/SelectionDAGISel.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000030#include "llvm/Target/TargetLowering.h"
Chris Lattner72939122007-05-03 00:32:00 +000031#include "llvm/Target/TargetOptions.h"
Chris Lattner3d62d782008-02-03 05:43:57 +000032#include "llvm/Support/Compiler.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000033#include "llvm/Support/Debug.h"
Torok Edwindac237e2009-07-08 20:53:28 +000034#include "llvm/Support/ErrorHandling.h"
35#include "llvm/Support/raw_ostream.h"
36
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000037using namespace llvm;
38
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000039//===--------------------------------------------------------------------===//
40/// ARMDAGToDAGISel - ARM specific code to select ARM machine
41/// instructions for SelectionDAG operations.
42///
43namespace {
44class ARMDAGToDAGISel : public SelectionDAGISel {
Anton Korobeynikovd49ea772009-06-26 21:28:53 +000045 ARMBaseTargetMachine &TM;
Evan Cheng3f7eb8e2008-09-18 07:24:33 +000046
Evan Chenga8e29892007-01-19 07:51:42 +000047 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
48 /// make the right decision when generating code for different targets.
49 const ARMSubtarget *Subtarget;
50
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000051public:
Bob Wilson522ce972009-09-28 14:30:20 +000052 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm,
53 CodeGenOpt::Level OptLevel)
54 : SelectionDAGISel(tm, OptLevel), TM(tm),
Evan Chenga8e29892007-01-19 07:51:42 +000055 Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000056 }
57
Evan Chenga8e29892007-01-19 07:51:42 +000058 virtual const char *getPassName() const {
59 return "ARM Instruction Selection";
Anton Korobeynikov52237112009-06-17 18:13:58 +000060 }
61
Bob Wilsonaf4a8912009-10-08 18:51:31 +000062 /// getI32Imm - Return a target constant of type i32 with the specified
63 /// value.
Anton Korobeynikov52237112009-06-17 18:13:58 +000064 inline SDValue getI32Imm(unsigned Imm) {
Owen Anderson825b72b2009-08-11 20:47:22 +000065 return CurDAG->getTargetConstant(Imm, MVT::i32);
Anton Korobeynikov52237112009-06-17 18:13:58 +000066 }
67
Dan Gohman475871a2008-07-27 21:46:04 +000068 SDNode *Select(SDValue Op);
Dan Gohmanf350b272008-08-23 02:25:05 +000069 virtual void InstructionSelect();
Evan Cheng055b0312009-06-29 07:51:04 +000070 bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A,
71 SDValue &B, SDValue &C);
Dan Gohman475871a2008-07-27 21:46:04 +000072 bool SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base,
73 SDValue &Offset, SDValue &Opc);
74 bool SelectAddrMode2Offset(SDValue Op, SDValue N,
75 SDValue &Offset, SDValue &Opc);
76 bool SelectAddrMode3(SDValue Op, SDValue N, SDValue &Base,
77 SDValue &Offset, SDValue &Opc);
78 bool SelectAddrMode3Offset(SDValue Op, SDValue N,
79 SDValue &Offset, SDValue &Opc);
Anton Korobeynikovbaf31082009-08-08 13:35:48 +000080 bool SelectAddrMode4(SDValue Op, SDValue N, SDValue &Addr,
81 SDValue &Mode);
Dan Gohman475871a2008-07-27 21:46:04 +000082 bool SelectAddrMode5(SDValue Op, SDValue N, SDValue &Base,
83 SDValue &Offset);
Bob Wilson8b024a52009-07-01 23:16:05 +000084 bool SelectAddrMode6(SDValue Op, SDValue N, SDValue &Addr, SDValue &Update,
85 SDValue &Opc);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000086
Dan Gohman475871a2008-07-27 21:46:04 +000087 bool SelectAddrModePC(SDValue Op, SDValue N, SDValue &Offset,
Bob Wilson8b024a52009-07-01 23:16:05 +000088 SDValue &Label);
Evan Chenga8e29892007-01-19 07:51:42 +000089
Dan Gohman475871a2008-07-27 21:46:04 +000090 bool SelectThumbAddrModeRR(SDValue Op, SDValue N, SDValue &Base,
91 SDValue &Offset);
92 bool SelectThumbAddrModeRI5(SDValue Op, SDValue N, unsigned Scale,
93 SDValue &Base, SDValue &OffImm,
94 SDValue &Offset);
95 bool SelectThumbAddrModeS1(SDValue Op, SDValue N, SDValue &Base,
96 SDValue &OffImm, SDValue &Offset);
97 bool SelectThumbAddrModeS2(SDValue Op, SDValue N, SDValue &Base,
98 SDValue &OffImm, SDValue &Offset);
99 bool SelectThumbAddrModeS4(SDValue Op, SDValue N, SDValue &Base,
100 SDValue &OffImm, SDValue &Offset);
101 bool SelectThumbAddrModeSP(SDValue Op, SDValue N, SDValue &Base,
102 SDValue &OffImm);
Evan Chenga8e29892007-01-19 07:51:42 +0000103
Evan Cheng9cb9e672009-06-27 02:26:13 +0000104 bool SelectT2ShifterOperandReg(SDValue Op, SDValue N,
105 SDValue &BaseReg, SDValue &Opc);
Evan Cheng055b0312009-06-29 07:51:04 +0000106 bool SelectT2AddrModeImm12(SDValue Op, SDValue N, SDValue &Base,
107 SDValue &OffImm);
108 bool SelectT2AddrModeImm8(SDValue Op, SDValue N, SDValue &Base,
109 SDValue &OffImm);
Evan Chenge88d5ce2009-07-02 07:28:31 +0000110 bool SelectT2AddrModeImm8Offset(SDValue Op, SDValue N,
111 SDValue &OffImm);
David Goodwin6647cea2009-06-30 22:50:01 +0000112 bool SelectT2AddrModeImm8s4(SDValue Op, SDValue N, SDValue &Base,
113 SDValue &OffImm);
Evan Cheng055b0312009-06-29 07:51:04 +0000114 bool SelectT2AddrModeSoReg(SDValue Op, SDValue N, SDValue &Base,
115 SDValue &OffReg, SDValue &ShImm);
116
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000117 // Include the pieces autogenerated from the target description.
118#include "ARMGenDAGISel.inc"
Bob Wilson224c2442009-05-19 05:53:42 +0000119
120private:
Evan Chenge88d5ce2009-07-02 07:28:31 +0000121 /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
122 /// ARM.
Evan Chengaf4550f2009-07-02 01:23:32 +0000123 SDNode *SelectARMIndexedLoad(SDValue Op);
Evan Chenge88d5ce2009-07-02 07:28:31 +0000124 SDNode *SelectT2IndexedLoad(SDValue Op);
125
Evan Cheng86198642009-08-07 00:34:42 +0000126 /// SelectDYN_ALLOC - Select dynamic alloc for Thumb.
127 SDNode *SelectDYN_ALLOC(SDValue Op);
Evan Chengaf4550f2009-07-02 01:23:32 +0000128
129 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
130 /// inline asm expressions.
131 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
132 char ConstraintCode,
133 std::vector<SDValue> &OutOps);
Bob Wilson3bf12ab2009-10-06 22:01:59 +0000134
135 /// PairDRegs - Insert a pair of double registers into an implicit def to
136 /// form a quad register.
137 SDNode *PairDRegs(EVT VT, SDValue V0, SDValue V1);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000138};
Evan Chenga8e29892007-01-19 07:51:42 +0000139}
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000140
Dan Gohmanf350b272008-08-23 02:25:05 +0000141void ARMDAGToDAGISel::InstructionSelect() {
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000142 DEBUG(BB->dump());
143
David Greene8ad4c002008-10-27 21:56:29 +0000144 SelectRoot(*CurDAG);
Dan Gohmanf350b272008-08-23 02:25:05 +0000145 CurDAG->RemoveDeadNodes();
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000146}
147
Evan Cheng055b0312009-06-29 07:51:04 +0000148bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op,
149 SDValue N,
150 SDValue &BaseReg,
151 SDValue &ShReg,
152 SDValue &Opc) {
153 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
154
155 // Don't match base register only case. That is matched to a separate
156 // lower complexity pattern with explicit register operand.
157 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbach764ab522009-08-11 15:33:49 +0000158
Evan Cheng055b0312009-06-29 07:51:04 +0000159 BaseReg = N.getOperand(0);
160 unsigned ShImmVal = 0;
161 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Owen Anderson825b72b2009-08-11 20:47:22 +0000162 ShReg = CurDAG->getRegister(0, MVT::i32);
Evan Cheng055b0312009-06-29 07:51:04 +0000163 ShImmVal = RHS->getZExtValue() & 31;
164 } else {
165 ShReg = N.getOperand(1);
166 }
167 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Owen Anderson825b72b2009-08-11 20:47:22 +0000168 MVT::i32);
Evan Cheng055b0312009-06-29 07:51:04 +0000169 return true;
170}
171
Dan Gohman475871a2008-07-27 21:46:04 +0000172bool ARMDAGToDAGISel::SelectAddrMode2(SDValue Op, SDValue N,
173 SDValue &Base, SDValue &Offset,
174 SDValue &Opc) {
Evan Chenga13fd102007-03-13 21:05:54 +0000175 if (N.getOpcode() == ISD::MUL) {
176 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
177 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000178 int RHSC = (int)RHS->getZExtValue();
Evan Chenga13fd102007-03-13 21:05:54 +0000179 if (RHSC & 1) {
180 RHSC = RHSC & ~1;
181 ARM_AM::AddrOpc AddSub = ARM_AM::add;
182 if (RHSC < 0) {
183 AddSub = ARM_AM::sub;
184 RHSC = - RHSC;
185 }
186 if (isPowerOf2_32(RHSC)) {
187 unsigned ShAmt = Log2_32(RHSC);
188 Base = Offset = N.getOperand(0);
189 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
190 ARM_AM::lsl),
Owen Anderson825b72b2009-08-11 20:47:22 +0000191 MVT::i32);
Evan Chenga13fd102007-03-13 21:05:54 +0000192 return true;
193 }
194 }
195 }
196 }
197
Evan Chenga8e29892007-01-19 07:51:42 +0000198 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) {
199 Base = N;
200 if (N.getOpcode() == ISD::FrameIndex) {
201 int FI = cast<FrameIndexSDNode>(N)->getIndex();
202 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
203 } else if (N.getOpcode() == ARMISD::Wrapper) {
204 Base = N.getOperand(0);
205 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000206 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000207 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
208 ARM_AM::no_shift),
Owen Anderson825b72b2009-08-11 20:47:22 +0000209 MVT::i32);
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000210 return true;
211 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000212
Evan Chenga8e29892007-01-19 07:51:42 +0000213 // Match simple R +/- imm12 operands.
214 if (N.getOpcode() == ISD::ADD)
215 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000216 int RHSC = (int)RHS->getZExtValue();
Evan Chenge966d642007-01-24 02:45:25 +0000217 if ((RHSC >= 0 && RHSC < 0x1000) ||
218 (RHSC < 0 && RHSC > -0x1000)) { // 12 bits.
Evan Chenga8e29892007-01-19 07:51:42 +0000219 Base = N.getOperand(0);
Evan Chenge966d642007-01-24 02:45:25 +0000220 if (Base.getOpcode() == ISD::FrameIndex) {
221 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
222 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
223 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000224 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Chenge966d642007-01-24 02:45:25 +0000225
226 ARM_AM::AddrOpc AddSub = ARM_AM::add;
227 if (RHSC < 0) {
228 AddSub = ARM_AM::sub;
229 RHSC = - RHSC;
230 }
231 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
Evan Chenga8e29892007-01-19 07:51:42 +0000232 ARM_AM::no_shift),
Owen Anderson825b72b2009-08-11 20:47:22 +0000233 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000234 return true;
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000235 }
Evan Chenga8e29892007-01-19 07:51:42 +0000236 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000237
Evan Chenga8e29892007-01-19 07:51:42 +0000238 // Otherwise this is R +/- [possibly shifted] R
239 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub;
240 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1));
241 unsigned ShAmt = 0;
Jim Grosbach764ab522009-08-11 15:33:49 +0000242
Evan Chenga8e29892007-01-19 07:51:42 +0000243 Base = N.getOperand(0);
244 Offset = N.getOperand(1);
Jim Grosbach764ab522009-08-11 15:33:49 +0000245
Evan Chenga8e29892007-01-19 07:51:42 +0000246 if (ShOpcVal != ARM_AM::no_shift) {
247 // Check to see if the RHS of the shift is a constant, if not, we can't fold
248 // it.
249 if (ConstantSDNode *Sh =
250 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000251 ShAmt = Sh->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000252 Offset = N.getOperand(1).getOperand(0);
253 } else {
254 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000255 }
256 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000257
Evan Chenga8e29892007-01-19 07:51:42 +0000258 // Try matching (R shl C) + (R).
259 if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) {
260 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0));
261 if (ShOpcVal != ARM_AM::no_shift) {
262 // Check to see if the RHS of the shift is a constant, if not, we can't
263 // fold it.
264 if (ConstantSDNode *Sh =
265 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000266 ShAmt = Sh->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000267 Offset = N.getOperand(0).getOperand(0);
268 Base = N.getOperand(1);
269 } else {
270 ShOpcVal = ARM_AM::no_shift;
271 }
272 }
273 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000274
Evan Chenga8e29892007-01-19 07:51:42 +0000275 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson825b72b2009-08-11 20:47:22 +0000276 MVT::i32);
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000277 return true;
278}
279
Dan Gohman475871a2008-07-27 21:46:04 +0000280bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDValue Op, SDValue N,
281 SDValue &Offset, SDValue &Opc) {
Evan Chenga8e29892007-01-19 07:51:42 +0000282 unsigned Opcode = Op.getOpcode();
283 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
284 ? cast<LoadSDNode>(Op)->getAddressingMode()
285 : cast<StoreSDNode>(Op)->getAddressingMode();
286 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
287 ? ARM_AM::add : ARM_AM::sub;
288 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000289 int Val = (int)C->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000290 if (Val >= 0 && Val < 0x1000) { // 12 bits.
Owen Anderson825b72b2009-08-11 20:47:22 +0000291 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000292 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
293 ARM_AM::no_shift),
Owen Anderson825b72b2009-08-11 20:47:22 +0000294 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000295 return true;
296 }
297 }
298
299 Offset = N;
300 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
301 unsigned ShAmt = 0;
302 if (ShOpcVal != ARM_AM::no_shift) {
303 // Check to see if the RHS of the shift is a constant, if not, we can't fold
304 // it.
305 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000306 ShAmt = Sh->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000307 Offset = N.getOperand(0);
308 } else {
309 ShOpcVal = ARM_AM::no_shift;
310 }
311 }
312
313 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson825b72b2009-08-11 20:47:22 +0000314 MVT::i32);
Rafael Espindola32bd5f42006-10-17 18:04:53 +0000315 return true;
316}
317
Evan Chenga8e29892007-01-19 07:51:42 +0000318
Dan Gohman475871a2008-07-27 21:46:04 +0000319bool ARMDAGToDAGISel::SelectAddrMode3(SDValue Op, SDValue N,
320 SDValue &Base, SDValue &Offset,
321 SDValue &Opc) {
Evan Chenga8e29892007-01-19 07:51:42 +0000322 if (N.getOpcode() == ISD::SUB) {
323 // X - C is canonicalize to X + -C, no need to handle it here.
324 Base = N.getOperand(0);
325 Offset = N.getOperand(1);
Owen Anderson825b72b2009-08-11 20:47:22 +0000326 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000327 return true;
328 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000329
Evan Chenga8e29892007-01-19 07:51:42 +0000330 if (N.getOpcode() != ISD::ADD) {
331 Base = N;
332 if (N.getOpcode() == ISD::FrameIndex) {
333 int FI = cast<FrameIndexSDNode>(N)->getIndex();
334 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
335 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000336 Offset = CurDAG->getRegister(0, MVT::i32);
337 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000338 return true;
339 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000340
Evan Chenga8e29892007-01-19 07:51:42 +0000341 // If the RHS is +/- imm8, fold into addr mode.
342 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000343 int RHSC = (int)RHS->getZExtValue();
Evan Chenge966d642007-01-24 02:45:25 +0000344 if ((RHSC >= 0 && RHSC < 256) ||
345 (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed.
Evan Chenga8e29892007-01-19 07:51:42 +0000346 Base = N.getOperand(0);
Evan Chenge966d642007-01-24 02:45:25 +0000347 if (Base.getOpcode() == ISD::FrameIndex) {
348 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
349 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
350 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000351 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Chenge966d642007-01-24 02:45:25 +0000352
353 ARM_AM::AddrOpc AddSub = ARM_AM::add;
354 if (RHSC < 0) {
355 AddSub = ARM_AM::sub;
356 RHSC = - RHSC;
357 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000358 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000359 return true;
360 }
361 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000362
Evan Chenga8e29892007-01-19 07:51:42 +0000363 Base = N.getOperand(0);
364 Offset = N.getOperand(1);
Owen Anderson825b72b2009-08-11 20:47:22 +0000365 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000366 return true;
367}
368
Dan Gohman475871a2008-07-27 21:46:04 +0000369bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDValue Op, SDValue N,
370 SDValue &Offset, SDValue &Opc) {
Evan Chenga8e29892007-01-19 07:51:42 +0000371 unsigned Opcode = Op.getOpcode();
372 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
373 ? cast<LoadSDNode>(Op)->getAddressingMode()
374 : cast<StoreSDNode>(Op)->getAddressingMode();
375 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
376 ? ARM_AM::add : ARM_AM::sub;
377 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000378 int Val = (int)C->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000379 if (Val >= 0 && Val < 256) {
Owen Anderson825b72b2009-08-11 20:47:22 +0000380 Offset = CurDAG->getRegister(0, MVT::i32);
381 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000382 return true;
383 }
384 }
385
386 Offset = N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000387 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000388 return true;
389}
390
Anton Korobeynikovbaf31082009-08-08 13:35:48 +0000391bool ARMDAGToDAGISel::SelectAddrMode4(SDValue Op, SDValue N,
392 SDValue &Addr, SDValue &Mode) {
393 Addr = N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000394 Mode = CurDAG->getTargetConstant(0, MVT::i32);
Anton Korobeynikovbaf31082009-08-08 13:35:48 +0000395 return true;
396}
Evan Chenga8e29892007-01-19 07:51:42 +0000397
Dan Gohman475871a2008-07-27 21:46:04 +0000398bool ARMDAGToDAGISel::SelectAddrMode5(SDValue Op, SDValue N,
399 SDValue &Base, SDValue &Offset) {
Evan Chenga8e29892007-01-19 07:51:42 +0000400 if (N.getOpcode() != ISD::ADD) {
401 Base = N;
402 if (N.getOpcode() == ISD::FrameIndex) {
403 int FI = cast<FrameIndexSDNode>(N)->getIndex();
404 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
405 } else if (N.getOpcode() == ARMISD::Wrapper) {
406 Base = N.getOperand(0);
407 }
408 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson825b72b2009-08-11 20:47:22 +0000409 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000410 return true;
411 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000412
Evan Chenga8e29892007-01-19 07:51:42 +0000413 // If the RHS is +/- imm8, fold into addr mode.
414 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000415 int RHSC = (int)RHS->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000416 if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4.
417 RHSC >>= 2;
Evan Chenge966d642007-01-24 02:45:25 +0000418 if ((RHSC >= 0 && RHSC < 256) ||
419 (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed.
Evan Chenga8e29892007-01-19 07:51:42 +0000420 Base = N.getOperand(0);
Evan Chenge966d642007-01-24 02:45:25 +0000421 if (Base.getOpcode() == ISD::FrameIndex) {
422 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
423 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
424 }
425
426 ARM_AM::AddrOpc AddSub = ARM_AM::add;
427 if (RHSC < 0) {
428 AddSub = ARM_AM::sub;
429 RHSC = - RHSC;
430 }
431 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
Owen Anderson825b72b2009-08-11 20:47:22 +0000432 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000433 return true;
434 }
435 }
436 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000437
Evan Chenga8e29892007-01-19 07:51:42 +0000438 Base = N;
439 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson825b72b2009-08-11 20:47:22 +0000440 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000441 return true;
442}
443
Bob Wilson8b024a52009-07-01 23:16:05 +0000444bool ARMDAGToDAGISel::SelectAddrMode6(SDValue Op, SDValue N,
445 SDValue &Addr, SDValue &Update,
446 SDValue &Opc) {
447 Addr = N;
Bob Wilsonff8952e2009-10-07 17:24:55 +0000448 // Default to no writeback.
Owen Anderson825b72b2009-08-11 20:47:22 +0000449 Update = CurDAG->getRegister(0, MVT::i32);
450 Opc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(false), MVT::i32);
Bob Wilson8b024a52009-07-01 23:16:05 +0000451 return true;
452}
453
Dan Gohman475871a2008-07-27 21:46:04 +0000454bool ARMDAGToDAGISel::SelectAddrModePC(SDValue Op, SDValue N,
Evan Chengbba9f5f2009-08-14 19:01:37 +0000455 SDValue &Offset, SDValue &Label) {
Evan Chenga8e29892007-01-19 07:51:42 +0000456 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
457 Offset = N.getOperand(0);
Dan Gohman475871a2008-07-27 21:46:04 +0000458 SDValue N1 = N.getOperand(1);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000459 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Owen Anderson825b72b2009-08-11 20:47:22 +0000460 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000461 return true;
462 }
463 return false;
464}
465
Dan Gohman475871a2008-07-27 21:46:04 +0000466bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue Op, SDValue N,
467 SDValue &Base, SDValue &Offset){
Dale Johannesenf5f5dce2009-02-06 19:16:40 +0000468 // FIXME dl should come from the parent load or store, not the address
469 DebugLoc dl = Op.getDebugLoc();
Evan Chengc38f2bc2007-01-23 22:59:13 +0000470 if (N.getOpcode() != ISD::ADD) {
Evan Cheng2f297df2009-07-11 07:08:13 +0000471 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
472 if (!NC || NC->getZExtValue() != 0)
473 return false;
474
475 Base = Offset = N;
Evan Chengc38f2bc2007-01-23 22:59:13 +0000476 return true;
477 }
478
Evan Chenga8e29892007-01-19 07:51:42 +0000479 Base = N.getOperand(0);
480 Offset = N.getOperand(1);
481 return true;
482}
483
Evan Cheng79d43262007-01-24 02:21:22 +0000484bool
Dan Gohman475871a2008-07-27 21:46:04 +0000485ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue Op, SDValue N,
486 unsigned Scale, SDValue &Base,
487 SDValue &OffImm, SDValue &Offset) {
Evan Cheng79d43262007-01-24 02:21:22 +0000488 if (Scale == 4) {
Dan Gohman475871a2008-07-27 21:46:04 +0000489 SDValue TmpBase, TmpOffImm;
Evan Cheng79d43262007-01-24 02:21:22 +0000490 if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm))
491 return false; // We want to select tLDRspi / tSTRspi instead.
Evan Cheng012f2d92007-01-24 08:53:17 +0000492 if (N.getOpcode() == ARMISD::Wrapper &&
493 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
494 return false; // We want to select tLDRpci instead.
Evan Cheng79d43262007-01-24 02:21:22 +0000495 }
496
Evan Chenga8e29892007-01-19 07:51:42 +0000497 if (N.getOpcode() != ISD::ADD) {
498 Base = (N.getOpcode() == ARMISD::Wrapper) ? N.getOperand(0) : N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000499 Offset = CurDAG->getRegister(0, MVT::i32);
500 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000501 return true;
502 }
503
Evan Chengad0e4652007-02-06 00:22:06 +0000504 // Thumb does not have [sp, r] address mode.
505 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
506 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
507 if ((LHSR && LHSR->getReg() == ARM::SP) ||
508 (RHSR && RHSR->getReg() == ARM::SP)) {
509 Base = N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000510 Offset = CurDAG->getRegister(0, MVT::i32);
511 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chengad0e4652007-02-06 00:22:06 +0000512 return true;
513 }
514
Evan Chenga8e29892007-01-19 07:51:42 +0000515 // If the RHS is + imm5 * scale, fold into addr mode.
516 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000517 int RHSC = (int)RHS->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000518 if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied.
519 RHSC /= Scale;
520 if (RHSC >= 0 && RHSC < 32) {
521 Base = N.getOperand(0);
Owen Anderson825b72b2009-08-11 20:47:22 +0000522 Offset = CurDAG->getRegister(0, MVT::i32);
523 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000524 return true;
525 }
526 }
527 }
528
Evan Chengc38f2bc2007-01-23 22:59:13 +0000529 Base = N.getOperand(0);
530 Offset = N.getOperand(1);
Owen Anderson825b72b2009-08-11 20:47:22 +0000531 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chengc38f2bc2007-01-23 22:59:13 +0000532 return true;
Evan Chenga8e29892007-01-19 07:51:42 +0000533}
534
Dan Gohman475871a2008-07-27 21:46:04 +0000535bool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDValue Op, SDValue N,
536 SDValue &Base, SDValue &OffImm,
537 SDValue &Offset) {
Evan Chengcea117d2007-01-30 02:35:32 +0000538 return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset);
Evan Chenga8e29892007-01-19 07:51:42 +0000539}
540
Dan Gohman475871a2008-07-27 21:46:04 +0000541bool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDValue Op, SDValue N,
542 SDValue &Base, SDValue &OffImm,
543 SDValue &Offset) {
Evan Chengcea117d2007-01-30 02:35:32 +0000544 return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset);
Evan Chenga8e29892007-01-19 07:51:42 +0000545}
546
Dan Gohman475871a2008-07-27 21:46:04 +0000547bool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDValue Op, SDValue N,
548 SDValue &Base, SDValue &OffImm,
549 SDValue &Offset) {
Evan Chengcea117d2007-01-30 02:35:32 +0000550 return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset);
Evan Chenga8e29892007-01-19 07:51:42 +0000551}
552
Dan Gohman475871a2008-07-27 21:46:04 +0000553bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue Op, SDValue N,
554 SDValue &Base, SDValue &OffImm) {
Evan Chenga8e29892007-01-19 07:51:42 +0000555 if (N.getOpcode() == ISD::FrameIndex) {
556 int FI = cast<FrameIndexSDNode>(N)->getIndex();
557 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Owen Anderson825b72b2009-08-11 20:47:22 +0000558 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000559 return true;
560 }
Evan Cheng79d43262007-01-24 02:21:22 +0000561
Evan Chengad0e4652007-02-06 00:22:06 +0000562 if (N.getOpcode() != ISD::ADD)
563 return false;
564
565 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Cheng8c1a73a2007-02-06 09:11:20 +0000566 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
567 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng79d43262007-01-24 02:21:22 +0000568 // If the RHS is + imm8 * scale, fold into addr mode.
569 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000570 int RHSC = (int)RHS->getZExtValue();
Evan Cheng79d43262007-01-24 02:21:22 +0000571 if ((RHSC & 3) == 0) { // The constant is implicitly multiplied.
572 RHSC >>= 2;
573 if (RHSC >= 0 && RHSC < 256) {
Evan Chengad0e4652007-02-06 00:22:06 +0000574 Base = N.getOperand(0);
Evan Cheng8c1a73a2007-02-06 09:11:20 +0000575 if (Base.getOpcode() == ISD::FrameIndex) {
576 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
577 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
578 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000579 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
Evan Cheng79d43262007-01-24 02:21:22 +0000580 return true;
581 }
582 }
583 }
584 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000585
Evan Chenga8e29892007-01-19 07:51:42 +0000586 return false;
587}
588
Evan Cheng9cb9e672009-06-27 02:26:13 +0000589bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue Op, SDValue N,
590 SDValue &BaseReg,
591 SDValue &Opc) {
592 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
593
594 // Don't match base register only case. That is matched to a separate
595 // lower complexity pattern with explicit register operand.
596 if (ShOpcVal == ARM_AM::no_shift) return false;
597
598 BaseReg = N.getOperand(0);
599 unsigned ShImmVal = 0;
600 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
601 ShImmVal = RHS->getZExtValue() & 31;
602 Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
603 return true;
604 }
605
606 return false;
607}
608
Evan Cheng055b0312009-06-29 07:51:04 +0000609bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue Op, SDValue N,
610 SDValue &Base, SDValue &OffImm) {
611 // Match simple R + imm12 operands.
David Goodwin31e7eba2009-07-20 15:55:39 +0000612
Evan Cheng3a214252009-08-11 08:52:18 +0000613 // Base only.
614 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) {
David Goodwin31e7eba2009-07-20 15:55:39 +0000615 if (N.getOpcode() == ISD::FrameIndex) {
Evan Cheng3a214252009-08-11 08:52:18 +0000616 // Match frame index...
David Goodwin31e7eba2009-07-20 15:55:39 +0000617 int FI = cast<FrameIndexSDNode>(N)->getIndex();
618 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Owen Anderson825b72b2009-08-11 20:47:22 +0000619 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
David Goodwin31e7eba2009-07-20 15:55:39 +0000620 return true;
Evan Cheng3a214252009-08-11 08:52:18 +0000621 } else if (N.getOpcode() == ARMISD::Wrapper) {
622 Base = N.getOperand(0);
623 if (Base.getOpcode() == ISD::TargetConstantPool)
624 return false; // We want to select t2LDRpci instead.
625 } else
626 Base = N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000627 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng3a214252009-08-11 08:52:18 +0000628 return true;
David Goodwin31e7eba2009-07-20 15:55:39 +0000629 }
Evan Cheng055b0312009-06-29 07:51:04 +0000630
631 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Evan Cheng3a214252009-08-11 08:52:18 +0000632 if (SelectT2AddrModeImm8(Op, N, Base, OffImm))
633 // Let t2LDRi8 handle (R - imm8).
634 return false;
635
Evan Cheng055b0312009-06-29 07:51:04 +0000636 int RHSC = (int)RHS->getZExtValue();
David Goodwind8c95b52009-07-30 18:56:48 +0000637 if (N.getOpcode() == ISD::SUB)
638 RHSC = -RHSC;
639
640 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Cheng055b0312009-06-29 07:51:04 +0000641 Base = N.getOperand(0);
David Goodwind8c95b52009-07-30 18:56:48 +0000642 if (Base.getOpcode() == ISD::FrameIndex) {
643 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
644 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
645 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000646 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
Evan Cheng055b0312009-06-29 07:51:04 +0000647 return true;
648 }
649 }
650
Evan Cheng3a214252009-08-11 08:52:18 +0000651 // Base only.
652 Base = N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000653 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng3a214252009-08-11 08:52:18 +0000654 return true;
Evan Cheng055b0312009-06-29 07:51:04 +0000655}
656
657bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue Op, SDValue N,
658 SDValue &Base, SDValue &OffImm) {
David Goodwind8c95b52009-07-30 18:56:48 +0000659 // Match simple R - imm8 operands.
Evan Cheng3a214252009-08-11 08:52:18 +0000660 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::SUB) {
David Goodwin07337c02009-07-30 22:45:52 +0000661 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
662 int RHSC = (int)RHS->getSExtValue();
663 if (N.getOpcode() == ISD::SUB)
664 RHSC = -RHSC;
Jim Grosbach764ab522009-08-11 15:33:49 +0000665
Evan Cheng3a214252009-08-11 08:52:18 +0000666 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
667 Base = N.getOperand(0);
David Goodwin07337c02009-07-30 22:45:52 +0000668 if (Base.getOpcode() == ISD::FrameIndex) {
669 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
670 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
671 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000672 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
David Goodwin07337c02009-07-30 22:45:52 +0000673 return true;
Evan Cheng055b0312009-06-29 07:51:04 +0000674 }
Evan Cheng055b0312009-06-29 07:51:04 +0000675 }
676 }
677
678 return false;
679}
680
Evan Chenge88d5ce2009-07-02 07:28:31 +0000681bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDValue Op, SDValue N,
682 SDValue &OffImm){
683 unsigned Opcode = Op.getOpcode();
684 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
685 ? cast<LoadSDNode>(Op)->getAddressingMode()
686 : cast<StoreSDNode>(Op)->getAddressingMode();
687 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N)) {
688 int RHSC = (int)RHS->getZExtValue();
689 if (RHSC >= 0 && RHSC < 0x100) { // 8 bits.
David Goodwin4cb73522009-07-14 21:29:29 +0000690 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Owen Anderson825b72b2009-08-11 20:47:22 +0000691 ? CurDAG->getTargetConstant(RHSC, MVT::i32)
692 : CurDAG->getTargetConstant(-RHSC, MVT::i32);
Evan Chenge88d5ce2009-07-02 07:28:31 +0000693 return true;
694 }
695 }
696
697 return false;
698}
699
David Goodwin6647cea2009-06-30 22:50:01 +0000700bool ARMDAGToDAGISel::SelectT2AddrModeImm8s4(SDValue Op, SDValue N,
701 SDValue &Base, SDValue &OffImm) {
702 if (N.getOpcode() == ISD::ADD) {
703 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
704 int RHSC = (int)RHS->getZExtValue();
Evan Cheng5c874172009-07-09 22:21:59 +0000705 if (((RHSC & 0x3) == 0) &&
706 ((RHSC >= 0 && RHSC < 0x400) || (RHSC < 0 && RHSC > -0x400))) { // 8 bits.
David Goodwin6647cea2009-06-30 22:50:01 +0000707 Base = N.getOperand(0);
Owen Anderson825b72b2009-08-11 20:47:22 +0000708 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
David Goodwin6647cea2009-06-30 22:50:01 +0000709 return true;
710 }
711 }
712 } else if (N.getOpcode() == ISD::SUB) {
713 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
714 int RHSC = (int)RHS->getZExtValue();
715 if (((RHSC & 0x3) == 0) && (RHSC >= 0 && RHSC < 0x400)) { // 8 bits.
716 Base = N.getOperand(0);
Owen Anderson825b72b2009-08-11 20:47:22 +0000717 OffImm = CurDAG->getTargetConstant(-RHSC, MVT::i32);
David Goodwin6647cea2009-06-30 22:50:01 +0000718 return true;
719 }
720 }
721 }
722
723 return false;
724}
725
Evan Cheng055b0312009-06-29 07:51:04 +0000726bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue Op, SDValue N,
727 SDValue &Base,
728 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng3a214252009-08-11 08:52:18 +0000729 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
730 if (N.getOpcode() != ISD::ADD)
731 return false;
Evan Cheng055b0312009-06-29 07:51:04 +0000732
Evan Cheng3a214252009-08-11 08:52:18 +0000733 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
734 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
735 int RHSC = (int)RHS->getZExtValue();
736 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
737 return false;
738 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwind8c95b52009-07-30 18:56:48 +0000739 return false;
740 }
741
Evan Cheng055b0312009-06-29 07:51:04 +0000742 // Look for (R + R) or (R + (R << [1,2,3])).
743 unsigned ShAmt = 0;
744 Base = N.getOperand(0);
745 OffReg = N.getOperand(1);
746
747 // Swap if it is ((R << c) + R).
748 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg);
749 if (ShOpcVal != ARM_AM::lsl) {
750 ShOpcVal = ARM_AM::getShiftOpcForNode(Base);
751 if (ShOpcVal == ARM_AM::lsl)
752 std::swap(Base, OffReg);
Jim Grosbach764ab522009-08-11 15:33:49 +0000753 }
754
Evan Cheng055b0312009-06-29 07:51:04 +0000755 if (ShOpcVal == ARM_AM::lsl) {
756 // Check to see if the RHS of the shift is a constant, if not, we can't fold
757 // it.
758 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
759 ShAmt = Sh->getZExtValue();
760 if (ShAmt >= 4) {
761 ShAmt = 0;
762 ShOpcVal = ARM_AM::no_shift;
763 } else
764 OffReg = OffReg.getOperand(0);
765 } else {
766 ShOpcVal = ARM_AM::no_shift;
767 }
David Goodwin7ecc8502009-07-15 15:50:19 +0000768 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000769
Owen Anderson825b72b2009-08-11 20:47:22 +0000770 ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32);
Evan Cheng055b0312009-06-29 07:51:04 +0000771
772 return true;
773}
774
775//===--------------------------------------------------------------------===//
776
Evan Chengee568cf2007-07-05 07:15:27 +0000777/// getAL - Returns a ARMCC::AL immediate node.
Dan Gohman475871a2008-07-27 21:46:04 +0000778static inline SDValue getAL(SelectionDAG *CurDAG) {
Owen Anderson825b72b2009-08-11 20:47:22 +0000779 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);
Evan Cheng44bec522007-05-15 01:29:07 +0000780}
781
Evan Chengaf4550f2009-07-02 01:23:32 +0000782SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDValue Op) {
783 LoadSDNode *LD = cast<LoadSDNode>(Op);
784 ISD::MemIndexedMode AM = LD->getAddressingMode();
785 if (AM == ISD::UNINDEXED)
786 return NULL;
787
Owen Andersone50ed302009-08-10 22:56:29 +0000788 EVT LoadedVT = LD->getMemoryVT();
Evan Chengaf4550f2009-07-02 01:23:32 +0000789 SDValue Offset, AMOpc;
790 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
791 unsigned Opcode = 0;
792 bool Match = false;
Owen Anderson825b72b2009-08-11 20:47:22 +0000793 if (LoadedVT == MVT::i32 &&
Evan Chengaf4550f2009-07-02 01:23:32 +0000794 SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) {
795 Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST;
796 Match = true;
Owen Anderson825b72b2009-08-11 20:47:22 +0000797 } else if (LoadedVT == MVT::i16 &&
Evan Chengaf4550f2009-07-02 01:23:32 +0000798 SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) {
799 Match = true;
800 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
801 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
802 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson825b72b2009-08-11 20:47:22 +0000803 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengaf4550f2009-07-02 01:23:32 +0000804 if (LD->getExtensionType() == ISD::SEXTLOAD) {
805 if (SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) {
806 Match = true;
807 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
808 }
809 } else {
810 if (SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) {
811 Match = true;
812 Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST;
813 }
814 }
815 }
816
817 if (Match) {
818 SDValue Chain = LD->getChain();
819 SDValue Base = LD->getBasePtr();
820 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG),
Owen Anderson825b72b2009-08-11 20:47:22 +0000821 CurDAG->getRegister(0, MVT::i32), Chain };
Dan Gohman602b0c82009-09-25 18:54:59 +0000822 return CurDAG->getMachineNode(Opcode, Op.getDebugLoc(), MVT::i32, MVT::i32,
823 MVT::Other, Ops, 6);
Evan Chengaf4550f2009-07-02 01:23:32 +0000824 }
825
826 return NULL;
827}
828
Evan Chenge88d5ce2009-07-02 07:28:31 +0000829SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDValue Op) {
830 LoadSDNode *LD = cast<LoadSDNode>(Op);
831 ISD::MemIndexedMode AM = LD->getAddressingMode();
832 if (AM == ISD::UNINDEXED)
833 return NULL;
834
Owen Andersone50ed302009-08-10 22:56:29 +0000835 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng4fbb9962009-07-02 23:16:11 +0000836 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Chenge88d5ce2009-07-02 07:28:31 +0000837 SDValue Offset;
838 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
839 unsigned Opcode = 0;
840 bool Match = false;
841 if (SelectT2AddrModeImm8Offset(Op, LD->getOffset(), Offset)) {
Owen Anderson825b72b2009-08-11 20:47:22 +0000842 switch (LoadedVT.getSimpleVT().SimpleTy) {
843 case MVT::i32:
Evan Chenge88d5ce2009-07-02 07:28:31 +0000844 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
845 break;
Owen Anderson825b72b2009-08-11 20:47:22 +0000846 case MVT::i16:
Evan Cheng4fbb9962009-07-02 23:16:11 +0000847 if (isSExtLd)
848 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
849 else
850 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Chenge88d5ce2009-07-02 07:28:31 +0000851 break;
Owen Anderson825b72b2009-08-11 20:47:22 +0000852 case MVT::i8:
853 case MVT::i1:
Evan Cheng4fbb9962009-07-02 23:16:11 +0000854 if (isSExtLd)
855 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
856 else
857 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Chenge88d5ce2009-07-02 07:28:31 +0000858 break;
859 default:
860 return NULL;
861 }
862 Match = true;
863 }
864
865 if (Match) {
866 SDValue Chain = LD->getChain();
867 SDValue Base = LD->getBasePtr();
868 SDValue Ops[]= { Base, Offset, getAL(CurDAG),
Owen Anderson825b72b2009-08-11 20:47:22 +0000869 CurDAG->getRegister(0, MVT::i32), Chain };
Dan Gohman602b0c82009-09-25 18:54:59 +0000870 return CurDAG->getMachineNode(Opcode, Op.getDebugLoc(), MVT::i32, MVT::i32,
871 MVT::Other, Ops, 5);
Evan Chenge88d5ce2009-07-02 07:28:31 +0000872 }
873
874 return NULL;
875}
876
Evan Cheng86198642009-08-07 00:34:42 +0000877SDNode *ARMDAGToDAGISel::SelectDYN_ALLOC(SDValue Op) {
878 SDNode *N = Op.getNode();
879 DebugLoc dl = N->getDebugLoc();
Owen Andersone50ed302009-08-10 22:56:29 +0000880 EVT VT = Op.getValueType();
Evan Cheng86198642009-08-07 00:34:42 +0000881 SDValue Chain = Op.getOperand(0);
882 SDValue Size = Op.getOperand(1);
883 SDValue Align = Op.getOperand(2);
Owen Anderson825b72b2009-08-11 20:47:22 +0000884 SDValue SP = CurDAG->getRegister(ARM::SP, MVT::i32);
Evan Cheng86198642009-08-07 00:34:42 +0000885 int32_t AlignVal = cast<ConstantSDNode>(Align)->getSExtValue();
886 if (AlignVal < 0)
887 // We need to align the stack. Use Thumb1 tAND which is the only thumb
888 // instruction that can read and write SP. This matches to a pseudo
889 // instruction that has a chain to ensure the result is written back to
890 // the stack pointer.
Dan Gohman602b0c82009-09-25 18:54:59 +0000891 SP = SDValue(CurDAG->getMachineNode(ARM::tANDsp, dl, VT, SP, Align), 0);
Evan Cheng86198642009-08-07 00:34:42 +0000892
893 bool isC = isa<ConstantSDNode>(Size);
894 uint32_t C = isC ? cast<ConstantSDNode>(Size)->getZExtValue() : ~0UL;
895 // Handle the most common case for both Thumb1 and Thumb2:
896 // tSUBspi - immediate is between 0 ... 508 inclusive.
897 if (C <= 508 && ((C & 3) == 0))
898 // FIXME: tSUBspi encode scale 4 implicitly.
Owen Anderson825b72b2009-08-11 20:47:22 +0000899 return CurDAG->SelectNodeTo(N, ARM::tSUBspi_, VT, MVT::Other, SP,
900 CurDAG->getTargetConstant(C/4, MVT::i32),
Evan Cheng86198642009-08-07 00:34:42 +0000901 Chain);
902
903 if (Subtarget->isThumb1Only()) {
Evan Chengb89030a2009-08-11 23:00:31 +0000904 // Use tADDspr since Thumb1 does not have a sub r, sp, r. ARMISelLowering
Evan Cheng86198642009-08-07 00:34:42 +0000905 // should have negated the size operand already. FIXME: We can't insert
906 // new target independent node at this stage so we are forced to negate
Jim Grosbach764ab522009-08-11 15:33:49 +0000907 // it earlier. Is there a better solution?
Owen Anderson825b72b2009-08-11 20:47:22 +0000908 return CurDAG->SelectNodeTo(N, ARM::tADDspr_, VT, MVT::Other, SP, Size,
Evan Cheng86198642009-08-07 00:34:42 +0000909 Chain);
910 } else if (Subtarget->isThumb2()) {
911 if (isC && Predicate_t2_so_imm(Size.getNode())) {
912 // t2SUBrSPi
Owen Anderson825b72b2009-08-11 20:47:22 +0000913 SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain };
914 return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi_, VT, MVT::Other, Ops, 3);
Evan Cheng86198642009-08-07 00:34:42 +0000915 } else if (isC && Predicate_imm0_4095(Size.getNode())) {
916 // t2SUBrSPi12
Owen Anderson825b72b2009-08-11 20:47:22 +0000917 SDValue Ops[] = { SP, CurDAG->getTargetConstant(C, MVT::i32), Chain };
918 return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPi12_, VT, MVT::Other, Ops, 3);
Evan Cheng86198642009-08-07 00:34:42 +0000919 } else {
920 // t2SUBrSPs
921 SDValue Ops[] = { SP, Size,
922 getI32Imm(ARM_AM::getSORegOpc(ARM_AM::lsl,0)), Chain };
Owen Anderson825b72b2009-08-11 20:47:22 +0000923 return CurDAG->SelectNodeTo(N, ARM::t2SUBrSPs_, VT, MVT::Other, Ops, 4);
Evan Cheng86198642009-08-07 00:34:42 +0000924 }
925 }
926
927 // FIXME: Add ADD / SUB sp instructions for ARM.
928 return 0;
929}
Evan Chenga8e29892007-01-19 07:51:42 +0000930
Bob Wilson3bf12ab2009-10-06 22:01:59 +0000931/// PairDRegs - Insert a pair of double registers into an implicit def to
932/// form a quad register.
933SDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) {
934 DebugLoc dl = V0.getNode()->getDebugLoc();
935 SDValue Undef =
936 SDValue(CurDAG->getMachineNode(TargetInstrInfo::IMPLICIT_DEF, dl, VT), 0);
937 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::DSUBREG_0, MVT::i32);
938 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::DSUBREG_1, MVT::i32);
939 SDNode *Pair = CurDAG->getMachineNode(TargetInstrInfo::INSERT_SUBREG, dl,
940 VT, Undef, V0, SubReg0);
941 return CurDAG->getMachineNode(TargetInstrInfo::INSERT_SUBREG, dl,
942 VT, SDValue(Pair, 0), V1, SubReg1);
943}
944
Dan Gohman475871a2008-07-27 21:46:04 +0000945SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000946 SDNode *N = Op.getNode();
Dale Johannesened2eee62009-02-06 01:31:28 +0000947 DebugLoc dl = N->getDebugLoc();
Evan Chenga8e29892007-01-19 07:51:42 +0000948
Dan Gohmane8be6c62008-07-17 19:10:17 +0000949 if (N->isMachineOpcode())
Evan Chenga8e29892007-01-19 07:51:42 +0000950 return NULL; // Already selected.
Rafael Espindola337c4ad62006-06-12 12:28:08 +0000951
952 switch (N->getOpcode()) {
Evan Chenga8e29892007-01-19 07:51:42 +0000953 default: break;
954 case ISD::Constant: {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000955 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000956 bool UseCP = true;
Anton Korobeynikov6a2fa322009-09-27 23:52:58 +0000957 if (Subtarget->hasThumb2())
958 // Thumb2-aware targets have the MOVT instruction, so all immediates can
959 // be done with MOV + MOVT, at worst.
960 UseCP = 0;
961 else {
962 if (Subtarget->isThumb()) {
Bob Wilsone64e3cf2009-06-22 17:29:13 +0000963 UseCP = (Val > 255 && // MOV
964 ~Val > 255 && // MOV + MVN
965 !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL
Anton Korobeynikov6a2fa322009-09-27 23:52:58 +0000966 } else
967 UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV
968 ARM_AM::getSOImmVal(~Val) == -1 && // MVN
969 !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs.
970 }
971
Evan Chenga8e29892007-01-19 07:51:42 +0000972 if (UseCP) {
Dan Gohman475871a2008-07-27 21:46:04 +0000973 SDValue CPIdx =
Owen Anderson1d0be152009-08-13 21:58:54 +0000974 CurDAG->getTargetConstantPool(ConstantInt::get(
975 Type::getInt32Ty(*CurDAG->getContext()), Val),
Evan Chenga8e29892007-01-19 07:51:42 +0000976 TLI.getPointerTy());
Evan Cheng012f2d92007-01-24 08:53:17 +0000977
978 SDNode *ResNode;
Evan Cheng446c4282009-07-11 06:43:01 +0000979 if (Subtarget->isThumb1Only()) {
Owen Anderson825b72b2009-08-11 20:47:22 +0000980 SDValue Pred = CurDAG->getTargetConstant(0xEULL, MVT::i32);
981 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Cheng446c4282009-07-11 06:43:01 +0000982 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Dan Gohman602b0c82009-09-25 18:54:59 +0000983 ResNode = CurDAG->getMachineNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other,
984 Ops, 4);
Evan Cheng446c4282009-07-11 06:43:01 +0000985 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000986 SDValue Ops[] = {
Jim Grosbach764ab522009-08-11 15:33:49 +0000987 CPIdx,
Owen Anderson825b72b2009-08-11 20:47:22 +0000988 CurDAG->getRegister(0, MVT::i32),
989 CurDAG->getTargetConstant(0, MVT::i32),
Evan Chengee568cf2007-07-05 07:15:27 +0000990 getAL(CurDAG),
Owen Anderson825b72b2009-08-11 20:47:22 +0000991 CurDAG->getRegister(0, MVT::i32),
Evan Cheng012f2d92007-01-24 08:53:17 +0000992 CurDAG->getEntryNode()
993 };
Dan Gohman602b0c82009-09-25 18:54:59 +0000994 ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
995 Ops, 6);
Evan Cheng012f2d92007-01-24 08:53:17 +0000996 }
Dan Gohman475871a2008-07-27 21:46:04 +0000997 ReplaceUses(Op, SDValue(ResNode, 0));
Evan Chenga8e29892007-01-19 07:51:42 +0000998 return NULL;
999 }
Jim Grosbach764ab522009-08-11 15:33:49 +00001000
Evan Chenga8e29892007-01-19 07:51:42 +00001001 // Other cases are autogenerated.
Rafael Espindola337c4ad62006-06-12 12:28:08 +00001002 break;
Evan Chenga8e29892007-01-19 07:51:42 +00001003 }
Rafael Espindolaf819a492006-11-09 13:58:55 +00001004 case ISD::FrameIndex: {
Evan Chenga8e29892007-01-19 07:51:42 +00001005 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindolaf819a492006-11-09 13:58:55 +00001006 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Dan Gohman475871a2008-07-27 21:46:04 +00001007 SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
David Goodwinf1daf7d2009-07-08 23:10:31 +00001008 if (Subtarget->isThumb1Only()) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001009 return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI,
1010 CurDAG->getTargetConstant(0, MVT::i32));
Jim Grosbach30eae3c2009-04-07 20:34:09 +00001011 } else {
David Goodwin419c6152009-07-14 18:48:51 +00001012 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
1013 ARM::t2ADDri : ARM::ADDri);
Owen Anderson825b72b2009-08-11 20:47:22 +00001014 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
1015 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
1016 CurDAG->getRegister(0, MVT::i32) };
1017 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Chengee568cf2007-07-05 07:15:27 +00001018 }
Evan Chenga8e29892007-01-19 07:51:42 +00001019 }
Evan Cheng86198642009-08-07 00:34:42 +00001020 case ARMISD::DYN_ALLOC:
1021 return SelectDYN_ALLOC(Op);
Evan Chenga8e29892007-01-19 07:51:42 +00001022 case ISD::MUL:
Evan Cheng5b9fcd12009-07-07 01:17:28 +00001023 if (Subtarget->isThumb1Only())
Evan Cheng79d43262007-01-24 02:21:22 +00001024 break;
Evan Chenga8e29892007-01-19 07:51:42 +00001025 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001026 unsigned RHSV = C->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +00001027 if (!RHSV) break;
1028 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Chengaf9e7a72009-07-21 00:31:12 +00001029 unsigned ShImm = Log2_32(RHSV-1);
1030 if (ShImm >= 32)
1031 break;
Dan Gohman475871a2008-07-27 21:46:04 +00001032 SDValue V = Op.getOperand(0);
Evan Chengaf9e7a72009-07-21 00:31:12 +00001033 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson825b72b2009-08-11 20:47:22 +00001034 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
1035 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng78dd9db2009-07-22 18:08:05 +00001036 if (Subtarget->isThumb()) {
Evan Chengaf9e7a72009-07-21 00:31:12 +00001037 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson825b72b2009-08-11 20:47:22 +00001038 return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6);
Evan Chengaf9e7a72009-07-21 00:31:12 +00001039 } else {
1040 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson825b72b2009-08-11 20:47:22 +00001041 return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7);
Evan Chengaf9e7a72009-07-21 00:31:12 +00001042 }
Evan Chenga8e29892007-01-19 07:51:42 +00001043 }
1044 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Chengaf9e7a72009-07-21 00:31:12 +00001045 unsigned ShImm = Log2_32(RHSV+1);
1046 if (ShImm >= 32)
1047 break;
Dan Gohman475871a2008-07-27 21:46:04 +00001048 SDValue V = Op.getOperand(0);
Evan Chengaf9e7a72009-07-21 00:31:12 +00001049 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson825b72b2009-08-11 20:47:22 +00001050 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
1051 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng78dd9db2009-07-22 18:08:05 +00001052 if (Subtarget->isThumb()) {
Evan Chengaf9e7a72009-07-21 00:31:12 +00001053 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0 };
Owen Anderson825b72b2009-08-11 20:47:22 +00001054 return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 5);
Evan Chengaf9e7a72009-07-21 00:31:12 +00001055 } else {
1056 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson825b72b2009-08-11 20:47:22 +00001057 return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7);
Evan Chengaf9e7a72009-07-21 00:31:12 +00001058 }
Evan Chenga8e29892007-01-19 07:51:42 +00001059 }
1060 }
1061 break;
1062 case ARMISD::FMRRD:
Dan Gohman602b0c82009-09-25 18:54:59 +00001063 return CurDAG->getMachineNode(ARM::FMRRD, dl, MVT::i32, MVT::i32,
1064 Op.getOperand(0), getAL(CurDAG),
1065 CurDAG->getRegister(0, MVT::i32));
Dan Gohman525178c2007-10-08 18:33:35 +00001066 case ISD::UMUL_LOHI: {
Evan Cheng5b9fcd12009-07-07 01:17:28 +00001067 if (Subtarget->isThumb1Only())
1068 break;
1069 if (Subtarget->isThumb()) {
1070 SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00001071 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
1072 CurDAG->getRegister(0, MVT::i32) };
Dan Gohman602b0c82009-09-25 18:54:59 +00001073 return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops,4);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00001074 } else {
1075 SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00001076 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
1077 CurDAG->getRegister(0, MVT::i32) };
Dan Gohman602b0c82009-09-25 18:54:59 +00001078 return CurDAG->getMachineNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00001079 }
Evan Chengee568cf2007-07-05 07:15:27 +00001080 }
Dan Gohman525178c2007-10-08 18:33:35 +00001081 case ISD::SMUL_LOHI: {
Evan Cheng5b9fcd12009-07-07 01:17:28 +00001082 if (Subtarget->isThumb1Only())
1083 break;
1084 if (Subtarget->isThumb()) {
1085 SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00001086 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
Dan Gohman602b0c82009-09-25 18:54:59 +00001087 return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops,4);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00001088 } else {
1089 SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00001090 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
1091 CurDAG->getRegister(0, MVT::i32) };
Dan Gohman602b0c82009-09-25 18:54:59 +00001092 return CurDAG->getMachineNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00001093 }
Evan Chengee568cf2007-07-05 07:15:27 +00001094 }
Evan Chenga8e29892007-01-19 07:51:42 +00001095 case ISD::LOAD: {
Evan Chenge88d5ce2009-07-02 07:28:31 +00001096 SDNode *ResNode = 0;
Evan Cheng5b9fcd12009-07-07 01:17:28 +00001097 if (Subtarget->isThumb() && Subtarget->hasThumb2())
Evan Chenge88d5ce2009-07-02 07:28:31 +00001098 ResNode = SelectT2IndexedLoad(Op);
1099 else
1100 ResNode = SelectARMIndexedLoad(Op);
Evan Chengaf4550f2009-07-02 01:23:32 +00001101 if (ResNode)
1102 return ResNode;
Evan Chenga8e29892007-01-19 07:51:42 +00001103 // Other cases are autogenerated.
Rafael Espindolaf819a492006-11-09 13:58:55 +00001104 break;
Rafael Espindola337c4ad62006-06-12 12:28:08 +00001105 }
Evan Chengee568cf2007-07-05 07:15:27 +00001106 case ARMISD::BRCOND: {
1107 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
1108 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
1109 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00001110
Evan Chengee568cf2007-07-05 07:15:27 +00001111 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
1112 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
1113 // Pattern complexity = 6 cost = 1 size = 0
1114
David Goodwin5e47a9a2009-06-30 18:04:13 +00001115 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
1116 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
1117 // Pattern complexity = 6 cost = 1 size = 0
1118
Jim Grosbach764ab522009-08-11 15:33:49 +00001119 unsigned Opc = Subtarget->isThumb() ?
David Goodwin5e47a9a2009-06-30 18:04:13 +00001120 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohman475871a2008-07-27 21:46:04 +00001121 SDValue Chain = Op.getOperand(0);
1122 SDValue N1 = Op.getOperand(1);
1123 SDValue N2 = Op.getOperand(2);
1124 SDValue N3 = Op.getOperand(3);
1125 SDValue InFlag = Op.getOperand(4);
Evan Chengee568cf2007-07-05 07:15:27 +00001126 assert(N1.getOpcode() == ISD::BasicBlock);
1127 assert(N2.getOpcode() == ISD::Constant);
1128 assert(N3.getOpcode() == ISD::Register);
1129
Dan Gohman475871a2008-07-27 21:46:04 +00001130 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001131 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00001132 MVT::i32);
Dan Gohman475871a2008-07-27 21:46:04 +00001133 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman602b0c82009-09-25 18:54:59 +00001134 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
1135 MVT::Flag, Ops, 5);
Dan Gohman475871a2008-07-27 21:46:04 +00001136 Chain = SDValue(ResNode, 0);
Gabor Greifba36cb52008-08-28 21:40:38 +00001137 if (Op.getNode()->getNumValues() == 2) {
Dan Gohman475871a2008-07-27 21:46:04 +00001138 InFlag = SDValue(ResNode, 1);
Gabor Greifba36cb52008-08-28 21:40:38 +00001139 ReplaceUses(SDValue(Op.getNode(), 1), InFlag);
Chris Lattnera47b9bc2008-02-03 03:20:59 +00001140 }
Gabor Greifba36cb52008-08-28 21:40:38 +00001141 ReplaceUses(SDValue(Op.getNode(), 0), SDValue(Chain.getNode(), Chain.getResNo()));
Evan Chengee568cf2007-07-05 07:15:27 +00001142 return NULL;
1143 }
1144 case ARMISD::CMOV: {
Owen Andersone50ed302009-08-10 22:56:29 +00001145 EVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001146 SDValue N0 = Op.getOperand(0);
1147 SDValue N1 = Op.getOperand(1);
1148 SDValue N2 = Op.getOperand(2);
1149 SDValue N3 = Op.getOperand(3);
1150 SDValue InFlag = Op.getOperand(4);
Evan Chengee568cf2007-07-05 07:15:27 +00001151 assert(N2.getOpcode() == ISD::Constant);
1152 assert(N3.getOpcode() == ISD::Register);
1153
Owen Anderson825b72b2009-08-11 20:47:22 +00001154 if (!Subtarget->isThumb1Only() && VT == MVT::i32) {
Evan Chenge253c952009-07-07 20:39:03 +00001155 // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
1156 // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
1157 // Pattern complexity = 18 cost = 1 size = 0
1158 SDValue CPTmp0;
1159 SDValue CPTmp1;
1160 SDValue CPTmp2;
1161 if (Subtarget->isThumb()) {
1162 if (SelectT2ShifterOperandReg(Op, N1, CPTmp0, CPTmp1)) {
Evan Cheng13f8b362009-08-01 01:43:45 +00001163 unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue();
1164 unsigned SOShOp = ARM_AM::getSORegShOp(SOVal);
1165 unsigned Opc = 0;
1166 switch (SOShOp) {
1167 case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break;
1168 case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break;
1169 case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break;
1170 case ARM_AM::ror: Opc = ARM::t2MOVCCror; break;
1171 default:
1172 llvm_unreachable("Unknown so_reg opcode!");
1173 break;
1174 }
1175 SDValue SOShImm =
Owen Anderson825b72b2009-08-11 20:47:22 +00001176 CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32);
Evan Chenge253c952009-07-07 20:39:03 +00001177 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
1178 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00001179 MVT::i32);
Evan Cheng13f8b362009-08-01 01:43:45 +00001180 SDValue Ops[] = { N0, CPTmp0, SOShImm, Tmp2, N3, InFlag };
Owen Anderson825b72b2009-08-11 20:47:22 +00001181 return CurDAG->SelectNodeTo(Op.getNode(), Opc, MVT::i32,Ops, 6);
Evan Chenge253c952009-07-07 20:39:03 +00001182 }
1183 } else {
1184 if (SelectShifterOperandReg(Op, N1, CPTmp0, CPTmp1, CPTmp2)) {
1185 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
1186 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00001187 MVT::i32);
Evan Chenge253c952009-07-07 20:39:03 +00001188 SDValue Ops[] = { N0, CPTmp0, CPTmp1, CPTmp2, Tmp2, N3, InFlag };
1189 return CurDAG->SelectNodeTo(Op.getNode(),
Owen Anderson825b72b2009-08-11 20:47:22 +00001190 ARM::MOVCCs, MVT::i32, Ops, 7);
Evan Chenge253c952009-07-07 20:39:03 +00001191 }
1192 }
Evan Chengee568cf2007-07-05 07:15:27 +00001193
Evan Chenge253c952009-07-07 20:39:03 +00001194 // Pattern: (ARMcmov:i32 GPR:i32:$false,
Evan Chenge7cbe412009-07-08 21:03:57 +00001195 // (imm:i32)<<P:Predicate_so_imm>>:$true,
Evan Chenge253c952009-07-07 20:39:03 +00001196 // (imm:i32):$cc)
1197 // Emits: (MOVCCi:i32 GPR:i32:$false,
Evan Chenge7cbe412009-07-08 21:03:57 +00001198 // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc)
Evan Chenge253c952009-07-07 20:39:03 +00001199 // Pattern complexity = 10 cost = 1 size = 0
1200 if (N3.getOpcode() == ISD::Constant) {
1201 if (Subtarget->isThumb()) {
1202 if (Predicate_t2_so_imm(N3.getNode())) {
1203 SDValue Tmp1 = CurDAG->getTargetConstant(((unsigned)
1204 cast<ConstantSDNode>(N1)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00001205 MVT::i32);
Evan Chenge253c952009-07-07 20:39:03 +00001206 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
1207 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00001208 MVT::i32);
Evan Chenge253c952009-07-07 20:39:03 +00001209 SDValue Ops[] = { N0, Tmp1, Tmp2, N3, InFlag };
1210 return CurDAG->SelectNodeTo(Op.getNode(),
Owen Anderson825b72b2009-08-11 20:47:22 +00001211 ARM::t2MOVCCi, MVT::i32, Ops, 5);
Evan Chenge253c952009-07-07 20:39:03 +00001212 }
1213 } else {
1214 if (Predicate_so_imm(N3.getNode())) {
1215 SDValue Tmp1 = CurDAG->getTargetConstant(((unsigned)
1216 cast<ConstantSDNode>(N1)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00001217 MVT::i32);
Evan Chenge253c952009-07-07 20:39:03 +00001218 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
1219 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00001220 MVT::i32);
Evan Chenge253c952009-07-07 20:39:03 +00001221 SDValue Ops[] = { N0, Tmp1, Tmp2, N3, InFlag };
1222 return CurDAG->SelectNodeTo(Op.getNode(),
Owen Anderson825b72b2009-08-11 20:47:22 +00001223 ARM::MOVCCi, MVT::i32, Ops, 5);
Evan Chenge253c952009-07-07 20:39:03 +00001224 }
1225 }
1226 }
Evan Chengee568cf2007-07-05 07:15:27 +00001227 }
1228
1229 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
1230 // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
1231 // Pattern complexity = 6 cost = 1 size = 0
1232 //
1233 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
1234 // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
1235 // Pattern complexity = 6 cost = 11 size = 0
1236 //
1237 // Also FCPYScc and FCPYDcc.
Dan Gohman475871a2008-07-27 21:46:04 +00001238 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001239 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00001240 MVT::i32);
Dan Gohman475871a2008-07-27 21:46:04 +00001241 SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag };
Evan Chengee568cf2007-07-05 07:15:27 +00001242 unsigned Opc = 0;
Owen Anderson825b72b2009-08-11 20:47:22 +00001243 switch (VT.getSimpleVT().SimpleTy) {
Evan Chengee568cf2007-07-05 07:15:27 +00001244 default: assert(false && "Illegal conditional move type!");
1245 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001246 case MVT::i32:
Evan Chenge253c952009-07-07 20:39:03 +00001247 Opc = Subtarget->isThumb()
Evan Cheng007ea272009-08-12 05:17:19 +00001248 ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo)
Evan Chenge253c952009-07-07 20:39:03 +00001249 : ARM::MOVCCr;
Evan Chengee568cf2007-07-05 07:15:27 +00001250 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001251 case MVT::f32:
Evan Chengee568cf2007-07-05 07:15:27 +00001252 Opc = ARM::FCPYScc;
1253 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001254 case MVT::f64:
Evan Chengee568cf2007-07-05 07:15:27 +00001255 Opc = ARM::FCPYDcc;
Jim Grosbach764ab522009-08-11 15:33:49 +00001256 break;
Evan Chengee568cf2007-07-05 07:15:27 +00001257 }
Gabor Greifba36cb52008-08-28 21:40:38 +00001258 return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5);
Evan Chengee568cf2007-07-05 07:15:27 +00001259 }
1260 case ARMISD::CNEG: {
Owen Andersone50ed302009-08-10 22:56:29 +00001261 EVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001262 SDValue N0 = Op.getOperand(0);
1263 SDValue N1 = Op.getOperand(1);
1264 SDValue N2 = Op.getOperand(2);
1265 SDValue N3 = Op.getOperand(3);
1266 SDValue InFlag = Op.getOperand(4);
Evan Chengee568cf2007-07-05 07:15:27 +00001267 assert(N2.getOpcode() == ISD::Constant);
1268 assert(N3.getOpcode() == ISD::Register);
1269
Dan Gohman475871a2008-07-27 21:46:04 +00001270 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001271 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00001272 MVT::i32);
Dan Gohman475871a2008-07-27 21:46:04 +00001273 SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag };
Evan Chengee568cf2007-07-05 07:15:27 +00001274 unsigned Opc = 0;
Owen Anderson825b72b2009-08-11 20:47:22 +00001275 switch (VT.getSimpleVT().SimpleTy) {
Evan Chengee568cf2007-07-05 07:15:27 +00001276 default: assert(false && "Illegal conditional move type!");
1277 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001278 case MVT::f32:
Evan Chengee568cf2007-07-05 07:15:27 +00001279 Opc = ARM::FNEGScc;
1280 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001281 case MVT::f64:
Evan Chengee568cf2007-07-05 07:15:27 +00001282 Opc = ARM::FNEGDcc;
Evan Chenge5ad88e2008-12-10 21:54:21 +00001283 break;
Evan Chengee568cf2007-07-05 07:15:27 +00001284 }
Gabor Greifba36cb52008-08-28 21:40:38 +00001285 return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5);
Evan Chengee568cf2007-07-05 07:15:27 +00001286 }
Evan Chenge5ad88e2008-12-10 21:54:21 +00001287
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00001288 case ARMISD::VZIP: {
1289 unsigned Opc = 0;
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00001290 EVT VT = N->getValueType(0);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00001291 switch (VT.getSimpleVT().SimpleTy) {
1292 default: return NULL;
1293 case MVT::v8i8: Opc = ARM::VZIPd8; break;
1294 case MVT::v4i16: Opc = ARM::VZIPd16; break;
1295 case MVT::v2f32:
1296 case MVT::v2i32: Opc = ARM::VZIPd32; break;
1297 case MVT::v16i8: Opc = ARM::VZIPq8; break;
1298 case MVT::v8i16: Opc = ARM::VZIPq16; break;
1299 case MVT::v4f32:
1300 case MVT::v4i32: Opc = ARM::VZIPq32; break;
1301 }
Dan Gohman602b0c82009-09-25 18:54:59 +00001302 return CurDAG->getMachineNode(Opc, dl, VT, VT,
1303 N->getOperand(0), N->getOperand(1));
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00001304 }
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00001305 case ARMISD::VUZP: {
1306 unsigned Opc = 0;
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00001307 EVT VT = N->getValueType(0);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00001308 switch (VT.getSimpleVT().SimpleTy) {
1309 default: return NULL;
1310 case MVT::v8i8: Opc = ARM::VUZPd8; break;
1311 case MVT::v4i16: Opc = ARM::VUZPd16; break;
1312 case MVT::v2f32:
1313 case MVT::v2i32: Opc = ARM::VUZPd32; break;
1314 case MVT::v16i8: Opc = ARM::VUZPq8; break;
1315 case MVT::v8i16: Opc = ARM::VUZPq16; break;
1316 case MVT::v4f32:
1317 case MVT::v4i32: Opc = ARM::VUZPq32; break;
1318 }
Dan Gohman602b0c82009-09-25 18:54:59 +00001319 return CurDAG->getMachineNode(Opc, dl, VT, VT,
1320 N->getOperand(0), N->getOperand(1));
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00001321 }
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00001322 case ARMISD::VTRN: {
1323 unsigned Opc = 0;
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00001324 EVT VT = N->getValueType(0);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00001325 switch (VT.getSimpleVT().SimpleTy) {
1326 default: return NULL;
1327 case MVT::v8i8: Opc = ARM::VTRNd8; break;
1328 case MVT::v4i16: Opc = ARM::VTRNd16; break;
1329 case MVT::v2f32:
1330 case MVT::v2i32: Opc = ARM::VTRNd32; break;
1331 case MVT::v16i8: Opc = ARM::VTRNq8; break;
1332 case MVT::v8i16: Opc = ARM::VTRNq16; break;
1333 case MVT::v4f32:
1334 case MVT::v4i32: Opc = ARM::VTRNq32; break;
1335 }
Dan Gohman602b0c82009-09-25 18:54:59 +00001336 return CurDAG->getMachineNode(Opc, dl, VT, VT,
1337 N->getOperand(0), N->getOperand(1));
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00001338 }
Bob Wilson31fb12f2009-08-26 17:39:53 +00001339
1340 case ISD::INTRINSIC_VOID:
1341 case ISD::INTRINSIC_W_CHAIN: {
1342 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
1343 EVT VT = N->getValueType(0);
1344 unsigned Opc = 0;
1345
1346 switch (IntNo) {
1347 default:
1348 break;
1349
1350 case Intrinsic::arm_neon_vld2: {
1351 SDValue MemAddr, MemUpdate, MemOpc;
1352 if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc))
1353 return NULL;
Bob Wilson228c08b2009-10-07 17:23:09 +00001354 if (VT.is64BitVector()) {
1355 switch (VT.getSimpleVT().SimpleTy) {
1356 default: llvm_unreachable("unhandled vld2 type");
1357 case MVT::v8i8: Opc = ARM::VLD2d8; break;
1358 case MVT::v4i16: Opc = ARM::VLD2d16; break;
1359 case MVT::v2f32:
1360 case MVT::v2i32: Opc = ARM::VLD2d32; break;
Bob Wilsona4288082009-10-07 22:57:01 +00001361 case MVT::v1i64: Opc = ARM::VLD2d64; break;
Bob Wilson228c08b2009-10-07 17:23:09 +00001362 }
1363 SDValue Chain = N->getOperand(0);
1364 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Chain };
1365 return CurDAG->getMachineNode(Opc, dl, VT, VT, MVT::Other, Ops, 4);
1366 }
1367 // Quad registers are loaded as pairs of double registers.
1368 EVT RegVT;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001369 switch (VT.getSimpleVT().SimpleTy) {
1370 default: llvm_unreachable("unhandled vld2 type");
Bob Wilson3bf12ab2009-10-06 22:01:59 +00001371 case MVT::v16i8: Opc = ARM::VLD2q8; RegVT = MVT::v8i8; break;
1372 case MVT::v8i16: Opc = ARM::VLD2q16; RegVT = MVT::v4i16; break;
1373 case MVT::v4f32: Opc = ARM::VLD2q32; RegVT = MVT::v2f32; break;
1374 case MVT::v4i32: Opc = ARM::VLD2q32; RegVT = MVT::v2i32; break;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001375 }
1376 SDValue Chain = N->getOperand(0);
1377 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Chain };
Bob Wilson3bf12ab2009-10-06 22:01:59 +00001378 std::vector<EVT> ResTys(4, RegVT);
1379 ResTys.push_back(MVT::Other);
1380 SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 4);
1381 SDNode *Q0 = PairDRegs(VT, SDValue(VLd, 0), SDValue(VLd, 1));
1382 SDNode *Q1 = PairDRegs(VT, SDValue(VLd, 2), SDValue(VLd, 3));
1383 ReplaceUses(SDValue(N, 0), SDValue(Q0, 0));
1384 ReplaceUses(SDValue(N, 1), SDValue(Q1, 0));
1385 ReplaceUses(SDValue(N, 2), SDValue(VLd, 4));
1386 return NULL;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001387 }
1388
1389 case Intrinsic::arm_neon_vld3: {
1390 SDValue MemAddr, MemUpdate, MemOpc;
1391 if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc))
1392 return NULL;
Bob Wilsonff8952e2009-10-07 17:24:55 +00001393 if (VT.is64BitVector()) {
1394 switch (VT.getSimpleVT().SimpleTy) {
1395 default: llvm_unreachable("unhandled vld3 type");
1396 case MVT::v8i8: Opc = ARM::VLD3d8; break;
1397 case MVT::v4i16: Opc = ARM::VLD3d16; break;
1398 case MVT::v2f32:
1399 case MVT::v2i32: Opc = ARM::VLD3d32; break;
Bob Wilsonc67160c2009-10-07 23:39:57 +00001400 case MVT::v1i64: Opc = ARM::VLD3d64; break;
Bob Wilsonff8952e2009-10-07 17:24:55 +00001401 }
1402 SDValue Chain = N->getOperand(0);
1403 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Chain };
1404 return CurDAG->getMachineNode(Opc, dl, VT, VT, VT, MVT::Other, Ops, 4);
1405 }
1406 // Quad registers are loaded with two separate instructions, where one
1407 // loads the even registers and the other loads the odd registers.
Bob Wilsoncd7e3272009-10-08 18:52:56 +00001408 EVT RegVT;
Bob Wilsonff8952e2009-10-07 17:24:55 +00001409 unsigned Opc2 = 0;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001410 switch (VT.getSimpleVT().SimpleTy) {
1411 default: llvm_unreachable("unhandled vld3 type");
Bob Wilsonff8952e2009-10-07 17:24:55 +00001412 case MVT::v16i8:
1413 Opc = ARM::VLD3q8a; Opc2 = ARM::VLD3q8b; RegVT = MVT::v8i8; break;
1414 case MVT::v8i16:
1415 Opc = ARM::VLD3q16a; Opc2 = ARM::VLD3q16b; RegVT = MVT::v4i16; break;
1416 case MVT::v4f32:
1417 Opc = ARM::VLD3q32a; Opc2 = ARM::VLD3q32b; RegVT = MVT::v2f32; break;
1418 case MVT::v4i32:
1419 Opc = ARM::VLD3q32a; Opc2 = ARM::VLD3q32b; RegVT = MVT::v2i32; break;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001420 }
1421 SDValue Chain = N->getOperand(0);
Bob Wilsonff8952e2009-10-07 17:24:55 +00001422 // Enable writeback to the address register.
1423 MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32);
1424
1425 std::vector<EVT> ResTys(3, RegVT);
1426 ResTys.push_back(MemAddr.getValueType());
1427 ResTys.push_back(MVT::Other);
1428
1429 const SDValue OpsA[] = { MemAddr, MemUpdate, MemOpc, Chain };
1430 SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 4);
1431 Chain = SDValue(VLdA, 4);
1432
1433 const SDValue OpsB[] = { SDValue(VLdA, 3), MemUpdate, MemOpc, Chain };
1434 SDNode *VLdB = CurDAG->getMachineNode(Opc2, dl, ResTys, OpsB, 4);
1435 Chain = SDValue(VLdB, 4);
1436
1437 SDNode *Q0 = PairDRegs(VT, SDValue(VLdA, 0), SDValue(VLdB, 0));
1438 SDNode *Q1 = PairDRegs(VT, SDValue(VLdA, 1), SDValue(VLdB, 1));
1439 SDNode *Q2 = PairDRegs(VT, SDValue(VLdA, 2), SDValue(VLdB, 2));
1440 ReplaceUses(SDValue(N, 0), SDValue(Q0, 0));
1441 ReplaceUses(SDValue(N, 1), SDValue(Q1, 0));
1442 ReplaceUses(SDValue(N, 2), SDValue(Q2, 0));
1443 ReplaceUses(SDValue(N, 3), Chain);
1444 return NULL;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001445 }
1446
1447 case Intrinsic::arm_neon_vld4: {
1448 SDValue MemAddr, MemUpdate, MemOpc;
1449 if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc))
1450 return NULL;
Bob Wilson7708c222009-10-07 18:09:32 +00001451 if (VT.is64BitVector()) {
1452 switch (VT.getSimpleVT().SimpleTy) {
1453 default: llvm_unreachable("unhandled vld4 type");
1454 case MVT::v8i8: Opc = ARM::VLD4d8; break;
1455 case MVT::v4i16: Opc = ARM::VLD4d16; break;
1456 case MVT::v2f32:
1457 case MVT::v2i32: Opc = ARM::VLD4d32; break;
Bob Wilson0ea38bb2009-10-07 23:54:04 +00001458 case MVT::v1i64: Opc = ARM::VLD4d64; break;
Bob Wilson7708c222009-10-07 18:09:32 +00001459 }
1460 SDValue Chain = N->getOperand(0);
1461 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Chain };
1462 std::vector<EVT> ResTys(4, VT);
1463 ResTys.push_back(MVT::Other);
1464 return CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 4);
1465 }
1466 // Quad registers are loaded with two separate instructions, where one
1467 // loads the even registers and the other loads the odd registers.
Bob Wilsoncd7e3272009-10-08 18:52:56 +00001468 EVT RegVT;
Bob Wilson7708c222009-10-07 18:09:32 +00001469 unsigned Opc2 = 0;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001470 switch (VT.getSimpleVT().SimpleTy) {
1471 default: llvm_unreachable("unhandled vld4 type");
Bob Wilson7708c222009-10-07 18:09:32 +00001472 case MVT::v16i8:
1473 Opc = ARM::VLD4q8a; Opc2 = ARM::VLD4q8b; RegVT = MVT::v8i8; break;
1474 case MVT::v8i16:
1475 Opc = ARM::VLD4q16a; Opc2 = ARM::VLD4q16b; RegVT = MVT::v4i16; break;
1476 case MVT::v4f32:
1477 Opc = ARM::VLD4q32a; Opc2 = ARM::VLD4q32b; RegVT = MVT::v2f32; break;
1478 case MVT::v4i32:
1479 Opc = ARM::VLD4q32a; Opc2 = ARM::VLD4q32b; RegVT = MVT::v2i32; break;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001480 }
1481 SDValue Chain = N->getOperand(0);
Bob Wilson7708c222009-10-07 18:09:32 +00001482 // Enable writeback to the address register.
1483 MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32);
1484
1485 std::vector<EVT> ResTys(4, RegVT);
1486 ResTys.push_back(MemAddr.getValueType());
Bob Wilson31fb12f2009-08-26 17:39:53 +00001487 ResTys.push_back(MVT::Other);
Bob Wilson7708c222009-10-07 18:09:32 +00001488
1489 const SDValue OpsA[] = { MemAddr, MemUpdate, MemOpc, Chain };
1490 SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 4);
1491 Chain = SDValue(VLdA, 5);
1492
1493 const SDValue OpsB[] = { SDValue(VLdA, 4), MemUpdate, MemOpc, Chain };
1494 SDNode *VLdB = CurDAG->getMachineNode(Opc2, dl, ResTys, OpsB, 4);
1495 Chain = SDValue(VLdB, 5);
1496
1497 SDNode *Q0 = PairDRegs(VT, SDValue(VLdA, 0), SDValue(VLdB, 0));
1498 SDNode *Q1 = PairDRegs(VT, SDValue(VLdA, 1), SDValue(VLdB, 1));
1499 SDNode *Q2 = PairDRegs(VT, SDValue(VLdA, 2), SDValue(VLdB, 2));
1500 SDNode *Q3 = PairDRegs(VT, SDValue(VLdA, 3), SDValue(VLdB, 3));
1501 ReplaceUses(SDValue(N, 0), SDValue(Q0, 0));
1502 ReplaceUses(SDValue(N, 1), SDValue(Q1, 0));
1503 ReplaceUses(SDValue(N, 2), SDValue(Q2, 0));
1504 ReplaceUses(SDValue(N, 3), SDValue(Q3, 0));
1505 ReplaceUses(SDValue(N, 4), Chain);
1506 return NULL;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001507 }
1508
Bob Wilson243fcc52009-09-01 04:26:28 +00001509 case Intrinsic::arm_neon_vld2lane: {
1510 SDValue MemAddr, MemUpdate, MemOpc;
1511 if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc))
1512 return NULL;
Bob Wilson30aea9d2009-10-08 18:56:10 +00001513 if (VT.is64BitVector()) {
1514 switch (VT.getSimpleVT().SimpleTy) {
1515 default: llvm_unreachable("unhandled vld2lane type");
1516 case MVT::v8i8: Opc = ARM::VLD2LNd8; break;
1517 case MVT::v4i16: Opc = ARM::VLD2LNd16; break;
1518 case MVT::v2f32:
1519 case MVT::v2i32: Opc = ARM::VLD2LNd32; break;
1520 }
1521 SDValue Chain = N->getOperand(0);
1522 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc,
1523 N->getOperand(3), N->getOperand(4),
1524 N->getOperand(5), Chain };
1525 return CurDAG->getMachineNode(Opc, dl, VT, VT, MVT::Other, Ops, 7);
1526 }
1527 // Quad registers are handled by extracting subregs, doing the load,
1528 // and then inserting the results as subregs.
1529 EVT RegVT;
1530 unsigned Opc2 = 0;
Bob Wilson243fcc52009-09-01 04:26:28 +00001531 switch (VT.getSimpleVT().SimpleTy) {
1532 default: llvm_unreachable("unhandled vld2lane type");
Bob Wilson30aea9d2009-10-08 18:56:10 +00001533 case MVT::v8i16:
1534 Opc = ARM::VLD2LNq16a;
1535 Opc2 = ARM::VLD2LNq16b;
1536 RegVT = MVT::v4i16;
1537 break;
1538 case MVT::v4f32:
1539 Opc = ARM::VLD2LNq32a;
1540 Opc2 = ARM::VLD2LNq32b;
1541 RegVT = MVT::v2f32;
1542 break;
1543 case MVT::v4i32:
1544 Opc = ARM::VLD2LNq32a;
1545 Opc2 = ARM::VLD2LNq32b;
1546 RegVT = MVT::v2i32;
1547 break;
Bob Wilson243fcc52009-09-01 04:26:28 +00001548 }
1549 SDValue Chain = N->getOperand(0);
Bob Wilson30aea9d2009-10-08 18:56:10 +00001550 unsigned Lane = cast<ConstantSDNode>(N->getOperand(5))->getZExtValue();
1551 unsigned NumElts = RegVT.getVectorNumElements();
1552 int SubregIdx = (Lane < NumElts) ? ARM::DSUBREG_0 : ARM::DSUBREG_1;
1553
1554 SDValue D0 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1555 N->getOperand(3));
1556 SDValue D1 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1557 N->getOperand(4));
1558 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, D0, D1,
1559 getI32Imm(Lane % NumElts), Chain };
1560 SDNode *VLdLn = CurDAG->getMachineNode((Lane < NumElts) ? Opc : Opc2,
1561 dl, RegVT, RegVT, MVT::Other,
1562 Ops, 7);
1563 SDValue Q0 = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT,
1564 N->getOperand(3),
1565 SDValue(VLdLn, 0));
1566 SDValue Q1 = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT,
1567 N->getOperand(4),
1568 SDValue(VLdLn, 1));
1569 Chain = SDValue(VLdLn, 2);
1570 ReplaceUses(SDValue(N, 0), Q0);
1571 ReplaceUses(SDValue(N, 1), Q1);
1572 ReplaceUses(SDValue(N, 2), Chain);
1573 return NULL;
Bob Wilson243fcc52009-09-01 04:26:28 +00001574 }
1575
1576 case Intrinsic::arm_neon_vld3lane: {
1577 SDValue MemAddr, MemUpdate, MemOpc;
1578 if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc))
1579 return NULL;
Bob Wilson0bf7d992009-10-08 22:27:33 +00001580 if (VT.is64BitVector()) {
1581 switch (VT.getSimpleVT().SimpleTy) {
1582 default: llvm_unreachable("unhandled vld3lane type");
1583 case MVT::v8i8: Opc = ARM::VLD3LNd8; break;
1584 case MVT::v4i16: Opc = ARM::VLD3LNd16; break;
1585 case MVT::v2f32:
1586 case MVT::v2i32: Opc = ARM::VLD3LNd32; break;
1587 }
1588 SDValue Chain = N->getOperand(0);
1589 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc,
1590 N->getOperand(3), N->getOperand(4),
1591 N->getOperand(5), N->getOperand(6), Chain };
1592 return CurDAG->getMachineNode(Opc, dl, VT, VT, VT, MVT::Other, Ops, 8);
1593 }
1594 // Quad registers are handled by extracting subregs, doing the load,
1595 // and then inserting the results as subregs.
1596 EVT RegVT;
1597 unsigned Opc2 = 0;
Bob Wilson243fcc52009-09-01 04:26:28 +00001598 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson62e053e2009-10-08 22:53:57 +00001599 default: llvm_unreachable("unhandled vld3lane type");
Bob Wilson0bf7d992009-10-08 22:27:33 +00001600 case MVT::v8i16:
1601 Opc = ARM::VLD3LNq16a;
1602 Opc2 = ARM::VLD3LNq16b;
1603 RegVT = MVT::v4i16;
1604 break;
1605 case MVT::v4f32:
1606 Opc = ARM::VLD3LNq32a;
1607 Opc2 = ARM::VLD3LNq32b;
1608 RegVT = MVT::v2f32;
1609 break;
1610 case MVT::v4i32:
1611 Opc = ARM::VLD3LNq32a;
1612 Opc2 = ARM::VLD3LNq32b;
1613 RegVT = MVT::v2i32;
1614 break;
Bob Wilson243fcc52009-09-01 04:26:28 +00001615 }
1616 SDValue Chain = N->getOperand(0);
Bob Wilson0bf7d992009-10-08 22:27:33 +00001617 unsigned Lane = cast<ConstantSDNode>(N->getOperand(6))->getZExtValue();
1618 unsigned NumElts = RegVT.getVectorNumElements();
1619 int SubregIdx = (Lane < NumElts) ? ARM::DSUBREG_0 : ARM::DSUBREG_1;
1620
1621 SDValue D0 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1622 N->getOperand(3));
1623 SDValue D1 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1624 N->getOperand(4));
1625 SDValue D2 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1626 N->getOperand(5));
1627 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, D0, D1, D2,
1628 getI32Imm(Lane % NumElts), Chain };
1629 SDNode *VLdLn = CurDAG->getMachineNode((Lane < NumElts) ? Opc : Opc2,
1630 dl, RegVT, RegVT, RegVT,
1631 MVT::Other, Ops, 8);
1632 SDValue Q0 = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT,
1633 N->getOperand(3),
1634 SDValue(VLdLn, 0));
1635 SDValue Q1 = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT,
1636 N->getOperand(4),
1637 SDValue(VLdLn, 1));
1638 SDValue Q2 = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT,
1639 N->getOperand(5),
1640 SDValue(VLdLn, 2));
1641 Chain = SDValue(VLdLn, 3);
1642 ReplaceUses(SDValue(N, 0), Q0);
1643 ReplaceUses(SDValue(N, 1), Q1);
1644 ReplaceUses(SDValue(N, 2), Q2);
1645 ReplaceUses(SDValue(N, 3), Chain);
1646 return NULL;
Bob Wilson243fcc52009-09-01 04:26:28 +00001647 }
1648
1649 case Intrinsic::arm_neon_vld4lane: {
1650 SDValue MemAddr, MemUpdate, MemOpc;
1651 if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc))
1652 return NULL;
Bob Wilson62e053e2009-10-08 22:53:57 +00001653 if (VT.is64BitVector()) {
1654 switch (VT.getSimpleVT().SimpleTy) {
1655 default: llvm_unreachable("unhandled vld4lane type");
1656 case MVT::v8i8: Opc = ARM::VLD4LNd8; break;
1657 case MVT::v4i16: Opc = ARM::VLD4LNd16; break;
1658 case MVT::v2f32:
1659 case MVT::v2i32: Opc = ARM::VLD4LNd32; break;
1660 }
1661 SDValue Chain = N->getOperand(0);
1662 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc,
1663 N->getOperand(3), N->getOperand(4),
1664 N->getOperand(5), N->getOperand(6),
1665 N->getOperand(7), Chain };
1666 std::vector<EVT> ResTys(4, VT);
1667 ResTys.push_back(MVT::Other);
1668 return CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 9);
1669 }
1670 // Quad registers are handled by extracting subregs, doing the load,
1671 // and then inserting the results as subregs.
1672 EVT RegVT;
1673 unsigned Opc2 = 0;
Bob Wilson243fcc52009-09-01 04:26:28 +00001674 switch (VT.getSimpleVT().SimpleTy) {
1675 default: llvm_unreachable("unhandled vld4lane type");
Bob Wilson62e053e2009-10-08 22:53:57 +00001676 case MVT::v8i16:
1677 Opc = ARM::VLD4LNq16a;
1678 Opc2 = ARM::VLD4LNq16b;
1679 RegVT = MVT::v4i16;
1680 break;
1681 case MVT::v4f32:
1682 Opc = ARM::VLD4LNq32a;
1683 Opc2 = ARM::VLD4LNq32b;
1684 RegVT = MVT::v2f32;
1685 break;
1686 case MVT::v4i32:
1687 Opc = ARM::VLD4LNq32a;
1688 Opc2 = ARM::VLD4LNq32b;
1689 RegVT = MVT::v2i32;
1690 break;
Bob Wilson243fcc52009-09-01 04:26:28 +00001691 }
1692 SDValue Chain = N->getOperand(0);
Bob Wilson62e053e2009-10-08 22:53:57 +00001693 unsigned Lane = cast<ConstantSDNode>(N->getOperand(7))->getZExtValue();
1694 unsigned NumElts = RegVT.getVectorNumElements();
1695 int SubregIdx = (Lane < NumElts) ? ARM::DSUBREG_0 : ARM::DSUBREG_1;
1696
1697 SDValue D0 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1698 N->getOperand(3));
1699 SDValue D1 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1700 N->getOperand(4));
1701 SDValue D2 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1702 N->getOperand(5));
1703 SDValue D3 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1704 N->getOperand(6));
1705 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, D0, D1, D2, D3,
1706 getI32Imm(Lane % NumElts), Chain };
1707 std::vector<EVT> ResTys(4, RegVT);
Bob Wilson243fcc52009-09-01 04:26:28 +00001708 ResTys.push_back(MVT::Other);
Bob Wilson62e053e2009-10-08 22:53:57 +00001709 SDNode *VLdLn = CurDAG->getMachineNode((Lane < NumElts) ? Opc : Opc2,
1710 dl, ResTys, Ops, 9);
1711 SDValue Q0 = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT,
1712 N->getOperand(3),
1713 SDValue(VLdLn, 0));
1714 SDValue Q1 = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT,
1715 N->getOperand(4),
1716 SDValue(VLdLn, 1));
1717 SDValue Q2 = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT,
1718 N->getOperand(5),
1719 SDValue(VLdLn, 2));
1720 SDValue Q3 = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT,
1721 N->getOperand(6),
1722 SDValue(VLdLn, 3));
1723 Chain = SDValue(VLdLn, 4);
1724 ReplaceUses(SDValue(N, 0), Q0);
1725 ReplaceUses(SDValue(N, 1), Q1);
1726 ReplaceUses(SDValue(N, 2), Q2);
1727 ReplaceUses(SDValue(N, 3), Q3);
1728 ReplaceUses(SDValue(N, 4), Chain);
1729 return NULL;
Bob Wilson243fcc52009-09-01 04:26:28 +00001730 }
1731
Bob Wilson31fb12f2009-08-26 17:39:53 +00001732 case Intrinsic::arm_neon_vst2: {
1733 SDValue MemAddr, MemUpdate, MemOpc;
1734 if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc))
1735 return NULL;
Bob Wilsond2855752009-10-07 18:47:39 +00001736 VT = N->getOperand(3).getValueType();
1737 if (VT.is64BitVector()) {
1738 switch (VT.getSimpleVT().SimpleTy) {
1739 default: llvm_unreachable("unhandled vst2 type");
1740 case MVT::v8i8: Opc = ARM::VST2d8; break;
1741 case MVT::v4i16: Opc = ARM::VST2d16; break;
1742 case MVT::v2f32:
1743 case MVT::v2i32: Opc = ARM::VST2d32; break;
Bob Wilson24e04c52009-10-08 00:21:01 +00001744 case MVT::v1i64: Opc = ARM::VST2d64; break;
Bob Wilsond2855752009-10-07 18:47:39 +00001745 }
1746 SDValue Chain = N->getOperand(0);
1747 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc,
1748 N->getOperand(3), N->getOperand(4), Chain };
1749 return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 6);
1750 }
1751 // Quad registers are stored as pairs of double registers.
1752 EVT RegVT;
1753 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson31fb12f2009-08-26 17:39:53 +00001754 default: llvm_unreachable("unhandled vst2 type");
Bob Wilsond2855752009-10-07 18:47:39 +00001755 case MVT::v16i8: Opc = ARM::VST2q8; RegVT = MVT::v8i8; break;
1756 case MVT::v8i16: Opc = ARM::VST2q16; RegVT = MVT::v4i16; break;
1757 case MVT::v4f32: Opc = ARM::VST2q32; RegVT = MVT::v2f32; break;
1758 case MVT::v4i32: Opc = ARM::VST2q32; RegVT = MVT::v2i32; break;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001759 }
1760 SDValue Chain = N->getOperand(0);
Bob Wilsond2855752009-10-07 18:47:39 +00001761 SDValue D0 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT,
1762 N->getOperand(3));
1763 SDValue D1 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
1764 N->getOperand(3));
1765 SDValue D2 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT,
1766 N->getOperand(4));
1767 SDValue D3 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
1768 N->getOperand(4));
Bob Wilson31fb12f2009-08-26 17:39:53 +00001769 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc,
Bob Wilsond2855752009-10-07 18:47:39 +00001770 D0, D1, D2, D3, Chain };
1771 return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 8);
Bob Wilson31fb12f2009-08-26 17:39:53 +00001772 }
1773
1774 case Intrinsic::arm_neon_vst3: {
1775 SDValue MemAddr, MemUpdate, MemOpc;
1776 if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc))
1777 return NULL;
Bob Wilson66a70632009-10-07 20:30:08 +00001778 VT = N->getOperand(3).getValueType();
1779 if (VT.is64BitVector()) {
1780 switch (VT.getSimpleVT().SimpleTy) {
1781 default: llvm_unreachable("unhandled vst3 type");
1782 case MVT::v8i8: Opc = ARM::VST3d8; break;
1783 case MVT::v4i16: Opc = ARM::VST3d16; break;
1784 case MVT::v2f32:
1785 case MVT::v2i32: Opc = ARM::VST3d32; break;
Bob Wilson5adf60c2009-10-08 00:28:28 +00001786 case MVT::v1i64: Opc = ARM::VST3d64; break;
Bob Wilson66a70632009-10-07 20:30:08 +00001787 }
1788 SDValue Chain = N->getOperand(0);
1789 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc,
1790 N->getOperand(3), N->getOperand(4),
1791 N->getOperand(5), Chain };
1792 return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 7);
1793 }
1794 // Quad registers are stored with two separate instructions, where one
1795 // stores the even registers and the other stores the odd registers.
1796 EVT RegVT;
1797 unsigned Opc2 = 0;
1798 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson31fb12f2009-08-26 17:39:53 +00001799 default: llvm_unreachable("unhandled vst3 type");
Bob Wilson66a70632009-10-07 20:30:08 +00001800 case MVT::v16i8:
1801 Opc = ARM::VST3q8a; Opc2 = ARM::VST3q8b; RegVT = MVT::v8i8; break;
1802 case MVT::v8i16:
1803 Opc = ARM::VST3q16a; Opc2 = ARM::VST3q16b; RegVT = MVT::v4i16; break;
1804 case MVT::v4f32:
1805 Opc = ARM::VST3q32a; Opc2 = ARM::VST3q32b; RegVT = MVT::v2f32; break;
1806 case MVT::v4i32:
1807 Opc = ARM::VST3q32a; Opc2 = ARM::VST3q32b; RegVT = MVT::v2i32; break;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001808 }
1809 SDValue Chain = N->getOperand(0);
Bob Wilson66a70632009-10-07 20:30:08 +00001810 // Enable writeback to the address register.
1811 MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32);
1812
1813 SDValue D0 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT,
1814 N->getOperand(3));
1815 SDValue D2 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT,
1816 N->getOperand(4));
1817 SDValue D4 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT,
1818 N->getOperand(5));
1819 const SDValue OpsA[] = { MemAddr, MemUpdate, MemOpc, D0, D2, D4, Chain };
1820 SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(),
1821 MVT::Other, OpsA, 7);
1822 Chain = SDValue(VStA, 1);
1823
1824 SDValue D1 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
1825 N->getOperand(3));
1826 SDValue D3 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
1827 N->getOperand(4));
1828 SDValue D5 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
1829 N->getOperand(5));
1830 MemAddr = SDValue(VStA, 0);
1831 const SDValue OpsB[] = { MemAddr, MemUpdate, MemOpc, D1, D3, D5, Chain };
1832 SDNode *VStB = CurDAG->getMachineNode(Opc2, dl, MemAddr.getValueType(),
1833 MVT::Other, OpsB, 7);
1834 Chain = SDValue(VStB, 1);
1835 ReplaceUses(SDValue(N, 0), Chain);
1836 return NULL;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001837 }
1838
1839 case Intrinsic::arm_neon_vst4: {
1840 SDValue MemAddr, MemUpdate, MemOpc;
1841 if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc))
1842 return NULL;
Bob Wilson63c90632009-10-07 20:49:18 +00001843 VT = N->getOperand(3).getValueType();
1844 if (VT.is64BitVector()) {
1845 switch (VT.getSimpleVT().SimpleTy) {
1846 default: llvm_unreachable("unhandled vst4 type");
1847 case MVT::v8i8: Opc = ARM::VST4d8; break;
1848 case MVT::v4i16: Opc = ARM::VST4d16; break;
1849 case MVT::v2f32:
1850 case MVT::v2i32: Opc = ARM::VST4d32; break;
Bob Wilsondeb31412009-10-08 05:18:18 +00001851 case MVT::v1i64: Opc = ARM::VST4d64; break;
Bob Wilson63c90632009-10-07 20:49:18 +00001852 }
1853 SDValue Chain = N->getOperand(0);
1854 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc,
1855 N->getOperand(3), N->getOperand(4),
1856 N->getOperand(5), N->getOperand(6), Chain };
1857 return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 8);
1858 }
1859 // Quad registers are stored with two separate instructions, where one
1860 // stores the even registers and the other stores the odd registers.
1861 EVT RegVT;
1862 unsigned Opc2 = 0;
1863 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson31fb12f2009-08-26 17:39:53 +00001864 default: llvm_unreachable("unhandled vst4 type");
Bob Wilson63c90632009-10-07 20:49:18 +00001865 case MVT::v16i8:
1866 Opc = ARM::VST4q8a; Opc2 = ARM::VST4q8b; RegVT = MVT::v8i8; break;
1867 case MVT::v8i16:
1868 Opc = ARM::VST4q16a; Opc2 = ARM::VST4q16b; RegVT = MVT::v4i16; break;
1869 case MVT::v4f32:
1870 Opc = ARM::VST4q32a; Opc2 = ARM::VST4q32b; RegVT = MVT::v2f32; break;
1871 case MVT::v4i32:
1872 Opc = ARM::VST4q32a; Opc2 = ARM::VST4q32b; RegVT = MVT::v2i32; break;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001873 }
1874 SDValue Chain = N->getOperand(0);
Bob Wilson63c90632009-10-07 20:49:18 +00001875 // Enable writeback to the address register.
1876 MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32);
1877
1878 SDValue D0 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT,
1879 N->getOperand(3));
1880 SDValue D2 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT,
1881 N->getOperand(4));
1882 SDValue D4 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT,
1883 N->getOperand(5));
1884 SDValue D6 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT,
1885 N->getOperand(6));
1886 const SDValue OpsA[] = { MemAddr, MemUpdate, MemOpc,
1887 D0, D2, D4, D6, Chain };
1888 SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(),
1889 MVT::Other, OpsA, 8);
1890 Chain = SDValue(VStA, 1);
1891
1892 SDValue D1 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
1893 N->getOperand(3));
1894 SDValue D3 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
1895 N->getOperand(4));
1896 SDValue D5 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
1897 N->getOperand(5));
1898 SDValue D7 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
1899 N->getOperand(6));
1900 MemAddr = SDValue(VStA, 0);
1901 const SDValue OpsB[] = { MemAddr, MemUpdate, MemOpc,
1902 D1, D3, D5, D7, Chain };
1903 SDNode *VStB = CurDAG->getMachineNode(Opc2, dl, MemAddr.getValueType(),
1904 MVT::Other, OpsB, 8);
1905 Chain = SDValue(VStB, 1);
1906 ReplaceUses(SDValue(N, 0), Chain);
1907 return NULL;
Bob Wilson31fb12f2009-08-26 17:39:53 +00001908 }
Bob Wilson8a3198b2009-09-01 18:51:56 +00001909
1910 case Intrinsic::arm_neon_vst2lane: {
1911 SDValue MemAddr, MemUpdate, MemOpc;
1912 if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc))
1913 return NULL;
Bob Wilsonc5c6edb2009-10-08 23:38:24 +00001914 VT = N->getOperand(3).getValueType();
1915 if (VT.is64BitVector()) {
1916 switch (VT.getSimpleVT().SimpleTy) {
1917 default: llvm_unreachable("unhandled vst2lane type");
1918 case MVT::v8i8: Opc = ARM::VST2LNd8; break;
1919 case MVT::v4i16: Opc = ARM::VST2LNd16; break;
1920 case MVT::v2f32:
1921 case MVT::v2i32: Opc = ARM::VST2LNd32; break;
1922 }
1923 SDValue Chain = N->getOperand(0);
1924 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc,
1925 N->getOperand(3), N->getOperand(4),
1926 N->getOperand(5), Chain };
1927 return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 7);
1928 }
1929 // Quad registers are handled by extracting subregs and then doing
1930 // the store.
1931 EVT RegVT;
1932 unsigned Opc2 = 0;
1933 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson8a3198b2009-09-01 18:51:56 +00001934 default: llvm_unreachable("unhandled vst2lane type");
Bob Wilsonc5c6edb2009-10-08 23:38:24 +00001935 case MVT::v8i16:
1936 Opc = ARM::VST2LNq16a;
1937 Opc2 = ARM::VST2LNq16b;
1938 RegVT = MVT::v4i16;
1939 break;
1940 case MVT::v4f32:
1941 Opc = ARM::VST2LNq32a;
1942 Opc2 = ARM::VST2LNq32b;
1943 RegVT = MVT::v2f32;
1944 break;
1945 case MVT::v4i32:
1946 Opc = ARM::VST2LNq32a;
1947 Opc2 = ARM::VST2LNq32b;
1948 RegVT = MVT::v2i32;
1949 break;
Bob Wilson8a3198b2009-09-01 18:51:56 +00001950 }
1951 SDValue Chain = N->getOperand(0);
Bob Wilsonc5c6edb2009-10-08 23:38:24 +00001952 unsigned Lane = cast<ConstantSDNode>(N->getOperand(5))->getZExtValue();
1953 unsigned NumElts = RegVT.getVectorNumElements();
1954 int SubregIdx = (Lane < NumElts) ? ARM::DSUBREG_0 : ARM::DSUBREG_1;
1955
1956 SDValue D0 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1957 N->getOperand(3));
1958 SDValue D1 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1959 N->getOperand(4));
1960 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, D0, D1,
1961 getI32Imm(Lane % NumElts), Chain };
1962 return CurDAG->getMachineNode((Lane < NumElts) ? Opc : Opc2,
1963 dl, MVT::Other, Ops, 7);
Bob Wilson8a3198b2009-09-01 18:51:56 +00001964 }
1965
1966 case Intrinsic::arm_neon_vst3lane: {
1967 SDValue MemAddr, MemUpdate, MemOpc;
1968 if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc))
1969 return NULL;
Bob Wilson8cdb2692009-10-08 23:51:31 +00001970 VT = N->getOperand(3).getValueType();
1971 if (VT.is64BitVector()) {
1972 switch (VT.getSimpleVT().SimpleTy) {
1973 default: llvm_unreachable("unhandled vst3lane type");
1974 case MVT::v8i8: Opc = ARM::VST3LNd8; break;
1975 case MVT::v4i16: Opc = ARM::VST3LNd16; break;
1976 case MVT::v2f32:
1977 case MVT::v2i32: Opc = ARM::VST3LNd32; break;
1978 }
1979 SDValue Chain = N->getOperand(0);
1980 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc,
1981 N->getOperand(3), N->getOperand(4),
1982 N->getOperand(5), N->getOperand(6), Chain };
1983 return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 8);
1984 }
1985 // Quad registers are handled by extracting subregs and then doing
1986 // the store.
1987 EVT RegVT;
1988 unsigned Opc2 = 0;
1989 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson8a3198b2009-09-01 18:51:56 +00001990 default: llvm_unreachable("unhandled vst3lane type");
Bob Wilson8cdb2692009-10-08 23:51:31 +00001991 case MVT::v8i16:
1992 Opc = ARM::VST3LNq16a;
1993 Opc2 = ARM::VST3LNq16b;
1994 RegVT = MVT::v4i16;
1995 break;
1996 case MVT::v4f32:
1997 Opc = ARM::VST3LNq32a;
1998 Opc2 = ARM::VST3LNq32b;
1999 RegVT = MVT::v2f32;
2000 break;
2001 case MVT::v4i32:
2002 Opc = ARM::VST3LNq32a;
2003 Opc2 = ARM::VST3LNq32b;
2004 RegVT = MVT::v2i32;
2005 break;
Bob Wilson8a3198b2009-09-01 18:51:56 +00002006 }
2007 SDValue Chain = N->getOperand(0);
Bob Wilson8cdb2692009-10-08 23:51:31 +00002008 unsigned Lane = cast<ConstantSDNode>(N->getOperand(6))->getZExtValue();
2009 unsigned NumElts = RegVT.getVectorNumElements();
2010 int SubregIdx = (Lane < NumElts) ? ARM::DSUBREG_0 : ARM::DSUBREG_1;
2011
2012 SDValue D0 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
2013 N->getOperand(3));
2014 SDValue D1 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
2015 N->getOperand(4));
2016 SDValue D2 = CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
2017 N->getOperand(5));
2018 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, D0, D1, D2,
2019 getI32Imm(Lane % NumElts), Chain };
2020 return CurDAG->getMachineNode((Lane < NumElts) ? Opc : Opc2,
2021 dl, MVT::Other, Ops, 8);
Bob Wilson8a3198b2009-09-01 18:51:56 +00002022 }
2023
2024 case Intrinsic::arm_neon_vst4lane: {
2025 SDValue MemAddr, MemUpdate, MemOpc;
2026 if (!SelectAddrMode6(Op, N->getOperand(2), MemAddr, MemUpdate, MemOpc))
2027 return NULL;
2028 switch (N->getOperand(3).getValueType().getSimpleVT().SimpleTy) {
2029 default: llvm_unreachable("unhandled vst4lane type");
2030 case MVT::v8i8: Opc = ARM::VST4LNd8; break;
2031 case MVT::v4i16: Opc = ARM::VST4LNd16; break;
2032 case MVT::v2f32:
2033 case MVT::v2i32: Opc = ARM::VST4LNd32; break;
2034 }
2035 SDValue Chain = N->getOperand(0);
2036 const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc,
2037 N->getOperand(3), N->getOperand(4),
2038 N->getOperand(5), N->getOperand(6),
2039 N->getOperand(7), Chain };
Dan Gohman602b0c82009-09-25 18:54:59 +00002040 return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 9);
Bob Wilson8a3198b2009-09-01 18:51:56 +00002041 }
Bob Wilson31fb12f2009-08-26 17:39:53 +00002042 }
2043 }
Evan Chenge5ad88e2008-12-10 21:54:21 +00002044 }
2045
Evan Chenga8e29892007-01-19 07:51:42 +00002046 return SelectCode(Op);
2047}
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00002048
Bob Wilson224c2442009-05-19 05:53:42 +00002049bool ARMDAGToDAGISel::
2050SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
2051 std::vector<SDValue> &OutOps) {
2052 assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
2053
2054 SDValue Base, Offset, Opc;
2055 if (!SelectAddrMode2(Op, Op, Base, Offset, Opc))
2056 return true;
Jim Grosbach764ab522009-08-11 15:33:49 +00002057
Bob Wilson224c2442009-05-19 05:53:42 +00002058 OutOps.push_back(Base);
2059 OutOps.push_back(Offset);
2060 OutOps.push_back(Opc);
2061 return false;
2062}
2063
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00002064/// createARMISelDag - This pass converts a legalized DAG into a
2065/// ARM-specific DAG, ready for instruction scheduling.
2066///
Bob Wilson522ce972009-09-28 14:30:20 +00002067FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
2068 CodeGenOpt::Level OptLevel) {
2069 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00002070}