blob: 81229794a2c2bc8325773881b8ac54cb99a85be4 [file] [log] [blame]
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00001//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the ARM target.
11//
12//===----------------------------------------------------------------------===//
13
Dale Johannesen51e28e62010-06-03 21:09:53 +000014#define DEBUG_TYPE "arm-isel"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000015#include "ARM.h"
Evan Cheng48575f62010-12-05 22:04:16 +000016#include "ARMBaseInstrInfo.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000017#include "ARMTargetMachine.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000018#include "MCTargetDesc/ARMAddressingModes.h"
Rafael Espindola84b19be2006-07-16 01:02:57 +000019#include "llvm/CallingConv.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000020#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/SelectionDAG.h"
24#include "llvm/CodeGen/SelectionDAGISel.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000025#include "llvm/Constants.h"
26#include "llvm/DerivedTypes.h"
27#include "llvm/Function.h"
28#include "llvm/Intrinsics.h"
29#include "llvm/LLVMContext.h"
Evan Cheng94cc6d32010-05-04 20:39:49 +000030#include "llvm/Support/CommandLine.h"
Chris Lattner3d62d782008-02-03 05:43:57 +000031#include "llvm/Support/Compiler.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000032#include "llvm/Support/Debug.h"
Torok Edwindac237e2009-07-08 20:53:28 +000033#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Support/raw_ostream.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000035#include "llvm/Target/TargetLowering.h"
36#include "llvm/Target/TargetOptions.h"
Torok Edwindac237e2009-07-08 20:53:28 +000037
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000038using namespace llvm;
39
Evan Chenga2c519b2010-07-30 23:33:54 +000040static cl::opt<bool>
41DisableShifterOp("disable-shifter-op", cl::Hidden,
42 cl::desc("Disable isel of shifter-op"),
43 cl::init(false));
44
Evan Cheng48575f62010-12-05 22:04:16 +000045static cl::opt<bool>
46CheckVMLxHazard("check-vmlx-hazard", cl::Hidden,
47 cl::desc("Check fp vmla / vmls hazard at isel time"),
Bob Wilson84c5eed2011-04-19 18:11:57 +000048 cl::init(true));
Evan Cheng48575f62010-12-05 22:04:16 +000049
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000050//===--------------------------------------------------------------------===//
51/// ARMDAGToDAGISel - ARM specific code to select ARM machine
52/// instructions for SelectionDAG operations.
53///
54namespace {
Jim Grosbach82891622010-09-29 19:03:54 +000055
56enum AddrMode2Type {
57 AM2_BASE, // Simple AM2 (+-imm12)
58 AM2_SHOP // Shifter-op AM2
59};
60
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000061class ARMDAGToDAGISel : public SelectionDAGISel {
Anton Korobeynikovd49ea772009-06-26 21:28:53 +000062 ARMBaseTargetMachine &TM;
Evan Cheng48575f62010-12-05 22:04:16 +000063 const ARMBaseInstrInfo *TII;
Evan Cheng3f7eb8e2008-09-18 07:24:33 +000064
Evan Chenga8e29892007-01-19 07:51:42 +000065 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
66 /// make the right decision when generating code for different targets.
67 const ARMSubtarget *Subtarget;
68
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000069public:
Bob Wilson522ce972009-09-28 14:30:20 +000070 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm,
71 CodeGenOpt::Level OptLevel)
72 : SelectionDAGISel(tm, OptLevel), TM(tm),
Evan Cheng48575f62010-12-05 22:04:16 +000073 TII(static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo())),
74 Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000075 }
76
Evan Chenga8e29892007-01-19 07:51:42 +000077 virtual const char *getPassName() const {
78 return "ARM Instruction Selection";
Anton Korobeynikov52237112009-06-17 18:13:58 +000079 }
80
Bob Wilsonaf4a8912009-10-08 18:51:31 +000081 /// getI32Imm - Return a target constant of type i32 with the specified
82 /// value.
Anton Korobeynikov52237112009-06-17 18:13:58 +000083 inline SDValue getI32Imm(unsigned Imm) {
Owen Anderson825b72b2009-08-11 20:47:22 +000084 return CurDAG->getTargetConstant(Imm, MVT::i32);
Anton Korobeynikov52237112009-06-17 18:13:58 +000085 }
86
Dan Gohmaneeb3a002010-01-05 01:24:18 +000087 SDNode *Select(SDNode *N);
Evan Cheng014bf212010-02-15 19:41:07 +000088
Evan Cheng48575f62010-12-05 22:04:16 +000089
90 bool hasNoVMLxHazardUse(SDNode *N) const;
Evan Chengf40deed2010-10-27 23:41:30 +000091 bool isShifterOpProfitable(const SDValue &Shift,
92 ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt);
Owen Anderson92a20222011-07-21 18:54:16 +000093 bool SelectRegShifterOperand(SDValue N, SDValue &A,
94 SDValue &B, SDValue &C,
95 bool CheckProfitability = true);
96 bool SelectImmShifterOperand(SDValue N, SDValue &A,
Owen Anderson152d4a42011-07-21 23:38:37 +000097 SDValue &B, bool CheckProfitability = true);
98 bool SelectShiftRegShifterOperand(SDValue N, SDValue &A,
Owen Anderson099e5552011-03-18 19:46:58 +000099 SDValue &B, SDValue &C) {
100 // Don't apply the profitability check
Owen Anderson152d4a42011-07-21 23:38:37 +0000101 return SelectRegShifterOperand(N, A, B, C, false);
102 }
103 bool SelectShiftImmShifterOperand(SDValue N, SDValue &A,
104 SDValue &B) {
105 // Don't apply the profitability check
106 return SelectImmShifterOperand(N, A, B, false);
Owen Anderson099e5552011-03-18 19:46:58 +0000107 }
108
Jim Grosbach3e556122010-10-26 22:37:02 +0000109 bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
110 bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);
111
Jim Grosbach82891622010-09-29 19:03:54 +0000112 AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base,
113 SDValue &Offset, SDValue &Opc);
114 bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset,
115 SDValue &Opc) {
116 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE;
117 }
118
119 bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset,
120 SDValue &Opc) {
121 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP;
122 }
123
124 bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset,
125 SDValue &Opc) {
126 SelectAddrMode2Worker(N, Base, Offset, Opc);
Jim Grosbach3e556122010-10-26 22:37:02 +0000127// return SelectAddrMode2ShOp(N, Base, Offset, Opc);
Jim Grosbach82891622010-09-29 19:03:54 +0000128 // This always matches one way or another.
129 return true;
130 }
131
Owen Anderson793e7962011-07-26 20:54:26 +0000132 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
133 SDValue &Offset, SDValue &Opc);
134 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000135 SDValue &Offset, SDValue &Opc);
Owen Andersonc4e16de2011-08-29 20:16:50 +0000136 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
137 SDValue &Offset, SDValue &Opc);
Jim Grosbach19dec202011-08-05 20:35:44 +0000138 bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
Chris Lattner52a261b2010-09-21 20:31:19 +0000139 bool SelectAddrMode3(SDValue N, SDValue &Base,
Dan Gohman475871a2008-07-27 21:46:04 +0000140 SDValue &Offset, SDValue &Opc);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000141 bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000142 SDValue &Offset, SDValue &Opc);
Chris Lattner52a261b2010-09-21 20:31:19 +0000143 bool SelectAddrMode5(SDValue N, SDValue &Base,
Dan Gohman475871a2008-07-27 21:46:04 +0000144 SDValue &Offset);
Bob Wilson665814b2010-11-01 23:40:51 +0000145 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
Bob Wilsonda525062011-02-25 06:42:42 +0000146 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000147
Evan Cheng5de5d4b2011-01-17 08:03:18 +0000148 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
Evan Chenga8e29892007-01-19 07:51:42 +0000149
Bill Wendlingf4caf692010-12-14 03:36:38 +0000150 // Thumb Addressing Modes:
Chris Lattner52a261b2010-09-21 20:31:19 +0000151 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
Bill Wendlingf4caf692010-12-14 03:36:38 +0000152 bool SelectThumbAddrModeRI(SDValue N, SDValue &Base, SDValue &Offset,
153 unsigned Scale);
154 bool SelectThumbAddrModeRI5S1(SDValue N, SDValue &Base, SDValue &Offset);
155 bool SelectThumbAddrModeRI5S2(SDValue N, SDValue &Base, SDValue &Offset);
156 bool SelectThumbAddrModeRI5S4(SDValue N, SDValue &Base, SDValue &Offset);
157 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
158 SDValue &OffImm);
159 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
160 SDValue &OffImm);
161 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
162 SDValue &OffImm);
163 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
164 SDValue &OffImm);
Chris Lattner52a261b2010-09-21 20:31:19 +0000165 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Chenga8e29892007-01-19 07:51:42 +0000166
Bill Wendlingf4caf692010-12-14 03:36:38 +0000167 // Thumb 2 Addressing Modes:
Chris Lattner52a261b2010-09-21 20:31:19 +0000168 bool SelectT2ShifterOperandReg(SDValue N,
Evan Cheng9cb9e672009-06-27 02:26:13 +0000169 SDValue &BaseReg, SDValue &Opc);
Chris Lattner52a261b2010-09-21 20:31:19 +0000170 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
171 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
Evan Cheng055b0312009-06-29 07:51:04 +0000172 SDValue &OffImm);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000173 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Chenge88d5ce2009-07-02 07:28:31 +0000174 SDValue &OffImm);
Chris Lattner52a261b2010-09-21 20:31:19 +0000175 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
Evan Cheng055b0312009-06-29 07:51:04 +0000176 SDValue &OffReg, SDValue &ShImm);
177
Evan Cheng875a6ac2010-11-12 22:42:47 +0000178 inline bool is_so_imm(unsigned Imm) const {
179 return ARM_AM::getSOImmVal(Imm) != -1;
180 }
181
182 inline bool is_so_imm_not(unsigned Imm) const {
183 return ARM_AM::getSOImmVal(~Imm) != -1;
184 }
185
186 inline bool is_t2_so_imm(unsigned Imm) const {
187 return ARM_AM::getT2SOImmVal(Imm) != -1;
188 }
189
190 inline bool is_t2_so_imm_not(unsigned Imm) const {
191 return ARM_AM::getT2SOImmVal(~Imm) != -1;
192 }
193
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000194 // Include the pieces autogenerated from the target description.
195#include "ARMGenDAGISel.inc"
Bob Wilson224c2442009-05-19 05:53:42 +0000196
197private:
Evan Chenge88d5ce2009-07-02 07:28:31 +0000198 /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
199 /// ARM.
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000200 SDNode *SelectARMIndexedLoad(SDNode *N);
201 SDNode *SelectT2IndexedLoad(SDNode *N);
Evan Chenge88d5ce2009-07-02 07:28:31 +0000202
Bob Wilson621f1952010-03-23 05:25:43 +0000203 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
204 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson3e36f132009-10-14 17:28:52 +0000205 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson621f1952010-03-23 05:25:43 +0000206 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson1c3ef902011-02-07 17:43:21 +0000207 SDNode *SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +0000208 const uint16_t *DOpcodes,
209 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilson3e36f132009-10-14 17:28:52 +0000210
Bob Wilson24f995d2009-10-14 18:32:29 +0000211 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilson11d98992010-03-23 06:20:33 +0000212 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson24f995d2009-10-14 18:32:29 +0000213 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilson11d98992010-03-23 06:20:33 +0000214 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson1c3ef902011-02-07 17:43:21 +0000215 SDNode *SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +0000216 const uint16_t *DOpcodes,
217 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilson24f995d2009-10-14 18:32:29 +0000218
Bob Wilson96493442009-10-14 16:46:45 +0000219 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilsona7c397c2009-10-14 16:19:03 +0000220 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson8466fa12010-09-13 23:01:35 +0000221 /// load/store of D registers and Q registers.
Bob Wilson1c3ef902011-02-07 17:43:21 +0000222 SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad,
223 bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +0000224 const uint16_t *DOpcodes, const uint16_t *QOpcodes);
Bob Wilsona7c397c2009-10-14 16:19:03 +0000225
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +0000226 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
227 /// should be 2, 3 or 4. The opcode array specifies the instructions used
228 /// for loading D registers. (Q registers are not supported.)
Bob Wilson1c3ef902011-02-07 17:43:21 +0000229 SDNode *SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +0000230 const uint16_t *Opcodes);
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +0000231
Bob Wilson78dfbc32010-07-07 00:08:54 +0000232 /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2,
233 /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be
234 /// generated to force the table registers to be consecutive.
235 SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc);
Bob Wilsond491d6e2010-07-06 23:36:25 +0000236
Sandeep Patel4e1ed882009-10-13 20:25:58 +0000237 /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
Jim Grosbach3a1287b2010-04-22 23:24:18 +0000238 SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel47eedaa2009-10-13 18:59:48 +0000239
Evan Cheng07ba9062009-11-19 21:45:22 +0000240 /// SelectCMOVOp - Select CMOV instructions for ARM.
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000241 SDNode *SelectCMOVOp(SDNode *N);
242 SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +0000243 ARMCC::CondCodes CCVal, SDValue CCR,
244 SDValue InFlag);
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000245 SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +0000246 ARMCC::CondCodes CCVal, SDValue CCR,
247 SDValue InFlag);
Jim Grosbacha4257162010-10-07 00:53:56 +0000248 SDNode *SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +0000249 ARMCC::CondCodes CCVal, SDValue CCR,
250 SDValue InFlag);
Jim Grosbach3bbdcea2010-10-07 00:42:42 +0000251 SDNode *SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +0000252 ARMCC::CondCodes CCVal, SDValue CCR,
253 SDValue InFlag);
Evan Cheng07ba9062009-11-19 21:45:22 +0000254
Bill Wendlingef2c86f2011-10-10 22:59:55 +0000255 // Select special operations if node forms integer ABS pattern
256 SDNode *SelectABSOp(SDNode *N);
257
Evan Chengde8aa4e2010-05-05 18:28:36 +0000258 SDNode *SelectConcatVector(SDNode *N);
259
Eli Friedman2bdffe42011-08-31 00:31:29 +0000260 SDNode *SelectAtomic64(SDNode *Node, unsigned Opc);
261
Evan Chengaf4550f2009-07-02 01:23:32 +0000262 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
263 /// inline asm expressions.
264 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
265 char ConstraintCode,
266 std::vector<SDValue> &OutOps);
Bob Wilson3bf12ab2009-10-06 22:01:59 +0000267
Weiming Zhao8b149cb2012-11-17 00:23:35 +0000268 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhaoe56764b2012-11-16 21:55:34 +0000269 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao8b149cb2012-11-17 00:23:35 +0000270 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
271 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
272 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Cheng603afbf2010-05-10 17:34:18 +0000273
Bob Wilson40cbe7d2010-06-04 00:04:02 +0000274 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao8b149cb2012-11-17 00:23:35 +0000275 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
276 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
277 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilson665814b2010-11-01 23:40:51 +0000278
279 // Get the alignment operand for a NEON VLD or VST instruction.
280 SDValue GetVLDSTAlign(SDValue Align, unsigned NumVecs, bool is64BitVector);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000281};
Evan Chenga8e29892007-01-19 07:51:42 +0000282}
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000283
Sandeep Patel47eedaa2009-10-13 18:59:48 +0000284/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
285/// operand. If so Imm will receive the 32-bit value.
286static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
287 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
288 Imm = cast<ConstantSDNode>(N)->getZExtValue();
289 return true;
290 }
291 return false;
292}
293
294// isInt32Immediate - This method tests to see if a constant operand.
295// If so Imm will receive the 32 bit value.
296static bool isInt32Immediate(SDValue N, unsigned &Imm) {
297 return isInt32Immediate(N.getNode(), Imm);
298}
299
300// isOpcWithIntImmediate - This method tests to see if the node is a specific
301// opcode and that it has a immediate integer right operand.
302// If so Imm will receive the 32 bit value.
303static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
304 return N->getOpcode() == Opc &&
305 isInt32Immediate(N->getOperand(1).getNode(), Imm);
306}
307
Daniel Dunbarec91d522011-01-19 15:12:16 +0000308/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenkoc5252da2012-09-14 14:57:36 +0000309/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbarec91d522011-01-19 15:12:16 +0000310///
311/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen11ebe3d2011-09-23 22:10:33 +0000312static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbarec91d522011-01-19 15:12:16 +0000313 int RangeMin, int RangeMax,
314 int &ScaledConstant) {
Jakob Stoklund Olesen11ebe3d2011-09-23 22:10:33 +0000315 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbarec91d522011-01-19 15:12:16 +0000316
317 // Check that this is a constant.
318 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
319 if (!C)
320 return false;
321
322 ScaledConstant = (int) C->getZExtValue();
323 if ((ScaledConstant % Scale) != 0)
324 return false;
325
326 ScaledConstant /= Scale;
327 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
328}
329
Evan Cheng48575f62010-12-05 22:04:16 +0000330/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
331/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
332/// least on current ARM implementations) which should be avoidded.
333bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
334 if (OptLevel == CodeGenOpt::None)
335 return true;
336
337 if (!CheckVMLxHazard)
338 return true;
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000339
340 if (!Subtarget->isCortexA8() && !Subtarget->isLikeA9() &&
341 !Subtarget->isSwift())
Evan Cheng48575f62010-12-05 22:04:16 +0000342 return true;
343
344 if (!N->hasOneUse())
345 return false;
346
347 SDNode *Use = *N->use_begin();
348 if (Use->getOpcode() == ISD::CopyToReg)
349 return true;
350 if (Use->isMachineOpcode()) {
Evan Chenge837dea2011-06-28 19:10:37 +0000351 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
352 if (MCID.mayStore())
Evan Cheng48575f62010-12-05 22:04:16 +0000353 return true;
Evan Chenge837dea2011-06-28 19:10:37 +0000354 unsigned Opcode = MCID.getOpcode();
Evan Cheng48575f62010-12-05 22:04:16 +0000355 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
356 return true;
357 // vmlx feeding into another vmlx. We actually want to unfold
358 // the use later in the MLxExpansion pass. e.g.
359 // vmla
360 // vmla (stall 8 cycles)
361 //
362 // vmul (5 cycles)
363 // vadd (5 cycles)
364 // vmla
365 // This adds up to about 18 - 19 cycles.
366 //
367 // vmla
368 // vmul (stall 4 cycles)
369 // vadd adds up to about 14 cycles.
370 return TII->isFpMLxInstruction(Opcode);
371 }
372
373 return false;
374}
Sandeep Patel47eedaa2009-10-13 18:59:48 +0000375
Evan Chengf40deed2010-10-27 23:41:30 +0000376bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
377 ARM_AM::ShiftOpc ShOpcVal,
378 unsigned ShAmt) {
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000379 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Chengf40deed2010-10-27 23:41:30 +0000380 return true;
381 if (Shift.hasOneUse())
382 return true;
383 // R << 2 is free.
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000384 return ShOpcVal == ARM_AM::lsl &&
385 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Chengf40deed2010-10-27 23:41:30 +0000386}
387
Owen Anderson92a20222011-07-21 18:54:16 +0000388bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Cheng055b0312009-06-29 07:51:04 +0000389 SDValue &BaseReg,
Owen Anderson099e5552011-03-18 19:46:58 +0000390 SDValue &Opc,
391 bool CheckProfitability) {
Evan Chenga2c519b2010-07-30 23:33:54 +0000392 if (DisableShifterOp)
393 return false;
394
Evan Chengee04a6d2011-07-20 23:34:39 +0000395 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng055b0312009-06-29 07:51:04 +0000396
397 // Don't match base register only case. That is matched to a separate
398 // lower complexity pattern with explicit register operand.
399 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbach764ab522009-08-11 15:33:49 +0000400
Evan Cheng055b0312009-06-29 07:51:04 +0000401 BaseReg = N.getOperand(0);
402 unsigned ShImmVal = 0;
Owen Anderson92a20222011-07-21 18:54:16 +0000403 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
404 if (!RHS) return false;
Owen Anderson92a20222011-07-21 18:54:16 +0000405 ShImmVal = RHS->getZExtValue() & 31;
Evan Chengf40deed2010-10-27 23:41:30 +0000406 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
407 MVT::i32);
408 return true;
409}
410
Owen Anderson92a20222011-07-21 18:54:16 +0000411bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
412 SDValue &BaseReg,
413 SDValue &ShReg,
414 SDValue &Opc,
415 bool CheckProfitability) {
416 if (DisableShifterOp)
417 return false;
418
419 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
420
421 // Don't match base register only case. That is matched to a separate
422 // lower complexity pattern with explicit register operand.
423 if (ShOpcVal == ARM_AM::no_shift) return false;
424
425 BaseReg = N.getOperand(0);
426 unsigned ShImmVal = 0;
427 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
428 if (RHS) return false;
429
430 ShReg = N.getOperand(1);
431 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
432 return false;
433 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
434 MVT::i32);
435 return true;
436}
437
438
Jim Grosbach3e556122010-10-26 22:37:02 +0000439bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
440 SDValue &Base,
441 SDValue &OffImm) {
442 // Match simple R + imm12 operands.
443
444 // Base only.
Chris Lattner0a9481f2011-02-13 22:25:43 +0000445 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
446 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach3e556122010-10-26 22:37:02 +0000447 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner0a9481f2011-02-13 22:25:43 +0000448 // Match frame index.
Jim Grosbach3e556122010-10-26 22:37:02 +0000449 int FI = cast<FrameIndexSDNode>(N)->getIndex();
450 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
451 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
452 return true;
Chris Lattner0a9481f2011-02-13 22:25:43 +0000453 }
Owen Anderson099e5552011-03-18 19:46:58 +0000454
Chris Lattner0a9481f2011-02-13 22:25:43 +0000455 if (N.getOpcode() == ARMISD::Wrapper &&
456 !(Subtarget->useMovt() &&
457 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Jim Grosbach3e556122010-10-26 22:37:02 +0000458 Base = N.getOperand(0);
459 } else
460 Base = N;
461 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
462 return true;
463 }
464
465 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
466 int RHSC = (int)RHS->getZExtValue();
467 if (N.getOpcode() == ISD::SUB)
468 RHSC = -RHSC;
469
470 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
471 Base = N.getOperand(0);
472 if (Base.getOpcode() == ISD::FrameIndex) {
473 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
474 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
475 }
476 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
477 return true;
478 }
479 }
480
481 // Base only.
482 Base = N;
483 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
484 return true;
485}
486
487
488
489bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
490 SDValue &Opc) {
Evan Chengf40deed2010-10-27 23:41:30 +0000491 if (N.getOpcode() == ISD::MUL &&
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000492 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach3e556122010-10-26 22:37:02 +0000493 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
494 // X * [3,5,9] -> X + X * [2,4,8] etc.
495 int RHSC = (int)RHS->getZExtValue();
496 if (RHSC & 1) {
497 RHSC = RHSC & ~1;
498 ARM_AM::AddrOpc AddSub = ARM_AM::add;
499 if (RHSC < 0) {
500 AddSub = ARM_AM::sub;
501 RHSC = - RHSC;
502 }
503 if (isPowerOf2_32(RHSC)) {
504 unsigned ShAmt = Log2_32(RHSC);
505 Base = Offset = N.getOperand(0);
506 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
507 ARM_AM::lsl),
508 MVT::i32);
509 return true;
510 }
511 }
512 }
513 }
514
Chris Lattner0a9481f2011-02-13 22:25:43 +0000515 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
516 // ISD::OR that is equivalent to an ISD::ADD.
517 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach3e556122010-10-26 22:37:02 +0000518 return false;
519
520 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner0a9481f2011-02-13 22:25:43 +0000521 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbarec91d522011-01-19 15:12:16 +0000522 int RHSC;
523 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
524 -0x1000+1, 0x1000, RHSC)) // 12 bits.
525 return false;
Jim Grosbach3e556122010-10-26 22:37:02 +0000526 }
527
528 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner0a9481f2011-02-13 22:25:43 +0000529 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chengee04a6d2011-07-20 23:34:39 +0000530 ARM_AM::ShiftOpc ShOpcVal =
531 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach3e556122010-10-26 22:37:02 +0000532 unsigned ShAmt = 0;
533
534 Base = N.getOperand(0);
535 Offset = N.getOperand(1);
536
537 if (ShOpcVal != ARM_AM::no_shift) {
538 // Check to see if the RHS of the shift is a constant, if not, we can't fold
539 // it.
540 if (ConstantSDNode *Sh =
541 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
542 ShAmt = Sh->getZExtValue();
Evan Chengf40deed2010-10-27 23:41:30 +0000543 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
544 Offset = N.getOperand(1).getOperand(0);
545 else {
546 ShAmt = 0;
547 ShOpcVal = ARM_AM::no_shift;
548 }
Jim Grosbach3e556122010-10-26 22:37:02 +0000549 } else {
550 ShOpcVal = ARM_AM::no_shift;
551 }
552 }
553
554 // Try matching (R shl C) + (R).
Chris Lattner0a9481f2011-02-13 22:25:43 +0000555 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000556 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
557 N.getOperand(0).hasOneUse())) {
Evan Chengee04a6d2011-07-20 23:34:39 +0000558 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach3e556122010-10-26 22:37:02 +0000559 if (ShOpcVal != ARM_AM::no_shift) {
560 // Check to see if the RHS of the shift is a constant, if not, we can't
561 // fold it.
562 if (ConstantSDNode *Sh =
563 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
564 ShAmt = Sh->getZExtValue();
Cameron Zwarich8f8aa812011-10-05 23:39:02 +0000565 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Chengf40deed2010-10-27 23:41:30 +0000566 Offset = N.getOperand(0).getOperand(0);
567 Base = N.getOperand(1);
568 } else {
569 ShAmt = 0;
570 ShOpcVal = ARM_AM::no_shift;
571 }
Jim Grosbach3e556122010-10-26 22:37:02 +0000572 } else {
573 ShOpcVal = ARM_AM::no_shift;
574 }
575 }
576 }
577
578 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
579 MVT::i32);
580 return true;
581}
582
583
Jim Grosbach3e556122010-10-26 22:37:02 +0000584//-----
585
Jim Grosbach82891622010-09-29 19:03:54 +0000586AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
587 SDValue &Base,
588 SDValue &Offset,
589 SDValue &Opc) {
Evan Chengf40deed2010-10-27 23:41:30 +0000590 if (N.getOpcode() == ISD::MUL &&
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000591 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Chenga13fd102007-03-13 21:05:54 +0000592 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
593 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000594 int RHSC = (int)RHS->getZExtValue();
Evan Chenga13fd102007-03-13 21:05:54 +0000595 if (RHSC & 1) {
596 RHSC = RHSC & ~1;
597 ARM_AM::AddrOpc AddSub = ARM_AM::add;
598 if (RHSC < 0) {
599 AddSub = ARM_AM::sub;
600 RHSC = - RHSC;
601 }
602 if (isPowerOf2_32(RHSC)) {
603 unsigned ShAmt = Log2_32(RHSC);
604 Base = Offset = N.getOperand(0);
605 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
606 ARM_AM::lsl),
Owen Anderson825b72b2009-08-11 20:47:22 +0000607 MVT::i32);
Jim Grosbach82891622010-09-29 19:03:54 +0000608 return AM2_SHOP;
Evan Chenga13fd102007-03-13 21:05:54 +0000609 }
610 }
611 }
612 }
613
Chris Lattner0a9481f2011-02-13 22:25:43 +0000614 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
615 // ISD::OR that is equivalent to an ADD.
616 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Chenga8e29892007-01-19 07:51:42 +0000617 Base = N;
618 if (N.getOpcode() == ISD::FrameIndex) {
619 int FI = cast<FrameIndexSDNode>(N)->getIndex();
620 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000621 } else if (N.getOpcode() == ARMISD::Wrapper &&
622 !(Subtarget->useMovt() &&
623 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Chenga8e29892007-01-19 07:51:42 +0000624 Base = N.getOperand(0);
625 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000626 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000627 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
628 ARM_AM::no_shift),
Owen Anderson825b72b2009-08-11 20:47:22 +0000629 MVT::i32);
Jim Grosbach82891622010-09-29 19:03:54 +0000630 return AM2_BASE;
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000631 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000632
Evan Chenga8e29892007-01-19 07:51:42 +0000633 // Match simple R +/- imm12 operands.
Chris Lattner0a9481f2011-02-13 22:25:43 +0000634 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbarec91d522011-01-19 15:12:16 +0000635 int RHSC;
636 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
637 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
638 Base = N.getOperand(0);
639 if (Base.getOpcode() == ISD::FrameIndex) {
640 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
641 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000642 }
Daniel Dunbarec91d522011-01-19 15:12:16 +0000643 Offset = CurDAG->getRegister(0, MVT::i32);
644
645 ARM_AM::AddrOpc AddSub = ARM_AM::add;
646 if (RHSC < 0) {
647 AddSub = ARM_AM::sub;
648 RHSC = - RHSC;
649 }
650 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
651 ARM_AM::no_shift),
652 MVT::i32);
653 return AM2_BASE;
Evan Chenga8e29892007-01-19 07:51:42 +0000654 }
Jim Grosbachbe912322010-09-29 17:32:29 +0000655 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000656
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000657 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Chengf40deed2010-10-27 23:41:30 +0000658 // Compute R +/- (R << N) and reuse it.
659 Base = N;
660 Offset = CurDAG->getRegister(0, MVT::i32);
661 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
662 ARM_AM::no_shift),
663 MVT::i32);
664 return AM2_BASE;
665 }
666
Johnny Chen6a3b5ee2009-10-27 17:25:15 +0000667 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner0a9481f2011-02-13 22:25:43 +0000668 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chengee04a6d2011-07-20 23:34:39 +0000669 ARM_AM::ShiftOpc ShOpcVal =
670 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Chenga8e29892007-01-19 07:51:42 +0000671 unsigned ShAmt = 0;
Jim Grosbach764ab522009-08-11 15:33:49 +0000672
Evan Chenga8e29892007-01-19 07:51:42 +0000673 Base = N.getOperand(0);
674 Offset = N.getOperand(1);
Jim Grosbach764ab522009-08-11 15:33:49 +0000675
Evan Chenga8e29892007-01-19 07:51:42 +0000676 if (ShOpcVal != ARM_AM::no_shift) {
677 // Check to see if the RHS of the shift is a constant, if not, we can't fold
678 // it.
679 if (ConstantSDNode *Sh =
680 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000681 ShAmt = Sh->getZExtValue();
Evan Chengf40deed2010-10-27 23:41:30 +0000682 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
683 Offset = N.getOperand(1).getOperand(0);
684 else {
685 ShAmt = 0;
686 ShOpcVal = ARM_AM::no_shift;
687 }
Evan Chenga8e29892007-01-19 07:51:42 +0000688 } else {
689 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000690 }
691 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000692
Evan Chenga8e29892007-01-19 07:51:42 +0000693 // Try matching (R shl C) + (R).
Chris Lattner0a9481f2011-02-13 22:25:43 +0000694 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsoneb1641d2012-09-29 21:43:49 +0000695 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
696 N.getOperand(0).hasOneUse())) {
Evan Chengee04a6d2011-07-20 23:34:39 +0000697 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Chenga8e29892007-01-19 07:51:42 +0000698 if (ShOpcVal != ARM_AM::no_shift) {
699 // Check to see if the RHS of the shift is a constant, if not, we can't
700 // fold it.
701 if (ConstantSDNode *Sh =
702 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000703 ShAmt = Sh->getZExtValue();
Cameron Zwarich8f8aa812011-10-05 23:39:02 +0000704 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Chengf40deed2010-10-27 23:41:30 +0000705 Offset = N.getOperand(0).getOperand(0);
706 Base = N.getOperand(1);
707 } else {
708 ShAmt = 0;
709 ShOpcVal = ARM_AM::no_shift;
710 }
Evan Chenga8e29892007-01-19 07:51:42 +0000711 } else {
712 ShOpcVal = ARM_AM::no_shift;
713 }
714 }
715 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000716
Evan Chenga8e29892007-01-19 07:51:42 +0000717 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson825b72b2009-08-11 20:47:22 +0000718 MVT::i32);
Jim Grosbach82891622010-09-29 19:03:54 +0000719 return AM2_SHOP;
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000720}
721
Owen Anderson793e7962011-07-26 20:54:26 +0000722bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000723 SDValue &Offset, SDValue &Opc) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000724 unsigned Opcode = Op->getOpcode();
Evan Chenga8e29892007-01-19 07:51:42 +0000725 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
726 ? cast<LoadSDNode>(Op)->getAddressingMode()
727 : cast<StoreSDNode>(Op)->getAddressingMode();
728 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
729 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbarec91d522011-01-19 15:12:16 +0000730 int Val;
Owen Anderson793e7962011-07-26 20:54:26 +0000731 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
732 return false;
Evan Chenga8e29892007-01-19 07:51:42 +0000733
734 Offset = N;
Evan Chengee04a6d2011-07-20 23:34:39 +0000735 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chenga8e29892007-01-19 07:51:42 +0000736 unsigned ShAmt = 0;
737 if (ShOpcVal != ARM_AM::no_shift) {
738 // Check to see if the RHS of the shift is a constant, if not, we can't fold
739 // it.
740 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000741 ShAmt = Sh->getZExtValue();
Evan Chengf40deed2010-10-27 23:41:30 +0000742 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
743 Offset = N.getOperand(0);
744 else {
745 ShAmt = 0;
746 ShOpcVal = ARM_AM::no_shift;
747 }
Evan Chenga8e29892007-01-19 07:51:42 +0000748 } else {
749 ShOpcVal = ARM_AM::no_shift;
750 }
751 }
752
753 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson825b72b2009-08-11 20:47:22 +0000754 MVT::i32);
Rafael Espindola32bd5f42006-10-17 18:04:53 +0000755 return true;
756}
757
Owen Andersonc4e16de2011-08-29 20:16:50 +0000758bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
759 SDValue &Offset, SDValue &Opc) {
Owen Andersond84192f2011-08-31 20:00:11 +0000760 unsigned Opcode = Op->getOpcode();
761 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
762 ? cast<LoadSDNode>(Op)->getAddressingMode()
763 : cast<StoreSDNode>(Op)->getAddressingMode();
764 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
765 ? ARM_AM::add : ARM_AM::sub;
Owen Andersonc4e16de2011-08-29 20:16:50 +0000766 int Val;
767 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Andersond84192f2011-08-31 20:00:11 +0000768 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Andersonc4e16de2011-08-29 20:16:50 +0000769 Offset = CurDAG->getRegister(0, MVT::i32);
770 Opc = CurDAG->getTargetConstant(Val, MVT::i32);
771 return true;
772 }
773
774 return false;
775}
776
777
Owen Anderson793e7962011-07-26 20:54:26 +0000778bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
779 SDValue &Offset, SDValue &Opc) {
780 unsigned Opcode = Op->getOpcode();
781 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
782 ? cast<LoadSDNode>(Op)->getAddressingMode()
783 : cast<StoreSDNode>(Op)->getAddressingMode();
784 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
785 ? ARM_AM::add : ARM_AM::sub;
786 int Val;
787 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
788 Offset = CurDAG->getRegister(0, MVT::i32);
789 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
790 ARM_AM::no_shift),
791 MVT::i32);
792 return true;
793 }
794
795 return false;
796}
797
Jim Grosbach19dec202011-08-05 20:35:44 +0000798bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
799 Base = N;
800 return true;
801}
Evan Chenga8e29892007-01-19 07:51:42 +0000802
Chris Lattner52a261b2010-09-21 20:31:19 +0000803bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000804 SDValue &Base, SDValue &Offset,
805 SDValue &Opc) {
Evan Chenga8e29892007-01-19 07:51:42 +0000806 if (N.getOpcode() == ISD::SUB) {
807 // X - C is canonicalize to X + -C, no need to handle it here.
808 Base = N.getOperand(0);
809 Offset = N.getOperand(1);
Owen Anderson825b72b2009-08-11 20:47:22 +0000810 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000811 return true;
812 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000813
Chris Lattner0a9481f2011-02-13 22:25:43 +0000814 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Chenga8e29892007-01-19 07:51:42 +0000815 Base = N;
816 if (N.getOpcode() == ISD::FrameIndex) {
817 int FI = cast<FrameIndexSDNode>(N)->getIndex();
818 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
819 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000820 Offset = CurDAG->getRegister(0, MVT::i32);
821 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000822 return true;
823 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000824
Evan Chenga8e29892007-01-19 07:51:42 +0000825 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbarec91d522011-01-19 15:12:16 +0000826 int RHSC;
827 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
828 -256 + 1, 256, RHSC)) { // 8 bits.
829 Base = N.getOperand(0);
830 if (Base.getOpcode() == ISD::FrameIndex) {
831 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
832 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Evan Chenga8e29892007-01-19 07:51:42 +0000833 }
Daniel Dunbarec91d522011-01-19 15:12:16 +0000834 Offset = CurDAG->getRegister(0, MVT::i32);
835
836 ARM_AM::AddrOpc AddSub = ARM_AM::add;
837 if (RHSC < 0) {
838 AddSub = ARM_AM::sub;
Chris Lattner0a9481f2011-02-13 22:25:43 +0000839 RHSC = -RHSC;
Daniel Dunbarec91d522011-01-19 15:12:16 +0000840 }
841 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32);
842 return true;
Evan Chenga8e29892007-01-19 07:51:42 +0000843 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000844
Evan Chenga8e29892007-01-19 07:51:42 +0000845 Base = N.getOperand(0);
846 Offset = N.getOperand(1);
Owen Anderson825b72b2009-08-11 20:47:22 +0000847 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000848 return true;
849}
850
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000851bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000852 SDValue &Offset, SDValue &Opc) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000853 unsigned Opcode = Op->getOpcode();
Evan Chenga8e29892007-01-19 07:51:42 +0000854 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
855 ? cast<LoadSDNode>(Op)->getAddressingMode()
856 : cast<StoreSDNode>(Op)->getAddressingMode();
857 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
858 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbarec91d522011-01-19 15:12:16 +0000859 int Val;
860 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
861 Offset = CurDAG->getRegister(0, MVT::i32);
862 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32);
863 return true;
Evan Chenga8e29892007-01-19 07:51:42 +0000864 }
865
866 Offset = N;
Owen Anderson825b72b2009-08-11 20:47:22 +0000867 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000868 return true;
869}
870
Jim Grosbach3ab56582010-10-21 19:38:40 +0000871bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000872 SDValue &Base, SDValue &Offset) {
Chris Lattner0a9481f2011-02-13 22:25:43 +0000873 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Chenga8e29892007-01-19 07:51:42 +0000874 Base = N;
875 if (N.getOpcode() == ISD::FrameIndex) {
876 int FI = cast<FrameIndexSDNode>(N)->getIndex();
877 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000878 } else if (N.getOpcode() == ARMISD::Wrapper &&
879 !(Subtarget->useMovt() &&
880 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Chenga8e29892007-01-19 07:51:42 +0000881 Base = N.getOperand(0);
882 }
883 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson825b72b2009-08-11 20:47:22 +0000884 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000885 return true;
886 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000887
Evan Chenga8e29892007-01-19 07:51:42 +0000888 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbarec91d522011-01-19 15:12:16 +0000889 int RHSC;
890 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
891 -256 + 1, 256, RHSC)) {
892 Base = N.getOperand(0);
893 if (Base.getOpcode() == ISD::FrameIndex) {
894 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
895 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Evan Chenga8e29892007-01-19 07:51:42 +0000896 }
Daniel Dunbarec91d522011-01-19 15:12:16 +0000897
898 ARM_AM::AddrOpc AddSub = ARM_AM::add;
899 if (RHSC < 0) {
900 AddSub = ARM_AM::sub;
Chris Lattner0a9481f2011-02-13 22:25:43 +0000901 RHSC = -RHSC;
Daniel Dunbarec91d522011-01-19 15:12:16 +0000902 }
903 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
904 MVT::i32);
905 return true;
Evan Chenga8e29892007-01-19 07:51:42 +0000906 }
Jim Grosbach764ab522009-08-11 15:33:49 +0000907
Evan Chenga8e29892007-01-19 07:51:42 +0000908 Base = N;
909 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson825b72b2009-08-11 20:47:22 +0000910 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000911 return true;
912}
913
Bob Wilson665814b2010-11-01 23:40:51 +0000914bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
915 SDValue &Align) {
Bob Wilson8b024a52009-07-01 23:16:05 +0000916 Addr = N;
Bob Wilson665814b2010-11-01 23:40:51 +0000917
918 unsigned Alignment = 0;
919 if (LSBaseSDNode *LSN = dyn_cast<LSBaseSDNode>(Parent)) {
920 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
921 // The maximum alignment is equal to the memory size being referenced.
922 unsigned LSNAlign = LSN->getAlignment();
923 unsigned MemSize = LSN->getMemoryVT().getSizeInBits() / 8;
Jakob Stoklund Olesenb0117ee2011-10-27 22:39:16 +0000924 if (LSNAlign >= MemSize && MemSize > 1)
Bob Wilson665814b2010-11-01 23:40:51 +0000925 Alignment = MemSize;
926 } else {
927 // All other uses of addrmode6 are for intrinsics. For now just record
928 // the raw alignment value; it will be refined later based on the legal
929 // alignment operands for the intrinsic.
930 Alignment = cast<MemIntrinsicSDNode>(Parent)->getAlignment();
931 }
932
933 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilson8b024a52009-07-01 23:16:05 +0000934 return true;
935}
936
Bob Wilsonda525062011-02-25 06:42:42 +0000937bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
938 SDValue &Offset) {
939 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
940 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
941 if (AM != ISD::POST_INC)
942 return false;
943 Offset = N;
944 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
945 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
946 Offset = CurDAG->getRegister(0, MVT::i32);
947 }
948 return true;
949}
950
Chris Lattner52a261b2010-09-21 20:31:19 +0000951bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Chengbba9f5f2009-08-14 19:01:37 +0000952 SDValue &Offset, SDValue &Label) {
Evan Chenga8e29892007-01-19 07:51:42 +0000953 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
954 Offset = N.getOperand(0);
Dan Gohman475871a2008-07-27 21:46:04 +0000955 SDValue N1 = N.getOperand(1);
Evan Cheng9fe20092011-01-20 08:34:58 +0000956 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
957 MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +0000958 return true;
959 }
Bill Wendlingf4caf692010-12-14 03:36:38 +0000960
Evan Chenga8e29892007-01-19 07:51:42 +0000961 return false;
962}
963
Bill Wendlingf4caf692010-12-14 03:36:38 +0000964
965//===----------------------------------------------------------------------===//
966// Thumb Addressing Modes
967//===----------------------------------------------------------------------===//
968
Chris Lattner52a261b2010-09-21 20:31:19 +0000969bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman475871a2008-07-27 21:46:04 +0000970 SDValue &Base, SDValue &Offset){
Chris Lattner0a9481f2011-02-13 22:25:43 +0000971 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng2f297df2009-07-11 07:08:13 +0000972 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmane368b462010-06-18 14:22:04 +0000973 if (!NC || !NC->isNullValue())
Evan Cheng2f297df2009-07-11 07:08:13 +0000974 return false;
975
976 Base = Offset = N;
Evan Chengc38f2bc2007-01-23 22:59:13 +0000977 return true;
978 }
979
Evan Chenga8e29892007-01-19 07:51:42 +0000980 Base = N.getOperand(0);
981 Offset = N.getOperand(1);
982 return true;
983}
984
Evan Cheng79d43262007-01-24 02:21:22 +0000985bool
Bill Wendlingf4caf692010-12-14 03:36:38 +0000986ARMDAGToDAGISel::SelectThumbAddrModeRI(SDValue N, SDValue &Base,
987 SDValue &Offset, unsigned Scale) {
Evan Cheng79d43262007-01-24 02:21:22 +0000988 if (Scale == 4) {
Dan Gohman475871a2008-07-27 21:46:04 +0000989 SDValue TmpBase, TmpOffImm;
Chris Lattner52a261b2010-09-21 20:31:19 +0000990 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
Evan Cheng79d43262007-01-24 02:21:22 +0000991 return false; // We want to select tLDRspi / tSTRspi instead.
Bill Wendlingf4caf692010-12-14 03:36:38 +0000992
Evan Cheng012f2d92007-01-24 08:53:17 +0000993 if (N.getOpcode() == ARMISD::Wrapper &&
994 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
995 return false; // We want to select tLDRpci instead.
Evan Cheng79d43262007-01-24 02:21:22 +0000996 }
997
Chris Lattner0a9481f2011-02-13 22:25:43 +0000998 if (!CurDAG->isBaseWithConstantOffset(N))
Bill Wendlingbc4224b2010-12-15 01:03:19 +0000999 return false;
Evan Chenga8e29892007-01-19 07:51:42 +00001000
Evan Chengad0e4652007-02-06 00:22:06 +00001001 // Thumb does not have [sp, r] address mode.
1002 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1003 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1004 if ((LHSR && LHSR->getReg() == ARM::SP) ||
Bill Wendlingbc4224b2010-12-15 01:03:19 +00001005 (RHSR && RHSR->getReg() == ARM::SP))
1006 return false;
Bill Wendlingf4caf692010-12-14 03:36:38 +00001007
Daniel Dunbarec91d522011-01-19 15:12:16 +00001008 // FIXME: Why do we explicitly check for a match here and then return false?
1009 // Presumably to allow something else to match, but shouldn't this be
1010 // documented?
1011 int RHSC;
1012 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC))
1013 return false;
Bill Wendlingf4caf692010-12-14 03:36:38 +00001014
1015 Base = N.getOperand(0);
1016 Offset = N.getOperand(1);
1017 return true;
1018}
1019
1020bool
1021ARMDAGToDAGISel::SelectThumbAddrModeRI5S1(SDValue N,
1022 SDValue &Base,
1023 SDValue &Offset) {
1024 return SelectThumbAddrModeRI(N, Base, Offset, 1);
1025}
1026
1027bool
1028ARMDAGToDAGISel::SelectThumbAddrModeRI5S2(SDValue N,
1029 SDValue &Base,
1030 SDValue &Offset) {
1031 return SelectThumbAddrModeRI(N, Base, Offset, 2);
1032}
1033
1034bool
1035ARMDAGToDAGISel::SelectThumbAddrModeRI5S4(SDValue N,
1036 SDValue &Base,
1037 SDValue &Offset) {
1038 return SelectThumbAddrModeRI(N, Base, Offset, 4);
1039}
1040
1041bool
1042ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1043 SDValue &Base, SDValue &OffImm) {
1044 if (Scale == 4) {
1045 SDValue TmpBase, TmpOffImm;
1046 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
1047 return false; // We want to select tLDRspi / tSTRspi instead.
1048
1049 if (N.getOpcode() == ARMISD::Wrapper &&
1050 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1051 return false; // We want to select tLDRpci instead.
1052 }
1053
Chris Lattner0a9481f2011-02-13 22:25:43 +00001054 if (!CurDAG->isBaseWithConstantOffset(N)) {
Bill Wendlingf4caf692010-12-14 03:36:38 +00001055 if (N.getOpcode() == ARMISD::Wrapper &&
1056 !(Subtarget->useMovt() &&
1057 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
1058 Base = N.getOperand(0);
1059 } else {
1060 Base = N;
1061 }
1062
Owen Anderson825b72b2009-08-11 20:47:22 +00001063 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chengad0e4652007-02-06 00:22:06 +00001064 return true;
1065 }
1066
Bill Wendlingbc4224b2010-12-15 01:03:19 +00001067 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1068 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1069 if ((LHSR && LHSR->getReg() == ARM::SP) ||
1070 (RHSR && RHSR->getReg() == ARM::SP)) {
1071 ConstantSDNode *LHS = dyn_cast<ConstantSDNode>(N.getOperand(0));
1072 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1073 unsigned LHSC = LHS ? LHS->getZExtValue() : 0;
1074 unsigned RHSC = RHS ? RHS->getZExtValue() : 0;
1075
1076 // Thumb does not have [sp, #imm5] address mode for non-zero imm5.
1077 if (LHSC != 0 || RHSC != 0) return false;
1078
1079 Base = N;
1080 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
1081 return true;
1082 }
1083
Evan Chenga8e29892007-01-19 07:51:42 +00001084 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbarec91d522011-01-19 15:12:16 +00001085 int RHSC;
1086 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1087 Base = N.getOperand(0);
1088 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1089 return true;
Evan Chenga8e29892007-01-19 07:51:42 +00001090 }
1091
Evan Chengc38f2bc2007-01-23 22:59:13 +00001092 Base = N.getOperand(0);
Owen Anderson825b72b2009-08-11 20:47:22 +00001093 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chengc38f2bc2007-01-23 22:59:13 +00001094 return true;
Evan Chenga8e29892007-01-19 07:51:42 +00001095}
1096
Bill Wendlingf4caf692010-12-14 03:36:38 +00001097bool
1098ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1099 SDValue &OffImm) {
1100 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Chenga8e29892007-01-19 07:51:42 +00001101}
1102
Bill Wendlingf4caf692010-12-14 03:36:38 +00001103bool
1104ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1105 SDValue &OffImm) {
1106 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Chenga8e29892007-01-19 07:51:42 +00001107}
1108
Bill Wendlingf4caf692010-12-14 03:36:38 +00001109bool
1110ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1111 SDValue &OffImm) {
1112 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Chenga8e29892007-01-19 07:51:42 +00001113}
1114
Chris Lattner52a261b2010-09-21 20:31:19 +00001115bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1116 SDValue &Base, SDValue &OffImm) {
Evan Chenga8e29892007-01-19 07:51:42 +00001117 if (N.getOpcode() == ISD::FrameIndex) {
1118 int FI = cast<FrameIndexSDNode>(N)->getIndex();
1119 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Owen Anderson825b72b2009-08-11 20:47:22 +00001120 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chenga8e29892007-01-19 07:51:42 +00001121 return true;
1122 }
Evan Cheng79d43262007-01-24 02:21:22 +00001123
Chris Lattner0a9481f2011-02-13 22:25:43 +00001124 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Chengad0e4652007-02-06 00:22:06 +00001125 return false;
1126
1127 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Cheng8c1a73a2007-02-06 09:11:20 +00001128 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1129 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng79d43262007-01-24 02:21:22 +00001130 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbarec91d522011-01-19 15:12:16 +00001131 int RHSC;
1132 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1133 Base = N.getOperand(0);
1134 if (Base.getOpcode() == ISD::FrameIndex) {
1135 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1136 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Evan Cheng79d43262007-01-24 02:21:22 +00001137 }
Daniel Dunbarec91d522011-01-19 15:12:16 +00001138 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1139 return true;
Evan Cheng79d43262007-01-24 02:21:22 +00001140 }
1141 }
Jim Grosbach764ab522009-08-11 15:33:49 +00001142
Evan Chenga8e29892007-01-19 07:51:42 +00001143 return false;
1144}
1145
Bill Wendlingf4caf692010-12-14 03:36:38 +00001146
1147//===----------------------------------------------------------------------===//
1148// Thumb 2 Addressing Modes
1149//===----------------------------------------------------------------------===//
1150
1151
Chris Lattner52a261b2010-09-21 20:31:19 +00001152bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg,
Evan Cheng9cb9e672009-06-27 02:26:13 +00001153 SDValue &Opc) {
Evan Chenga2c519b2010-07-30 23:33:54 +00001154 if (DisableShifterOp)
1155 return false;
1156
Evan Chengee04a6d2011-07-20 23:34:39 +00001157 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng9cb9e672009-06-27 02:26:13 +00001158
1159 // Don't match base register only case. That is matched to a separate
1160 // lower complexity pattern with explicit register operand.
1161 if (ShOpcVal == ARM_AM::no_shift) return false;
1162
1163 BaseReg = N.getOperand(0);
1164 unsigned ShImmVal = 0;
1165 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1166 ShImmVal = RHS->getZExtValue() & 31;
1167 Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
1168 return true;
1169 }
1170
1171 return false;
1172}
1173
Chris Lattner52a261b2010-09-21 20:31:19 +00001174bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Cheng055b0312009-06-29 07:51:04 +00001175 SDValue &Base, SDValue &OffImm) {
1176 // Match simple R + imm12 operands.
David Goodwin31e7eba2009-07-20 15:55:39 +00001177
Evan Cheng3a214252009-08-11 08:52:18 +00001178 // Base only.
Chris Lattner0a9481f2011-02-13 22:25:43 +00001179 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1180 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin31e7eba2009-07-20 15:55:39 +00001181 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner0a9481f2011-02-13 22:25:43 +00001182 // Match frame index.
David Goodwin31e7eba2009-07-20 15:55:39 +00001183 int FI = cast<FrameIndexSDNode>(N)->getIndex();
1184 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Owen Anderson825b72b2009-08-11 20:47:22 +00001185 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
David Goodwin31e7eba2009-07-20 15:55:39 +00001186 return true;
Chris Lattner0a9481f2011-02-13 22:25:43 +00001187 }
Owen Anderson099e5552011-03-18 19:46:58 +00001188
Chris Lattner0a9481f2011-02-13 22:25:43 +00001189 if (N.getOpcode() == ARMISD::Wrapper &&
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +00001190 !(Subtarget->useMovt() &&
1191 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Cheng3a214252009-08-11 08:52:18 +00001192 Base = N.getOperand(0);
1193 if (Base.getOpcode() == ISD::TargetConstantPool)
1194 return false; // We want to select t2LDRpci instead.
1195 } else
1196 Base = N;
Owen Anderson825b72b2009-08-11 20:47:22 +00001197 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng3a214252009-08-11 08:52:18 +00001198 return true;
David Goodwin31e7eba2009-07-20 15:55:39 +00001199 }
Evan Cheng055b0312009-06-29 07:51:04 +00001200
1201 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner52a261b2010-09-21 20:31:19 +00001202 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng3a214252009-08-11 08:52:18 +00001203 // Let t2LDRi8 handle (R - imm8).
1204 return false;
1205
Evan Cheng055b0312009-06-29 07:51:04 +00001206 int RHSC = (int)RHS->getZExtValue();
David Goodwind8c95b52009-07-30 18:56:48 +00001207 if (N.getOpcode() == ISD::SUB)
1208 RHSC = -RHSC;
1209
1210 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Cheng055b0312009-06-29 07:51:04 +00001211 Base = N.getOperand(0);
David Goodwind8c95b52009-07-30 18:56:48 +00001212 if (Base.getOpcode() == ISD::FrameIndex) {
1213 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1214 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
1215 }
Owen Anderson825b72b2009-08-11 20:47:22 +00001216 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
Evan Cheng055b0312009-06-29 07:51:04 +00001217 return true;
1218 }
1219 }
1220
Evan Cheng3a214252009-08-11 08:52:18 +00001221 // Base only.
1222 Base = N;
Owen Anderson825b72b2009-08-11 20:47:22 +00001223 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng3a214252009-08-11 08:52:18 +00001224 return true;
Evan Cheng055b0312009-06-29 07:51:04 +00001225}
1226
Chris Lattner52a261b2010-09-21 20:31:19 +00001227bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Cheng055b0312009-06-29 07:51:04 +00001228 SDValue &Base, SDValue &OffImm) {
David Goodwind8c95b52009-07-30 18:56:48 +00001229 // Match simple R - imm8 operands.
Chris Lattner0a9481f2011-02-13 22:25:43 +00001230 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1231 !CurDAG->isBaseWithConstantOffset(N))
1232 return false;
Owen Anderson099e5552011-03-18 19:46:58 +00001233
Chris Lattner0a9481f2011-02-13 22:25:43 +00001234 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1235 int RHSC = (int)RHS->getSExtValue();
1236 if (N.getOpcode() == ISD::SUB)
1237 RHSC = -RHSC;
Jim Grosbach764ab522009-08-11 15:33:49 +00001238
Chris Lattner0a9481f2011-02-13 22:25:43 +00001239 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1240 Base = N.getOperand(0);
1241 if (Base.getOpcode() == ISD::FrameIndex) {
1242 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1243 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
Evan Cheng055b0312009-06-29 07:51:04 +00001244 }
Chris Lattner0a9481f2011-02-13 22:25:43 +00001245 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1246 return true;
Evan Cheng055b0312009-06-29 07:51:04 +00001247 }
1248 }
1249
1250 return false;
1251}
1252
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001253bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Chenge88d5ce2009-07-02 07:28:31 +00001254 SDValue &OffImm){
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001255 unsigned Opcode = Op->getOpcode();
Evan Chenge88d5ce2009-07-02 07:28:31 +00001256 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1257 ? cast<LoadSDNode>(Op)->getAddressingMode()
1258 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbarec91d522011-01-19 15:12:16 +00001259 int RHSC;
1260 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1261 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
1262 ? CurDAG->getTargetConstant(RHSC, MVT::i32)
1263 : CurDAG->getTargetConstant(-RHSC, MVT::i32);
1264 return true;
Evan Chenge88d5ce2009-07-02 07:28:31 +00001265 }
1266
1267 return false;
1268}
1269
Chris Lattner52a261b2010-09-21 20:31:19 +00001270bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Cheng055b0312009-06-29 07:51:04 +00001271 SDValue &Base,
1272 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng3a214252009-08-11 08:52:18 +00001273 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner0a9481f2011-02-13 22:25:43 +00001274 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng3a214252009-08-11 08:52:18 +00001275 return false;
Evan Cheng055b0312009-06-29 07:51:04 +00001276
Evan Cheng3a214252009-08-11 08:52:18 +00001277 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1278 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1279 int RHSC = (int)RHS->getZExtValue();
1280 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1281 return false;
1282 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwind8c95b52009-07-30 18:56:48 +00001283 return false;
1284 }
1285
Evan Cheng055b0312009-06-29 07:51:04 +00001286 // Look for (R + R) or (R + (R << [1,2,3])).
1287 unsigned ShAmt = 0;
1288 Base = N.getOperand(0);
1289 OffReg = N.getOperand(1);
1290
1291 // Swap if it is ((R << c) + R).
Evan Chengee04a6d2011-07-20 23:34:39 +00001292 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Cheng055b0312009-06-29 07:51:04 +00001293 if (ShOpcVal != ARM_AM::lsl) {
Evan Chengee04a6d2011-07-20 23:34:39 +00001294 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Cheng055b0312009-06-29 07:51:04 +00001295 if (ShOpcVal == ARM_AM::lsl)
1296 std::swap(Base, OffReg);
Jim Grosbach764ab522009-08-11 15:33:49 +00001297 }
1298
Evan Cheng055b0312009-06-29 07:51:04 +00001299 if (ShOpcVal == ARM_AM::lsl) {
1300 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1301 // it.
1302 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1303 ShAmt = Sh->getZExtValue();
Evan Chengf40deed2010-10-27 23:41:30 +00001304 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1305 OffReg = OffReg.getOperand(0);
1306 else {
Evan Cheng055b0312009-06-29 07:51:04 +00001307 ShAmt = 0;
1308 ShOpcVal = ARM_AM::no_shift;
Evan Chengf40deed2010-10-27 23:41:30 +00001309 }
Evan Cheng055b0312009-06-29 07:51:04 +00001310 } else {
1311 ShOpcVal = ARM_AM::no_shift;
1312 }
David Goodwin7ecc8502009-07-15 15:50:19 +00001313 }
Jim Grosbach764ab522009-08-11 15:33:49 +00001314
Owen Anderson825b72b2009-08-11 20:47:22 +00001315 ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32);
Evan Cheng055b0312009-06-29 07:51:04 +00001316
1317 return true;
1318}
1319
1320//===--------------------------------------------------------------------===//
1321
Evan Chengee568cf2007-07-05 07:15:27 +00001322/// getAL - Returns a ARMCC::AL immediate node.
Dan Gohman475871a2008-07-27 21:46:04 +00001323static inline SDValue getAL(SelectionDAG *CurDAG) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001324 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);
Evan Cheng44bec522007-05-15 01:29:07 +00001325}
1326
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001327SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
1328 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengaf4550f2009-07-02 01:23:32 +00001329 ISD::MemIndexedMode AM = LD->getAddressingMode();
1330 if (AM == ISD::UNINDEXED)
1331 return NULL;
1332
Owen Andersone50ed302009-08-10 22:56:29 +00001333 EVT LoadedVT = LD->getMemoryVT();
Evan Chengaf4550f2009-07-02 01:23:32 +00001334 SDValue Offset, AMOpc;
1335 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1336 unsigned Opcode = 0;
1337 bool Match = false;
Owen Andersonc4e16de2011-08-29 20:16:50 +00001338 if (LoadedVT == MVT::i32 && isPre &&
1339 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1340 Opcode = ARM::LDR_PRE_IMM;
1341 Match = true;
1342 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson793e7962011-07-26 20:54:26 +00001343 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Andersonc4e16de2011-08-29 20:16:50 +00001344 Opcode = ARM::LDR_POST_IMM;
Evan Chengaf4550f2009-07-02 01:23:32 +00001345 Match = true;
Owen Anderson793e7962011-07-26 20:54:26 +00001346 } else if (LoadedVT == MVT::i32 &&
1347 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson9ab0f252011-08-26 20:43:14 +00001348 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson793e7962011-07-26 20:54:26 +00001349 Match = true;
1350
Owen Anderson825b72b2009-08-11 20:47:22 +00001351 } else if (LoadedVT == MVT::i16 &&
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001352 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengaf4550f2009-07-02 01:23:32 +00001353 Match = true;
1354 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1355 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1356 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson825b72b2009-08-11 20:47:22 +00001357 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengaf4550f2009-07-02 01:23:32 +00001358 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001359 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengaf4550f2009-07-02 01:23:32 +00001360 Match = true;
1361 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1362 }
1363 } else {
Owen Andersonc4e16de2011-08-29 20:16:50 +00001364 if (isPre &&
1365 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengaf4550f2009-07-02 01:23:32 +00001366 Match = true;
Owen Andersonc4e16de2011-08-29 20:16:50 +00001367 Opcode = ARM::LDRB_PRE_IMM;
1368 } else if (!isPre &&
1369 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1370 Match = true;
1371 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson793e7962011-07-26 20:54:26 +00001372 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1373 Match = true;
Owen Anderson9ab0f252011-08-26 20:43:14 +00001374 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengaf4550f2009-07-02 01:23:32 +00001375 }
1376 }
1377 }
1378
1379 if (Match) {
Owen Anderson2b568fb2011-08-26 21:12:37 +00001380 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1381 SDValue Chain = LD->getChain();
1382 SDValue Base = LD->getBasePtr();
1383 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG),
1384 CurDAG->getRegister(0, MVT::i32), Chain };
Jim Grosbachb04546f2011-09-13 20:30:37 +00001385 return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32,
1386 MVT::i32, MVT::Other, Ops, 5);
Owen Anderson2b568fb2011-08-26 21:12:37 +00001387 } else {
1388 SDValue Chain = LD->getChain();
1389 SDValue Base = LD->getBasePtr();
1390 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG),
1391 CurDAG->getRegister(0, MVT::i32), Chain };
Jim Grosbachb04546f2011-09-13 20:30:37 +00001392 return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32,
1393 MVT::i32, MVT::Other, Ops, 6);
Owen Anderson2b568fb2011-08-26 21:12:37 +00001394 }
Evan Chengaf4550f2009-07-02 01:23:32 +00001395 }
1396
1397 return NULL;
1398}
1399
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001400SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
1401 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chenge88d5ce2009-07-02 07:28:31 +00001402 ISD::MemIndexedMode AM = LD->getAddressingMode();
1403 if (AM == ISD::UNINDEXED)
1404 return NULL;
1405
Owen Andersone50ed302009-08-10 22:56:29 +00001406 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng4fbb9962009-07-02 23:16:11 +00001407 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Chenge88d5ce2009-07-02 07:28:31 +00001408 SDValue Offset;
1409 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1410 unsigned Opcode = 0;
1411 bool Match = false;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001412 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001413 switch (LoadedVT.getSimpleVT().SimpleTy) {
1414 case MVT::i32:
Evan Chenge88d5ce2009-07-02 07:28:31 +00001415 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1416 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001417 case MVT::i16:
Evan Cheng4fbb9962009-07-02 23:16:11 +00001418 if (isSExtLd)
1419 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1420 else
1421 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Chenge88d5ce2009-07-02 07:28:31 +00001422 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001423 case MVT::i8:
1424 case MVT::i1:
Evan Cheng4fbb9962009-07-02 23:16:11 +00001425 if (isSExtLd)
1426 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1427 else
1428 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Chenge88d5ce2009-07-02 07:28:31 +00001429 break;
1430 default:
1431 return NULL;
1432 }
1433 Match = true;
1434 }
1435
1436 if (Match) {
1437 SDValue Chain = LD->getChain();
1438 SDValue Base = LD->getBasePtr();
1439 SDValue Ops[]= { Base, Offset, getAL(CurDAG),
Owen Anderson825b72b2009-08-11 20:47:22 +00001440 CurDAG->getRegister(0, MVT::i32), Chain };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001441 return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32,
Dan Gohman602b0c82009-09-25 18:54:59 +00001442 MVT::Other, Ops, 5);
Evan Chenge88d5ce2009-07-02 07:28:31 +00001443 }
1444
1445 return NULL;
1446}
1447
Weiming Zhaoe56764b2012-11-16 21:55:34 +00001448/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1449SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
1450 DebugLoc dl = V0.getNode()->getDebugLoc();
1451 SDValue RegClass =
1452 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, MVT::i32);
1453 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32);
1454 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32);
1455 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1456 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 5);
1457}
1458
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001459/// \brief Form a D register from a pair of S registers.
1460SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001461 DebugLoc dl = V0.getNode()->getDebugLoc();
Owen Anderson1300f302011-06-16 18:17:13 +00001462 SDValue RegClass =
1463 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, MVT::i32);
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001464 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1465 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
Owen Anderson1300f302011-06-16 18:17:13 +00001466 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1467 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 5);
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001468}
1469
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001470/// \brief Form a quad register from a pair of D registers.
1471SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Bob Wilson3bf12ab2009-10-06 22:01:59 +00001472 DebugLoc dl = V0.getNode()->getDebugLoc();
Owen Anderson1300f302011-06-16 18:17:13 +00001473 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, MVT::i32);
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001474 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1475 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
Owen Anderson1300f302011-06-16 18:17:13 +00001476 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1477 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 5);
Bob Wilson3bf12ab2009-10-06 22:01:59 +00001478}
1479
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001480/// \brief Form 4 consecutive D registers from a pair of Q registers.
1481SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Evan Cheng603afbf2010-05-10 17:34:18 +00001482 DebugLoc dl = V0.getNode()->getDebugLoc();
Owen Anderson1300f302011-06-16 18:17:13 +00001483 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001484 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1485 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
Owen Anderson1300f302011-06-16 18:17:13 +00001486 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
1487 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 5);
Evan Cheng603afbf2010-05-10 17:34:18 +00001488}
1489
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001490/// \brief Form 4 consecutive S registers.
1491SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001492 SDValue V2, SDValue V3) {
1493 DebugLoc dl = V0.getNode()->getDebugLoc();
Owen Anderson1300f302011-06-16 18:17:13 +00001494 SDValue RegClass =
1495 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, MVT::i32);
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001496 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1497 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
1498 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, MVT::i32);
1499 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, MVT::i32);
Owen Anderson1300f302011-06-16 18:17:13 +00001500 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1501 V2, SubReg2, V3, SubReg3 };
1502 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 9);
Bob Wilson40cbe7d2010-06-04 00:04:02 +00001503}
1504
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001505/// \brief Form 4 consecutive D registers.
1506SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng603afbf2010-05-10 17:34:18 +00001507 SDValue V2, SDValue V3) {
1508 DebugLoc dl = V0.getNode()->getDebugLoc();
Owen Anderson1300f302011-06-16 18:17:13 +00001509 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001510 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1511 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
1512 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32);
1513 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32);
Owen Anderson1300f302011-06-16 18:17:13 +00001514 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1515 V2, SubReg2, V3, SubReg3 };
1516 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 9);
Evan Cheng603afbf2010-05-10 17:34:18 +00001517}
1518
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001519/// \brief Form 4 consecutive Q registers.
1520SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng8f6de382010-05-16 03:27:48 +00001521 SDValue V2, SDValue V3) {
1522 DebugLoc dl = V0.getNode()->getDebugLoc();
Owen Anderson1300f302011-06-16 18:17:13 +00001523 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen558661d2010-05-24 16:54:32 +00001524 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1525 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
1526 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32);
1527 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32);
Owen Anderson1300f302011-06-16 18:17:13 +00001528 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1529 V2, SubReg2, V3, SubReg3 };
1530 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 9);
Evan Cheng8f6de382010-05-16 03:27:48 +00001531}
1532
Bob Wilson2a6e6162010-09-23 23:42:37 +00001533/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1534/// of a NEON VLD or VST instruction. The supported values depend on the
1535/// number of registers being loaded.
Bob Wilson665814b2010-11-01 23:40:51 +00001536SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, unsigned NumVecs,
1537 bool is64BitVector) {
Bob Wilson2a6e6162010-09-23 23:42:37 +00001538 unsigned NumRegs = NumVecs;
1539 if (!is64BitVector && NumVecs < 3)
1540 NumRegs *= 2;
1541
Bob Wilson665814b2010-11-01 23:40:51 +00001542 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson2a6e6162010-09-23 23:42:37 +00001543 if (Alignment >= 32 && NumRegs == 4)
Bob Wilson665814b2010-11-01 23:40:51 +00001544 Alignment = 32;
1545 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1546 Alignment = 16;
1547 else if (Alignment >= 8)
1548 Alignment = 8;
1549 else
1550 Alignment = 0;
1551
1552 return CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilson2a6e6162010-09-23 23:42:37 +00001553}
1554
Jim Grosbach10b90a92011-10-24 21:45:13 +00001555// Get the register stride update opcode of a VLD/VST instruction that
1556// is otherwise equivalent to the given fixed stride updating instruction.
1557static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
1558 switch (Opc) {
1559 default: break;
1560 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1561 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1562 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1563 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1564 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1565 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1566 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1567 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jim Grosbach4334e032011-10-31 21:50:31 +00001568
1569 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1570 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1571 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1572 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1573 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1574 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1575 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1576 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbachd5ca2012011-11-29 22:38:04 +00001577 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach4c7edb32011-11-29 22:58:48 +00001578 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbacha4e3c7f2011-12-09 21:28:25 +00001579
Jim Grosbach28f08c92012-03-05 19:33:30 +00001580 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1581 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1582 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbacha4e3c7f2011-12-09 21:28:25 +00001583 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1584 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1585 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1586
Jim Grosbach28f08c92012-03-05 19:33:30 +00001587 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1588 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1589 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbachbb3a2e42011-12-14 21:32:11 +00001590 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1591 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1592 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbache6949b12011-12-21 19:40:55 +00001593
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001594 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1595 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1596 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach10b90a92011-10-24 21:45:13 +00001597 }
1598 return Opc; // If not one we handle, return it unchanged.
1599}
1600
Bob Wilson1c3ef902011-02-07 17:43:21 +00001601SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +00001602 const uint16_t *DOpcodes,
1603 const uint16_t *QOpcodes0,
1604 const uint16_t *QOpcodes1) {
Bob Wilson621f1952010-03-23 05:25:43 +00001605 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Bob Wilson3e36f132009-10-14 17:28:52 +00001606 DebugLoc dl = N->getDebugLoc();
1607
Bob Wilson226036e2010-03-20 22:13:40 +00001608 SDValue MemAddr, Align;
Bob Wilson1c3ef902011-02-07 17:43:21 +00001609 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1610 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilson3e36f132009-10-14 17:28:52 +00001611 return NULL;
1612
1613 SDValue Chain = N->getOperand(0);
1614 EVT VT = N->getValueType(0);
1615 bool is64BitVector = VT.is64BitVector();
Bob Wilson665814b2010-11-01 23:40:51 +00001616 Align = GetVLDSTAlign(Align, NumVecs, is64BitVector);
Bob Wilson40ff01a2010-09-23 21:43:54 +00001617
Bob Wilson3e36f132009-10-14 17:28:52 +00001618 unsigned OpcodeIndex;
1619 switch (VT.getSimpleVT().SimpleTy) {
1620 default: llvm_unreachable("unhandled vld type");
1621 // Double-register operations:
1622 case MVT::v8i8: OpcodeIndex = 0; break;
1623 case MVT::v4i16: OpcodeIndex = 1; break;
1624 case MVT::v2f32:
1625 case MVT::v2i32: OpcodeIndex = 2; break;
1626 case MVT::v1i64: OpcodeIndex = 3; break;
1627 // Quad-register operations:
1628 case MVT::v16i8: OpcodeIndex = 0; break;
1629 case MVT::v8i16: OpcodeIndex = 1; break;
1630 case MVT::v4f32:
1631 case MVT::v4i32: OpcodeIndex = 2; break;
Bob Wilson621f1952010-03-23 05:25:43 +00001632 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilson11d98992010-03-23 06:20:33 +00001633 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson621f1952010-03-23 05:25:43 +00001634 break;
Bob Wilson3e36f132009-10-14 17:28:52 +00001635 }
1636
Bob Wilsonf5721912010-09-03 18:16:02 +00001637 EVT ResTy;
1638 if (NumVecs == 1)
1639 ResTy = VT;
1640 else {
1641 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1642 if (!is64BitVector)
1643 ResTyElts *= 2;
1644 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1645 }
Bob Wilson1c3ef902011-02-07 17:43:21 +00001646 std::vector<EVT> ResTys;
1647 ResTys.push_back(ResTy);
1648 if (isUpdating)
1649 ResTys.push_back(MVT::i32);
1650 ResTys.push_back(MVT::Other);
Bob Wilsonf5721912010-09-03 18:16:02 +00001651
Evan Cheng47b7b9f2010-04-16 05:46:06 +00001652 SDValue Pred = getAL(CurDAG);
Bob Wilson226036e2010-03-20 22:13:40 +00001653 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson1c3ef902011-02-07 17:43:21 +00001654 SDNode *VLd;
1655 SmallVector<SDValue, 7> Ops;
Evan Chenge9e2ba02010-05-10 21:26:24 +00001656
Bob Wilson1c3ef902011-02-07 17:43:21 +00001657 // Double registers and VLD1/VLD2 quad registers are directly supported.
1658 if (is64BitVector || NumVecs <= 2) {
1659 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1660 QOpcodes0[OpcodeIndex]);
1661 Ops.push_back(MemAddr);
1662 Ops.push_back(Align);
1663 if (isUpdating) {
1664 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbacha4e3c7f2011-12-09 21:28:25 +00001665 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach10b90a92011-10-24 21:45:13 +00001666 // case entirely when the rest are updated to that form, too.
Jim Grosbacha4e3c7f2011-12-09 21:28:25 +00001667 if ((NumVecs == 1 || NumVecs == 2) && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach10b90a92011-10-24 21:45:13 +00001668 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jim Grosbacha4e3c7f2011-12-09 21:28:25 +00001669 // We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach4334e032011-10-31 21:50:31 +00001670 // check for that explicitly too. Horribly hacky, but temporary.
Jim Grosbach28f08c92012-03-05 19:33:30 +00001671 if ((NumVecs != 1 && NumVecs != 2 && Opc != ARM::VLD1q64wb_fixed) ||
Jim Grosbach4334e032011-10-31 21:50:31 +00001672 !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach10b90a92011-10-24 21:45:13 +00001673 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Evan Chenge9e2ba02010-05-10 21:26:24 +00001674 }
Bob Wilson1c3ef902011-02-07 17:43:21 +00001675 Ops.push_back(Pred);
1676 Ops.push_back(Reg0);
1677 Ops.push_back(Chain);
1678 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size());
Bob Wilsonffde0802010-09-02 16:00:54 +00001679
Bob Wilson3e36f132009-10-14 17:28:52 +00001680 } else {
1681 // Otherwise, quad registers are loaded with two separate instructions,
1682 // where one loads the even registers and the other loads the odd registers.
Bob Wilsonf5721912010-09-03 18:16:02 +00001683 EVT AddrTy = MemAddr.getValueType();
Bob Wilson3e36f132009-10-14 17:28:52 +00001684
Bob Wilson1c3ef902011-02-07 17:43:21 +00001685 // Load the even subregs. This is always an updating load, so that it
1686 // provides the address to the second load for the odd subregs.
Bob Wilsonf5721912010-09-03 18:16:02 +00001687 SDValue ImplDef =
1688 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1689 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilson7de68142011-02-07 17:43:15 +00001690 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
1691 ResTy, AddrTy, MVT::Other, OpsA, 7);
Bob Wilsonf5721912010-09-03 18:16:02 +00001692 Chain = SDValue(VLdA, 2);
Bob Wilson3e36f132009-10-14 17:28:52 +00001693
Bob Wilson24f995d2009-10-14 18:32:29 +00001694 // Load the odd subregs.
Bob Wilson1c3ef902011-02-07 17:43:21 +00001695 Ops.push_back(SDValue(VLdA, 1));
1696 Ops.push_back(Align);
1697 if (isUpdating) {
1698 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1699 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1700 "only constant post-increment update allowed for VLD3/4");
1701 (void)Inc;
1702 Ops.push_back(Reg0);
1703 }
1704 Ops.push_back(SDValue(VLdA, 0));
1705 Ops.push_back(Pred);
1706 Ops.push_back(Reg0);
1707 Ops.push_back(Chain);
1708 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
1709 Ops.data(), Ops.size());
Bob Wilsonf5721912010-09-03 18:16:02 +00001710 }
Bob Wilson3e36f132009-10-14 17:28:52 +00001711
Evan Chengb58a3402011-04-19 00:04:03 +00001712 // Transfer memoperands.
1713 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1714 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1715 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1716
Bob Wilson1c3ef902011-02-07 17:43:21 +00001717 if (NumVecs == 1)
1718 return VLd;
1719
1720 // Extract out the subregisters.
1721 SDValue SuperReg = SDValue(VLd, 0);
1722 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
1723 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
1724 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1725 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1726 ReplaceUses(SDValue(N, Vec),
1727 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1728 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1729 if (isUpdating)
1730 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Bob Wilson3e36f132009-10-14 17:28:52 +00001731 return NULL;
1732}
1733
Bob Wilson1c3ef902011-02-07 17:43:21 +00001734SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +00001735 const uint16_t *DOpcodes,
1736 const uint16_t *QOpcodes0,
1737 const uint16_t *QOpcodes1) {
Bob Wilsond491d6e2010-07-06 23:36:25 +00001738 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Bob Wilson24f995d2009-10-14 18:32:29 +00001739 DebugLoc dl = N->getDebugLoc();
1740
Bob Wilson226036e2010-03-20 22:13:40 +00001741 SDValue MemAddr, Align;
Bob Wilson1c3ef902011-02-07 17:43:21 +00001742 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1743 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1744 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilson24f995d2009-10-14 18:32:29 +00001745 return NULL;
1746
Evan Chengb58a3402011-04-19 00:04:03 +00001747 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1748 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1749
Bob Wilson24f995d2009-10-14 18:32:29 +00001750 SDValue Chain = N->getOperand(0);
Bob Wilson1c3ef902011-02-07 17:43:21 +00001751 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson24f995d2009-10-14 18:32:29 +00001752 bool is64BitVector = VT.is64BitVector();
Bob Wilson665814b2010-11-01 23:40:51 +00001753 Align = GetVLDSTAlign(Align, NumVecs, is64BitVector);
Bob Wilson2a6e6162010-09-23 23:42:37 +00001754
Bob Wilson24f995d2009-10-14 18:32:29 +00001755 unsigned OpcodeIndex;
1756 switch (VT.getSimpleVT().SimpleTy) {
1757 default: llvm_unreachable("unhandled vst type");
1758 // Double-register operations:
1759 case MVT::v8i8: OpcodeIndex = 0; break;
1760 case MVT::v4i16: OpcodeIndex = 1; break;
1761 case MVT::v2f32:
1762 case MVT::v2i32: OpcodeIndex = 2; break;
1763 case MVT::v1i64: OpcodeIndex = 3; break;
1764 // Quad-register operations:
1765 case MVT::v16i8: OpcodeIndex = 0; break;
1766 case MVT::v8i16: OpcodeIndex = 1; break;
1767 case MVT::v4f32:
1768 case MVT::v4i32: OpcodeIndex = 2; break;
Bob Wilson11d98992010-03-23 06:20:33 +00001769 case MVT::v2i64: OpcodeIndex = 3;
1770 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
1771 break;
Bob Wilson24f995d2009-10-14 18:32:29 +00001772 }
1773
Bob Wilson1c3ef902011-02-07 17:43:21 +00001774 std::vector<EVT> ResTys;
1775 if (isUpdating)
1776 ResTys.push_back(MVT::i32);
1777 ResTys.push_back(MVT::Other);
1778
Evan Cheng47b7b9f2010-04-16 05:46:06 +00001779 SDValue Pred = getAL(CurDAG);
Bob Wilson226036e2010-03-20 22:13:40 +00001780 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson1c3ef902011-02-07 17:43:21 +00001781 SmallVector<SDValue, 7> Ops;
Evan Chengac0869d2009-11-21 06:21:52 +00001782
Bob Wilson1c3ef902011-02-07 17:43:21 +00001783 // Double registers and VST1/VST2 quad registers are directly supported.
1784 if (is64BitVector || NumVecs <= 2) {
Bob Wilson7de68142011-02-07 17:43:15 +00001785 SDValue SrcReg;
Bob Wilsone5ce4f62010-08-28 05:12:57 +00001786 if (NumVecs == 1) {
Bob Wilson1c3ef902011-02-07 17:43:21 +00001787 SrcReg = N->getOperand(Vec0Idx);
1788 } else if (is64BitVector) {
Evan Cheng0ce537a2010-05-11 01:19:40 +00001789 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson1c3ef902011-02-07 17:43:21 +00001790 SDValue V0 = N->getOperand(Vec0Idx + 0);
1791 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Cheng0ce537a2010-05-11 01:19:40 +00001792 if (NumVecs == 2)
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001793 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Cheng0ce537a2010-05-11 01:19:40 +00001794 else {
Bob Wilson1c3ef902011-02-07 17:43:21 +00001795 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson7de68142011-02-07 17:43:15 +00001796 // If it's a vst3, form a quad D-register and leave the last part as
Evan Cheng0ce537a2010-05-11 01:19:40 +00001797 // an undef.
1798 SDValue V3 = (NumVecs == 3)
1799 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson1c3ef902011-02-07 17:43:21 +00001800 : N->getOperand(Vec0Idx + 3);
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001801 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Cheng0ce537a2010-05-11 01:19:40 +00001802 }
Bob Wilsone5ce4f62010-08-28 05:12:57 +00001803 } else {
1804 // Form a QQ register.
Bob Wilson1c3ef902011-02-07 17:43:21 +00001805 SDValue Q0 = N->getOperand(Vec0Idx);
1806 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001807 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilson24f995d2009-10-14 18:32:29 +00001808 }
Bob Wilson1c3ef902011-02-07 17:43:21 +00001809
1810 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1811 QOpcodes0[OpcodeIndex]);
1812 Ops.push_back(MemAddr);
1813 Ops.push_back(Align);
1814 if (isUpdating) {
1815 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachbb3a2e42011-12-14 21:32:11 +00001816 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach4334e032011-10-31 21:50:31 +00001817 // case entirely when the rest are updated to that form, too.
Jim Grosbachbb3a2e42011-12-14 21:32:11 +00001818 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach4334e032011-10-31 21:50:31 +00001819 Opc = getVLDSTRegisterUpdateOpcode(Opc);
1820 // We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
1821 // check for that explicitly too. Horribly hacky, but temporary.
Jim Grosbach28f08c92012-03-05 19:33:30 +00001822 if ((NumVecs > 2 && Opc != ARM::VST1q64wb_fixed) ||
Jim Grosbach4334e032011-10-31 21:50:31 +00001823 !isa<ConstantSDNode>(Inc.getNode()))
1824 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Bob Wilson1c3ef902011-02-07 17:43:21 +00001825 }
1826 Ops.push_back(SrcReg);
1827 Ops.push_back(Pred);
1828 Ops.push_back(Reg0);
1829 Ops.push_back(Chain);
Evan Chengb58a3402011-04-19 00:04:03 +00001830 SDNode *VSt =
1831 CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size());
1832
1833 // Transfer memoperands.
1834 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
1835
1836 return VSt;
Bob Wilson24f995d2009-10-14 18:32:29 +00001837 }
1838
1839 // Otherwise, quad registers are stored with two separate instructions,
1840 // where one stores the even registers and the other stores the odd registers.
Evan Cheng7189fd02010-05-15 07:53:37 +00001841
Bob Wilson07f6e802010-06-16 21:34:01 +00001842 // Form the QQQQ REG_SEQUENCE.
Bob Wilson1c3ef902011-02-07 17:43:21 +00001843 SDValue V0 = N->getOperand(Vec0Idx + 0);
1844 SDValue V1 = N->getOperand(Vec0Idx + 1);
1845 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsone5ce4f62010-08-28 05:12:57 +00001846 SDValue V3 = (NumVecs == 3)
1847 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson1c3ef902011-02-07 17:43:21 +00001848 : N->getOperand(Vec0Idx + 3);
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001849 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson07f6e802010-06-16 21:34:01 +00001850
Bob Wilson1c3ef902011-02-07 17:43:21 +00001851 // Store the even D registers. This is always an updating store, so that it
1852 // provides the address to the second store for the odd subregs.
Bob Wilson7de68142011-02-07 17:43:15 +00001853 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
1854 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
1855 MemAddr.getValueType(),
1856 MVT::Other, OpsA, 7);
Evan Chengb58a3402011-04-19 00:04:03 +00001857 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson07f6e802010-06-16 21:34:01 +00001858 Chain = SDValue(VStA, 1);
1859
1860 // Store the odd D registers.
Bob Wilson1c3ef902011-02-07 17:43:21 +00001861 Ops.push_back(SDValue(VStA, 0));
1862 Ops.push_back(Align);
1863 if (isUpdating) {
1864 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1865 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1866 "only constant post-increment update allowed for VST3/4");
1867 (void)Inc;
1868 Ops.push_back(Reg0);
1869 }
1870 Ops.push_back(RegSeq);
1871 Ops.push_back(Pred);
1872 Ops.push_back(Reg0);
1873 Ops.push_back(Chain);
Evan Chengb58a3402011-04-19 00:04:03 +00001874 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
1875 Ops.data(), Ops.size());
1876 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
1877 return VStB;
Bob Wilson24f995d2009-10-14 18:32:29 +00001878}
1879
Dan Gohmaneeb3a002010-01-05 01:24:18 +00001880SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
Bob Wilson1c3ef902011-02-07 17:43:21 +00001881 bool isUpdating, unsigned NumVecs,
Craig Topper51f50c12012-05-24 05:17:00 +00001882 const uint16_t *DOpcodes,
1883 const uint16_t *QOpcodes) {
Bob Wilson96493442009-10-14 16:46:45 +00001884 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Bob Wilsona7c397c2009-10-14 16:19:03 +00001885 DebugLoc dl = N->getDebugLoc();
1886
Bob Wilson226036e2010-03-20 22:13:40 +00001887 SDValue MemAddr, Align;
Bob Wilson1c3ef902011-02-07 17:43:21 +00001888 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1889 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1890 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilsona7c397c2009-10-14 16:19:03 +00001891 return NULL;
1892
Evan Chengb58a3402011-04-19 00:04:03 +00001893 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1894 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1895
Bob Wilsona7c397c2009-10-14 16:19:03 +00001896 SDValue Chain = N->getOperand(0);
1897 unsigned Lane =
Bob Wilson1c3ef902011-02-07 17:43:21 +00001898 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
1899 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsona7c397c2009-10-14 16:19:03 +00001900 bool is64BitVector = VT.is64BitVector();
1901
Bob Wilson665814b2010-11-01 23:40:51 +00001902 unsigned Alignment = 0;
Bob Wilson3454ed92010-10-19 00:16:32 +00001903 if (NumVecs != 3) {
Bob Wilson665814b2010-11-01 23:40:51 +00001904 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson3454ed92010-10-19 00:16:32 +00001905 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
1906 if (Alignment > NumBytes)
1907 Alignment = NumBytes;
Bob Wilsona92bac62010-12-10 19:37:42 +00001908 if (Alignment < 8 && Alignment < NumBytes)
1909 Alignment = 0;
Bob Wilson3454ed92010-10-19 00:16:32 +00001910 // Alignment must be a power of two; make sure of that.
1911 Alignment = (Alignment & -Alignment);
Bob Wilson665814b2010-11-01 23:40:51 +00001912 if (Alignment == 1)
1913 Alignment = 0;
Bob Wilson3454ed92010-10-19 00:16:32 +00001914 }
Bob Wilson665814b2010-11-01 23:40:51 +00001915 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilson3454ed92010-10-19 00:16:32 +00001916
Bob Wilsona7c397c2009-10-14 16:19:03 +00001917 unsigned OpcodeIndex;
1918 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson96493442009-10-14 16:46:45 +00001919 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilsona7c397c2009-10-14 16:19:03 +00001920 // Double-register operations:
1921 case MVT::v8i8: OpcodeIndex = 0; break;
1922 case MVT::v4i16: OpcodeIndex = 1; break;
1923 case MVT::v2f32:
1924 case MVT::v2i32: OpcodeIndex = 2; break;
1925 // Quad-register operations:
1926 case MVT::v8i16: OpcodeIndex = 0; break;
1927 case MVT::v4f32:
1928 case MVT::v4i32: OpcodeIndex = 1; break;
1929 }
1930
Bob Wilson1c3ef902011-02-07 17:43:21 +00001931 std::vector<EVT> ResTys;
1932 if (IsLoad) {
1933 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1934 if (!is64BitVector)
1935 ResTyElts *= 2;
1936 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
1937 MVT::i64, ResTyElts));
1938 }
1939 if (isUpdating)
1940 ResTys.push_back(MVT::i32);
1941 ResTys.push_back(MVT::Other);
1942
Evan Cheng47b7b9f2010-04-16 05:46:06 +00001943 SDValue Pred = getAL(CurDAG);
Bob Wilson226036e2010-03-20 22:13:40 +00001944 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengac0869d2009-11-21 06:21:52 +00001945
Bob Wilson1c3ef902011-02-07 17:43:21 +00001946 SmallVector<SDValue, 8> Ops;
Bob Wilsona7c397c2009-10-14 16:19:03 +00001947 Ops.push_back(MemAddr);
Jim Grosbach8a5ec862009-11-07 21:25:39 +00001948 Ops.push_back(Align);
Bob Wilson1c3ef902011-02-07 17:43:21 +00001949 if (isUpdating) {
1950 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1951 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
1952 }
Bob Wilson07f6e802010-06-16 21:34:01 +00001953
Bob Wilson8466fa12010-09-13 23:01:35 +00001954 SDValue SuperReg;
Bob Wilson1c3ef902011-02-07 17:43:21 +00001955 SDValue V0 = N->getOperand(Vec0Idx + 0);
1956 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilson8466fa12010-09-13 23:01:35 +00001957 if (NumVecs == 2) {
1958 if (is64BitVector)
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001959 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilson8466fa12010-09-13 23:01:35 +00001960 else
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001961 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilsona7c397c2009-10-14 16:19:03 +00001962 } else {
Bob Wilson1c3ef902011-02-07 17:43:21 +00001963 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson8466fa12010-09-13 23:01:35 +00001964 SDValue V3 = (NumVecs == 3)
Bob Wilson1c3ef902011-02-07 17:43:21 +00001965 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
1966 : N->getOperand(Vec0Idx + 3);
Bob Wilson8466fa12010-09-13 23:01:35 +00001967 if (is64BitVector)
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001968 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilson8466fa12010-09-13 23:01:35 +00001969 else
Weiming Zhao8b149cb2012-11-17 00:23:35 +00001970 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilsona7c397c2009-10-14 16:19:03 +00001971 }
Bob Wilson8466fa12010-09-13 23:01:35 +00001972 Ops.push_back(SuperReg);
Bob Wilsona7c397c2009-10-14 16:19:03 +00001973 Ops.push_back(getI32Imm(Lane));
Evan Chengac0869d2009-11-21 06:21:52 +00001974 Ops.push_back(Pred);
Bob Wilson226036e2010-03-20 22:13:40 +00001975 Ops.push_back(Reg0);
Bob Wilsona7c397c2009-10-14 16:19:03 +00001976 Ops.push_back(Chain);
1977
Bob Wilson1c3ef902011-02-07 17:43:21 +00001978 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1979 QOpcodes[OpcodeIndex]);
1980 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys,
1981 Ops.data(), Ops.size());
Evan Chengb58a3402011-04-19 00:04:03 +00001982 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson96493442009-10-14 16:46:45 +00001983 if (!IsLoad)
Bob Wilson1c3ef902011-02-07 17:43:21 +00001984 return VLdLn;
Evan Cheng7092c2b2010-05-15 01:36:29 +00001985
Bob Wilson8466fa12010-09-13 23:01:35 +00001986 // Extract the subregisters.
Bob Wilson1c3ef902011-02-07 17:43:21 +00001987 SuperReg = SDValue(VLdLn, 0);
1988 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
1989 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
1990 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson07f6e802010-06-16 21:34:01 +00001991 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1992 ReplaceUses(SDValue(N, Vec),
Bob Wilson1c3ef902011-02-07 17:43:21 +00001993 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1994 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
1995 if (isUpdating)
1996 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Bob Wilsona7c397c2009-10-14 16:19:03 +00001997 return NULL;
1998}
1999
Bob Wilson1c3ef902011-02-07 17:43:21 +00002000SDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating,
Craig Topper51f50c12012-05-24 05:17:00 +00002001 unsigned NumVecs,
2002 const uint16_t *Opcodes) {
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002003 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
2004 DebugLoc dl = N->getDebugLoc();
2005
2006 SDValue MemAddr, Align;
2007 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
2008 return NULL;
2009
Evan Chengb58a3402011-04-19 00:04:03 +00002010 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2011 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2012
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002013 SDValue Chain = N->getOperand(0);
2014 EVT VT = N->getValueType(0);
2015
2016 unsigned Alignment = 0;
2017 if (NumVecs != 3) {
2018 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2019 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2020 if (Alignment > NumBytes)
2021 Alignment = NumBytes;
Bob Wilsona92bac62010-12-10 19:37:42 +00002022 if (Alignment < 8 && Alignment < NumBytes)
2023 Alignment = 0;
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002024 // Alignment must be a power of two; make sure of that.
2025 Alignment = (Alignment & -Alignment);
2026 if (Alignment == 1)
2027 Alignment = 0;
2028 }
2029 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
2030
2031 unsigned OpcodeIndex;
2032 switch (VT.getSimpleVT().SimpleTy) {
2033 default: llvm_unreachable("unhandled vld-dup type");
2034 case MVT::v8i8: OpcodeIndex = 0; break;
2035 case MVT::v4i16: OpcodeIndex = 1; break;
2036 case MVT::v2f32:
2037 case MVT::v2i32: OpcodeIndex = 2; break;
2038 }
2039
2040 SDValue Pred = getAL(CurDAG);
2041 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2042 SDValue SuperReg;
2043 unsigned Opc = Opcodes[OpcodeIndex];
Bob Wilson1c3ef902011-02-07 17:43:21 +00002044 SmallVector<SDValue, 6> Ops;
2045 Ops.push_back(MemAddr);
2046 Ops.push_back(Align);
2047 if (isUpdating) {
Jim Grosbache6949b12011-12-21 19:40:55 +00002048 // fixed-stride update instructions don't have an explicit writeback
2049 // operand. It's implicit in the opcode itself.
Bob Wilson1c3ef902011-02-07 17:43:21 +00002050 SDValue Inc = N->getOperand(2);
Jim Grosbache6949b12011-12-21 19:40:55 +00002051 if (!isa<ConstantSDNode>(Inc.getNode()))
2052 Ops.push_back(Inc);
2053 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2054 else if (NumVecs > 2)
2055 Ops.push_back(Reg0);
Bob Wilson1c3ef902011-02-07 17:43:21 +00002056 }
2057 Ops.push_back(Pred);
2058 Ops.push_back(Reg0);
2059 Ops.push_back(Chain);
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002060
2061 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson1c3ef902011-02-07 17:43:21 +00002062 std::vector<EVT> ResTys;
Evan Chengb58a3402011-04-19 00:04:03 +00002063 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson1c3ef902011-02-07 17:43:21 +00002064 if (isUpdating)
2065 ResTys.push_back(MVT::i32);
2066 ResTys.push_back(MVT::Other);
2067 SDNode *VLdDup =
2068 CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size());
Evan Chengb58a3402011-04-19 00:04:03 +00002069 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002070 SuperReg = SDValue(VLdDup, 0);
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002071
2072 // Extract the subregisters.
2073 assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
2074 unsigned SubIdx = ARM::dsub_0;
2075 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2076 ReplaceUses(SDValue(N, Vec),
2077 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Bob Wilson1c3ef902011-02-07 17:43:21 +00002078 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2079 if (isUpdating)
2080 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002081 return NULL;
2082}
2083
Bob Wilson78dfbc32010-07-07 00:08:54 +00002084SDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2085 unsigned Opc) {
Bob Wilsond491d6e2010-07-06 23:36:25 +00002086 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
2087 DebugLoc dl = N->getDebugLoc();
2088 EVT VT = N->getValueType(0);
Bob Wilson78dfbc32010-07-07 00:08:54 +00002089 unsigned FirstTblReg = IsExt ? 2 : 1;
Bob Wilsond491d6e2010-07-06 23:36:25 +00002090
2091 // Form a REG_SEQUENCE to force register allocation.
2092 SDValue RegSeq;
Bob Wilson78dfbc32010-07-07 00:08:54 +00002093 SDValue V0 = N->getOperand(FirstTblReg + 0);
2094 SDValue V1 = N->getOperand(FirstTblReg + 1);
Bob Wilsond491d6e2010-07-06 23:36:25 +00002095 if (NumVecs == 2)
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002096 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bob Wilsond491d6e2010-07-06 23:36:25 +00002097 else {
Bob Wilson78dfbc32010-07-07 00:08:54 +00002098 SDValue V2 = N->getOperand(FirstTblReg + 2);
Jim Grosbach3ab56582010-10-21 19:38:40 +00002099 // If it's a vtbl3, form a quad D-register and leave the last part as
Bob Wilsond491d6e2010-07-06 23:36:25 +00002100 // an undef.
2101 SDValue V3 = (NumVecs == 3)
2102 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson78dfbc32010-07-07 00:08:54 +00002103 : N->getOperand(FirstTblReg + 3);
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002104 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond491d6e2010-07-06 23:36:25 +00002105 }
2106
Bob Wilson78dfbc32010-07-07 00:08:54 +00002107 SmallVector<SDValue, 6> Ops;
2108 if (IsExt)
2109 Ops.push_back(N->getOperand(1));
Bob Wilsonbd916c52010-09-13 23:55:10 +00002110 Ops.push_back(RegSeq);
Bob Wilson78dfbc32010-07-07 00:08:54 +00002111 Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
Bob Wilsond491d6e2010-07-06 23:36:25 +00002112 Ops.push_back(getAL(CurDAG)); // predicate
2113 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
Bob Wilson78dfbc32010-07-07 00:08:54 +00002114 return CurDAG->getMachineNode(Opc, dl, VT, Ops.data(), Ops.size());
Bob Wilsond491d6e2010-07-06 23:36:25 +00002115}
2116
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002117SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002118 bool isSigned) {
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002119 if (!Subtarget->hasV6T2Ops())
2120 return NULL;
Bob Wilson96493442009-10-14 16:46:45 +00002121
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002122 unsigned Opc = isSigned ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
2123 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
2124
2125
2126 // For unsigned extracts, check for a shift right and mask
2127 unsigned And_imm = 0;
2128 if (N->getOpcode() == ISD::AND) {
2129 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2130
Sylvestre Ledru94c22712012-09-27 10:14:43 +00002131 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002132 if (And_imm & (And_imm + 1))
2133 return NULL;
2134
2135 unsigned Srl_imm = 0;
2136 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2137 Srl_imm)) {
2138 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2139
Jim Grosbachfb8989e2011-07-27 21:09:25 +00002140 // Note: The width operand is encoded as width-1.
2141 unsigned Width = CountTrailingOnes_32(And_imm) - 1;
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002142 unsigned LSB = Srl_imm;
2143 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2144 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2145 CurDAG->getTargetConstant(LSB, MVT::i32),
2146 CurDAG->getTargetConstant(Width, MVT::i32),
2147 getAL(CurDAG), Reg0 };
2148 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
2149 }
2150 }
2151 return NULL;
2152 }
2153
2154 // Otherwise, we're looking for a shift of a shift
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002155 unsigned Shl_imm = 0;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002156 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002157 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2158 unsigned Srl_imm = 0;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002159 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002160 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbachfb8989e2011-07-27 21:09:25 +00002161 // Note: The width operand is encoded as width-1.
2162 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002163 int LSB = Srl_imm - Shl_imm;
Evan Cheng8000c6c2009-10-22 00:40:00 +00002164 if (LSB < 0)
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002165 return NULL;
2166 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002167 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002168 CurDAG->getTargetConstant(LSB, MVT::i32),
2169 CurDAG->getTargetConstant(Width, MVT::i32),
2170 getAL(CurDAG), Reg0 };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002171 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002172 }
2173 }
2174 return NULL;
2175}
2176
Evan Cheng9ef48352009-11-20 00:54:03 +00002177SDNode *ARMDAGToDAGISel::
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002178SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002179 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
2180 SDValue CPTmp0;
2181 SDValue CPTmp1;
Chris Lattner52a261b2010-09-21 20:31:19 +00002182 if (SelectT2ShifterOperandReg(TrueVal, CPTmp0, CPTmp1)) {
Evan Cheng9ef48352009-11-20 00:54:03 +00002183 unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue();
2184 unsigned SOShOp = ARM_AM::getSORegShOp(SOVal);
2185 unsigned Opc = 0;
2186 switch (SOShOp) {
2187 case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break;
2188 case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break;
2189 case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break;
2190 case ARM_AM::ror: Opc = ARM::t2MOVCCror; break;
2191 default:
2192 llvm_unreachable("Unknown so_reg opcode!");
Evan Cheng9ef48352009-11-20 00:54:03 +00002193 }
2194 SDValue SOShImm =
2195 CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32);
2196 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2197 SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag };
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002198 return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6);
Evan Cheng9ef48352009-11-20 00:54:03 +00002199 }
2200 return 0;
2201}
2202
2203SDNode *ARMDAGToDAGISel::
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002204SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002205 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
2206 SDValue CPTmp0;
2207 SDValue CPTmp1;
2208 SDValue CPTmp2;
Owen Anderson152d4a42011-07-21 23:38:37 +00002209 if (SelectImmShifterOperand(TrueVal, CPTmp0, CPTmp2)) {
Evan Cheng9ef48352009-11-20 00:54:03 +00002210 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
Owen Andersone0a03142011-07-22 18:30:30 +00002211 SDValue Ops[] = { FalseVal, CPTmp0, CPTmp2, CC, CCR, InFlag };
2212 return CurDAG->SelectNodeTo(N, ARM::MOVCCsi, MVT::i32, Ops, 6);
Owen Anderson92a20222011-07-21 18:54:16 +00002213 }
2214
2215 if (SelectRegShifterOperand(TrueVal, CPTmp0, CPTmp1, CPTmp2)) {
2216 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2217 SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag };
2218 return CurDAG->SelectNodeTo(N, ARM::MOVCCsr, MVT::i32, Ops, 7);
Evan Cheng9ef48352009-11-20 00:54:03 +00002219 }
2220 return 0;
2221}
2222
2223SDNode *ARMDAGToDAGISel::
Jim Grosbacha4257162010-10-07 00:53:56 +00002224SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng6b194912010-11-17 20:56:30 +00002225 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
Evan Cheng9ef48352009-11-20 00:54:03 +00002226 ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal);
Evan Chengff96b632010-11-19 23:01:16 +00002227 if (!T)
Evan Cheng9ef48352009-11-20 00:54:03 +00002228 return 0;
2229
Evan Cheng63f35442010-11-13 02:25:14 +00002230 unsigned Opc = 0;
Jim Grosbacha4257162010-10-07 00:53:56 +00002231 unsigned TrueImm = T->getZExtValue();
Evan Cheng6b194912010-11-17 20:56:30 +00002232 if (is_t2_so_imm(TrueImm)) {
2233 Opc = ARM::t2MOVCCi;
2234 } else if (TrueImm <= 0xffff) {
2235 Opc = ARM::t2MOVCCi16;
Evan Cheng63f35442010-11-13 02:25:14 +00002236 } else if (is_t2_so_imm_not(TrueImm)) {
2237 TrueImm = ~TrueImm;
2238 Opc = ARM::t2MVNCCi;
Evan Cheng6b194912010-11-17 20:56:30 +00002239 } else if (TrueVal.getNode()->hasOneUse() && Subtarget->hasV6T2Ops()) {
Evan Cheng63f35442010-11-13 02:25:14 +00002240 // Large immediate.
2241 Opc = ARM::t2MOVCCi32imm;
2242 }
2243
2244 if (Opc) {
Evan Cheng875a6ac2010-11-12 22:42:47 +00002245 SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32);
Evan Cheng9ef48352009-11-20 00:54:03 +00002246 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2247 SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
Evan Cheng63f35442010-11-13 02:25:14 +00002248 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Cheng9ef48352009-11-20 00:54:03 +00002249 }
Evan Cheng63f35442010-11-13 02:25:14 +00002250
Evan Cheng9ef48352009-11-20 00:54:03 +00002251 return 0;
2252}
2253
2254SDNode *ARMDAGToDAGISel::
Jim Grosbach3bbdcea2010-10-07 00:42:42 +00002255SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng6b194912010-11-17 20:56:30 +00002256 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
Evan Cheng9ef48352009-11-20 00:54:03 +00002257 ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal);
2258 if (!T)
2259 return 0;
2260
Evan Cheng63f35442010-11-13 02:25:14 +00002261 unsigned Opc = 0;
Jim Grosbach3bbdcea2010-10-07 00:42:42 +00002262 unsigned TrueImm = T->getZExtValue();
Evan Cheng875a6ac2010-11-12 22:42:47 +00002263 bool isSoImm = is_so_imm(TrueImm);
Evan Cheng6b194912010-11-17 20:56:30 +00002264 if (isSoImm) {
2265 Opc = ARM::MOVCCi;
2266 } else if (Subtarget->hasV6T2Ops() && TrueImm <= 0xffff) {
2267 Opc = ARM::MOVCCi16;
Evan Cheng63f35442010-11-13 02:25:14 +00002268 } else if (is_so_imm_not(TrueImm)) {
2269 TrueImm = ~TrueImm;
2270 Opc = ARM::MVNCCi;
Evan Cheng6b194912010-11-17 20:56:30 +00002271 } else if (TrueVal.getNode()->hasOneUse() &&
2272 (Subtarget->hasV6T2Ops() || ARM_AM::isSOImmTwoPartVal(TrueImm))) {
Evan Cheng63f35442010-11-13 02:25:14 +00002273 // Large immediate.
2274 Opc = ARM::MOVCCi32imm;
2275 }
2276
2277 if (Opc) {
Jim Grosbach3bbdcea2010-10-07 00:42:42 +00002278 SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32);
Evan Cheng9ef48352009-11-20 00:54:03 +00002279 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2280 SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
Evan Cheng63f35442010-11-13 02:25:14 +00002281 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Cheng9ef48352009-11-20 00:54:03 +00002282 }
Andrew Trick6e8f4c42010-12-24 04:28:06 +00002283
Evan Cheng9ef48352009-11-20 00:54:03 +00002284 return 0;
2285}
2286
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002287SDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) {
2288 EVT VT = N->getValueType(0);
2289 SDValue FalseVal = N->getOperand(0);
2290 SDValue TrueVal = N->getOperand(1);
2291 SDValue CC = N->getOperand(2);
2292 SDValue CCR = N->getOperand(3);
2293 SDValue InFlag = N->getOperand(4);
Evan Cheng9ef48352009-11-20 00:54:03 +00002294 assert(CC.getOpcode() == ISD::Constant);
2295 assert(CCR.getOpcode() == ISD::Register);
2296 ARMCC::CondCodes CCVal =
2297 (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue();
Evan Cheng07ba9062009-11-19 21:45:22 +00002298
2299 if (!Subtarget->isThumb1Only() && VT == MVT::i32) {
2300 // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
2301 // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
2302 // Pattern complexity = 18 cost = 1 size = 0
Evan Cheng07ba9062009-11-19 21:45:22 +00002303 if (Subtarget->isThumb()) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002304 SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002305 CCVal, CCR, InFlag);
2306 if (!Res)
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002307 Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002308 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2309 if (Res)
2310 return Res;
Evan Cheng07ba9062009-11-19 21:45:22 +00002311 } else {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002312 SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002313 CCVal, CCR, InFlag);
2314 if (!Res)
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002315 Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002316 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2317 if (Res)
2318 return Res;
Evan Cheng07ba9062009-11-19 21:45:22 +00002319 }
2320
2321 // Pattern: (ARMcmov:i32 GPR:i32:$false,
Jakob Stoklund Olesen00d3dda2010-08-17 20:39:04 +00002322 // (imm:i32)<<P:Pred_so_imm>>:$true,
Evan Cheng07ba9062009-11-19 21:45:22 +00002323 // (imm:i32):$cc)
2324 // Emits: (MOVCCi:i32 GPR:i32:$false,
2325 // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc)
2326 // Pattern complexity = 10 cost = 1 size = 0
Evan Cheng9ef48352009-11-20 00:54:03 +00002327 if (Subtarget->isThumb()) {
Jim Grosbacha4257162010-10-07 00:53:56 +00002328 SDNode *Res = SelectT2CMOVImmOp(N, FalseVal, TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002329 CCVal, CCR, InFlag);
2330 if (!Res)
Jim Grosbacha4257162010-10-07 00:53:56 +00002331 Res = SelectT2CMOVImmOp(N, TrueVal, FalseVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002332 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2333 if (Res)
2334 return Res;
2335 } else {
Jim Grosbach3bbdcea2010-10-07 00:42:42 +00002336 SDNode *Res = SelectARMCMOVImmOp(N, FalseVal, TrueVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002337 CCVal, CCR, InFlag);
2338 if (!Res)
Jim Grosbach3bbdcea2010-10-07 00:42:42 +00002339 Res = SelectARMCMOVImmOp(N, TrueVal, FalseVal,
Evan Cheng9ef48352009-11-20 00:54:03 +00002340 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2341 if (Res)
2342 return Res;
Evan Cheng07ba9062009-11-19 21:45:22 +00002343 }
2344 }
2345
2346 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2347 // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2348 // Pattern complexity = 6 cost = 1 size = 0
2349 //
2350 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2351 // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2352 // Pattern complexity = 6 cost = 11 size = 0
2353 //
Jim Grosbach3c5edaa2011-03-11 23:15:02 +00002354 // Also VMOVScc and VMOVDcc.
Evan Cheng9ef48352009-11-20 00:54:03 +00002355 SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32);
2356 SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag };
Evan Cheng07ba9062009-11-19 21:45:22 +00002357 unsigned Opc = 0;
2358 switch (VT.getSimpleVT().SimpleTy) {
Craig Topperbc219812012-02-07 02:50:20 +00002359 default: llvm_unreachable("Illegal conditional move type!");
Evan Cheng07ba9062009-11-19 21:45:22 +00002360 case MVT::i32:
2361 Opc = Subtarget->isThumb()
2362 ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo)
2363 : ARM::MOVCCr;
2364 break;
2365 case MVT::f32:
2366 Opc = ARM::VMOVScc;
2367 break;
2368 case MVT::f64:
2369 Opc = ARM::VMOVDcc;
2370 break;
2371 }
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002372 return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5);
Evan Cheng07ba9062009-11-19 21:45:22 +00002373}
2374
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002375/// Target-specific DAG combining for ISD::XOR.
2376/// Target-independent combining lowers SELECT_CC nodes of the form
2377/// select_cc setg[ge] X, 0, X, -X
2378/// select_cc setgt X, -1, X, -X
2379/// select_cc setl[te] X, 0, -X, X
2380/// select_cc setlt X, 1, -X, X
2381/// which represent Integer ABS into:
2382/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2383/// ARM instruction selection detects the latter and matches it to
2384/// ARM::ABS or ARM::t2ABS machine node.
2385SDNode *ARMDAGToDAGISel::SelectABSOp(SDNode *N){
2386 SDValue XORSrc0 = N->getOperand(0);
2387 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002388 EVT VT = N->getValueType(0);
2389
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002390 if (Subtarget->isThumb1Only())
2391 return NULL;
2392
Jim Grosbach27690282012-08-01 20:33:00 +00002393 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002394 return NULL;
2395
2396 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2397 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2398 SDValue SRASrc0 = XORSrc1.getOperand(0);
2399 SDValue SRASrc1 = XORSrc1.getOperand(1);
2400 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2401 EVT XType = SRASrc0.getValueType();
2402 unsigned Size = XType.getSizeInBits() - 1;
2403
Jim Grosbach27690282012-08-01 20:33:00 +00002404 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
2405 XType.isInteger() && SRAConstant != NULL &&
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002406 Size == SRAConstant->getZExtValue()) {
Jim Grosbach27690282012-08-01 20:33:00 +00002407 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002408 return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2409 }
2410
2411 return NULL;
2412}
2413
Evan Chengde8aa4e2010-05-05 18:28:36 +00002414SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
2415 // The only time a CONCAT_VECTORS operation can have legal types is when
2416 // two 64-bit vectors are concatenated to a 128-bit vector.
2417 EVT VT = N->getValueType(0);
2418 if (!VT.is128BitVector() || N->getNumOperands() != 2)
2419 llvm_unreachable("unexpected CONCAT_VECTORS");
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002420 return createDRegPairNode(VT, N->getOperand(0), N->getOperand(1));
Evan Chengde8aa4e2010-05-05 18:28:36 +00002421}
2422
Eli Friedman2bdffe42011-08-31 00:31:29 +00002423SDNode *ARMDAGToDAGISel::SelectAtomic64(SDNode *Node, unsigned Opc) {
Eli Friedman4d3f3292011-08-31 17:52:22 +00002424 SmallVector<SDValue, 6> Ops;
2425 Ops.push_back(Node->getOperand(1)); // Ptr
2426 Ops.push_back(Node->getOperand(2)); // Low part of Val1
2427 Ops.push_back(Node->getOperand(3)); // High part of Val1
Owen Andersond84192f2011-08-31 20:00:11 +00002428 if (Opc == ARM::ATOMCMPXCHG6432) {
Eli Friedman4d3f3292011-08-31 17:52:22 +00002429 Ops.push_back(Node->getOperand(4)); // Low part of Val2
2430 Ops.push_back(Node->getOperand(5)); // High part of Val2
2431 }
2432 Ops.push_back(Node->getOperand(0)); // Chain
Eli Friedman2bdffe42011-08-31 00:31:29 +00002433 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2434 MemOp[0] = cast<MemSDNode>(Node)->getMemOperand();
Eli Friedman2bdffe42011-08-31 00:31:29 +00002435 SDNode *ResNode = CurDAG->getMachineNode(Opc, Node->getDebugLoc(),
Eli Friedman4d3f3292011-08-31 17:52:22 +00002436 MVT::i32, MVT::i32, MVT::Other,
2437 Ops.data() ,Ops.size());
Eli Friedman2bdffe42011-08-31 00:31:29 +00002438 cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp + 1);
2439 return ResNode;
2440}
2441
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002442SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
Dale Johannesened2eee62009-02-06 01:31:28 +00002443 DebugLoc dl = N->getDebugLoc();
Evan Chenga8e29892007-01-19 07:51:42 +00002444
Dan Gohmane8be6c62008-07-17 19:10:17 +00002445 if (N->isMachineOpcode())
Evan Chenga8e29892007-01-19 07:51:42 +00002446 return NULL; // Already selected.
Rafael Espindola337c4ad62006-06-12 12:28:08 +00002447
2448 switch (N->getOpcode()) {
Evan Chenga8e29892007-01-19 07:51:42 +00002449 default: break;
Bill Wendlingef2c86f2011-10-10 22:59:55 +00002450 case ISD::XOR: {
2451 // Select special operations if XOR node forms integer ABS pattern
2452 SDNode *ResNode = SelectABSOp(N);
2453 if (ResNode)
2454 return ResNode;
2455 // Other cases are autogenerated.
2456 break;
2457 }
Evan Chenga8e29892007-01-19 07:51:42 +00002458 case ISD::Constant: {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002459 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +00002460 bool UseCP = true;
Anton Korobeynikov6a2fa322009-09-27 23:52:58 +00002461 if (Subtarget->hasThumb2())
2462 // Thumb2-aware targets have the MOVT instruction, so all immediates can
2463 // be done with MOV + MOVT, at worst.
2464 UseCP = 0;
2465 else {
2466 if (Subtarget->isThumb()) {
Bob Wilsone64e3cf2009-06-22 17:29:13 +00002467 UseCP = (Val > 255 && // MOV
2468 ~Val > 255 && // MOV + MVN
2469 !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL
Anton Korobeynikov6a2fa322009-09-27 23:52:58 +00002470 } else
2471 UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV
2472 ARM_AM::getSOImmVal(~Val) == -1 && // MVN
2473 !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs.
2474 }
2475
Evan Chenga8e29892007-01-19 07:51:42 +00002476 if (UseCP) {
Dan Gohman475871a2008-07-27 21:46:04 +00002477 SDValue CPIdx =
Owen Anderson1d0be152009-08-13 21:58:54 +00002478 CurDAG->getTargetConstantPool(ConstantInt::get(
2479 Type::getInt32Ty(*CurDAG->getContext()), Val),
Evan Chenga8e29892007-01-19 07:51:42 +00002480 TLI.getPointerTy());
Evan Cheng012f2d92007-01-24 08:53:17 +00002481
2482 SDNode *ResNode;
Evan Cheng446c4282009-07-11 06:43:01 +00002483 if (Subtarget->isThumb1Only()) {
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002484 SDValue Pred = getAL(CurDAG);
Owen Anderson825b72b2009-08-11 20:47:22 +00002485 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Cheng446c4282009-07-11 06:43:01 +00002486 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbach3e333632010-12-15 23:52:36 +00002487 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Dan Gohman602b0c82009-09-25 18:54:59 +00002488 Ops, 4);
Evan Cheng446c4282009-07-11 06:43:01 +00002489 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00002490 SDValue Ops[] = {
Jim Grosbach764ab522009-08-11 15:33:49 +00002491 CPIdx,
Owen Anderson825b72b2009-08-11 20:47:22 +00002492 CurDAG->getTargetConstant(0, MVT::i32),
Evan Chengee568cf2007-07-05 07:15:27 +00002493 getAL(CurDAG),
Owen Anderson825b72b2009-08-11 20:47:22 +00002494 CurDAG->getRegister(0, MVT::i32),
Evan Cheng012f2d92007-01-24 08:53:17 +00002495 CurDAG->getEntryNode()
2496 };
Dan Gohman602b0c82009-09-25 18:54:59 +00002497 ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
Jim Grosbach3e556122010-10-26 22:37:02 +00002498 Ops, 5);
Evan Cheng012f2d92007-01-24 08:53:17 +00002499 }
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002500 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
Evan Chenga8e29892007-01-19 07:51:42 +00002501 return NULL;
2502 }
Jim Grosbach764ab522009-08-11 15:33:49 +00002503
Evan Chenga8e29892007-01-19 07:51:42 +00002504 // Other cases are autogenerated.
Rafael Espindola337c4ad62006-06-12 12:28:08 +00002505 break;
Evan Chenga8e29892007-01-19 07:51:42 +00002506 }
Rafael Espindolaf819a492006-11-09 13:58:55 +00002507 case ISD::FrameIndex: {
Evan Chenga8e29892007-01-19 07:51:42 +00002508 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindolaf819a492006-11-09 13:58:55 +00002509 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Dan Gohman475871a2008-07-27 21:46:04 +00002510 SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
David Goodwinf1daf7d2009-07-08 23:10:31 +00002511 if (Subtarget->isThumb1Only()) {
Jim Grosbach5b815842011-08-24 17:46:13 +00002512 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
2513 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2514 return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, Ops, 4);
Jim Grosbach30eae3c2009-04-07 20:34:09 +00002515 } else {
David Goodwin419c6152009-07-14 18:48:51 +00002516 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2517 ARM::t2ADDri : ARM::ADDri);
Owen Anderson825b72b2009-08-11 20:47:22 +00002518 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
2519 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2520 CurDAG->getRegister(0, MVT::i32) };
2521 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Chengee568cf2007-07-05 07:15:27 +00002522 }
Evan Chenga8e29892007-01-19 07:51:42 +00002523 }
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002524 case ISD::SRL:
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002525 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002526 return I;
2527 break;
2528 case ISD::SRA:
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002529 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true))
Sandeep Patel47eedaa2009-10-13 18:59:48 +00002530 return I;
2531 break;
Evan Chenga8e29892007-01-19 07:51:42 +00002532 case ISD::MUL:
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002533 if (Subtarget->isThumb1Only())
Evan Cheng79d43262007-01-24 02:21:22 +00002534 break;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002535 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002536 unsigned RHSV = C->getZExtValue();
Evan Chenga8e29892007-01-19 07:51:42 +00002537 if (!RHSV) break;
2538 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Chengaf9e7a72009-07-21 00:31:12 +00002539 unsigned ShImm = Log2_32(RHSV-1);
2540 if (ShImm >= 32)
2541 break;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002542 SDValue V = N->getOperand(0);
Evan Chengaf9e7a72009-07-21 00:31:12 +00002543 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson825b72b2009-08-11 20:47:22 +00002544 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
2545 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng78dd9db2009-07-22 18:08:05 +00002546 if (Subtarget->isThumb()) {
Evan Chengaf9e7a72009-07-21 00:31:12 +00002547 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson825b72b2009-08-11 20:47:22 +00002548 return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6);
Evan Chengaf9e7a72009-07-21 00:31:12 +00002549 } else {
2550 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson92a20222011-07-21 18:54:16 +00002551 return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops, 7);
Evan Chengaf9e7a72009-07-21 00:31:12 +00002552 }
Evan Chenga8e29892007-01-19 07:51:42 +00002553 }
2554 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Chengaf9e7a72009-07-21 00:31:12 +00002555 unsigned ShImm = Log2_32(RHSV+1);
2556 if (ShImm >= 32)
2557 break;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002558 SDValue V = N->getOperand(0);
Evan Chengaf9e7a72009-07-21 00:31:12 +00002559 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson825b72b2009-08-11 20:47:22 +00002560 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
2561 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng78dd9db2009-07-22 18:08:05 +00002562 if (Subtarget->isThumb()) {
Bob Wilson13ef8402010-05-28 00:27:15 +00002563 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
2564 return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 6);
Evan Chengaf9e7a72009-07-21 00:31:12 +00002565 } else {
2566 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson92a20222011-07-21 18:54:16 +00002567 return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops, 7);
Evan Chengaf9e7a72009-07-21 00:31:12 +00002568 }
Evan Chenga8e29892007-01-19 07:51:42 +00002569 }
2570 }
2571 break;
Evan Cheng20956592009-10-21 08:15:52 +00002572 case ISD::AND: {
Jim Grosbach3a1287b2010-04-22 23:24:18 +00002573 // Check for unsigned bitfield extract
2574 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
2575 return I;
2576
Evan Cheng20956592009-10-21 08:15:52 +00002577 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2578 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2579 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2580 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2581 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002582 EVT VT = N->getValueType(0);
Evan Cheng20956592009-10-21 08:15:52 +00002583 if (VT != MVT::i32)
2584 break;
2585 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2586 ? ARM::t2MOVTi16
2587 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2588 if (!Opc)
2589 break;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002590 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
Evan Cheng20956592009-10-21 08:15:52 +00002591 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
2592 if (!N1C)
2593 break;
2594 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2595 SDValue N2 = N0.getOperand(1);
2596 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2597 if (!N2C)
2598 break;
2599 unsigned N1CVal = N1C->getZExtValue();
2600 unsigned N2CVal = N2C->getZExtValue();
2601 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2602 (N1CVal & 0xffffU) == 0xffffU &&
2603 (N2CVal & 0xffffU) == 0x0U) {
2604 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
2605 MVT::i32);
2606 SDValue Ops[] = { N0.getOperand(0), Imm16,
2607 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2608 return CurDAG->getMachineNode(Opc, dl, VT, Ops, 4);
2609 }
2610 }
2611 break;
2612 }
Jim Grosbache5165492009-11-09 00:11:35 +00002613 case ARMISD::VMOVRRD:
2614 return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002615 N->getOperand(0), getAL(CurDAG),
Dan Gohman602b0c82009-09-25 18:54:59 +00002616 CurDAG->getRegister(0, MVT::i32));
Dan Gohman525178c2007-10-08 18:33:35 +00002617 case ISD::UMUL_LOHI: {
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002618 if (Subtarget->isThumb1Only())
2619 break;
2620 if (Subtarget->isThumb()) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002621 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00002622 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2623 CurDAG->getRegister(0, MVT::i32) };
Jim Grosbach18f30e62010-06-02 21:53:11 +00002624 return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32,Ops,4);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002625 } else {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002626 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00002627 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2628 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov4d728602011-01-01 20:38:38 +00002629 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2630 ARM::UMULL : ARM::UMULLv5,
2631 dl, MVT::i32, MVT::i32, Ops, 5);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002632 }
Evan Chengee568cf2007-07-05 07:15:27 +00002633 }
Dan Gohman525178c2007-10-08 18:33:35 +00002634 case ISD::SMUL_LOHI: {
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002635 if (Subtarget->isThumb1Only())
2636 break;
2637 if (Subtarget->isThumb()) {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002638 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00002639 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
Jim Grosbach18f30e62010-06-02 21:53:11 +00002640 return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32,Ops,4);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002641 } else {
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002642 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson825b72b2009-08-11 20:47:22 +00002643 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2644 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov4d728602011-01-01 20:38:38 +00002645 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2646 ARM::SMULL : ARM::SMULLv5,
2647 dl, MVT::i32, MVT::i32, Ops, 5);
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002648 }
Evan Chengee568cf2007-07-05 07:15:27 +00002649 }
Arnold Schwaighofer67514e92012-09-04 14:37:49 +00002650 case ARMISD::UMLAL:{
2651 if (Subtarget->isThumb()) {
2652 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2653 N->getOperand(3), getAL(CurDAG),
2654 CurDAG->getRegister(0, MVT::i32)};
2655 return CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops, 6);
2656 }else{
2657 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2658 N->getOperand(3), getAL(CurDAG),
2659 CurDAG->getRegister(0, MVT::i32),
2660 CurDAG->getRegister(0, MVT::i32) };
2661 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2662 ARM::UMLAL : ARM::UMLALv5,
2663 dl, MVT::i32, MVT::i32, Ops, 7);
2664 }
2665 }
2666 case ARMISD::SMLAL:{
2667 if (Subtarget->isThumb()) {
2668 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2669 N->getOperand(3), getAL(CurDAG),
2670 CurDAG->getRegister(0, MVT::i32)};
2671 return CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops, 6);
2672 }else{
2673 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2674 N->getOperand(3), getAL(CurDAG),
2675 CurDAG->getRegister(0, MVT::i32),
2676 CurDAG->getRegister(0, MVT::i32) };
2677 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2678 ARM::SMLAL : ARM::SMLALv5,
2679 dl, MVT::i32, MVT::i32, Ops, 7);
2680 }
2681 }
Evan Chenga8e29892007-01-19 07:51:42 +00002682 case ISD::LOAD: {
Evan Chenge88d5ce2009-07-02 07:28:31 +00002683 SDNode *ResNode = 0;
Evan Cheng5b9fcd12009-07-07 01:17:28 +00002684 if (Subtarget->isThumb() && Subtarget->hasThumb2())
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002685 ResNode = SelectT2IndexedLoad(N);
Evan Chenge88d5ce2009-07-02 07:28:31 +00002686 else
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002687 ResNode = SelectARMIndexedLoad(N);
Evan Chengaf4550f2009-07-02 01:23:32 +00002688 if (ResNode)
2689 return ResNode;
Evan Chenga8e29892007-01-19 07:51:42 +00002690 // Other cases are autogenerated.
Rafael Espindolaf819a492006-11-09 13:58:55 +00002691 break;
Rafael Espindola337c4ad62006-06-12 12:28:08 +00002692 }
Evan Chengee568cf2007-07-05 07:15:27 +00002693 case ARMISD::BRCOND: {
2694 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2695 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2696 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00002697
Evan Chengee568cf2007-07-05 07:15:27 +00002698 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2699 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2700 // Pattern complexity = 6 cost = 1 size = 0
2701
David Goodwin5e47a9a2009-06-30 18:04:13 +00002702 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2703 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2704 // Pattern complexity = 6 cost = 1 size = 0
2705
Jim Grosbach764ab522009-08-11 15:33:49 +00002706 unsigned Opc = Subtarget->isThumb() ?
David Goodwin5e47a9a2009-06-30 18:04:13 +00002707 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002708 SDValue Chain = N->getOperand(0);
2709 SDValue N1 = N->getOperand(1);
2710 SDValue N2 = N->getOperand(2);
2711 SDValue N3 = N->getOperand(3);
2712 SDValue InFlag = N->getOperand(4);
Evan Chengee568cf2007-07-05 07:15:27 +00002713 assert(N1.getOpcode() == ISD::BasicBlock);
2714 assert(N2.getOpcode() == ISD::Constant);
2715 assert(N3.getOpcode() == ISD::Register);
2716
Dan Gohman475871a2008-07-27 21:46:04 +00002717 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002718 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson825b72b2009-08-11 20:47:22 +00002719 MVT::i32);
Dan Gohman475871a2008-07-27 21:46:04 +00002720 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman602b0c82009-09-25 18:54:59 +00002721 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Chris Lattnerf1b4eaf2010-12-21 02:38:05 +00002722 MVT::Glue, Ops, 5);
Dan Gohman475871a2008-07-27 21:46:04 +00002723 Chain = SDValue(ResNode, 0);
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002724 if (N->getNumValues() == 2) {
Dan Gohman475871a2008-07-27 21:46:04 +00002725 InFlag = SDValue(ResNode, 1);
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002726 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnera47b9bc2008-02-03 03:20:59 +00002727 }
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002728 ReplaceUses(SDValue(N, 0),
Evan Chenged54de42009-11-19 08:16:50 +00002729 SDValue(Chain.getNode(), Chain.getResNo()));
Evan Chengee568cf2007-07-05 07:15:27 +00002730 return NULL;
2731 }
Evan Cheng07ba9062009-11-19 21:45:22 +00002732 case ARMISD::CMOV:
Dan Gohmaneeb3a002010-01-05 01:24:18 +00002733 return SelectCMOVOp(N);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002734 case ARMISD::VZIP: {
2735 unsigned Opc = 0;
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002736 EVT VT = N->getValueType(0);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002737 switch (VT.getSimpleVT().SimpleTy) {
2738 default: return NULL;
2739 case MVT::v8i8: Opc = ARM::VZIPd8; break;
2740 case MVT::v4i16: Opc = ARM::VZIPd16; break;
2741 case MVT::v2f32:
Jim Grosbach6073b302012-04-11 16:53:25 +00002742 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2743 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002744 case MVT::v16i8: Opc = ARM::VZIPq8; break;
2745 case MVT::v8i16: Opc = ARM::VZIPq16; break;
2746 case MVT::v4f32:
2747 case MVT::v4i32: Opc = ARM::VZIPq32; break;
2748 }
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002749 SDValue Pred = getAL(CurDAG);
Evan Chengac0869d2009-11-21 06:21:52 +00002750 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2751 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
2752 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4);
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002753 }
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002754 case ARMISD::VUZP: {
2755 unsigned Opc = 0;
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002756 EVT VT = N->getValueType(0);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002757 switch (VT.getSimpleVT().SimpleTy) {
2758 default: return NULL;
2759 case MVT::v8i8: Opc = ARM::VUZPd8; break;
2760 case MVT::v4i16: Opc = ARM::VUZPd16; break;
2761 case MVT::v2f32:
Jim Grosbach18355472012-04-11 17:40:18 +00002762 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2763 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002764 case MVT::v16i8: Opc = ARM::VUZPq8; break;
2765 case MVT::v8i16: Opc = ARM::VUZPq16; break;
2766 case MVT::v4f32:
2767 case MVT::v4i32: Opc = ARM::VUZPq32; break;
2768 }
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002769 SDValue Pred = getAL(CurDAG);
Evan Chengac0869d2009-11-21 06:21:52 +00002770 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2771 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
2772 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4);
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002773 }
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002774 case ARMISD::VTRN: {
2775 unsigned Opc = 0;
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002776 EVT VT = N->getValueType(0);
Anton Korobeynikov051cfd62009-08-21 12:41:42 +00002777 switch (VT.getSimpleVT().SimpleTy) {
2778 default: return NULL;
2779 case MVT::v8i8: Opc = ARM::VTRNd8; break;
2780 case MVT::v4i16: Opc = ARM::VTRNd16; break;
2781 case MVT::v2f32:
2782 case MVT::v2i32: Opc = ARM::VTRNd32; break;
2783 case MVT::v16i8: Opc = ARM::VTRNq8; break;
2784 case MVT::v8i16: Opc = ARM::VTRNq16; break;
2785 case MVT::v4f32:
2786 case MVT::v4i32: Opc = ARM::VTRNq32; break;
2787 }
Evan Cheng47b7b9f2010-04-16 05:46:06 +00002788 SDValue Pred = getAL(CurDAG);
Evan Chengac0869d2009-11-21 06:21:52 +00002789 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2790 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
2791 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4);
Anton Korobeynikov62e84f12009-08-21 12:40:50 +00002792 }
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002793 case ARMISD::BUILD_VECTOR: {
2794 EVT VecVT = N->getValueType(0);
2795 EVT EltVT = VecVT.getVectorElementType();
2796 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sandscdfad362010-11-03 12:17:33 +00002797 if (EltVT == MVT::f64) {
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002798 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002799 return createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002800 }
Duncan Sandscdfad362010-11-03 12:17:33 +00002801 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002802 if (NumElts == 2)
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002803 return createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002804 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Weiming Zhao8b149cb2012-11-17 00:23:35 +00002805 return createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
Bob Wilson40cbe7d2010-06-04 00:04:02 +00002806 N->getOperand(2), N->getOperand(3));
2807 }
Bob Wilson31fb12f2009-08-26 17:39:53 +00002808
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002809 case ARMISD::VLD2DUP: {
Craig Topper51f50c12012-05-24 05:17:00 +00002810 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
2811 ARM::VLD2DUPd32 };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002812 return SelectVLDDup(N, false, 2, Opcodes);
Bob Wilsonb1dfa7a2010-11-28 06:51:26 +00002813 }
2814
Bob Wilson86c6d802010-11-29 19:35:29 +00002815 case ARMISD::VLD3DUP: {
Craig Topper51f50c12012-05-24 05:17:00 +00002816 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
2817 ARM::VLD3DUPd16Pseudo,
2818 ARM::VLD3DUPd32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002819 return SelectVLDDup(N, false, 3, Opcodes);
Bob Wilson86c6d802010-11-29 19:35:29 +00002820 }
2821
Bob Wilson6c4c9822010-11-30 00:00:35 +00002822 case ARMISD::VLD4DUP: {
Craig Topper51f50c12012-05-24 05:17:00 +00002823 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
2824 ARM::VLD4DUPd16Pseudo,
2825 ARM::VLD4DUPd32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002826 return SelectVLDDup(N, false, 4, Opcodes);
2827 }
2828
2829 case ARMISD::VLD2DUP_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002830 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
2831 ARM::VLD2DUPd16wb_fixed,
2832 ARM::VLD2DUPd32wb_fixed };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002833 return SelectVLDDup(N, true, 2, Opcodes);
2834 }
2835
2836 case ARMISD::VLD3DUP_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002837 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
2838 ARM::VLD3DUPd16Pseudo_UPD,
2839 ARM::VLD3DUPd32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002840 return SelectVLDDup(N, true, 3, Opcodes);
2841 }
2842
2843 case ARMISD::VLD4DUP_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002844 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
2845 ARM::VLD4DUPd16Pseudo_UPD,
2846 ARM::VLD4DUPd32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002847 return SelectVLDDup(N, true, 4, Opcodes);
2848 }
2849
2850 case ARMISD::VLD1_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002851 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
2852 ARM::VLD1d16wb_fixed,
2853 ARM::VLD1d32wb_fixed,
2854 ARM::VLD1d64wb_fixed };
2855 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
2856 ARM::VLD1q16wb_fixed,
2857 ARM::VLD1q32wb_fixed,
2858 ARM::VLD1q64wb_fixed };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002859 return SelectVLD(N, true, 1, DOpcodes, QOpcodes, 0);
2860 }
2861
2862 case ARMISD::VLD2_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002863 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
2864 ARM::VLD2d16wb_fixed,
2865 ARM::VLD2d32wb_fixed,
2866 ARM::VLD1q64wb_fixed};
2867 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
2868 ARM::VLD2q16PseudoWB_fixed,
2869 ARM::VLD2q32PseudoWB_fixed };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002870 return SelectVLD(N, true, 2, DOpcodes, QOpcodes, 0);
2871 }
2872
2873 case ARMISD::VLD3_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002874 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
2875 ARM::VLD3d16Pseudo_UPD,
2876 ARM::VLD3d32Pseudo_UPD,
2877 ARM::VLD1q64wb_fixed};
2878 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
2879 ARM::VLD3q16Pseudo_UPD,
2880 ARM::VLD3q32Pseudo_UPD };
2881 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
2882 ARM::VLD3q16oddPseudo_UPD,
2883 ARM::VLD3q32oddPseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002884 return SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
2885 }
2886
2887 case ARMISD::VLD4_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002888 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
2889 ARM::VLD4d16Pseudo_UPD,
2890 ARM::VLD4d32Pseudo_UPD,
2891 ARM::VLD1q64wb_fixed};
2892 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
2893 ARM::VLD4q16Pseudo_UPD,
2894 ARM::VLD4q32Pseudo_UPD };
2895 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
2896 ARM::VLD4q16oddPseudo_UPD,
2897 ARM::VLD4q32oddPseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002898 return SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
2899 }
2900
2901 case ARMISD::VLD2LN_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002902 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
2903 ARM::VLD2LNd16Pseudo_UPD,
2904 ARM::VLD2LNd32Pseudo_UPD };
2905 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
2906 ARM::VLD2LNq32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002907 return SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
2908 }
2909
2910 case ARMISD::VLD3LN_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002911 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
2912 ARM::VLD3LNd16Pseudo_UPD,
2913 ARM::VLD3LNd32Pseudo_UPD };
2914 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
2915 ARM::VLD3LNq32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002916 return SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
2917 }
2918
2919 case ARMISD::VLD4LN_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002920 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
2921 ARM::VLD4LNd16Pseudo_UPD,
2922 ARM::VLD4LNd32Pseudo_UPD };
2923 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
2924 ARM::VLD4LNq32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002925 return SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
2926 }
2927
2928 case ARMISD::VST1_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002929 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
2930 ARM::VST1d16wb_fixed,
2931 ARM::VST1d32wb_fixed,
2932 ARM::VST1d64wb_fixed };
2933 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
2934 ARM::VST1q16wb_fixed,
2935 ARM::VST1q32wb_fixed,
2936 ARM::VST1q64wb_fixed };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002937 return SelectVST(N, true, 1, DOpcodes, QOpcodes, 0);
2938 }
2939
2940 case ARMISD::VST2_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002941 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
2942 ARM::VST2d16wb_fixed,
2943 ARM::VST2d32wb_fixed,
2944 ARM::VST1q64wb_fixed};
2945 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
2946 ARM::VST2q16PseudoWB_fixed,
2947 ARM::VST2q32PseudoWB_fixed };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002948 return SelectVST(N, true, 2, DOpcodes, QOpcodes, 0);
2949 }
2950
2951 case ARMISD::VST3_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002952 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
2953 ARM::VST3d16Pseudo_UPD,
2954 ARM::VST3d32Pseudo_UPD,
2955 ARM::VST1d64TPseudoWB_fixed};
2956 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
2957 ARM::VST3q16Pseudo_UPD,
2958 ARM::VST3q32Pseudo_UPD };
2959 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
2960 ARM::VST3q16oddPseudo_UPD,
2961 ARM::VST3q32oddPseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002962 return SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
2963 }
2964
2965 case ARMISD::VST4_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002966 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
2967 ARM::VST4d16Pseudo_UPD,
2968 ARM::VST4d32Pseudo_UPD,
2969 ARM::VST1d64QPseudoWB_fixed};
2970 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
2971 ARM::VST4q16Pseudo_UPD,
2972 ARM::VST4q32Pseudo_UPD };
2973 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
2974 ARM::VST4q16oddPseudo_UPD,
2975 ARM::VST4q32oddPseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002976 return SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
2977 }
2978
2979 case ARMISD::VST2LN_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002980 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
2981 ARM::VST2LNd16Pseudo_UPD,
2982 ARM::VST2LNd32Pseudo_UPD };
2983 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
2984 ARM::VST2LNq32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002985 return SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
2986 }
2987
2988 case ARMISD::VST3LN_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002989 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
2990 ARM::VST3LNd16Pseudo_UPD,
2991 ARM::VST3LNd32Pseudo_UPD };
2992 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
2993 ARM::VST3LNq32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00002994 return SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
2995 }
2996
2997 case ARMISD::VST4LN_UPD: {
Craig Topper51f50c12012-05-24 05:17:00 +00002998 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
2999 ARM::VST4LNd16Pseudo_UPD,
3000 ARM::VST4LNd32Pseudo_UPD };
3001 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3002 ARM::VST4LNq32Pseudo_UPD };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003003 return SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
Bob Wilson6c4c9822010-11-30 00:00:35 +00003004 }
3005
Bob Wilson31fb12f2009-08-26 17:39:53 +00003006 case ISD::INTRINSIC_VOID:
3007 case ISD::INTRINSIC_W_CHAIN: {
3008 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilson31fb12f2009-08-26 17:39:53 +00003009 switch (IntNo) {
3010 default:
Bob Wilson429009b2010-05-06 16:05:26 +00003011 break;
Bob Wilson31fb12f2009-08-26 17:39:53 +00003012
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003013 case Intrinsic::arm_ldrexd: {
3014 SDValue MemAddr = N->getOperand(2);
3015 DebugLoc dl = N->getDebugLoc();
3016 SDValue Chain = N->getOperand(0);
3017
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003018 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3019 unsigned NewOpc = isThumb ? ARM::t2LDREXD :ARM::LDREXD;
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003020
3021 // arm_ldrexd returns a i64 value in {i32, i32}
3022 std::vector<EVT> ResTys;
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003023 if (isThumb) {
3024 ResTys.push_back(MVT::i32);
3025 ResTys.push_back(MVT::i32);
3026 } else
3027 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003028 ResTys.push_back(MVT::Other);
3029
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003030 // Place arguments in the right order.
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003031 SmallVector<SDValue, 7> Ops;
3032 Ops.push_back(MemAddr);
3033 Ops.push_back(getAL(CurDAG));
3034 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3035 Ops.push_back(Chain);
3036 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops.data(),
3037 Ops.size());
3038 // Transfer memoperands.
3039 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3040 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3041 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3042
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003043 // Remap uses.
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003044 SDValue Glue = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003045 if (!SDValue(N, 0).use_empty()) {
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003046 SDValue Result;
3047 if (isThumb)
3048 Result = SDValue(Ld, 0);
3049 else {
3050 SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32);
3051 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
3052 dl, MVT::i32, MVT::Glue, SDValue(Ld, 0), SubRegIdx, Glue);
3053 Result = SDValue(ResNode,0);
3054 Glue = Result.getValue(1);
3055 }
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003056 ReplaceUses(SDValue(N, 0), Result);
3057 }
3058 if (!SDValue(N, 1).use_empty()) {
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003059 SDValue Result;
3060 if (isThumb)
3061 Result = SDValue(Ld, 1);
3062 else {
3063 SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32);
3064 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
3065 dl, MVT::i32, MVT::Glue, SDValue(Ld, 0), SubRegIdx, Glue);
3066 Result = SDValue(ResNode,0);
3067 Glue = Result.getValue(1);
3068 }
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003069 ReplaceUses(SDValue(N, 1), Result);
3070 }
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003071 ReplaceUses(SDValue(N, 2), Glue);
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003072 return NULL;
3073 }
3074
3075 case Intrinsic::arm_strexd: {
3076 DebugLoc dl = N->getDebugLoc();
3077 SDValue Chain = N->getOperand(0);
3078 SDValue Val0 = N->getOperand(2);
3079 SDValue Val1 = N->getOperand(3);
3080 SDValue MemAddr = N->getOperand(4);
3081
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003082 // Store exclusive double return a i32 value which is the return status
3083 // of the issued store.
3084 std::vector<EVT> ResTys;
3085 ResTys.push_back(MVT::i32);
3086 ResTys.push_back(MVT::Other);
3087
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003088 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3089 // Place arguments in the right order.
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003090 SmallVector<SDValue, 7> Ops;
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003091 if (isThumb) {
3092 Ops.push_back(Val0);
3093 Ops.push_back(Val1);
3094 } else
3095 // arm_strexd uses GPRPair.
3096 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003097 Ops.push_back(MemAddr);
3098 Ops.push_back(getAL(CurDAG));
3099 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3100 Ops.push_back(Chain);
3101
Weiming Zhaoe56764b2012-11-16 21:55:34 +00003102 unsigned NewOpc = isThumb ? ARM::t2STREXD : ARM::STREXD;
Bruno Cardoso Lopesa0112d02011-05-28 04:07:29 +00003103
3104 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops.data(),
3105 Ops.size());
3106 // Transfer memoperands.
3107 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3108 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3109 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3110
3111 return St;
3112 }
3113
Bob Wilson621f1952010-03-23 05:25:43 +00003114 case Intrinsic::arm_neon_vld1: {
Craig Topper51f50c12012-05-24 05:17:00 +00003115 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3116 ARM::VLD1d32, ARM::VLD1d64 };
3117 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3118 ARM::VLD1q32, ARM::VLD1q64};
Bob Wilson1c3ef902011-02-07 17:43:21 +00003119 return SelectVLD(N, false, 1, DOpcodes, QOpcodes, 0);
Bob Wilson621f1952010-03-23 05:25:43 +00003120 }
3121
Bob Wilson31fb12f2009-08-26 17:39:53 +00003122 case Intrinsic::arm_neon_vld2: {
Craig Topper51f50c12012-05-24 05:17:00 +00003123 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3124 ARM::VLD2d32, ARM::VLD1q64 };
3125 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3126 ARM::VLD2q32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003127 return SelectVLD(N, false, 2, DOpcodes, QOpcodes, 0);
Bob Wilson31fb12f2009-08-26 17:39:53 +00003128 }
3129
3130 case Intrinsic::arm_neon_vld3: {
Craig Topper51f50c12012-05-24 05:17:00 +00003131 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3132 ARM::VLD3d16Pseudo,
3133 ARM::VLD3d32Pseudo,
3134 ARM::VLD1d64TPseudo };
3135 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3136 ARM::VLD3q16Pseudo_UPD,
3137 ARM::VLD3q32Pseudo_UPD };
3138 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3139 ARM::VLD3q16oddPseudo,
3140 ARM::VLD3q32oddPseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003141 return SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson31fb12f2009-08-26 17:39:53 +00003142 }
3143
3144 case Intrinsic::arm_neon_vld4: {
Craig Topper51f50c12012-05-24 05:17:00 +00003145 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3146 ARM::VLD4d16Pseudo,
3147 ARM::VLD4d32Pseudo,
3148 ARM::VLD1d64QPseudo };
3149 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3150 ARM::VLD4q16Pseudo_UPD,
3151 ARM::VLD4q32Pseudo_UPD };
3152 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3153 ARM::VLD4q16oddPseudo,
3154 ARM::VLD4q32oddPseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003155 return SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson31fb12f2009-08-26 17:39:53 +00003156 }
3157
Bob Wilson243fcc52009-09-01 04:26:28 +00003158 case Intrinsic::arm_neon_vld2lane: {
Craig Topper51f50c12012-05-24 05:17:00 +00003159 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3160 ARM::VLD2LNd16Pseudo,
3161 ARM::VLD2LNd32Pseudo };
3162 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3163 ARM::VLD2LNq32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003164 return SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
Bob Wilson243fcc52009-09-01 04:26:28 +00003165 }
3166
3167 case Intrinsic::arm_neon_vld3lane: {
Craig Topper51f50c12012-05-24 05:17:00 +00003168 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3169 ARM::VLD3LNd16Pseudo,
3170 ARM::VLD3LNd32Pseudo };
3171 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3172 ARM::VLD3LNq32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003173 return SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
Bob Wilson243fcc52009-09-01 04:26:28 +00003174 }
3175
3176 case Intrinsic::arm_neon_vld4lane: {
Craig Topper51f50c12012-05-24 05:17:00 +00003177 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3178 ARM::VLD4LNd16Pseudo,
3179 ARM::VLD4LNd32Pseudo };
3180 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3181 ARM::VLD4LNq32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003182 return SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
Bob Wilson243fcc52009-09-01 04:26:28 +00003183 }
3184
Bob Wilson11d98992010-03-23 06:20:33 +00003185 case Intrinsic::arm_neon_vst1: {
Craig Topper51f50c12012-05-24 05:17:00 +00003186 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3187 ARM::VST1d32, ARM::VST1d64 };
3188 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3189 ARM::VST1q32, ARM::VST1q64 };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003190 return SelectVST(N, false, 1, DOpcodes, QOpcodes, 0);
Bob Wilson11d98992010-03-23 06:20:33 +00003191 }
3192
Bob Wilson31fb12f2009-08-26 17:39:53 +00003193 case Intrinsic::arm_neon_vst2: {
Craig Topper51f50c12012-05-24 05:17:00 +00003194 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3195 ARM::VST2d32, ARM::VST1q64 };
3196 static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3197 ARM::VST2q32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003198 return SelectVST(N, false, 2, DOpcodes, QOpcodes, 0);
Bob Wilson31fb12f2009-08-26 17:39:53 +00003199 }
3200
3201 case Intrinsic::arm_neon_vst3: {
Craig Topper51f50c12012-05-24 05:17:00 +00003202 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3203 ARM::VST3d16Pseudo,
3204 ARM::VST3d32Pseudo,
3205 ARM::VST1d64TPseudo };
3206 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3207 ARM::VST3q16Pseudo_UPD,
3208 ARM::VST3q32Pseudo_UPD };
3209 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3210 ARM::VST3q16oddPseudo,
3211 ARM::VST3q32oddPseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003212 return SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson31fb12f2009-08-26 17:39:53 +00003213 }
3214
3215 case Intrinsic::arm_neon_vst4: {
Craig Topper51f50c12012-05-24 05:17:00 +00003216 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3217 ARM::VST4d16Pseudo,
3218 ARM::VST4d32Pseudo,
3219 ARM::VST1d64QPseudo };
3220 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3221 ARM::VST4q16Pseudo_UPD,
3222 ARM::VST4q32Pseudo_UPD };
3223 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3224 ARM::VST4q16oddPseudo,
3225 ARM::VST4q32oddPseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003226 return SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilson31fb12f2009-08-26 17:39:53 +00003227 }
Bob Wilson8a3198b2009-09-01 18:51:56 +00003228
3229 case Intrinsic::arm_neon_vst2lane: {
Craig Topper51f50c12012-05-24 05:17:00 +00003230 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3231 ARM::VST2LNd16Pseudo,
3232 ARM::VST2LNd32Pseudo };
3233 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3234 ARM::VST2LNq32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003235 return SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
Bob Wilson8a3198b2009-09-01 18:51:56 +00003236 }
3237
3238 case Intrinsic::arm_neon_vst3lane: {
Craig Topper51f50c12012-05-24 05:17:00 +00003239 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3240 ARM::VST3LNd16Pseudo,
3241 ARM::VST3LNd32Pseudo };
3242 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3243 ARM::VST3LNq32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003244 return SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
Bob Wilson8a3198b2009-09-01 18:51:56 +00003245 }
3246
3247 case Intrinsic::arm_neon_vst4lane: {
Craig Topper51f50c12012-05-24 05:17:00 +00003248 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3249 ARM::VST4LNd16Pseudo,
3250 ARM::VST4LNd32Pseudo };
3251 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3252 ARM::VST4LNq32Pseudo };
Bob Wilson1c3ef902011-02-07 17:43:21 +00003253 return SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
Bob Wilson8a3198b2009-09-01 18:51:56 +00003254 }
Bob Wilson31fb12f2009-08-26 17:39:53 +00003255 }
Bob Wilson429009b2010-05-06 16:05:26 +00003256 break;
Bob Wilson31fb12f2009-08-26 17:39:53 +00003257 }
Evan Chengde8aa4e2010-05-05 18:28:36 +00003258
Bob Wilsond491d6e2010-07-06 23:36:25 +00003259 case ISD::INTRINSIC_WO_CHAIN: {
3260 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3261 switch (IntNo) {
3262 default:
3263 break;
3264
3265 case Intrinsic::arm_neon_vtbl2:
Jim Grosbach28f08c92012-03-05 19:33:30 +00003266 return SelectVTBL(N, false, 2, ARM::VTBL2);
Bob Wilsond491d6e2010-07-06 23:36:25 +00003267 case Intrinsic::arm_neon_vtbl3:
Bob Wilsonbd916c52010-09-13 23:55:10 +00003268 return SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
Bob Wilsond491d6e2010-07-06 23:36:25 +00003269 case Intrinsic::arm_neon_vtbl4:
Bob Wilsonbd916c52010-09-13 23:55:10 +00003270 return SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
Bob Wilson78dfbc32010-07-07 00:08:54 +00003271
3272 case Intrinsic::arm_neon_vtbx2:
Jim Grosbach28f08c92012-03-05 19:33:30 +00003273 return SelectVTBL(N, true, 2, ARM::VTBX2);
Bob Wilson78dfbc32010-07-07 00:08:54 +00003274 case Intrinsic::arm_neon_vtbx3:
Bob Wilsonbd916c52010-09-13 23:55:10 +00003275 return SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
Bob Wilson78dfbc32010-07-07 00:08:54 +00003276 case Intrinsic::arm_neon_vtbx4:
Bob Wilsonbd916c52010-09-13 23:55:10 +00003277 return SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
Bob Wilsond491d6e2010-07-06 23:36:25 +00003278 }
3279 break;
3280 }
3281
Bill Wendling69a05a72011-03-14 23:02:38 +00003282 case ARMISD::VTBL1: {
3283 DebugLoc dl = N->getDebugLoc();
3284 EVT VT = N->getValueType(0);
3285 SmallVector<SDValue, 6> Ops;
3286
3287 Ops.push_back(N->getOperand(0));
3288 Ops.push_back(N->getOperand(1));
3289 Ops.push_back(getAL(CurDAG)); // Predicate
3290 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
3291 return CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops.data(), Ops.size());
3292 }
3293 case ARMISD::VTBL2: {
3294 DebugLoc dl = N->getDebugLoc();
3295 EVT VT = N->getValueType(0);
3296
3297 // Form a REG_SEQUENCE to force register allocation.
3298 SDValue V0 = N->getOperand(0);
3299 SDValue V1 = N->getOperand(1);
Weiming Zhao8b149cb2012-11-17 00:23:35 +00003300 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendling69a05a72011-03-14 23:02:38 +00003301
3302 SmallVector<SDValue, 6> Ops;
3303 Ops.push_back(RegSeq);
3304 Ops.push_back(N->getOperand(2));
3305 Ops.push_back(getAL(CurDAG)); // Predicate
3306 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Jim Grosbach28f08c92012-03-05 19:33:30 +00003307 return CurDAG->getMachineNode(ARM::VTBL2, dl, VT,
Bill Wendling69a05a72011-03-14 23:02:38 +00003308 Ops.data(), Ops.size());
3309 }
3310
Bob Wilson429009b2010-05-06 16:05:26 +00003311 case ISD::CONCAT_VECTORS:
Evan Chengde8aa4e2010-05-05 18:28:36 +00003312 return SelectConcatVector(N);
Eli Friedman2bdffe42011-08-31 00:31:29 +00003313
3314 case ARMISD::ATOMOR64_DAG:
3315 return SelectAtomic64(N, ARM::ATOMOR6432);
3316 case ARMISD::ATOMXOR64_DAG:
3317 return SelectAtomic64(N, ARM::ATOMXOR6432);
3318 case ARMISD::ATOMADD64_DAG:
3319 return SelectAtomic64(N, ARM::ATOMADD6432);
3320 case ARMISD::ATOMSUB64_DAG:
3321 return SelectAtomic64(N, ARM::ATOMSUB6432);
3322 case ARMISD::ATOMNAND64_DAG:
3323 return SelectAtomic64(N, ARM::ATOMNAND6432);
3324 case ARMISD::ATOMAND64_DAG:
3325 return SelectAtomic64(N, ARM::ATOMAND6432);
3326 case ARMISD::ATOMSWAP64_DAG:
3327 return SelectAtomic64(N, ARM::ATOMSWAP6432);
Eli Friedman4d3f3292011-08-31 17:52:22 +00003328 case ARMISD::ATOMCMPXCHG64_DAG:
3329 return SelectAtomic64(N, ARM::ATOMCMPXCHG6432);
Silviu Baranga35b3df62012-11-29 14:41:25 +00003330
3331 case ARMISD::ATOMMIN64_DAG:
3332 return SelectAtomic64(N, ARM::ATOMMIN6432);
3333 case ARMISD::ATOMUMIN64_DAG:
3334 return SelectAtomic64(N, ARM::ATOMUMIN6432);
3335 case ARMISD::ATOMMAX64_DAG:
3336 return SelectAtomic64(N, ARM::ATOMMAX6432);
3337 case ARMISD::ATOMUMAX64_DAG:
3338 return SelectAtomic64(N, ARM::ATOMUMAX6432);
Evan Chengde8aa4e2010-05-05 18:28:36 +00003339 }
Evan Chenge5ad88e2008-12-10 21:54:21 +00003340
Dan Gohmaneeb3a002010-01-05 01:24:18 +00003341 return SelectCode(N);
Evan Chenga8e29892007-01-19 07:51:42 +00003342}
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00003343
Bob Wilson224c2442009-05-19 05:53:42 +00003344bool ARMDAGToDAGISel::
3345SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
3346 std::vector<SDValue> &OutOps) {
3347 assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
Bob Wilson765cc0b2009-10-13 20:50:28 +00003348 // Require the address to be in a register. That is safe for all ARM
3349 // variants and it is hard to do anything much smarter without knowing
3350 // how the operand is used.
3351 OutOps.push_back(Op);
Bob Wilson224c2442009-05-19 05:53:42 +00003352 return false;
3353}
3354
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00003355/// createARMISelDag - This pass converts a legalized DAG into a
3356/// ARM-specific DAG, ready for instruction scheduling.
3357///
Bob Wilson522ce972009-09-28 14:30:20 +00003358FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
3359 CodeGenOpt::Level OptLevel) {
3360 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00003361}