blob: d7c2fe0182c92fd4c9acd0b10516e35edaebc0ce [file] [log] [blame]
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00001//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the ARM target.
11//
12//===----------------------------------------------------------------------===//
13
Dale Johannesen51e28e62010-06-03 21:09:53 +000014#define DEBUG_TYPE "arm-isel"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000015#include "ARM.h"
Evan Chenge5ad88e2008-12-10 21:54:21 +000016#include "ARMAddressingModes.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000017#include "ARMTargetMachine.h"
Rafael Espindola84b19be2006-07-16 01:02:57 +000018#include "llvm/CallingConv.h"
Evan Chenga8e29892007-01-19 07:51:42 +000019#include "llvm/Constants.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000020#include "llvm/DerivedTypes.h"
21#include "llvm/Function.h"
22#include "llvm/Intrinsics.h"
Owen Anderson9adc0ab2009-07-14 23:09:55 +000023#include "llvm/LLVMContext.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000024#include "llvm/CodeGen/MachineFrameInfo.h"
25#include "llvm/CodeGen/MachineFunction.h"
26#include "llvm/CodeGen/MachineInstrBuilder.h"
27#include "llvm/CodeGen/SelectionDAG.h"
28#include "llvm/CodeGen/SelectionDAGISel.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000029#include "llvm/Target/TargetLowering.h"
Chris Lattner72939122007-05-03 00:32:00 +000030#include "llvm/Target/TargetOptions.h"
Evan Cheng94cc6d32010-05-04 20:39:49 +000031#include "llvm/Support/CommandLine.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
Evan Cheng94cc6d32010-05-04 20:39:49 +000039static cl::opt<bool>
40UseRegSeq("neon-reg-sequence", cl::Hidden,
Evan Cheng62061242010-05-17 19:51:20 +000041 cl::desc("Use reg_sequence to model ld / st of multiple neon regs"),
42 cl::init(true));
Evan Cheng94cc6d32010-05-04 20:39:49 +000043
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000044//===--------------------------------------------------------------------===//
45/// ARMDAGToDAGISel - ARM specific code to select ARM machine
46/// instructions for SelectionDAG operations.
47///
48namespace {
49class ARMDAGToDAGISel : public SelectionDAGISel {
Anton Korobeynikovd49ea772009-06-26 21:28:53 +000050 ARMBaseTargetMachine &TM;
Evan Cheng3f7eb8e2008-09-18 07:24:33 +000051
Evan Chenga8e29892007-01-19 07:51:42 +000052 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
53 /// make the right decision when generating code for different targets.
54 const ARMSubtarget *Subtarget;
55
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000056public:
Bob Wilson522ce972009-09-28 14:30:20 +000057 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm,
58 CodeGenOpt::Level OptLevel)
59 : SelectionDAGISel(tm, OptLevel), TM(tm),
Evan Chenga8e29892007-01-19 07:51:42 +000060 Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000061 }
62
Evan Chenga8e29892007-01-19 07:51:42 +000063 virtual const char *getPassName() const {
64 return "ARM Instruction Selection";
Anton Korobeynikov52237112009-06-17 18:13:58 +000065 }
66
Bob Wilsonaf4a8912009-10-08 18:51:31 +000067 /// getI32Imm - Return a target constant of type i32 with the specified
68 /// value.
Anton Korobeynikov52237112009-06-17 18:13:58 +000069 inline SDValue getI32Imm(unsigned Imm) {
Owen Anderson825b72b2009-08-11 20:47:22 +000070 return CurDAG->getTargetConstant(Imm, MVT::i32);
Anton Korobeynikov52237112009-06-17 18:13:58 +000071 }
72
Dan Gohmaneeb3a002010-01-05 01:24:18 +000073 SDNode *Select(SDNode *N);
Evan Cheng014bf212010-02-15 19:41:07 +000074
Dan Gohmaneeb3a002010-01-05 01:24:18 +000075 bool SelectShifterOperandReg(SDNode *Op, SDValue N, SDValue &A,
Evan Cheng055b0312009-06-29 07:51:04 +000076 SDValue &B, SDValue &C);
Dan Gohmaneeb3a002010-01-05 01:24:18 +000077 bool SelectAddrMode2(SDNode *Op, SDValue N, SDValue &Base,
Dan Gohman475871a2008-07-27 21:46:04 +000078 SDValue &Offset, SDValue &Opc);
Dan Gohmaneeb3a002010-01-05 01:24:18 +000079 bool SelectAddrMode2Offset(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +000080 SDValue &Offset, SDValue &Opc);
Dan Gohmaneeb3a002010-01-05 01:24:18 +000081 bool SelectAddrMode3(SDNode *Op, SDValue N, SDValue &Base,
Dan Gohman475871a2008-07-27 21:46:04 +000082 SDValue &Offset, SDValue &Opc);
Dan Gohmaneeb3a002010-01-05 01:24:18 +000083 bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +000084 SDValue &Offset, SDValue &Opc);
Dan Gohmaneeb3a002010-01-05 01:24:18 +000085 bool SelectAddrMode4(SDNode *Op, SDValue N, SDValue &Addr,
Anton Korobeynikovbaf31082009-08-08 13:35:48 +000086 SDValue &Mode);
Dan Gohmaneeb3a002010-01-05 01:24:18 +000087 bool SelectAddrMode5(SDNode *Op, SDValue N, SDValue &Base,
Dan Gohman475871a2008-07-27 21:46:04 +000088 SDValue &Offset);
Bob Wilson226036e2010-03-20 22:13:40 +000089 bool SelectAddrMode6(SDNode *Op, SDValue N, SDValue &Addr, SDValue &Align);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000090
Dan Gohmaneeb3a002010-01-05 01:24:18 +000091 bool SelectAddrModePC(SDNode *Op, SDValue N, SDValue &Offset,
Bob Wilson8b024a52009-07-01 23:16:05 +000092 SDValue &Label);
Evan Chenga8e29892007-01-19 07:51:42 +000093
Dan Gohmaneeb3a002010-01-05 01:24:18 +000094 bool SelectThumbAddrModeRR(SDNode *Op, SDValue N, SDValue &Base,
Dan Gohman475871a2008-07-27 21:46:04 +000095 SDValue &Offset);
Dan Gohmaneeb3a002010-01-05 01:24:18 +000096 bool SelectThumbAddrModeRI5(SDNode *Op, SDValue N, unsigned Scale,
Dan Gohman475871a2008-07-27 21:46:04 +000097 SDValue &Base, SDValue &OffImm,
98 SDValue &Offset);
Dan Gohmaneeb3a002010-01-05 01:24:18 +000099 bool SelectThumbAddrModeS1(SDNode *Op, SDValue N, SDValue &Base,
Dan Gohman475871a2008-07-27 21:46:04 +0000100 SDValue &OffImm, SDValue &Offset);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000101 bool SelectThumbAddrModeS2(SDNode *Op, SDValue N, SDValue &Base,
Dan Gohman475871a2008-07-27 21:46:04 +0000102 SDValue &OffImm, SDValue &Offset);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000103 bool SelectThumbAddrModeS4(SDNode *Op, SDValue N, SDValue &Base,
Dan Gohman475871a2008-07-27 21:46:04 +0000104 SDValue &OffImm, SDValue &Offset);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000105 bool SelectThumbAddrModeSP(SDNode *Op, SDValue N, SDValue &Base,
Dan Gohman475871a2008-07-27 21:46:04 +0000106 SDValue &OffImm);
Evan Chenga8e29892007-01-19 07:51:42 +0000107
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000108 bool SelectT2ShifterOperandReg(SDNode *Op, SDValue N,
Evan Cheng9cb9e672009-06-27 02:26:13 +0000109 SDValue &BaseReg, SDValue &Opc);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000110 bool SelectT2AddrModeImm12(SDNode *Op, SDValue N, SDValue &Base,
Evan Cheng055b0312009-06-29 07:51:04 +0000111 SDValue &OffImm);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000112 bool SelectT2AddrModeImm8(SDNode *Op, SDValue N, SDValue &Base,
Evan Cheng055b0312009-06-29 07:51:04 +0000113 SDValue &OffImm);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000114 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Chenge88d5ce2009-07-02 07:28:31 +0000115 SDValue &OffImm);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000116 bool SelectT2AddrModeImm8s4(SDNode *Op, SDValue N, SDValue &Base,
David Goodwin6647cea2009-06-30 22:50:01 +0000117 SDValue &OffImm);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000118 bool SelectT2AddrModeSoReg(SDNode *Op, SDValue N, SDValue &Base,
Evan Cheng055b0312009-06-29 07:51:04 +0000119 SDValue &OffReg, SDValue &ShImm);
120
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000121 // Include the pieces autogenerated from the target description.
122#include "ARMGenDAGISel.inc"
Bob Wilson224c2442009-05-19 05:53:42 +0000123
124private:
Evan Chenge88d5ce2009-07-02 07:28:31 +0000125 /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
126 /// ARM.
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000127 SDNode *SelectARMIndexedLoad(SDNode *N);
128 SDNode *SelectT2IndexedLoad(SDNode *N);
Evan Chenge88d5ce2009-07-02 07:28:31 +0000129
Bob Wilson621f1952010-03-23 05:25:43 +0000130 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
131 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson3e36f132009-10-14 17:28:52 +0000132 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson621f1952010-03-23 05:25:43 +0000133 /// For NumVecs <= 2, QOpcodes1 is not used.
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000134 SDNode *SelectVLD(SDNode *N, unsigned NumVecs, unsigned *DOpcodes,
Bob Wilson3e36f132009-10-14 17:28:52 +0000135 unsigned *QOpcodes0, unsigned *QOpcodes1);
136
Bob Wilson24f995d2009-10-14 18:32:29 +0000137 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilson11d98992010-03-23 06:20:33 +0000138 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson24f995d2009-10-14 18:32:29 +0000139 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilson11d98992010-03-23 06:20:33 +0000140 /// For NumVecs <= 2, QOpcodes1 is not used.
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000141 SDNode *SelectVST(SDNode *N, unsigned NumVecs, unsigned *DOpcodes,
Bob Wilson24f995d2009-10-14 18:32:29 +0000142 unsigned *QOpcodes0, unsigned *QOpcodes1);
143
Bob Wilson96493442009-10-14 16:46:45 +0000144 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilsona7c397c2009-10-14 16:19:03 +0000145 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson96493442009-10-14 16:46:45 +0000146 /// load/store of D registers and even subregs and odd subregs of Q registers.
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000147 SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad, unsigned NumVecs,
Bob Wilson96493442009-10-14 16:46:45 +0000148 unsigned *DOpcodes, unsigned *QOpcodes0,
149 unsigned *QOpcodes1);
Bob Wilsona7c397c2009-10-14 16:19:03 +0000150
Sandeep Patel4e1ed882009-10-13 20:25:58 +0000151 /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
Jim Grosbach3a1287b2010-04-22 23:24:18 +0000152 SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel47eedaa2009-10-13 18:59:48 +0000153
Evan Cheng07ba9062009-11-19 21:45:22 +0000154 /// SelectCMOVOp - Select CMOV instructions for ARM.
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000155 SDNode *SelectCMOVOp(SDNode *N);
156 SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +0000157 ARMCC::CondCodes CCVal, SDValue CCR,
158 SDValue InFlag);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000159 SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +0000160 ARMCC::CondCodes CCVal, SDValue CCR,
161 SDValue InFlag);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000162 SDNode *SelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +0000163 ARMCC::CondCodes CCVal, SDValue CCR,
164 SDValue InFlag);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000165 SDNode *SelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +0000166 ARMCC::CondCodes CCVal, SDValue CCR,
167 SDValue InFlag);
Evan Cheng07ba9062009-11-19 21:45:22 +0000168
Evan Chengde8aa4e2010-05-05 18:28:36 +0000169 SDNode *SelectConcatVector(SDNode *N);
170
Evan Chengaf4550f2009-07-02 01:23:32 +0000171 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
172 /// inline asm expressions.
173 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
174 char ConstraintCode,
175 std::vector<SDValue> &OutOps);
Bob Wilson3bf12ab2009-10-06 22:01:59 +0000176
Bob Wilson40cbe7d2010-06-04 00:04:02 +0000177 // Form pairs of consecutive S, D, or Q registers.
178 SDNode *PairSRegs(EVT VT, SDValue V0, SDValue V1);
Bob Wilson3bf12ab2009-10-06 22:01:59 +0000179 SDNode *PairDRegs(EVT VT, SDValue V0, SDValue V1);
Evan Cheng603afbf2010-05-10 17:34:18 +0000180 SDNode *PairQRegs(EVT VT, SDValue V0, SDValue V1);
181
Bob Wilson40cbe7d2010-06-04 00:04:02 +0000182 // Form sequences of 4 consecutive S, D, or Q registers.
183 SDNode *QuadSRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Evan Cheng603afbf2010-05-10 17:34:18 +0000184 SDNode *QuadDRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Evan Cheng8f6de382010-05-16 03:27:48 +0000185 SDNode *QuadQRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
186
Bob Wilson40cbe7d2010-06-04 00:04:02 +0000187 // Form sequences of 8 consecutive D registers.
Evan Cheng5c6aba22010-05-14 18:54:59 +0000188 SDNode *OctoDRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3,
189 SDValue V4, SDValue V5, SDValue V6, SDValue V7);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000190};
Evan Chenga8e29892007-01-19 07:51:42 +0000191}
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000192
Sandeep Patel47eedaa2009-10-13 18:59:48 +0000193/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
194/// operand. If so Imm will receive the 32-bit value.
195static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
196 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
197 Imm = cast<ConstantSDNode>(N)->getZExtValue();
198 return true;
199 }
200 return false;
201}
202
203// isInt32Immediate - This method tests to see if a constant operand.
204// If so Imm will receive the 32 bit value.
205static bool isInt32Immediate(SDValue N, unsigned &Imm) {
206 return isInt32Immediate(N.getNode(), Imm);
207}
208
209// isOpcWithIntImmediate - This method tests to see if the node is a specific
210// opcode and that it has a immediate integer right operand.
211// If so Imm will receive the 32 bit value.
212static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
213 return N->getOpcode() == Opc &&
214 isInt32Immediate(N->getOperand(1).getNode(), Imm);
215}
216
217
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000218bool ARMDAGToDAGISel::SelectShifterOperandReg(SDNode *Op,
Evan Cheng055b0312009-06-29 07:51:04 +0000219 SDValue N,
220 SDValue &BaseReg,
221 SDValue &ShReg,
222 SDValue &Opc) {
223 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
224
225 // Don't match base register only case. That is matched to a separate
226 // lower complexity pattern with explicit register operand.
227 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbach764ab522009-08-11 15:33:49 +0000228
Evan Cheng055b0312009-06-29 07:51:04 +0000229 BaseReg = N.getOperand(0);
230 unsigned ShImmVal = 0;
231 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Owen Anderson825b72b2009-08-11 20:47:22 +0000232 ShReg = CurDAG->getRegister(0, MVT::i32);
Evan Cheng055b0312009-06-29 07:51:04 +0000233 ShImmVal = RHS->getZExtValue() & 31;
234 } else {
235 ShReg = N.getOperand(1);
236 }
237 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Owen Anderson825b72b2009-08-11 20:47:22 +0000238 MVT::i32);
Evan Cheng055b0312009-06-29 07:51:04 +0000239 return true;
240}
241
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000242bool ARMDAGToDAGISel::SelectAddrMode2(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000243 SDValue &Base, SDValue &Offset,
244 SDValue &Opc) {
Evan Chenga13fd102007-03-13 21:05:54 +0000245 if (N.getOpcode() == ISD::MUL) {
246 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
247 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000248 int RHSC = (int)RHS->getZExtValue();
Evan Chenga13fd102007-03-13 21:05:54 +0000249 if (RHSC & 1) {
250 RHSC = RHSC & ~1;
251 ARM_AM::AddrOpc AddSub = ARM_AM::add;
252 if (RHSC < 0) {
253 AddSub = ARM_AM::sub;
254 RHSC = - RHSC;
255 }
256 if (isPowerOf2_32(RHSC)) {
257 unsigned ShAmt = Log2_32(RHSC);
258 Base = Offset = N.getOperand(0);
259 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
260 ARM_AM::lsl),
Owen Anderson825b72b2009-08-11 20:47:22 +0000261 MVT::i32);
Evan Chenga13fd102007-03-13 21:05:54 +0000262 return true;
263 }
264 }
265 }
266 }
267
Evan Chenga8e29892007-01-19 07:51:42 +0000268 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) {
269 Base = N;
270 if (N.getOpcode() == ISD::FrameIndex) {
271 int FI = cast<FrameIndexSDNode>(N)->getIndex();
272 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000273 } else if (N.getOpcode() == ARMISD::Wrapper &&
274 !(Subtarget->useMovt() &&
275 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Chenga8e29892007-01-19 07:51:42 +0000276 Base = N.getOperand(0);
277 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000278 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000279 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
280 ARM_AM::no_shift),
Owen Anderson825b72b2009-08-11 20:47:22 +0000281 MVT::i32);
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000282 return true;
283 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000284
Evan Chenga8e29892007-01-19 07:51:42 +0000285 // Match simple R +/- imm12 operands.
286 if (N.getOpcode() == ISD::ADD)
287 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000288 int RHSC = (int)RHS->getZExtValue();
Evan Chenge966d642007-01-24 02:45:25 +0000289 if ((RHSC >= 0 && RHSC < 0x1000) ||
290 (RHSC < 0 && RHSC > -0x1000)) { // 12 bits.
Evan Chenga8e29892007-01-19 07:51:42 +0000291 Base = N.getOperand(0);
Evan Chenge966d642007-01-24 02:45:25 +0000292 if (Base.getOpcode() == ISD::FrameIndex) {
293 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
294 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
295 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000296 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Chenge966d642007-01-24 02:45:25 +0000297
298 ARM_AM::AddrOpc AddSub = ARM_AM::add;
299 if (RHSC < 0) {
300 AddSub = ARM_AM::sub;
301 RHSC = - RHSC;
302 }
303 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
Evan Chenga8e29892007-01-19 07:51:42 +0000304 ARM_AM::no_shift),
Owen Anderson825b72b2009-08-11 20:47:22 +0000305 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000306 return true;
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000307 }
Evan Chenga8e29892007-01-19 07:51:42 +0000308 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000309
Johnny Chen6a3b5ee2009-10-27 17:25:15 +0000310 // Otherwise this is R +/- [possibly shifted] R.
Evan Chenga8e29892007-01-19 07:51:42 +0000311 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub;
312 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1));
313 unsigned ShAmt = 0;
Jim Grosbach764ab522009-08-11 15:33:49 +0000314
Evan Chenga8e29892007-01-19 07:51:42 +0000315 Base = N.getOperand(0);
316 Offset = N.getOperand(1);
Jim Grosbach764ab522009-08-11 15:33:49 +0000317
Evan Chenga8e29892007-01-19 07:51:42 +0000318 if (ShOpcVal != ARM_AM::no_shift) {
319 // Check to see if the RHS of the shift is a constant, if not, we can't fold
320 // it.
321 if (ConstantSDNode *Sh =
322 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000323 ShAmt = Sh->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000324 Offset = N.getOperand(1).getOperand(0);
325 } else {
326 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000327 }
328 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000329
Evan Chenga8e29892007-01-19 07:51:42 +0000330 // Try matching (R shl C) + (R).
331 if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) {
332 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0));
333 if (ShOpcVal != ARM_AM::no_shift) {
334 // Check to see if the RHS of the shift is a constant, if not, we can't
335 // fold it.
336 if (ConstantSDNode *Sh =
337 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000338 ShAmt = Sh->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000339 Offset = N.getOperand(0).getOperand(0);
340 Base = N.getOperand(1);
341 } else {
342 ShOpcVal = ARM_AM::no_shift;
343 }
344 }
345 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000346
Evan Chenga8e29892007-01-19 07:51:42 +0000347 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson825b72b2009-08-11 20:47:22 +0000348 MVT::i32);
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000349 return true;
350}
351
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000352bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000353 SDValue &Offset, SDValue &Opc) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000354 unsigned Opcode = Op->getOpcode();
Evan Chenga8e29892007-01-19 07:51:42 +0000355 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
356 ? cast<LoadSDNode>(Op)->getAddressingMode()
357 : cast<StoreSDNode>(Op)->getAddressingMode();
358 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
359 ? ARM_AM::add : ARM_AM::sub;
360 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000361 int Val = (int)C->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000362 if (Val >= 0 && Val < 0x1000) { // 12 bits.
Owen Anderson825b72b2009-08-11 20:47:22 +0000363 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000364 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
365 ARM_AM::no_shift),
Owen Anderson825b72b2009-08-11 20:47:22 +0000366 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000367 return true;
368 }
369 }
370
371 Offset = N;
372 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
373 unsigned ShAmt = 0;
374 if (ShOpcVal != ARM_AM::no_shift) {
375 // Check to see if the RHS of the shift is a constant, if not, we can't fold
376 // it.
377 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000378 ShAmt = Sh->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000379 Offset = N.getOperand(0);
380 } else {
381 ShOpcVal = ARM_AM::no_shift;
382 }
383 }
384
385 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson825b72b2009-08-11 20:47:22 +0000386 MVT::i32);
Rafael Espindola32bd5f42006-10-17 18:04:53 +0000387 return true;
388}
389
Evan Chenga8e29892007-01-19 07:51:42 +0000390
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000391bool ARMDAGToDAGISel::SelectAddrMode3(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000392 SDValue &Base, SDValue &Offset,
393 SDValue &Opc) {
Evan Chenga8e29892007-01-19 07:51:42 +0000394 if (N.getOpcode() == ISD::SUB) {
395 // X - C is canonicalize to X + -C, no need to handle it here.
396 Base = N.getOperand(0);
397 Offset = N.getOperand(1);
Owen Anderson825b72b2009-08-11 20:47:22 +0000398 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000399 return true;
400 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000401
Evan Chenga8e29892007-01-19 07:51:42 +0000402 if (N.getOpcode() != ISD::ADD) {
403 Base = N;
404 if (N.getOpcode() == ISD::FrameIndex) {
405 int FI = cast<FrameIndexSDNode>(N)->getIndex();
406 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
407 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000408 Offset = CurDAG->getRegister(0, MVT::i32);
409 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),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 Chenge966d642007-01-24 02:45:25 +0000416 if ((RHSC >= 0 && RHSC < 256) ||
417 (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed.
Evan Chenga8e29892007-01-19 07:51:42 +0000418 Base = N.getOperand(0);
Evan Chenge966d642007-01-24 02:45:25 +0000419 if (Base.getOpcode() == ISD::FrameIndex) {
420 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
421 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
422 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000423 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Chenge966d642007-01-24 02:45:25 +0000424
425 ARM_AM::AddrOpc AddSub = ARM_AM::add;
426 if (RHSC < 0) {
427 AddSub = ARM_AM::sub;
428 RHSC = - RHSC;
429 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000430 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000431 return true;
432 }
433 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000434
Evan Chenga8e29892007-01-19 07:51:42 +0000435 Base = N.getOperand(0);
436 Offset = N.getOperand(1);
Owen Anderson825b72b2009-08-11 20:47:22 +0000437 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000438 return true;
439}
440
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000441bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000442 SDValue &Offset, SDValue &Opc) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000443 unsigned Opcode = Op->getOpcode();
Evan Chenga8e29892007-01-19 07:51:42 +0000444 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
445 ? cast<LoadSDNode>(Op)->getAddressingMode()
446 : cast<StoreSDNode>(Op)->getAddressingMode();
447 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
448 ? ARM_AM::add : ARM_AM::sub;
449 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000450 int Val = (int)C->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000451 if (Val >= 0 && Val < 256) {
Owen Anderson825b72b2009-08-11 20:47:22 +0000452 Offset = CurDAG->getRegister(0, MVT::i32);
453 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000454 return true;
455 }
456 }
457
458 Offset = N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000459 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000460 return true;
461}
462
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000463bool ARMDAGToDAGISel::SelectAddrMode4(SDNode *Op, SDValue N,
Anton Korobeynikovbaf31082009-08-08 13:35:48 +0000464 SDValue &Addr, SDValue &Mode) {
465 Addr = N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000466 Mode = CurDAG->getTargetConstant(0, MVT::i32);
Anton Korobeynikovbaf31082009-08-08 13:35:48 +0000467 return true;
468}
Evan Chenga8e29892007-01-19 07:51:42 +0000469
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000470bool ARMDAGToDAGISel::SelectAddrMode5(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000471 SDValue &Base, SDValue &Offset) {
Evan Chenga8e29892007-01-19 07:51:42 +0000472 if (N.getOpcode() != ISD::ADD) {
473 Base = N;
474 if (N.getOpcode() == ISD::FrameIndex) {
475 int FI = cast<FrameIndexSDNode>(N)->getIndex();
476 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000477 } else if (N.getOpcode() == ARMISD::Wrapper &&
478 !(Subtarget->useMovt() &&
479 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Chenga8e29892007-01-19 07:51:42 +0000480 Base = N.getOperand(0);
481 }
482 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson825b72b2009-08-11 20:47:22 +0000483 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000484 return true;
485 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000486
Evan Chenga8e29892007-01-19 07:51:42 +0000487 // If the RHS is +/- imm8, fold into addr mode.
488 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000489 int RHSC = (int)RHS->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000490 if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4.
491 RHSC >>= 2;
Evan Chenge966d642007-01-24 02:45:25 +0000492 if ((RHSC >= 0 && RHSC < 256) ||
493 (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed.
Evan Chenga8e29892007-01-19 07:51:42 +0000494 Base = N.getOperand(0);
Evan Chenge966d642007-01-24 02:45:25 +0000495 if (Base.getOpcode() == ISD::FrameIndex) {
496 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
497 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
498 }
499
500 ARM_AM::AddrOpc AddSub = ARM_AM::add;
501 if (RHSC < 0) {
502 AddSub = ARM_AM::sub;
503 RHSC = - RHSC;
504 }
505 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
Owen Anderson825b72b2009-08-11 20:47:22 +0000506 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000507 return true;
508 }
509 }
510 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000511
Evan Chenga8e29892007-01-19 07:51:42 +0000512 Base = N;
513 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson825b72b2009-08-11 20:47:22 +0000514 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000515 return true;
516}
517
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000518bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Op, SDValue N,
Bob Wilson226036e2010-03-20 22:13:40 +0000519 SDValue &Addr, SDValue &Align) {
Bob Wilson8b024a52009-07-01 23:16:05 +0000520 Addr = N;
Jim Grosbach8a5ec862009-11-07 21:25:39 +0000521 // Default to no alignment.
522 Align = CurDAG->getTargetConstant(0, MVT::i32);
Bob Wilson8b024a52009-07-01 23:16:05 +0000523 return true;
524}
525
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000526bool ARMDAGToDAGISel::SelectAddrModePC(SDNode *Op, SDValue N,
Evan Chengbba9f5f2009-08-14 19:01:37 +0000527 SDValue &Offset, SDValue &Label) {
Evan Chenga8e29892007-01-19 07:51:42 +0000528 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
529 Offset = N.getOperand(0);
Dan Gohman475871a2008-07-27 21:46:04 +0000530 SDValue N1 = N.getOperand(1);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000531 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Owen Anderson825b72b2009-08-11 20:47:22 +0000532 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000533 return true;
534 }
535 return false;
536}
537
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000538bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000539 SDValue &Base, SDValue &Offset){
Dale Johannesenf5f5dce2009-02-06 19:16:40 +0000540 // FIXME dl should come from the parent load or store, not the address
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000541 DebugLoc dl = Op->getDebugLoc();
Evan Chengc38f2bc2007-01-23 22:59:13 +0000542 if (N.getOpcode() != ISD::ADD) {
Evan Cheng2f297df2009-07-11 07:08:13 +0000543 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
544 if (!NC || NC->getZExtValue() != 0)
545 return false;
546
547 Base = Offset = N;
Evan Chengc38f2bc2007-01-23 22:59:13 +0000548 return true;
549 }
550
Evan Chenga8e29892007-01-19 07:51:42 +0000551 Base = N.getOperand(0);
552 Offset = N.getOperand(1);
553 return true;
554}
555
Evan Cheng79d43262007-01-24 02:21:22 +0000556bool
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000557ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000558 unsigned Scale, SDValue &Base,
559 SDValue &OffImm, SDValue &Offset) {
Evan Cheng79d43262007-01-24 02:21:22 +0000560 if (Scale == 4) {
Dan Gohman475871a2008-07-27 21:46:04 +0000561 SDValue TmpBase, TmpOffImm;
Evan Cheng79d43262007-01-24 02:21:22 +0000562 if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm))
563 return false; // We want to select tLDRspi / tSTRspi instead.
Evan Cheng012f2d92007-01-24 08:53:17 +0000564 if (N.getOpcode() == ARMISD::Wrapper &&
565 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
566 return false; // We want to select tLDRpci instead.
Evan Cheng79d43262007-01-24 02:21:22 +0000567 }
568
Evan Chenga8e29892007-01-19 07:51:42 +0000569 if (N.getOpcode() != ISD::ADD) {
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000570 if (N.getOpcode() == ARMISD::Wrapper &&
571 !(Subtarget->useMovt() &&
572 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
573 Base = N.getOperand(0);
574 } else
575 Base = N;
576
Owen Anderson825b72b2009-08-11 20:47:22 +0000577 Offset = CurDAG->getRegister(0, MVT::i32);
578 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000579 return true;
580 }
581
Evan Chengad0e4652007-02-06 00:22:06 +0000582 // Thumb does not have [sp, r] address mode.
583 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
584 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
585 if ((LHSR && LHSR->getReg() == ARM::SP) ||
586 (RHSR && RHSR->getReg() == ARM::SP)) {
587 Base = N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000588 Offset = CurDAG->getRegister(0, MVT::i32);
589 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chengad0e4652007-02-06 00:22:06 +0000590 return true;
591 }
592
Evan Chenga8e29892007-01-19 07:51:42 +0000593 // If the RHS is + imm5 * scale, fold into addr mode.
594 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000595 int RHSC = (int)RHS->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +0000596 if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied.
597 RHSC /= Scale;
598 if (RHSC >= 0 && RHSC < 32) {
599 Base = N.getOperand(0);
Owen Anderson825b72b2009-08-11 20:47:22 +0000600 Offset = CurDAG->getRegister(0, MVT::i32);
601 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000602 return true;
603 }
604 }
605 }
606
Evan Chengc38f2bc2007-01-23 22:59:13 +0000607 Base = N.getOperand(0);
608 Offset = N.getOperand(1);
Owen Anderson825b72b2009-08-11 20:47:22 +0000609 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chengc38f2bc2007-01-23 22:59:13 +0000610 return true;
Evan Chenga8e29892007-01-19 07:51:42 +0000611}
612
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000613bool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000614 SDValue &Base, SDValue &OffImm,
615 SDValue &Offset) {
Evan Chengcea117d2007-01-30 02:35:32 +0000616 return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset);
Evan Chenga8e29892007-01-19 07:51:42 +0000617}
618
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000619bool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000620 SDValue &Base, SDValue &OffImm,
621 SDValue &Offset) {
Evan Chengcea117d2007-01-30 02:35:32 +0000622 return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset);
Evan Chenga8e29892007-01-19 07:51:42 +0000623}
624
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000625bool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000626 SDValue &Base, SDValue &OffImm,
627 SDValue &Offset) {
Evan Chengcea117d2007-01-30 02:35:32 +0000628 return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset);
Evan Chenga8e29892007-01-19 07:51:42 +0000629}
630
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000631bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000632 SDValue &Base, SDValue &OffImm) {
Evan Chenga8e29892007-01-19 07:51:42 +0000633 if (N.getOpcode() == ISD::FrameIndex) {
634 int FI = cast<FrameIndexSDNode>(N)->getIndex();
635 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Owen Anderson825b72b2009-08-11 20:47:22 +0000636 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000637 return true;
638 }
Evan Cheng79d43262007-01-24 02:21:22 +0000639
Evan Chengad0e4652007-02-06 00:22:06 +0000640 if (N.getOpcode() != ISD::ADD)
641 return false;
642
643 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Cheng8c1a73a2007-02-06 09:11:20 +0000644 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
645 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng79d43262007-01-24 02:21:22 +0000646 // If the RHS is + imm8 * scale, fold into addr mode.
647 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000648 int RHSC = (int)RHS->getZExtValue();
Evan Cheng79d43262007-01-24 02:21:22 +0000649 if ((RHSC & 3) == 0) { // The constant is implicitly multiplied.
650 RHSC >>= 2;
651 if (RHSC >= 0 && RHSC < 256) {
Evan Chengad0e4652007-02-06 00:22:06 +0000652 Base = N.getOperand(0);
Evan Cheng8c1a73a2007-02-06 09:11:20 +0000653 if (Base.getOpcode() == ISD::FrameIndex) {
654 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
655 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
656 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000657 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
Evan Cheng79d43262007-01-24 02:21:22 +0000658 return true;
659 }
660 }
661 }
662 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000663
Evan Chenga8e29892007-01-19 07:51:42 +0000664 return false;
665}
666
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000667bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDNode *Op, SDValue N,
Evan Cheng9cb9e672009-06-27 02:26:13 +0000668 SDValue &BaseReg,
669 SDValue &Opc) {
670 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
671
672 // Don't match base register only case. That is matched to a separate
673 // lower complexity pattern with explicit register operand.
674 if (ShOpcVal == ARM_AM::no_shift) return false;
675
676 BaseReg = N.getOperand(0);
677 unsigned ShImmVal = 0;
678 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
679 ShImmVal = RHS->getZExtValue() & 31;
680 Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
681 return true;
682 }
683
684 return false;
685}
686
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000687bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDNode *Op, SDValue N,
Evan Cheng055b0312009-06-29 07:51:04 +0000688 SDValue &Base, SDValue &OffImm) {
689 // Match simple R + imm12 operands.
David Goodwin31e7eba2009-07-20 15:55:39 +0000690
Evan Cheng3a214252009-08-11 08:52:18 +0000691 // Base only.
692 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) {
David Goodwin31e7eba2009-07-20 15:55:39 +0000693 if (N.getOpcode() == ISD::FrameIndex) {
Evan Cheng3a214252009-08-11 08:52:18 +0000694 // Match frame index...
David Goodwin31e7eba2009-07-20 15:55:39 +0000695 int FI = cast<FrameIndexSDNode>(N)->getIndex();
696 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Owen Anderson825b72b2009-08-11 20:47:22 +0000697 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
David Goodwin31e7eba2009-07-20 15:55:39 +0000698 return true;
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000699 } else if (N.getOpcode() == ARMISD::Wrapper &&
700 !(Subtarget->useMovt() &&
701 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Cheng3a214252009-08-11 08:52:18 +0000702 Base = N.getOperand(0);
703 if (Base.getOpcode() == ISD::TargetConstantPool)
704 return false; // We want to select t2LDRpci instead.
705 } else
706 Base = N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000707 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng3a214252009-08-11 08:52:18 +0000708 return true;
David Goodwin31e7eba2009-07-20 15:55:39 +0000709 }
Evan Cheng055b0312009-06-29 07:51:04 +0000710
711 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Evan Cheng3a214252009-08-11 08:52:18 +0000712 if (SelectT2AddrModeImm8(Op, N, Base, OffImm))
713 // Let t2LDRi8 handle (R - imm8).
714 return false;
715
Evan Cheng055b0312009-06-29 07:51:04 +0000716 int RHSC = (int)RHS->getZExtValue();
David Goodwind8c95b52009-07-30 18:56:48 +0000717 if (N.getOpcode() == ISD::SUB)
718 RHSC = -RHSC;
719
720 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Cheng055b0312009-06-29 07:51:04 +0000721 Base = N.getOperand(0);
David Goodwind8c95b52009-07-30 18:56:48 +0000722 if (Base.getOpcode() == ISD::FrameIndex) {
723 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
724 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
725 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000726 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
Evan Cheng055b0312009-06-29 07:51:04 +0000727 return true;
728 }
729 }
730
Evan Cheng3a214252009-08-11 08:52:18 +0000731 // Base only.
732 Base = N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000733 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng3a214252009-08-11 08:52:18 +0000734 return true;
Evan Cheng055b0312009-06-29 07:51:04 +0000735}
736
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000737bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDNode *Op, SDValue N,
Evan Cheng055b0312009-06-29 07:51:04 +0000738 SDValue &Base, SDValue &OffImm) {
David Goodwind8c95b52009-07-30 18:56:48 +0000739 // Match simple R - imm8 operands.
Evan Cheng3a214252009-08-11 08:52:18 +0000740 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::SUB) {
David Goodwin07337c02009-07-30 22:45:52 +0000741 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
742 int RHSC = (int)RHS->getSExtValue();
743 if (N.getOpcode() == ISD::SUB)
744 RHSC = -RHSC;
Jim Grosbach764ab522009-08-11 15:33:49 +0000745
Evan Cheng3a214252009-08-11 08:52:18 +0000746 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
747 Base = N.getOperand(0);
David Goodwin07337c02009-07-30 22:45:52 +0000748 if (Base.getOpcode() == ISD::FrameIndex) {
749 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
750 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
751 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000752 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
David Goodwin07337c02009-07-30 22:45:52 +0000753 return true;
Evan Cheng055b0312009-06-29 07:51:04 +0000754 }
Evan Cheng055b0312009-06-29 07:51:04 +0000755 }
756 }
757
758 return false;
759}
760
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000761bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Chenge88d5ce2009-07-02 07:28:31 +0000762 SDValue &OffImm){
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000763 unsigned Opcode = Op->getOpcode();
Evan Chenge88d5ce2009-07-02 07:28:31 +0000764 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
765 ? cast<LoadSDNode>(Op)->getAddressingMode()
766 : cast<StoreSDNode>(Op)->getAddressingMode();
767 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N)) {
768 int RHSC = (int)RHS->getZExtValue();
769 if (RHSC >= 0 && RHSC < 0x100) { // 8 bits.
David Goodwin4cb73522009-07-14 21:29:29 +0000770 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Owen Anderson825b72b2009-08-11 20:47:22 +0000771 ? CurDAG->getTargetConstant(RHSC, MVT::i32)
772 : CurDAG->getTargetConstant(-RHSC, MVT::i32);
Evan Chenge88d5ce2009-07-02 07:28:31 +0000773 return true;
774 }
775 }
776
777 return false;
778}
779
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000780bool ARMDAGToDAGISel::SelectT2AddrModeImm8s4(SDNode *Op, SDValue N,
David Goodwin6647cea2009-06-30 22:50:01 +0000781 SDValue &Base, SDValue &OffImm) {
782 if (N.getOpcode() == ISD::ADD) {
783 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
784 int RHSC = (int)RHS->getZExtValue();
Jim Grosbach18f30e62010-06-02 21:53:11 +0000785 // 8 bits.
Evan Cheng5c874172009-07-09 22:21:59 +0000786 if (((RHSC & 0x3) == 0) &&
Jim Grosbach18f30e62010-06-02 21:53:11 +0000787 ((RHSC >= 0 && RHSC < 0x400) || (RHSC < 0 && RHSC > -0x400))) {
David Goodwin6647cea2009-06-30 22:50:01 +0000788 Base = N.getOperand(0);
Owen Anderson825b72b2009-08-11 20:47:22 +0000789 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
David Goodwin6647cea2009-06-30 22:50:01 +0000790 return true;
791 }
792 }
793 } else if (N.getOpcode() == ISD::SUB) {
794 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
795 int RHSC = (int)RHS->getZExtValue();
Jim Grosbach18f30e62010-06-02 21:53:11 +0000796 // 8 bits.
797 if (((RHSC & 0x3) == 0) && (RHSC >= 0 && RHSC < 0x400)) {
David Goodwin6647cea2009-06-30 22:50:01 +0000798 Base = N.getOperand(0);
Owen Anderson825b72b2009-08-11 20:47:22 +0000799 OffImm = CurDAG->getTargetConstant(-RHSC, MVT::i32);
David Goodwin6647cea2009-06-30 22:50:01 +0000800 return true;
801 }
802 }
803 }
804
805 return false;
806}
807
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000808bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDNode *Op, SDValue N,
Evan Cheng055b0312009-06-29 07:51:04 +0000809 SDValue &Base,
810 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng3a214252009-08-11 08:52:18 +0000811 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
812 if (N.getOpcode() != ISD::ADD)
813 return false;
Evan Cheng055b0312009-06-29 07:51:04 +0000814
Evan Cheng3a214252009-08-11 08:52:18 +0000815 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
816 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
817 int RHSC = (int)RHS->getZExtValue();
818 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
819 return false;
820 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwind8c95b52009-07-30 18:56:48 +0000821 return false;
822 }
823
Evan Cheng055b0312009-06-29 07:51:04 +0000824 // Look for (R + R) or (R + (R << [1,2,3])).
825 unsigned ShAmt = 0;
826 Base = N.getOperand(0);
827 OffReg = N.getOperand(1);
828
829 // Swap if it is ((R << c) + R).
830 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg);
831 if (ShOpcVal != ARM_AM::lsl) {
832 ShOpcVal = ARM_AM::getShiftOpcForNode(Base);
833 if (ShOpcVal == ARM_AM::lsl)
834 std::swap(Base, OffReg);
Jim Grosbach764ab522009-08-11 15:33:49 +0000835 }
836
Evan Cheng055b0312009-06-29 07:51:04 +0000837 if (ShOpcVal == ARM_AM::lsl) {
838 // Check to see if the RHS of the shift is a constant, if not, we can't fold
839 // it.
840 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
841 ShAmt = Sh->getZExtValue();
842 if (ShAmt >= 4) {
843 ShAmt = 0;
844 ShOpcVal = ARM_AM::no_shift;
845 } else
846 OffReg = OffReg.getOperand(0);
847 } else {
848 ShOpcVal = ARM_AM::no_shift;
849 }
David Goodwin7ecc8502009-07-15 15:50:19 +0000850 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000851
Owen Anderson825b72b2009-08-11 20:47:22 +0000852 ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32);
Evan Cheng055b0312009-06-29 07:51:04 +0000853
854 return true;
855}
856
857//===--------------------------------------------------------------------===//
858
Evan Chengee568cf2007-07-05 07:15:27 +0000859/// getAL - Returns a ARMCC::AL immediate node.
Dan Gohman475871a2008-07-27 21:46:04 +0000860static inline SDValue getAL(SelectionDAG *CurDAG) {
Owen Anderson825b72b2009-08-11 20:47:22 +0000861 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);
Evan Cheng44bec522007-05-15 01:29:07 +0000862}
863
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000864SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
865 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengaf4550f2009-07-02 01:23:32 +0000866 ISD::MemIndexedMode AM = LD->getAddressingMode();
867 if (AM == ISD::UNINDEXED)
868 return NULL;
869
Owen Andersone50ed302009-08-10 22:56:29 +0000870 EVT LoadedVT = LD->getMemoryVT();
Evan Chengaf4550f2009-07-02 01:23:32 +0000871 SDValue Offset, AMOpc;
872 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
873 unsigned Opcode = 0;
874 bool Match = false;
Owen Anderson825b72b2009-08-11 20:47:22 +0000875 if (LoadedVT == MVT::i32 &&
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000876 SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengaf4550f2009-07-02 01:23:32 +0000877 Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST;
878 Match = true;
Owen Anderson825b72b2009-08-11 20:47:22 +0000879 } else if (LoadedVT == MVT::i16 &&
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000880 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengaf4550f2009-07-02 01:23:32 +0000881 Match = true;
882 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
883 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
884 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson825b72b2009-08-11 20:47:22 +0000885 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengaf4550f2009-07-02 01:23:32 +0000886 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000887 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengaf4550f2009-07-02 01:23:32 +0000888 Match = true;
889 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
890 }
891 } else {
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000892 if (SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengaf4550f2009-07-02 01:23:32 +0000893 Match = true;
894 Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST;
895 }
896 }
897 }
898
899 if (Match) {
900 SDValue Chain = LD->getChain();
901 SDValue Base = LD->getBasePtr();
902 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG),
Owen Anderson825b72b2009-08-11 20:47:22 +0000903 CurDAG->getRegister(0, MVT::i32), Chain };
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000904 return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32,
Dan Gohman602b0c82009-09-25 18:54:59 +0000905 MVT::Other, Ops, 6);
Evan Chengaf4550f2009-07-02 01:23:32 +0000906 }
907
908 return NULL;
909}
910
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000911SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
912 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chenge88d5ce2009-07-02 07:28:31 +0000913 ISD::MemIndexedMode AM = LD->getAddressingMode();
914 if (AM == ISD::UNINDEXED)
915 return NULL;
916
Owen Andersone50ed302009-08-10 22:56:29 +0000917 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng4fbb9962009-07-02 23:16:11 +0000918 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Chenge88d5ce2009-07-02 07:28:31 +0000919 SDValue Offset;
920 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
921 unsigned Opcode = 0;
922 bool Match = false;
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000923 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson825b72b2009-08-11 20:47:22 +0000924 switch (LoadedVT.getSimpleVT().SimpleTy) {
925 case MVT::i32:
Evan Chenge88d5ce2009-07-02 07:28:31 +0000926 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
927 break;
Owen Anderson825b72b2009-08-11 20:47:22 +0000928 case MVT::i16:
Evan Cheng4fbb9962009-07-02 23:16:11 +0000929 if (isSExtLd)
930 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
931 else
932 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Chenge88d5ce2009-07-02 07:28:31 +0000933 break;
Owen Anderson825b72b2009-08-11 20:47:22 +0000934 case MVT::i8:
935 case MVT::i1:
Evan Cheng4fbb9962009-07-02 23:16:11 +0000936 if (isSExtLd)
937 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
938 else
939 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Chenge88d5ce2009-07-02 07:28:31 +0000940 break;
941 default:
942 return NULL;
943 }
944 Match = true;
945 }
946
947 if (Match) {
948 SDValue Chain = LD->getChain();
949 SDValue Base = LD->getBasePtr();
950 SDValue Ops[]= { Base, Offset, getAL(CurDAG),
Owen Anderson825b72b2009-08-11 20:47:22 +0000951 CurDAG->getRegister(0, MVT::i32), Chain };
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000952 return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32,
Dan Gohman602b0c82009-09-25 18:54:59 +0000953 MVT::Other, Ops, 5);
Evan Chenge88d5ce2009-07-02 07:28:31 +0000954 }
955
956 return NULL;
957}
958
Bob Wilson40cbe7d2010-06-04 00:04:02 +0000959/// PairSRegs - Form a D register from a pair of S registers.
960///
961SDNode *ARMDAGToDAGISel::PairSRegs(EVT VT, SDValue V0, SDValue V1) {
962 DebugLoc dl = V0.getNode()->getDebugLoc();
963 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
964 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
965 if (llvm::ModelWithRegSequence()) {
966 const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 };
967 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4);
968 }
969 SDValue Undef =
970 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0);
971 SDNode *Pair = CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
972 VT, Undef, V0, SubReg0);
973 return CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
974 VT, SDValue(Pair, 0), V1, SubReg1);
975}
976
Evan Cheng603afbf2010-05-10 17:34:18 +0000977/// PairDRegs - Form a quad register from a pair of D registers.
978///
Bob Wilson3bf12ab2009-10-06 22:01:59 +0000979SDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) {
980 DebugLoc dl = V0.getNode()->getDebugLoc();
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +0000981 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
982 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
Evan Chengde8aa4e2010-05-05 18:28:36 +0000983 if (llvm::ModelWithRegSequence()) {
Evan Cheng94cc6d32010-05-04 20:39:49 +0000984 const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 };
985 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4);
986 }
987 SDValue Undef =
988 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0);
Chris Lattner518bb532010-02-09 19:54:29 +0000989 SDNode *Pair = CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
Bob Wilson3bf12ab2009-10-06 22:01:59 +0000990 VT, Undef, V0, SubReg0);
Chris Lattner518bb532010-02-09 19:54:29 +0000991 return CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
Bob Wilson3bf12ab2009-10-06 22:01:59 +0000992 VT, SDValue(Pair, 0), V1, SubReg1);
993}
994
Evan Cheng7f687192010-05-14 00:21:45 +0000995/// PairQRegs - Form 4 consecutive D registers from a pair of Q registers.
Evan Cheng603afbf2010-05-10 17:34:18 +0000996///
997SDNode *ARMDAGToDAGISel::PairQRegs(EVT VT, SDValue V0, SDValue V1) {
998 DebugLoc dl = V0.getNode()->getDebugLoc();
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +0000999 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1000 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
Evan Cheng603afbf2010-05-10 17:34:18 +00001001 const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 };
1002 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4);
1003}
1004
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001005/// QuadSRegs - Form 4 consecutive S registers.
1006///
1007SDNode *ARMDAGToDAGISel::QuadSRegs(EVT VT, SDValue V0, SDValue V1,
1008 SDValue V2, SDValue V3) {
1009 DebugLoc dl = V0.getNode()->getDebugLoc();
1010 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1011 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
1012 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, MVT::i32);
1013 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, MVT::i32);
1014 const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 };
1015 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8);
1016}
1017
Evan Cheng7f687192010-05-14 00:21:45 +00001018/// QuadDRegs - Form 4 consecutive D registers.
Evan Cheng603afbf2010-05-10 17:34:18 +00001019///
1020SDNode *ARMDAGToDAGISel::QuadDRegs(EVT VT, SDValue V0, SDValue V1,
1021 SDValue V2, SDValue V3) {
1022 DebugLoc dl = V0.getNode()->getDebugLoc();
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001023 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1024 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
1025 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32);
1026 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32);
Evan Cheng603afbf2010-05-10 17:34:18 +00001027 const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 };
1028 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8);
1029}
1030
Evan Cheng8f6de382010-05-16 03:27:48 +00001031/// QuadQRegs - Form 4 consecutive Q registers.
1032///
1033SDNode *ARMDAGToDAGISel::QuadQRegs(EVT VT, SDValue V0, SDValue V1,
1034 SDValue V2, SDValue V3) {
1035 DebugLoc dl = V0.getNode()->getDebugLoc();
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001036 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1037 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
1038 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32);
1039 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32);
Evan Cheng8f6de382010-05-16 03:27:48 +00001040 const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 };
1041 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8);
1042}
1043
Evan Cheng5c6aba22010-05-14 18:54:59 +00001044/// OctoDRegs - Form 8 consecutive D registers.
1045///
1046SDNode *ARMDAGToDAGISel::OctoDRegs(EVT VT, SDValue V0, SDValue V1,
1047 SDValue V2, SDValue V3,
1048 SDValue V4, SDValue V5,
1049 SDValue V6, SDValue V7) {
1050 DebugLoc dl = V0.getNode()->getDebugLoc();
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001051 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1052 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
1053 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32);
1054 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32);
1055 SDValue SubReg4 = CurDAG->getTargetConstant(ARM::dsub_4, MVT::i32);
1056 SDValue SubReg5 = CurDAG->getTargetConstant(ARM::dsub_5, MVT::i32);
1057 SDValue SubReg6 = CurDAG->getTargetConstant(ARM::dsub_6, MVT::i32);
1058 SDValue SubReg7 = CurDAG->getTargetConstant(ARM::dsub_7, MVT::i32);
Evan Cheng5c6aba22010-05-14 18:54:59 +00001059 const SDValue Ops[] ={ V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3,
1060 V4, SubReg4, V5, SubReg5, V6, SubReg6, V7, SubReg7 };
1061 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 16);
1062}
1063
Bob Wilsona7c397c2009-10-14 16:19:03 +00001064/// GetNEONSubregVT - Given a type for a 128-bit NEON vector, return the type
1065/// for a 64-bit subregister of the vector.
1066static EVT GetNEONSubregVT(EVT VT) {
1067 switch (VT.getSimpleVT().SimpleTy) {
1068 default: llvm_unreachable("unhandled NEON type");
1069 case MVT::v16i8: return MVT::v8i8;
1070 case MVT::v8i16: return MVT::v4i16;
1071 case MVT::v4f32: return MVT::v2f32;
1072 case MVT::v4i32: return MVT::v2i32;
1073 case MVT::v2i64: return MVT::v1i64;
1074 }
1075}
1076
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001077SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs,
Bob Wilson3e36f132009-10-14 17:28:52 +00001078 unsigned *DOpcodes, unsigned *QOpcodes0,
1079 unsigned *QOpcodes1) {
Bob Wilson621f1952010-03-23 05:25:43 +00001080 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Bob Wilson3e36f132009-10-14 17:28:52 +00001081 DebugLoc dl = N->getDebugLoc();
1082
Bob Wilson226036e2010-03-20 22:13:40 +00001083 SDValue MemAddr, Align;
1084 if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align))
Bob Wilson3e36f132009-10-14 17:28:52 +00001085 return NULL;
1086
1087 SDValue Chain = N->getOperand(0);
1088 EVT VT = N->getValueType(0);
1089 bool is64BitVector = VT.is64BitVector();
1090
1091 unsigned OpcodeIndex;
1092 switch (VT.getSimpleVT().SimpleTy) {
1093 default: llvm_unreachable("unhandled vld type");
1094 // Double-register operations:
1095 case MVT::v8i8: OpcodeIndex = 0; break;
1096 case MVT::v4i16: OpcodeIndex = 1; break;
1097 case MVT::v2f32:
1098 case MVT::v2i32: OpcodeIndex = 2; break;
1099 case MVT::v1i64: OpcodeIndex = 3; break;
1100 // Quad-register operations:
1101 case MVT::v16i8: OpcodeIndex = 0; break;
1102 case MVT::v8i16: OpcodeIndex = 1; break;
1103 case MVT::v4f32:
1104 case MVT::v4i32: OpcodeIndex = 2; break;
Bob Wilson621f1952010-03-23 05:25:43 +00001105 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilson11d98992010-03-23 06:20:33 +00001106 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson621f1952010-03-23 05:25:43 +00001107 break;
Bob Wilson3e36f132009-10-14 17:28:52 +00001108 }
1109
Evan Cheng47b7b9f2010-04-16 05:46:06 +00001110 SDValue Pred = getAL(CurDAG);
Bob Wilson226036e2010-03-20 22:13:40 +00001111 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson3e36f132009-10-14 17:28:52 +00001112 if (is64BitVector) {
1113 unsigned Opc = DOpcodes[OpcodeIndex];
Bob Wilson226036e2010-03-20 22:13:40 +00001114 const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain };
Bob Wilson3e36f132009-10-14 17:28:52 +00001115 std::vector<EVT> ResTys(NumVecs, VT);
1116 ResTys.push_back(MVT::Other);
Evan Chenge9e2ba02010-05-10 21:26:24 +00001117 SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 5);
1118 if (!llvm::ModelWithRegSequence() || NumVecs < 2)
1119 return VLd;
1120
Evan Cheng0ce537a2010-05-11 01:19:40 +00001121 SDValue RegSeq;
Evan Chenge9e2ba02010-05-10 21:26:24 +00001122 SDValue V0 = SDValue(VLd, 0);
1123 SDValue V1 = SDValue(VLd, 1);
Evan Chenge9e2ba02010-05-10 21:26:24 +00001124
Evan Cheng0ce537a2010-05-11 01:19:40 +00001125 // Form a REG_SEQUENCE to force register allocation.
Evan Chenge9e2ba02010-05-10 21:26:24 +00001126 if (NumVecs == 2)
1127 RegSeq = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0);
1128 else {
1129 SDValue V2 = SDValue(VLd, 2);
Evan Cheng0ce537a2010-05-11 01:19:40 +00001130 // If it's a vld3, form a quad D-register but discard the last part.
Evan Chenge9e2ba02010-05-10 21:26:24 +00001131 SDValue V3 = (NumVecs == 3)
1132 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
1133 : SDValue(VLd, 3);
1134 RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0);
1135 }
1136
Jakob Stoklund Olesen7bb31e32010-05-24 17:13:28 +00001137 assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
Evan Cheng5c6aba22010-05-14 18:54:59 +00001138 for (unsigned Vec = 0; Vec < NumVecs; ++Vec) {
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001139 SDValue D = CurDAG->getTargetExtractSubreg(ARM::dsub_0+Vec,
Evan Cheng5c6aba22010-05-14 18:54:59 +00001140 dl, VT, RegSeq);
1141 ReplaceUses(SDValue(N, Vec), D);
Evan Chenge9e2ba02010-05-10 21:26:24 +00001142 }
1143 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, NumVecs));
1144 return NULL;
Bob Wilson3e36f132009-10-14 17:28:52 +00001145 }
1146
1147 EVT RegVT = GetNEONSubregVT(VT);
Bob Wilson621f1952010-03-23 05:25:43 +00001148 if (NumVecs <= 2) {
1149 // Quad registers are directly supported for VLD1 and VLD2,
1150 // loading pairs of D regs.
Bob Wilson3e36f132009-10-14 17:28:52 +00001151 unsigned Opc = QOpcodes0[OpcodeIndex];
Bob Wilson226036e2010-03-20 22:13:40 +00001152 const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain };
Bob Wilson621f1952010-03-23 05:25:43 +00001153 std::vector<EVT> ResTys(2 * NumVecs, RegVT);
Bob Wilson3e36f132009-10-14 17:28:52 +00001154 ResTys.push_back(MVT::Other);
Bob Wilson226036e2010-03-20 22:13:40 +00001155 SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 5);
Bob Wilson621f1952010-03-23 05:25:43 +00001156 Chain = SDValue(VLd, 2 * NumVecs);
Bob Wilson3e36f132009-10-14 17:28:52 +00001157
1158 // Combine the even and odd subregs to produce the result.
Evan Cheng603afbf2010-05-10 17:34:18 +00001159 if (llvm::ModelWithRegSequence()) {
1160 if (NumVecs == 1) {
1161 SDNode *Q = PairDRegs(VT, SDValue(VLd, 0), SDValue(VLd, 1));
1162 ReplaceUses(SDValue(N, 0), SDValue(Q, 0));
1163 } else {
1164 SDValue QQ = SDValue(QuadDRegs(MVT::v4i64,
1165 SDValue(VLd, 0), SDValue(VLd, 1),
1166 SDValue(VLd, 2), SDValue(VLd, 3)), 0);
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001167 SDValue Q0 = CurDAG->getTargetExtractSubreg(ARM::qsub_0, dl, VT, QQ);
1168 SDValue Q1 = CurDAG->getTargetExtractSubreg(ARM::qsub_1, dl, VT, QQ);
Evan Cheng603afbf2010-05-10 17:34:18 +00001169 ReplaceUses(SDValue(N, 0), Q0);
1170 ReplaceUses(SDValue(N, 1), Q1);
1171 }
1172 } else {
1173 for (unsigned Vec = 0; Vec < NumVecs; ++Vec) {
1174 SDNode *Q = PairDRegs(VT, SDValue(VLd, 2*Vec), SDValue(VLd, 2*Vec+1));
1175 ReplaceUses(SDValue(N, Vec), SDValue(Q, 0));
1176 }
Bob Wilson3e36f132009-10-14 17:28:52 +00001177 }
1178 } else {
1179 // Otherwise, quad registers are loaded with two separate instructions,
1180 // where one loads the even registers and the other loads the odd registers.
1181
Bob Wilson3e36f132009-10-14 17:28:52 +00001182 std::vector<EVT> ResTys(NumVecs, RegVT);
1183 ResTys.push_back(MemAddr.getValueType());
1184 ResTys.push_back(MVT::Other);
1185
Bob Wilson24f995d2009-10-14 18:32:29 +00001186 // Load the even subregs.
Bob Wilson3e36f132009-10-14 17:28:52 +00001187 unsigned Opc = QOpcodes0[OpcodeIndex];
Bob Wilson226036e2010-03-20 22:13:40 +00001188 const SDValue OpsA[] = { MemAddr, Align, Reg0, Pred, Reg0, Chain };
1189 SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 6);
Bob Wilson3e36f132009-10-14 17:28:52 +00001190 Chain = SDValue(VLdA, NumVecs+1);
1191
Bob Wilson24f995d2009-10-14 18:32:29 +00001192 // Load the odd subregs.
Bob Wilson3e36f132009-10-14 17:28:52 +00001193 Opc = QOpcodes1[OpcodeIndex];
Bob Wilson226036e2010-03-20 22:13:40 +00001194 const SDValue OpsB[] = { SDValue(VLdA, NumVecs),
1195 Align, Reg0, Pred, Reg0, Chain };
1196 SDNode *VLdB = CurDAG->getMachineNode(Opc, dl, ResTys, OpsB, 6);
Bob Wilson3e36f132009-10-14 17:28:52 +00001197 Chain = SDValue(VLdB, NumVecs+1);
1198
Evan Cheng5c6aba22010-05-14 18:54:59 +00001199 if (llvm::ModelWithRegSequence()) {
1200 SDValue V0 = SDValue(VLdA, 0);
1201 SDValue V1 = SDValue(VLdB, 0);
1202 SDValue V2 = SDValue(VLdA, 1);
1203 SDValue V3 = SDValue(VLdB, 1);
1204 SDValue V4 = SDValue(VLdA, 2);
1205 SDValue V5 = SDValue(VLdB, 2);
1206 SDValue V6 = (NumVecs == 3)
1207 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,RegVT),
1208 0)
1209 : SDValue(VLdA, 3);
1210 SDValue V7 = (NumVecs == 3)
1211 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,RegVT),
1212 0)
1213 : SDValue(VLdB, 3);
1214 SDValue RegSeq = SDValue(OctoDRegs(MVT::v8i64, V0, V1, V2, V3,
1215 V4, V5, V6, V7), 0);
1216
1217 // Extract out the 3 / 4 Q registers.
Jakob Stoklund Olesen7bb31e32010-05-24 17:13:28 +00001218 assert(ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
Evan Cheng5c6aba22010-05-14 18:54:59 +00001219 for (unsigned Vec = 0; Vec < NumVecs; ++Vec) {
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001220 SDValue Q = CurDAG->getTargetExtractSubreg(ARM::qsub_0+Vec,
Evan Cheng5c6aba22010-05-14 18:54:59 +00001221 dl, VT, RegSeq);
1222 ReplaceUses(SDValue(N, Vec), Q);
1223 }
1224 } else {
1225 // Combine the even and odd subregs to produce the result.
1226 for (unsigned Vec = 0; Vec < NumVecs; ++Vec) {
1227 SDNode *Q = PairDRegs(VT, SDValue(VLdA, Vec), SDValue(VLdB, Vec));
1228 ReplaceUses(SDValue(N, Vec), SDValue(Q, 0));
1229 }
Bob Wilson3e36f132009-10-14 17:28:52 +00001230 }
1231 }
1232 ReplaceUses(SDValue(N, NumVecs), Chain);
1233 return NULL;
1234}
1235
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001236SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, unsigned NumVecs,
Bob Wilson24f995d2009-10-14 18:32:29 +00001237 unsigned *DOpcodes, unsigned *QOpcodes0,
1238 unsigned *QOpcodes1) {
Bob Wilson11d98992010-03-23 06:20:33 +00001239 assert(NumVecs >=1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Bob Wilson24f995d2009-10-14 18:32:29 +00001240 DebugLoc dl = N->getDebugLoc();
1241
Bob Wilson226036e2010-03-20 22:13:40 +00001242 SDValue MemAddr, Align;
1243 if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align))
Bob Wilson24f995d2009-10-14 18:32:29 +00001244 return NULL;
1245
1246 SDValue Chain = N->getOperand(0);
1247 EVT VT = N->getOperand(3).getValueType();
1248 bool is64BitVector = VT.is64BitVector();
1249
1250 unsigned OpcodeIndex;
1251 switch (VT.getSimpleVT().SimpleTy) {
1252 default: llvm_unreachable("unhandled vst type");
1253 // Double-register operations:
1254 case MVT::v8i8: OpcodeIndex = 0; break;
1255 case MVT::v4i16: OpcodeIndex = 1; break;
1256 case MVT::v2f32:
1257 case MVT::v2i32: OpcodeIndex = 2; break;
1258 case MVT::v1i64: OpcodeIndex = 3; break;
1259 // Quad-register operations:
1260 case MVT::v16i8: OpcodeIndex = 0; break;
1261 case MVT::v8i16: OpcodeIndex = 1; break;
1262 case MVT::v4f32:
1263 case MVT::v4i32: OpcodeIndex = 2; break;
Bob Wilson11d98992010-03-23 06:20:33 +00001264 case MVT::v2i64: OpcodeIndex = 3;
1265 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
1266 break;
Bob Wilson24f995d2009-10-14 18:32:29 +00001267 }
1268
Evan Cheng47b7b9f2010-04-16 05:46:06 +00001269 SDValue Pred = getAL(CurDAG);
Bob Wilson226036e2010-03-20 22:13:40 +00001270 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengac0869d2009-11-21 06:21:52 +00001271
Bob Wilson226036e2010-03-20 22:13:40 +00001272 SmallVector<SDValue, 10> Ops;
Bob Wilson24f995d2009-10-14 18:32:29 +00001273 Ops.push_back(MemAddr);
Jim Grosbach8a5ec862009-11-07 21:25:39 +00001274 Ops.push_back(Align);
Bob Wilson24f995d2009-10-14 18:32:29 +00001275
1276 if (is64BitVector) {
Evan Cheng0ce537a2010-05-11 01:19:40 +00001277 if (llvm::ModelWithRegSequence() && NumVecs >= 2) {
Evan Cheng0ce537a2010-05-11 01:19:40 +00001278 SDValue RegSeq;
1279 SDValue V0 = N->getOperand(0+3);
1280 SDValue V1 = N->getOperand(1+3);
1281
1282 // Form a REG_SEQUENCE to force register allocation.
1283 if (NumVecs == 2)
1284 RegSeq = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0);
1285 else {
1286 SDValue V2 = N->getOperand(2+3);
1287 // If it's a vld3, form a quad D-register and leave the last part as
1288 // an undef.
1289 SDValue V3 = (NumVecs == 3)
1290 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
1291 : N->getOperand(3+3);
1292 RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0);
1293 }
1294
1295 // Now extract the D registers back out.
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001296 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, VT,
Evan Cheng0ce537a2010-05-11 01:19:40 +00001297 RegSeq));
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001298 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, VT,
Evan Cheng0ce537a2010-05-11 01:19:40 +00001299 RegSeq));
1300 if (NumVecs > 2)
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001301 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_2, dl, VT,
Evan Cheng0ce537a2010-05-11 01:19:40 +00001302 RegSeq));
1303 if (NumVecs > 3)
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001304 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_3, dl, VT,
Evan Cheng0ce537a2010-05-11 01:19:40 +00001305 RegSeq));
1306 } else {
1307 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1308 Ops.push_back(N->getOperand(Vec+3));
1309 }
Evan Chengac0869d2009-11-21 06:21:52 +00001310 Ops.push_back(Pred);
Bob Wilson226036e2010-03-20 22:13:40 +00001311 Ops.push_back(Reg0); // predicate register
Bob Wilson24f995d2009-10-14 18:32:29 +00001312 Ops.push_back(Chain);
Evan Cheng0ce537a2010-05-11 01:19:40 +00001313 unsigned Opc = DOpcodes[OpcodeIndex];
Bob Wilson226036e2010-03-20 22:13:40 +00001314 return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+5);
Bob Wilson24f995d2009-10-14 18:32:29 +00001315 }
1316
1317 EVT RegVT = GetNEONSubregVT(VT);
Bob Wilson11d98992010-03-23 06:20:33 +00001318 if (NumVecs <= 2) {
1319 // Quad registers are directly supported for VST1 and VST2,
1320 // storing pairs of D regs.
Bob Wilson24f995d2009-10-14 18:32:29 +00001321 unsigned Opc = QOpcodes0[OpcodeIndex];
Evan Cheng603afbf2010-05-10 17:34:18 +00001322 if (llvm::ModelWithRegSequence() && NumVecs == 2) {
Evan Cheng0ce537a2010-05-11 01:19:40 +00001323 // First extract the pair of Q registers.
Evan Cheng603afbf2010-05-10 17:34:18 +00001324 SDValue Q0 = N->getOperand(3);
1325 SDValue Q1 = N->getOperand(4);
1326
1327 // Form a QQ register.
1328 SDValue QQ = SDValue(PairQRegs(MVT::v4i64, Q0, Q1), 0);
1329
1330 // Now extract the D registers back out.
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001331 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, RegVT,
Evan Cheng603afbf2010-05-10 17:34:18 +00001332 QQ));
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001333 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, RegVT,
Evan Cheng603afbf2010-05-10 17:34:18 +00001334 QQ));
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001335 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_2, dl, RegVT,
Evan Cheng603afbf2010-05-10 17:34:18 +00001336 QQ));
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001337 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_3, dl, RegVT,
Evan Cheng603afbf2010-05-10 17:34:18 +00001338 QQ));
1339 Ops.push_back(Pred);
1340 Ops.push_back(Reg0); // predicate register
1341 Ops.push_back(Chain);
1342 return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 5 + 4);
1343 } else {
1344 for (unsigned Vec = 0; Vec < NumVecs; ++Vec) {
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001345 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, RegVT,
Evan Cheng603afbf2010-05-10 17:34:18 +00001346 N->getOperand(Vec+3)));
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001347 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, RegVT,
Evan Cheng603afbf2010-05-10 17:34:18 +00001348 N->getOperand(Vec+3)));
1349 }
1350 Ops.push_back(Pred);
1351 Ops.push_back(Reg0); // predicate register
1352 Ops.push_back(Chain);
1353 return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(),
1354 5 + 2 * NumVecs);
Bob Wilson24f995d2009-10-14 18:32:29 +00001355 }
Bob Wilson24f995d2009-10-14 18:32:29 +00001356 }
1357
1358 // Otherwise, quad registers are stored with two separate instructions,
1359 // where one stores the even registers and the other stores the odd registers.
Evan Cheng12c24692010-05-14 22:54:52 +00001360 if (llvm::ModelWithRegSequence()) {
Evan Cheng12c24692010-05-14 22:54:52 +00001361 // Form the QQQQ REG_SEQUENCE.
1362 SDValue V[8];
1363 for (unsigned Vec = 0, i = 0; Vec < NumVecs; ++Vec, i+=2) {
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001364 V[i] = CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, RegVT,
Evan Cheng12c24692010-05-14 22:54:52 +00001365 N->getOperand(Vec+3));
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001366 V[i+1] = CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, RegVT,
Evan Cheng12c24692010-05-14 22:54:52 +00001367 N->getOperand(Vec+3));
1368 }
1369 if (NumVecs == 3)
Evan Cheng7189fd02010-05-15 07:53:37 +00001370 V[6] = V[7] = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
1371 dl, RegVT), 0);
1372
Evan Cheng12c24692010-05-14 22:54:52 +00001373 SDValue RegSeq = SDValue(OctoDRegs(MVT::v8i64, V[0], V[1], V[2], V[3],
1374 V[4], V[5], V[6], V[7]), 0);
Bob Wilsona43e6bf2010-03-16 23:01:13 +00001375
Evan Cheng12c24692010-05-14 22:54:52 +00001376 // Store the even D registers.
Jakob Stoklund Olesen7bb31e32010-05-24 17:13:28 +00001377 assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
Evan Cheng12c24692010-05-14 22:54:52 +00001378 Ops.push_back(Reg0); // post-access address offset
1379 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001380 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0+Vec*2, dl,
Evan Cheng12c24692010-05-14 22:54:52 +00001381 RegVT, RegSeq));
1382 Ops.push_back(Pred);
1383 Ops.push_back(Reg0); // predicate register
1384 Ops.push_back(Chain);
1385 unsigned Opc = QOpcodes0[OpcodeIndex];
1386 SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(),
1387 MVT::Other, Ops.data(), NumVecs+6);
1388 Chain = SDValue(VStA, 1);
Bob Wilson24f995d2009-10-14 18:32:29 +00001389
Evan Cheng12c24692010-05-14 22:54:52 +00001390 // Store the odd D registers.
1391 Ops[0] = SDValue(VStA, 0); // MemAddr
1392 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001393 Ops[Vec+3] = CurDAG->getTargetExtractSubreg(ARM::dsub_1+Vec*2, dl,
Evan Cheng12c24692010-05-14 22:54:52 +00001394 RegVT, RegSeq);
1395 Ops[NumVecs+5] = Chain;
1396 Opc = QOpcodes1[OpcodeIndex];
1397 SDNode *VStB = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(),
1398 MVT::Other, Ops.data(), NumVecs+6);
1399 Chain = SDValue(VStB, 1);
1400 ReplaceUses(SDValue(N, 0), Chain);
1401 return NULL;
1402 } else {
1403 Ops.push_back(Reg0); // post-access address offset
1404
1405 // Store the even subregs.
1406 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001407 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, RegVT,
Evan Cheng12c24692010-05-14 22:54:52 +00001408 N->getOperand(Vec+3)));
1409 Ops.push_back(Pred);
1410 Ops.push_back(Reg0); // predicate register
1411 Ops.push_back(Chain);
1412 unsigned Opc = QOpcodes0[OpcodeIndex];
1413 SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(),
1414 MVT::Other, Ops.data(), NumVecs+6);
1415 Chain = SDValue(VStA, 1);
1416
1417 // Store the odd subregs.
1418 Ops[0] = SDValue(VStA, 0); // MemAddr
1419 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001420 Ops[Vec+3] = CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, RegVT,
Evan Cheng12c24692010-05-14 22:54:52 +00001421 N->getOperand(Vec+3));
1422 Ops[NumVecs+5] = Chain;
1423 Opc = QOpcodes1[OpcodeIndex];
1424 SDNode *VStB = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(),
1425 MVT::Other, Ops.data(), NumVecs+6);
1426 Chain = SDValue(VStB, 1);
1427 ReplaceUses(SDValue(N, 0), Chain);
1428 return NULL;
1429 }
Bob Wilson24f995d2009-10-14 18:32:29 +00001430}
1431
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001432SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
Bob Wilson96493442009-10-14 16:46:45 +00001433 unsigned NumVecs, unsigned *DOpcodes,
1434 unsigned *QOpcodes0,
1435 unsigned *QOpcodes1) {
1436 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Bob Wilsona7c397c2009-10-14 16:19:03 +00001437 DebugLoc dl = N->getDebugLoc();
1438
Bob Wilson226036e2010-03-20 22:13:40 +00001439 SDValue MemAddr, Align;
1440 if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align))
Bob Wilsona7c397c2009-10-14 16:19:03 +00001441 return NULL;
1442
1443 SDValue Chain = N->getOperand(0);
1444 unsigned Lane =
1445 cast<ConstantSDNode>(N->getOperand(NumVecs+3))->getZExtValue();
Bob Wilson96493442009-10-14 16:46:45 +00001446 EVT VT = IsLoad ? N->getValueType(0) : N->getOperand(3).getValueType();
Bob Wilsona7c397c2009-10-14 16:19:03 +00001447 bool is64BitVector = VT.is64BitVector();
1448
Bob Wilson96493442009-10-14 16:46:45 +00001449 // Quad registers are handled by load/store of subregs. Find the subreg info.
Bob Wilsona7c397c2009-10-14 16:19:03 +00001450 unsigned NumElts = 0;
1451 int SubregIdx = 0;
Evan Cheng8f6de382010-05-16 03:27:48 +00001452 bool Even = false;
Bob Wilsona7c397c2009-10-14 16:19:03 +00001453 EVT RegVT = VT;
1454 if (!is64BitVector) {
1455 RegVT = GetNEONSubregVT(VT);
1456 NumElts = RegVT.getVectorNumElements();
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001457 SubregIdx = (Lane < NumElts) ? ARM::dsub_0 : ARM::dsub_1;
Evan Cheng8f6de382010-05-16 03:27:48 +00001458 Even = Lane < NumElts;
Bob Wilsona7c397c2009-10-14 16:19:03 +00001459 }
1460
1461 unsigned OpcodeIndex;
1462 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson96493442009-10-14 16:46:45 +00001463 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilsona7c397c2009-10-14 16:19:03 +00001464 // Double-register operations:
1465 case MVT::v8i8: OpcodeIndex = 0; break;
1466 case MVT::v4i16: OpcodeIndex = 1; break;
1467 case MVT::v2f32:
1468 case MVT::v2i32: OpcodeIndex = 2; break;
1469 // Quad-register operations:
1470 case MVT::v8i16: OpcodeIndex = 0; break;
1471 case MVT::v4f32:
1472 case MVT::v4i32: OpcodeIndex = 1; break;
1473 }
1474
Evan Cheng47b7b9f2010-04-16 05:46:06 +00001475 SDValue Pred = getAL(CurDAG);
Bob Wilson226036e2010-03-20 22:13:40 +00001476 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengac0869d2009-11-21 06:21:52 +00001477
Bob Wilson226036e2010-03-20 22:13:40 +00001478 SmallVector<SDValue, 10> Ops;
Bob Wilsona7c397c2009-10-14 16:19:03 +00001479 Ops.push_back(MemAddr);
Jim Grosbach8a5ec862009-11-07 21:25:39 +00001480 Ops.push_back(Align);
Bob Wilsona7c397c2009-10-14 16:19:03 +00001481
1482 unsigned Opc = 0;
1483 if (is64BitVector) {
1484 Opc = DOpcodes[OpcodeIndex];
Evan Cheng8f6de382010-05-16 03:27:48 +00001485 if (llvm::ModelWithRegSequence()) {
1486 SDValue RegSeq;
1487 SDValue V0 = N->getOperand(0+3);
1488 SDValue V1 = N->getOperand(1+3);
1489 if (NumVecs == 2) {
1490 RegSeq = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0);
1491 } else {
1492 SDValue V2 = N->getOperand(2+3);
1493 SDValue V3 = (NumVecs == 3)
1494 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
1495 : N->getOperand(3+3);
1496 RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0);
1497 }
1498
1499 // Now extract the D registers back out.
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001500 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_0, dl, VT,
Evan Cheng8f6de382010-05-16 03:27:48 +00001501 RegSeq));
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001502 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_1, dl, VT,
Evan Cheng8f6de382010-05-16 03:27:48 +00001503 RegSeq));
1504 if (NumVecs > 2)
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001505 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_2, dl, VT,
Evan Cheng8f6de382010-05-16 03:27:48 +00001506 RegSeq));
1507 if (NumVecs > 3)
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001508 Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::dsub_3, dl, VT,
Evan Cheng8f6de382010-05-16 03:27:48 +00001509 RegSeq));
1510 } else {
1511 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1512 Ops.push_back(N->getOperand(Vec+3));
1513 }
Bob Wilsona7c397c2009-10-14 16:19:03 +00001514 } else {
1515 // Check if this is loading the even or odd subreg of a Q register.
1516 if (Lane < NumElts) {
1517 Opc = QOpcodes0[OpcodeIndex];
1518 } else {
1519 Lane -= NumElts;
1520 Opc = QOpcodes1[OpcodeIndex];
1521 }
Evan Cheng8f6de382010-05-16 03:27:48 +00001522
1523 if (llvm::ModelWithRegSequence()) {
1524 SDValue RegSeq;
1525 SDValue V0 = N->getOperand(0+3);
1526 SDValue V1 = N->getOperand(1+3);
1527 if (NumVecs == 2) {
1528 RegSeq = SDValue(PairQRegs(MVT::v4i64, V0, V1), 0);
1529 } else {
1530 SDValue V2 = N->getOperand(2+3);
1531 SDValue V3 = (NumVecs == 3)
1532 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
1533 : N->getOperand(3+3);
1534 RegSeq = SDValue(QuadQRegs(MVT::v8i64, V0, V1, V2, V3), 0);
1535 }
1536
1537 // Extract the subregs of the input vector.
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001538 unsigned SubIdx = Even ? ARM::dsub_0 : ARM::dsub_1;
Evan Cheng8f6de382010-05-16 03:27:48 +00001539 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1540 Ops.push_back(CurDAG->getTargetExtractSubreg(SubIdx+Vec*2, dl, RegVT,
1541 RegSeq));
1542 } else {
1543 // Extract the subregs of the input vector.
1544 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1545 Ops.push_back(CurDAG->getTargetExtractSubreg(SubregIdx, dl, RegVT,
1546 N->getOperand(Vec+3)));
1547 }
Bob Wilsona7c397c2009-10-14 16:19:03 +00001548 }
1549 Ops.push_back(getI32Imm(Lane));
Evan Chengac0869d2009-11-21 06:21:52 +00001550 Ops.push_back(Pred);
Bob Wilson226036e2010-03-20 22:13:40 +00001551 Ops.push_back(Reg0);
Bob Wilsona7c397c2009-10-14 16:19:03 +00001552 Ops.push_back(Chain);
1553
Bob Wilson96493442009-10-14 16:46:45 +00001554 if (!IsLoad)
Bob Wilson226036e2010-03-20 22:13:40 +00001555 return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+6);
Bob Wilson96493442009-10-14 16:46:45 +00001556
Bob Wilsona7c397c2009-10-14 16:19:03 +00001557 std::vector<EVT> ResTys(NumVecs, RegVT);
1558 ResTys.push_back(MVT::Other);
Evan Cheng7092c2b2010-05-15 01:36:29 +00001559 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(),NumVecs+6);
1560
Evan Cheng7189fd02010-05-15 07:53:37 +00001561 if (llvm::ModelWithRegSequence()) {
Evan Cheng7092c2b2010-05-15 01:36:29 +00001562 // Form a REG_SEQUENCE to force register allocation.
Evan Cheng7189fd02010-05-15 07:53:37 +00001563 SDValue RegSeq;
1564 if (is64BitVector) {
1565 SDValue V0 = SDValue(VLdLn, 0);
1566 SDValue V1 = SDValue(VLdLn, 1);
1567 if (NumVecs == 2) {
1568 RegSeq = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0);
1569 } else {
1570 SDValue V2 = SDValue(VLdLn, 2);
1571 // If it's a vld3, form a quad D-register but discard the last part.
1572 SDValue V3 = (NumVecs == 3)
Evan Cheng7092c2b2010-05-15 01:36:29 +00001573 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
1574 : SDValue(VLdLn, 3);
Evan Cheng7189fd02010-05-15 07:53:37 +00001575 RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0);
1576 }
1577 } else {
Jim Grosbach18f30e62010-06-02 21:53:11 +00001578 // For 128-bit vectors, take the 64-bit results of the load and insert
1579 // them as subregs into the result.
Evan Cheng7189fd02010-05-15 07:53:37 +00001580 SDValue V[8];
1581 for (unsigned Vec = 0, i = 0; Vec < NumVecs; ++Vec, i+=2) {
Evan Cheng8f6de382010-05-16 03:27:48 +00001582 if (Even) {
Evan Cheng7189fd02010-05-15 07:53:37 +00001583 V[i] = SDValue(VLdLn, Vec);
1584 V[i+1] = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
1585 dl, RegVT), 0);
1586 } else {
1587 V[i] = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
1588 dl, RegVT), 0);
1589 V[i+1] = SDValue(VLdLn, Vec);
1590 }
1591 }
1592 if (NumVecs == 3)
1593 V[6] = V[7] = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
1594 dl, RegVT), 0);
1595
1596 if (NumVecs == 2)
1597 RegSeq = SDValue(QuadDRegs(MVT::v4i64, V[0], V[1], V[2], V[3]), 0);
1598 else
1599 RegSeq = SDValue(OctoDRegs(MVT::v8i64, V[0], V[1], V[2], V[3],
1600 V[4], V[5], V[6], V[7]), 0);
Evan Cheng7092c2b2010-05-15 01:36:29 +00001601 }
1602
Jakob Stoklund Olesen7bb31e32010-05-24 17:13:28 +00001603 assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
1604 assert(ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001605 unsigned SubIdx = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Evan Cheng7189fd02010-05-15 07:53:37 +00001606 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1607 ReplaceUses(SDValue(N, Vec),
1608 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, RegSeq));
Evan Cheng7092c2b2010-05-15 01:36:29 +00001609 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, NumVecs));
1610 return NULL;
1611 }
1612
Bob Wilsona7c397c2009-10-14 16:19:03 +00001613 // For a 64-bit vector load to D registers, nothing more needs to be done.
1614 if (is64BitVector)
1615 return VLdLn;
1616
1617 // For 128-bit vectors, take the 64-bit results of the load and insert them
1618 // as subregs into the result.
1619 for (unsigned Vec = 0; Vec < NumVecs; ++Vec) {
1620 SDValue QuadVec = CurDAG->getTargetInsertSubreg(SubregIdx, dl, VT,
1621 N->getOperand(Vec+3),
1622 SDValue(VLdLn, Vec));
1623 ReplaceUses(SDValue(N, Vec), QuadVec);
1624 }
1625
1626 Chain = SDValue(VLdLn, NumVecs);
1627 ReplaceUses(SDValue(N, NumVecs), Chain);
1628 return NULL;
1629}
1630
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001631SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
Jim Grosbach3a1287b2010-04-22 23:24:18 +00001632 bool isSigned) {
Sandeep Patel47eedaa2009-10-13 18:59:48 +00001633 if (!Subtarget->hasV6T2Ops())
1634 return NULL;
Bob Wilson96493442009-10-14 16:46:45 +00001635
Jim Grosbach3a1287b2010-04-22 23:24:18 +00001636 unsigned Opc = isSigned ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
1637 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
1638
1639
1640 // For unsigned extracts, check for a shift right and mask
1641 unsigned And_imm = 0;
1642 if (N->getOpcode() == ISD::AND) {
1643 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
1644
1645 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
1646 if (And_imm & (And_imm + 1))
1647 return NULL;
1648
1649 unsigned Srl_imm = 0;
1650 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
1651 Srl_imm)) {
1652 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
1653
1654 unsigned Width = CountTrailingOnes_32(And_imm);
1655 unsigned LSB = Srl_imm;
1656 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
1657 SDValue Ops[] = { N->getOperand(0).getOperand(0),
1658 CurDAG->getTargetConstant(LSB, MVT::i32),
1659 CurDAG->getTargetConstant(Width, MVT::i32),
1660 getAL(CurDAG), Reg0 };
1661 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
1662 }
1663 }
1664 return NULL;
1665 }
1666
1667 // Otherwise, we're looking for a shift of a shift
Sandeep Patel47eedaa2009-10-13 18:59:48 +00001668 unsigned Shl_imm = 0;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001669 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel47eedaa2009-10-13 18:59:48 +00001670 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
1671 unsigned Srl_imm = 0;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001672 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel47eedaa2009-10-13 18:59:48 +00001673 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
1674 unsigned Width = 32 - Srl_imm;
1675 int LSB = Srl_imm - Shl_imm;
Evan Cheng8000c6c2009-10-22 00:40:00 +00001676 if (LSB < 0)
Sandeep Patel47eedaa2009-10-13 18:59:48 +00001677 return NULL;
1678 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001679 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sandeep Patel47eedaa2009-10-13 18:59:48 +00001680 CurDAG->getTargetConstant(LSB, MVT::i32),
1681 CurDAG->getTargetConstant(Width, MVT::i32),
1682 getAL(CurDAG), Reg0 };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001683 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Sandeep Patel47eedaa2009-10-13 18:59:48 +00001684 }
1685 }
1686 return NULL;
1687}
1688
Evan Cheng9ef48352009-11-20 00:54:03 +00001689SDNode *ARMDAGToDAGISel::
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001690SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00001691 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
1692 SDValue CPTmp0;
1693 SDValue CPTmp1;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001694 if (SelectT2ShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1)) {
Evan Cheng9ef48352009-11-20 00:54:03 +00001695 unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue();
1696 unsigned SOShOp = ARM_AM::getSORegShOp(SOVal);
1697 unsigned Opc = 0;
1698 switch (SOShOp) {
1699 case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break;
1700 case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break;
1701 case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break;
1702 case ARM_AM::ror: Opc = ARM::t2MOVCCror; break;
1703 default:
1704 llvm_unreachable("Unknown so_reg opcode!");
1705 break;
1706 }
1707 SDValue SOShImm =
1708 CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32);
1709 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
1710 SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001711 return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6);
Evan Cheng9ef48352009-11-20 00:54:03 +00001712 }
1713 return 0;
1714}
1715
1716SDNode *ARMDAGToDAGISel::
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001717SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00001718 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
1719 SDValue CPTmp0;
1720 SDValue CPTmp1;
1721 SDValue CPTmp2;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001722 if (SelectShifterOperandReg(N, TrueVal, CPTmp0, CPTmp1, CPTmp2)) {
Evan Cheng9ef48352009-11-20 00:54:03 +00001723 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
1724 SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001725 return CurDAG->SelectNodeTo(N, ARM::MOVCCs, MVT::i32, Ops, 7);
Evan Cheng9ef48352009-11-20 00:54:03 +00001726 }
1727 return 0;
1728}
1729
1730SDNode *ARMDAGToDAGISel::
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001731SelectT2CMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00001732 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
1733 ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal);
1734 if (!T)
1735 return 0;
1736
1737 if (Predicate_t2_so_imm(TrueVal.getNode())) {
1738 SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32);
1739 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
1740 SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001741 return CurDAG->SelectNodeTo(N,
Evan Cheng9ef48352009-11-20 00:54:03 +00001742 ARM::t2MOVCCi, MVT::i32, Ops, 5);
1743 }
1744 return 0;
1745}
1746
1747SDNode *ARMDAGToDAGISel::
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001748SelectARMCMOVSoImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00001749 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
1750 ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal);
1751 if (!T)
1752 return 0;
1753
1754 if (Predicate_so_imm(TrueVal.getNode())) {
1755 SDValue True = CurDAG->getTargetConstant(T->getZExtValue(), MVT::i32);
1756 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
1757 SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001758 return CurDAG->SelectNodeTo(N,
Evan Cheng9ef48352009-11-20 00:54:03 +00001759 ARM::MOVCCi, MVT::i32, Ops, 5);
1760 }
1761 return 0;
1762}
1763
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001764SDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) {
1765 EVT VT = N->getValueType(0);
1766 SDValue FalseVal = N->getOperand(0);
1767 SDValue TrueVal = N->getOperand(1);
1768 SDValue CC = N->getOperand(2);
1769 SDValue CCR = N->getOperand(3);
1770 SDValue InFlag = N->getOperand(4);
Evan Cheng9ef48352009-11-20 00:54:03 +00001771 assert(CC.getOpcode() == ISD::Constant);
1772 assert(CCR.getOpcode() == ISD::Register);
1773 ARMCC::CondCodes CCVal =
1774 (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue();
Evan Cheng07ba9062009-11-19 21:45:22 +00001775
1776 if (!Subtarget->isThumb1Only() && VT == MVT::i32) {
1777 // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
1778 // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
1779 // Pattern complexity = 18 cost = 1 size = 0
1780 SDValue CPTmp0;
1781 SDValue CPTmp1;
1782 SDValue CPTmp2;
1783 if (Subtarget->isThumb()) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001784 SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00001785 CCVal, CCR, InFlag);
1786 if (!Res)
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001787 Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00001788 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
1789 if (Res)
1790 return Res;
Evan Cheng07ba9062009-11-19 21:45:22 +00001791 } else {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001792 SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00001793 CCVal, CCR, InFlag);
1794 if (!Res)
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001795 Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00001796 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
1797 if (Res)
1798 return Res;
Evan Cheng07ba9062009-11-19 21:45:22 +00001799 }
1800
1801 // Pattern: (ARMcmov:i32 GPR:i32:$false,
1802 // (imm:i32)<<P:Predicate_so_imm>>:$true,
1803 // (imm:i32):$cc)
1804 // Emits: (MOVCCi:i32 GPR:i32:$false,
1805 // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc)
1806 // Pattern complexity = 10 cost = 1 size = 0
Evan Cheng9ef48352009-11-20 00:54:03 +00001807 if (Subtarget->isThumb()) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001808 SDNode *Res = SelectT2CMOVSoImmOp(N, FalseVal, TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00001809 CCVal, CCR, InFlag);
1810 if (!Res)
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001811 Res = SelectT2CMOVSoImmOp(N, TrueVal, FalseVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00001812 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
1813 if (Res)
1814 return Res;
1815 } else {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001816 SDNode *Res = SelectARMCMOVSoImmOp(N, FalseVal, TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00001817 CCVal, CCR, InFlag);
1818 if (!Res)
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001819 Res = SelectARMCMOVSoImmOp(N, TrueVal, FalseVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00001820 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
1821 if (Res)
1822 return Res;
Evan Cheng07ba9062009-11-19 21:45:22 +00001823 }
1824 }
1825
1826 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
1827 // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
1828 // Pattern complexity = 6 cost = 1 size = 0
1829 //
1830 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
1831 // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
1832 // Pattern complexity = 6 cost = 11 size = 0
1833 //
1834 // Also FCPYScc and FCPYDcc.
Evan Cheng9ef48352009-11-20 00:54:03 +00001835 SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32);
1836 SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag };
Evan Cheng07ba9062009-11-19 21:45:22 +00001837 unsigned Opc = 0;
1838 switch (VT.getSimpleVT().SimpleTy) {
1839 default: assert(false && "Illegal conditional move type!");
1840 break;
1841 case MVT::i32:
1842 Opc = Subtarget->isThumb()
1843 ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo)
1844 : ARM::MOVCCr;
1845 break;
1846 case MVT::f32:
1847 Opc = ARM::VMOVScc;
1848 break;
1849 case MVT::f64:
1850 Opc = ARM::VMOVDcc;
1851 break;
1852 }
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001853 return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5);
Evan Cheng07ba9062009-11-19 21:45:22 +00001854}
1855
Evan Chengde8aa4e2010-05-05 18:28:36 +00001856SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
1857 // The only time a CONCAT_VECTORS operation can have legal types is when
1858 // two 64-bit vectors are concatenated to a 128-bit vector.
1859 EVT VT = N->getValueType(0);
1860 if (!VT.is128BitVector() || N->getNumOperands() != 2)
1861 llvm_unreachable("unexpected CONCAT_VECTORS");
1862 DebugLoc dl = N->getDebugLoc();
1863 SDValue V0 = N->getOperand(0);
1864 SDValue V1 = N->getOperand(1);
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001865 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1866 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
Evan Chengde8aa4e2010-05-05 18:28:36 +00001867 const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 };
1868 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4);
1869}
1870
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001871SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
Dale Johannesened2eee62009-02-06 01:31:28 +00001872 DebugLoc dl = N->getDebugLoc();
Evan Chenga8e29892007-01-19 07:51:42 +00001873
Dan Gohmane8be6c62008-07-17 19:10:17 +00001874 if (N->isMachineOpcode())
Evan Chenga8e29892007-01-19 07:51:42 +00001875 return NULL; // Already selected.
Rafael Espindola337c4ad62006-06-12 12:28:08 +00001876
1877 switch (N->getOpcode()) {
Evan Chenga8e29892007-01-19 07:51:42 +00001878 default: break;
1879 case ISD::Constant: {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001880 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +00001881 bool UseCP = true;
Anton Korobeynikov6a2fa322009-09-27 23:52:58 +00001882 if (Subtarget->hasThumb2())
1883 // Thumb2-aware targets have the MOVT instruction, so all immediates can
1884 // be done with MOV + MOVT, at worst.
1885 UseCP = 0;
1886 else {
1887 if (Subtarget->isThumb()) {
Bob Wilsone64e3cf2009-06-22 17:29:13 +00001888 UseCP = (Val > 255 && // MOV
1889 ~Val > 255 && // MOV + MVN
1890 !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL
Anton Korobeynikov6a2fa322009-09-27 23:52:58 +00001891 } else
1892 UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV
1893 ARM_AM::getSOImmVal(~Val) == -1 && // MVN
1894 !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs.
1895 }
1896
Evan Chenga8e29892007-01-19 07:51:42 +00001897 if (UseCP) {
Dan Gohman475871a2008-07-27 21:46:04 +00001898 SDValue CPIdx =
Owen Anderson1d0be152009-08-13 21:58:54 +00001899 CurDAG->getTargetConstantPool(ConstantInt::get(
1900 Type::getInt32Ty(*CurDAG->getContext()), Val),
Evan Chenga8e29892007-01-19 07:51:42 +00001901 TLI.getPointerTy());
Evan Cheng012f2d92007-01-24 08:53:17 +00001902
1903 SDNode *ResNode;
Evan Cheng446c4282009-07-11 06:43:01 +00001904 if (Subtarget->isThumb1Only()) {
Evan Cheng47b7b9f2010-04-16 05:46:06 +00001905 SDValue Pred = getAL(CurDAG);
Owen Anderson825b72b2009-08-11 20:47:22 +00001906 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Cheng446c4282009-07-11 06:43:01 +00001907 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Dan Gohman602b0c82009-09-25 18:54:59 +00001908 ResNode = CurDAG->getMachineNode(ARM::tLDRcp, dl, MVT::i32, MVT::Other,
1909 Ops, 4);
Evan Cheng446c4282009-07-11 06:43:01 +00001910 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001911 SDValue Ops[] = {
Jim Grosbach764ab522009-08-11 15:33:49 +00001912 CPIdx,
Owen Anderson825b72b2009-08-11 20:47:22 +00001913 CurDAG->getRegister(0, MVT::i32),
1914 CurDAG->getTargetConstant(0, MVT::i32),
Evan Chengee568cf2007-07-05 07:15:27 +00001915 getAL(CurDAG),
Owen Anderson825b72b2009-08-11 20:47:22 +00001916 CurDAG->getRegister(0, MVT::i32),
Evan Cheng012f2d92007-01-24 08:53:17 +00001917 CurDAG->getEntryNode()
1918 };
Dan Gohman602b0c82009-09-25 18:54:59 +00001919 ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
1920 Ops, 6);
Evan Cheng012f2d92007-01-24 08:53:17 +00001921 }
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001922 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
Evan Chenga8e29892007-01-19 07:51:42 +00001923 return NULL;
1924 }
Jim Grosbach764ab522009-08-11 15:33:49 +00001925
Evan Chenga8e29892007-01-19 07:51:42 +00001926 // Other cases are autogenerated.
Rafael Espindola337c4ad62006-06-12 12:28:08 +00001927 break;
Evan Chenga8e29892007-01-19 07:51:42 +00001928 }
Rafael Espindolaf819a492006-11-09 13:58:55 +00001929 case ISD::FrameIndex: {
Evan Chenga8e29892007-01-19 07:51:42 +00001930 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindolaf819a492006-11-09 13:58:55 +00001931 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Dan Gohman475871a2008-07-27 21:46:04 +00001932 SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
David Goodwinf1daf7d2009-07-08 23:10:31 +00001933 if (Subtarget->isThumb1Only()) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001934 return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI,
1935 CurDAG->getTargetConstant(0, MVT::i32));
Jim Grosbach30eae3c2009-04-07 20:34:09 +00001936 } else {
David Goodwin419c6152009-07-14 18:48:51 +00001937 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
1938 ARM::t2ADDri : ARM::ADDri);
Owen Anderson825b72b2009-08-11 20:47:22 +00001939 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
1940 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
1941 CurDAG->getRegister(0, MVT::i32) };
1942 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Chengee568cf2007-07-05 07:15:27 +00001943 }
Evan Chenga8e29892007-01-19 07:51:42 +00001944 }
Sandeep Patel47eedaa2009-10-13 18:59:48 +00001945 case ISD::SRL:
Jim Grosbach3a1287b2010-04-22 23:24:18 +00001946 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
Sandeep Patel47eedaa2009-10-13 18:59:48 +00001947 return I;
1948 break;
1949 case ISD::SRA:
Jim Grosbach3a1287b2010-04-22 23:24:18 +00001950 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true))
Sandeep Patel47eedaa2009-10-13 18:59:48 +00001951 return I;
1952 break;
Evan Chenga8e29892007-01-19 07:51:42 +00001953 case ISD::MUL:
Evan Cheng5b9fcd12009-07-07 01:17:28 +00001954 if (Subtarget->isThumb1Only())
Evan Cheng79d43262007-01-24 02:21:22 +00001955 break;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001956 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001957 unsigned RHSV = C->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +00001958 if (!RHSV) break;
1959 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Chengaf9e7a72009-07-21 00:31:12 +00001960 unsigned ShImm = Log2_32(RHSV-1);
1961 if (ShImm >= 32)
1962 break;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001963 SDValue V = N->getOperand(0);
Evan Chengaf9e7a72009-07-21 00:31:12 +00001964 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson825b72b2009-08-11 20:47:22 +00001965 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
1966 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng78dd9db2009-07-22 18:08:05 +00001967 if (Subtarget->isThumb()) {
Evan Chengaf9e7a72009-07-21 00:31:12 +00001968 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson825b72b2009-08-11 20:47:22 +00001969 return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6);
Evan Chengaf9e7a72009-07-21 00:31:12 +00001970 } else {
1971 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson825b72b2009-08-11 20:47:22 +00001972 return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7);
Evan Chengaf9e7a72009-07-21 00:31:12 +00001973 }
Evan Chenga8e29892007-01-19 07:51:42 +00001974 }
1975 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Chengaf9e7a72009-07-21 00:31:12 +00001976 unsigned ShImm = Log2_32(RHSV+1);
1977 if (ShImm >= 32)
1978 break;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001979 SDValue V = N->getOperand(0);
Evan Chengaf9e7a72009-07-21 00:31:12 +00001980 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson825b72b2009-08-11 20:47:22 +00001981 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
1982 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng78dd9db2009-07-22 18:08:05 +00001983 if (Subtarget->isThumb()) {
Bob Wilson13ef8402010-05-28 00:27:15 +00001984 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
1985 return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 6);
Evan Chengaf9e7a72009-07-21 00:31:12 +00001986 } else {
1987 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson825b72b2009-08-11 20:47:22 +00001988 return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7);
Evan Chengaf9e7a72009-07-21 00:31:12 +00001989 }
Evan Chenga8e29892007-01-19 07:51:42 +00001990 }
1991 }
1992 break;
Evan Cheng20956592009-10-21 08:15:52 +00001993 case ISD::AND: {
Jim Grosbach3a1287b2010-04-22 23:24:18 +00001994 // Check for unsigned bitfield extract
1995 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
1996 return I;
1997
Evan Cheng20956592009-10-21 08:15:52 +00001998 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
1999 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2000 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2001 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2002 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002003 EVT VT = N->getValueType(0);
Evan Cheng20956592009-10-21 08:15:52 +00002004 if (VT != MVT::i32)
2005 break;
2006 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2007 ? ARM::t2MOVTi16
2008 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2009 if (!Opc)
2010 break;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002011 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
Evan Cheng20956592009-10-21 08:15:52 +00002012 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
2013 if (!N1C)
2014 break;
2015 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2016 SDValue N2 = N0.getOperand(1);
2017 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2018 if (!N2C)
2019 break;
2020 unsigned N1CVal = N1C->getZExtValue();
2021 unsigned N2CVal = N2C->getZExtValue();
2022 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2023 (N1CVal & 0xffffU) == 0xffffU &&
2024 (N2CVal & 0xffffU) == 0x0U) {
2025 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
2026 MVT::i32);
2027 SDValue Ops[] = { N0.getOperand(0), Imm16,
2028 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2029 return CurDAG->getMachineNode(Opc, dl, VT, Ops, 4);
2030 }
2031 }
2032 break;
2033 }
Jim Grosbache5165492009-11-09 00:11:35 +00002034 case ARMISD::VMOVRRD:
2035 return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002036 N->getOperand(0), getAL(CurDAG),
Dan Gohman602b0c82009-09-25 18:54:59 +00002037 CurDAG->getRegister(0, MVT::i32));
Dan Gohman525178c2007-10-08 18:33:35 +00002038 case ISD::UMUL_LOHI: {
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002039 if (Subtarget->isThumb1Only())
2040 break;
2041 if (Subtarget->isThumb()) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002042 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00002043 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2044 CurDAG->getRegister(0, MVT::i32) };
Jim Grosbach18f30e62010-06-02 21:53:11 +00002045 return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32,Ops,4);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002046 } else {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002047 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00002048 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2049 CurDAG->getRegister(0, MVT::i32) };
Dan Gohman602b0c82009-09-25 18:54:59 +00002050 return CurDAG->getMachineNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002051 }
Evan Chengee568cf2007-07-05 07:15:27 +00002052 }
Dan Gohman525178c2007-10-08 18:33:35 +00002053 case ISD::SMUL_LOHI: {
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002054 if (Subtarget->isThumb1Only())
2055 break;
2056 if (Subtarget->isThumb()) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002057 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00002058 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
Jim Grosbach18f30e62010-06-02 21:53:11 +00002059 return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32,Ops,4);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002060 } else {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002061 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00002062 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2063 CurDAG->getRegister(0, MVT::i32) };
Dan Gohman602b0c82009-09-25 18:54:59 +00002064 return CurDAG->getMachineNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002065 }
Evan Chengee568cf2007-07-05 07:15:27 +00002066 }
Evan Chenga8e29892007-01-19 07:51:42 +00002067 case ISD::LOAD: {
Evan Chenge88d5ce2009-07-02 07:28:31 +00002068 SDNode *ResNode = 0;
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002069 if (Subtarget->isThumb() && Subtarget->hasThumb2())
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002070 ResNode = SelectT2IndexedLoad(N);
Evan Chenge88d5ce2009-07-02 07:28:31 +00002071 else
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002072 ResNode = SelectARMIndexedLoad(N);
Evan Chengaf4550f2009-07-02 01:23:32 +00002073 if (ResNode)
2074 return ResNode;
Bob Wilsondf9a4f02010-03-23 18:54:46 +00002075
2076 // VLDMQ must be custom-selected for "v2f64 load" to set the AM5Opc value.
2077 if (Subtarget->hasVFP2() &&
2078 N->getValueType(0).getSimpleVT().SimpleTy == MVT::v2f64) {
2079 SDValue Chain = N->getOperand(0);
2080 SDValue AM5Opc =
2081 CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::ia, 4), MVT::i32);
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002082 SDValue Pred = getAL(CurDAG);
Bob Wilsondf9a4f02010-03-23 18:54:46 +00002083 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2084 SDValue Ops[] = { N->getOperand(1), AM5Opc, Pred, PredReg, Chain };
Evan Cheng3c3195c2010-05-19 06:06:09 +00002085 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2086 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
2087 SDNode *Ret = CurDAG->getMachineNode(ARM::VLDMQ, dl,
2088 MVT::v2f64, MVT::Other, Ops, 5);
2089 cast<MachineSDNode>(Ret)->setMemRefs(MemOp, MemOp + 1);
2090 return Ret;
Bob Wilsondf9a4f02010-03-23 18:54:46 +00002091 }
2092 // Other cases are autogenerated.
2093 break;
2094 }
2095 case ISD::STORE: {
2096 // VSTMQ must be custom-selected for "v2f64 store" to set the AM5Opc value.
2097 if (Subtarget->hasVFP2() &&
2098 N->getOperand(1).getValueType().getSimpleVT().SimpleTy == MVT::v2f64) {
2099 SDValue Chain = N->getOperand(0);
2100 SDValue AM5Opc =
2101 CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::ia, 4), MVT::i32);
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002102 SDValue Pred = getAL(CurDAG);
Bob Wilsondf9a4f02010-03-23 18:54:46 +00002103 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2104 SDValue Ops[] = { N->getOperand(1), N->getOperand(2),
2105 AM5Opc, Pred, PredReg, Chain };
Evan Cheng3c3195c2010-05-19 06:06:09 +00002106 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2107 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
2108 SDNode *Ret = CurDAG->getMachineNode(ARM::VSTMQ, dl, MVT::Other, Ops, 6);
2109 cast<MachineSDNode>(Ret)->setMemRefs(MemOp, MemOp + 1);
2110 return Ret;
Bob Wilsondf9a4f02010-03-23 18:54:46 +00002111 }
Evan Chenga8e29892007-01-19 07:51:42 +00002112 // Other cases are autogenerated.
Rafael Espindolaf819a492006-11-09 13:58:55 +00002113 break;
Rafael Espindola337c4ad62006-06-12 12:28:08 +00002114 }
Evan Chengee568cf2007-07-05 07:15:27 +00002115 case ARMISD::BRCOND: {
2116 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2117 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2118 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00002119
Evan Chengee568cf2007-07-05 07:15:27 +00002120 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2121 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2122 // Pattern complexity = 6 cost = 1 size = 0
2123
David Goodwin5e47a9a2009-06-30 18:04:13 +00002124 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2125 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2126 // Pattern complexity = 6 cost = 1 size = 0
2127
Jim Grosbach764ab522009-08-11 15:33:49 +00002128 unsigned Opc = Subtarget->isThumb() ?
David Goodwin5e47a9a2009-06-30 18:04:13 +00002129 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002130 SDValue Chain = N->getOperand(0);
2131 SDValue N1 = N->getOperand(1);
2132 SDValue N2 = N->getOperand(2);
2133 SDValue N3 = N->getOperand(3);
2134 SDValue InFlag = N->getOperand(4);
Evan Chengee568cf2007-07-05 07:15:27 +00002135 assert(N1.getOpcode() == ISD::BasicBlock);
2136 assert(N2.getOpcode() == ISD::Constant);
2137 assert(N3.getOpcode() == ISD::Register);
2138
Dan Gohman475871a2008-07-27 21:46:04 +00002139 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002140 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00002141 MVT::i32);
Dan Gohman475871a2008-07-27 21:46:04 +00002142 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman602b0c82009-09-25 18:54:59 +00002143 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
2144 MVT::Flag, Ops, 5);
Dan Gohman475871a2008-07-27 21:46:04 +00002145 Chain = SDValue(ResNode, 0);
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002146 if (N->getNumValues() == 2) {
Dan Gohman475871a2008-07-27 21:46:04 +00002147 InFlag = SDValue(ResNode, 1);
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002148 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnera47b9bc2008-02-03 03:20:59 +00002149 }
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002150 ReplaceUses(SDValue(N, 0),
Evan Chenged54de42009-11-19 08:16:50 +00002151 SDValue(Chain.getNode(), Chain.getResNo()));
Evan Chengee568cf2007-07-05 07:15:27 +00002152 return NULL;
2153 }
Evan Cheng07ba9062009-11-19 21:45:22 +00002154 case ARMISD::CMOV:
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002155 return SelectCMOVOp(N);
Evan Chengee568cf2007-07-05 07:15:27 +00002156 case ARMISD::CNEG: {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002157 EVT VT = N->getValueType(0);
2158 SDValue N0 = N->getOperand(0);
2159 SDValue N1 = N->getOperand(1);
2160 SDValue N2 = N->getOperand(2);
2161 SDValue N3 = N->getOperand(3);
2162 SDValue InFlag = N->getOperand(4);
Evan Chengee568cf2007-07-05 07:15:27 +00002163 assert(N2.getOpcode() == ISD::Constant);
2164 assert(N3.getOpcode() == ISD::Register);
2165
Dan Gohman475871a2008-07-27 21:46:04 +00002166 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002167 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00002168 MVT::i32);
Dan Gohman475871a2008-07-27 21:46:04 +00002169 SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag };
Evan Chengee568cf2007-07-05 07:15:27 +00002170 unsigned Opc = 0;
Owen Anderson825b72b2009-08-11 20:47:22 +00002171 switch (VT.getSimpleVT().SimpleTy) {
Evan Chengee568cf2007-07-05 07:15:27 +00002172 default: assert(false && "Illegal conditional move type!");
2173 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00002174 case MVT::f32:
Jim Grosbache5165492009-11-09 00:11:35 +00002175 Opc = ARM::VNEGScc;
Evan Chengee568cf2007-07-05 07:15:27 +00002176 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00002177 case MVT::f64:
Jim Grosbache5165492009-11-09 00:11:35 +00002178 Opc = ARM::VNEGDcc;
Evan Chenge5ad88e2008-12-10 21:54:21 +00002179 break;
Evan Chengee568cf2007-07-05 07:15:27 +00002180 }
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002181 return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5);
Evan Chengee568cf2007-07-05 07:15:27 +00002182 }
Evan Chenge5ad88e2008-12-10 21:54:21 +00002183
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002184 case ARMISD::VZIP: {
2185 unsigned Opc = 0;
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002186 EVT VT = N->getValueType(0);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002187 switch (VT.getSimpleVT().SimpleTy) {
2188 default: return NULL;
2189 case MVT::v8i8: Opc = ARM::VZIPd8; break;
2190 case MVT::v4i16: Opc = ARM::VZIPd16; break;
2191 case MVT::v2f32:
2192 case MVT::v2i32: Opc = ARM::VZIPd32; break;
2193 case MVT::v16i8: Opc = ARM::VZIPq8; break;
2194 case MVT::v8i16: Opc = ARM::VZIPq16; break;
2195 case MVT::v4f32:
2196 case MVT::v4i32: Opc = ARM::VZIPq32; break;
2197 }
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002198 SDValue Pred = getAL(CurDAG);
Evan Chengac0869d2009-11-21 06:21:52 +00002199 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2200 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
2201 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4);
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002202 }
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002203 case ARMISD::VUZP: {
2204 unsigned Opc = 0;
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002205 EVT VT = N->getValueType(0);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002206 switch (VT.getSimpleVT().SimpleTy) {
2207 default: return NULL;
2208 case MVT::v8i8: Opc = ARM::VUZPd8; break;
2209 case MVT::v4i16: Opc = ARM::VUZPd16; break;
2210 case MVT::v2f32:
2211 case MVT::v2i32: Opc = ARM::VUZPd32; break;
2212 case MVT::v16i8: Opc = ARM::VUZPq8; break;
2213 case MVT::v8i16: Opc = ARM::VUZPq16; break;
2214 case MVT::v4f32:
2215 case MVT::v4i32: Opc = ARM::VUZPq32; break;
2216 }
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002217 SDValue Pred = getAL(CurDAG);
Evan Chengac0869d2009-11-21 06:21:52 +00002218 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2219 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
2220 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4);
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002221 }
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002222 case ARMISD::VTRN: {
2223 unsigned Opc = 0;
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002224 EVT VT = N->getValueType(0);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002225 switch (VT.getSimpleVT().SimpleTy) {
2226 default: return NULL;
2227 case MVT::v8i8: Opc = ARM::VTRNd8; break;
2228 case MVT::v4i16: Opc = ARM::VTRNd16; break;
2229 case MVT::v2f32:
2230 case MVT::v2i32: Opc = ARM::VTRNd32; break;
2231 case MVT::v16i8: Opc = ARM::VTRNq8; break;
2232 case MVT::v8i16: Opc = ARM::VTRNq16; break;
2233 case MVT::v4f32:
2234 case MVT::v4i32: Opc = ARM::VTRNq32; break;
2235 }
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002236 SDValue Pred = getAL(CurDAG);
Evan Chengac0869d2009-11-21 06:21:52 +00002237 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2238 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
2239 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4);
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002240 }
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002241 case ARMISD::BUILD_VECTOR: {
2242 EVT VecVT = N->getValueType(0);
2243 EVT EltVT = VecVT.getVectorElementType();
2244 unsigned NumElts = VecVT.getVectorNumElements();
2245 if (EltVT.getSimpleVT() == MVT::f64) {
2246 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
2247 return PairDRegs(VecVT, N->getOperand(0), N->getOperand(1));
2248 }
2249 assert(EltVT.getSimpleVT() == MVT::f32 &&
2250 "unexpected type for BUILD_VECTOR");
2251 if (NumElts == 2)
2252 return PairSRegs(VecVT, N->getOperand(0), N->getOperand(1));
2253 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
2254 return QuadSRegs(VecVT, N->getOperand(0), N->getOperand(1),
2255 N->getOperand(2), N->getOperand(3));
2256 }
Bob Wilson31fb12f2009-08-26 17:39:53 +00002257
2258 case ISD::INTRINSIC_VOID:
2259 case ISD::INTRINSIC_W_CHAIN: {
2260 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilson31fb12f2009-08-26 17:39:53 +00002261 switch (IntNo) {
2262 default:
Bob Wilson429009b2010-05-06 16:05:26 +00002263 break;
Bob Wilson31fb12f2009-08-26 17:39:53 +00002264
Bob Wilson621f1952010-03-23 05:25:43 +00002265 case Intrinsic::arm_neon_vld1: {
2266 unsigned DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
2267 ARM::VLD1d32, ARM::VLD1d64 };
2268 unsigned QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
2269 ARM::VLD1q32, ARM::VLD1q64 };
2270 return SelectVLD(N, 1, DOpcodes, QOpcodes, 0);
2271 }
2272
Bob Wilson31fb12f2009-08-26 17:39:53 +00002273 case Intrinsic::arm_neon_vld2: {
Bob Wilson3e36f132009-10-14 17:28:52 +00002274 unsigned DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
Bob Wilson621f1952010-03-23 05:25:43 +00002275 ARM::VLD2d32, ARM::VLD1q64 };
Bob Wilson3e36f132009-10-14 17:28:52 +00002276 unsigned QOpcodes[] = { ARM::VLD2q8, ARM::VLD2q16, ARM::VLD2q32 };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002277 return SelectVLD(N, 2, DOpcodes, QOpcodes, 0);
Bob Wilson31fb12f2009-08-26 17:39:53 +00002278 }
2279
2280 case Intrinsic::arm_neon_vld3: {
Bob Wilson3e36f132009-10-14 17:28:52 +00002281 unsigned DOpcodes[] = { ARM::VLD3d8, ARM::VLD3d16,
Bob Wilsona6979752010-03-22 18:13:18 +00002282 ARM::VLD3d32, ARM::VLD1d64T };
Bob Wilson95ffecd2010-03-20 18:35:24 +00002283 unsigned QOpcodes0[] = { ARM::VLD3q8_UPD,
2284 ARM::VLD3q16_UPD,
2285 ARM::VLD3q32_UPD };
2286 unsigned QOpcodes1[] = { ARM::VLD3q8odd_UPD,
2287 ARM::VLD3q16odd_UPD,
2288 ARM::VLD3q32odd_UPD };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002289 return SelectVLD(N, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson31fb12f2009-08-26 17:39:53 +00002290 }
2291
2292 case Intrinsic::arm_neon_vld4: {
Bob Wilson3e36f132009-10-14 17:28:52 +00002293 unsigned DOpcodes[] = { ARM::VLD4d8, ARM::VLD4d16,
Bob Wilsona6979752010-03-22 18:13:18 +00002294 ARM::VLD4d32, ARM::VLD1d64Q };
Bob Wilson95ffecd2010-03-20 18:35:24 +00002295 unsigned QOpcodes0[] = { ARM::VLD4q8_UPD,
2296 ARM::VLD4q16_UPD,
2297 ARM::VLD4q32_UPD };
2298 unsigned QOpcodes1[] = { ARM::VLD4q8odd_UPD,
2299 ARM::VLD4q16odd_UPD,
2300 ARM::VLD4q32odd_UPD };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002301 return SelectVLD(N, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson31fb12f2009-08-26 17:39:53 +00002302 }
2303
Bob Wilson243fcc52009-09-01 04:26:28 +00002304 case Intrinsic::arm_neon_vld2lane: {
Bob Wilsona7c397c2009-10-14 16:19:03 +00002305 unsigned DOpcodes[] = { ARM::VLD2LNd8, ARM::VLD2LNd16, ARM::VLD2LNd32 };
Bob Wilson95ffecd2010-03-20 18:35:24 +00002306 unsigned QOpcodes0[] = { ARM::VLD2LNq16, ARM::VLD2LNq32 };
2307 unsigned QOpcodes1[] = { ARM::VLD2LNq16odd, ARM::VLD2LNq32odd };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002308 return SelectVLDSTLane(N, true, 2, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson243fcc52009-09-01 04:26:28 +00002309 }
2310
2311 case Intrinsic::arm_neon_vld3lane: {
Bob Wilsona7c397c2009-10-14 16:19:03 +00002312 unsigned DOpcodes[] = { ARM::VLD3LNd8, ARM::VLD3LNd16, ARM::VLD3LNd32 };
Bob Wilson95ffecd2010-03-20 18:35:24 +00002313 unsigned QOpcodes0[] = { ARM::VLD3LNq16, ARM::VLD3LNq32 };
2314 unsigned QOpcodes1[] = { ARM::VLD3LNq16odd, ARM::VLD3LNq32odd };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002315 return SelectVLDSTLane(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson243fcc52009-09-01 04:26:28 +00002316 }
2317
2318 case Intrinsic::arm_neon_vld4lane: {
Bob Wilsona7c397c2009-10-14 16:19:03 +00002319 unsigned DOpcodes[] = { ARM::VLD4LNd8, ARM::VLD4LNd16, ARM::VLD4LNd32 };
Bob Wilson95ffecd2010-03-20 18:35:24 +00002320 unsigned QOpcodes0[] = { ARM::VLD4LNq16, ARM::VLD4LNq32 };
2321 unsigned QOpcodes1[] = { ARM::VLD4LNq16odd, ARM::VLD4LNq32odd };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002322 return SelectVLDSTLane(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson243fcc52009-09-01 04:26:28 +00002323 }
2324
Bob Wilson11d98992010-03-23 06:20:33 +00002325 case Intrinsic::arm_neon_vst1: {
2326 unsigned DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
2327 ARM::VST1d32, ARM::VST1d64 };
2328 unsigned QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
2329 ARM::VST1q32, ARM::VST1q64 };
2330 return SelectVST(N, 1, DOpcodes, QOpcodes, 0);
2331 }
2332
Bob Wilson31fb12f2009-08-26 17:39:53 +00002333 case Intrinsic::arm_neon_vst2: {
Bob Wilson24f995d2009-10-14 18:32:29 +00002334 unsigned DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
Bob Wilson11d98992010-03-23 06:20:33 +00002335 ARM::VST2d32, ARM::VST1q64 };
Bob Wilson24f995d2009-10-14 18:32:29 +00002336 unsigned QOpcodes[] = { ARM::VST2q8, ARM::VST2q16, ARM::VST2q32 };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002337 return SelectVST(N, 2, DOpcodes, QOpcodes, 0);
Bob Wilson31fb12f2009-08-26 17:39:53 +00002338 }
2339
2340 case Intrinsic::arm_neon_vst3: {
Bob Wilson24f995d2009-10-14 18:32:29 +00002341 unsigned DOpcodes[] = { ARM::VST3d8, ARM::VST3d16,
Bob Wilsona6979752010-03-22 18:13:18 +00002342 ARM::VST3d32, ARM::VST1d64T };
Bob Wilson95ffecd2010-03-20 18:35:24 +00002343 unsigned QOpcodes0[] = { ARM::VST3q8_UPD,
2344 ARM::VST3q16_UPD,
2345 ARM::VST3q32_UPD };
2346 unsigned QOpcodes1[] = { ARM::VST3q8odd_UPD,
2347 ARM::VST3q16odd_UPD,
2348 ARM::VST3q32odd_UPD };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002349 return SelectVST(N, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson31fb12f2009-08-26 17:39:53 +00002350 }
2351
2352 case Intrinsic::arm_neon_vst4: {
Bob Wilson24f995d2009-10-14 18:32:29 +00002353 unsigned DOpcodes[] = { ARM::VST4d8, ARM::VST4d16,
Bob Wilsona6979752010-03-22 18:13:18 +00002354 ARM::VST4d32, ARM::VST1d64Q };
Bob Wilson95ffecd2010-03-20 18:35:24 +00002355 unsigned QOpcodes0[] = { ARM::VST4q8_UPD,
2356 ARM::VST4q16_UPD,
2357 ARM::VST4q32_UPD };
2358 unsigned QOpcodes1[] = { ARM::VST4q8odd_UPD,
2359 ARM::VST4q16odd_UPD,
2360 ARM::VST4q32odd_UPD };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002361 return SelectVST(N, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson31fb12f2009-08-26 17:39:53 +00002362 }
Bob Wilson8a3198b2009-09-01 18:51:56 +00002363
2364 case Intrinsic::arm_neon_vst2lane: {
Bob Wilson96493442009-10-14 16:46:45 +00002365 unsigned DOpcodes[] = { ARM::VST2LNd8, ARM::VST2LNd16, ARM::VST2LNd32 };
Bob Wilson95ffecd2010-03-20 18:35:24 +00002366 unsigned QOpcodes0[] = { ARM::VST2LNq16, ARM::VST2LNq32 };
2367 unsigned QOpcodes1[] = { ARM::VST2LNq16odd, ARM::VST2LNq32odd };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002368 return SelectVLDSTLane(N, false, 2, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson8a3198b2009-09-01 18:51:56 +00002369 }
2370
2371 case Intrinsic::arm_neon_vst3lane: {
Bob Wilson96493442009-10-14 16:46:45 +00002372 unsigned DOpcodes[] = { ARM::VST3LNd8, ARM::VST3LNd16, ARM::VST3LNd32 };
Bob Wilson95ffecd2010-03-20 18:35:24 +00002373 unsigned QOpcodes0[] = { ARM::VST3LNq16, ARM::VST3LNq32 };
2374 unsigned QOpcodes1[] = { ARM::VST3LNq16odd, ARM::VST3LNq32odd };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002375 return SelectVLDSTLane(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson8a3198b2009-09-01 18:51:56 +00002376 }
2377
2378 case Intrinsic::arm_neon_vst4lane: {
Bob Wilson96493442009-10-14 16:46:45 +00002379 unsigned DOpcodes[] = { ARM::VST4LNd8, ARM::VST4LNd16, ARM::VST4LNd32 };
Bob Wilson95ffecd2010-03-20 18:35:24 +00002380 unsigned QOpcodes0[] = { ARM::VST4LNq16, ARM::VST4LNq32 };
2381 unsigned QOpcodes1[] = { ARM::VST4LNq16odd, ARM::VST4LNq32odd };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002382 return SelectVLDSTLane(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson8a3198b2009-09-01 18:51:56 +00002383 }
Bob Wilson31fb12f2009-08-26 17:39:53 +00002384 }
Bob Wilson429009b2010-05-06 16:05:26 +00002385 break;
Bob Wilson31fb12f2009-08-26 17:39:53 +00002386 }
Evan Chengde8aa4e2010-05-05 18:28:36 +00002387
Bob Wilson429009b2010-05-06 16:05:26 +00002388 case ISD::CONCAT_VECTORS:
Evan Chengde8aa4e2010-05-05 18:28:36 +00002389 return SelectConcatVector(N);
2390 }
Evan Chenge5ad88e2008-12-10 21:54:21 +00002391
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002392 return SelectCode(N);
Evan Chenga8e29892007-01-19 07:51:42 +00002393}
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00002394
Bob Wilson224c2442009-05-19 05:53:42 +00002395bool ARMDAGToDAGISel::
2396SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
2397 std::vector<SDValue> &OutOps) {
2398 assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
Bob Wilson765cc0b2009-10-13 20:50:28 +00002399 // Require the address to be in a register. That is safe for all ARM
2400 // variants and it is hard to do anything much smarter without knowing
2401 // how the operand is used.
2402 OutOps.push_back(Op);
Bob Wilson224c2442009-05-19 05:53:42 +00002403 return false;
2404}
2405
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00002406/// createARMISelDag - This pass converts a legalized DAG into a
2407/// ARM-specific DAG, ready for instruction scheduling.
2408///
Bob Wilson522ce972009-09-28 14:30:20 +00002409FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
2410 CodeGenOpt::Level OptLevel) {
2411 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00002412}
Evan Chengde8aa4e2010-05-05 18:28:36 +00002413
2414/// ModelWithRegSequence - Return true if isel should use REG_SEQUENCE to model
2415/// operations involving sub-registers.
2416bool llvm::ModelWithRegSequence() {
2417 return UseRegSeq;
2418}