blob: 970c63342c02d1dab06dd4487bdf452ec8ab8b37 [file] [log] [blame]
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00001//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattnerf3ebc3f2007-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 Espindolaffdc24b2006-05-14 22:18:28 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the ARM target.
11//
12//===----------------------------------------------------------------------===//
13
Dale Johannesend679ff72010-06-03 21:09:53 +000014#define DEBUG_TYPE "arm-isel"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000015#include "ARM.h"
Evan Cheng62c7b5b2010-12-05 22:04:16 +000016#include "ARMBaseInstrInfo.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000017#include "ARMTargetMachine.h"
Evan Chenga20cde32011-07-20 23:34:39 +000018#include "MCTargetDesc/ARMAddressingModes.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000019#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineFunction.h"
21#include "llvm/CodeGen/MachineInstrBuilder.h"
Weiming Zhaoc5987002013-02-14 18:10:21 +000022#include "llvm/CodeGen/MachineRegisterInfo.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000023#include "llvm/CodeGen/SelectionDAG.h"
24#include "llvm/CodeGen/SelectionDAGISel.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000025#include "llvm/IR/CallingConv.h"
26#include "llvm/IR/Constants.h"
27#include "llvm/IR/DerivedTypes.h"
28#include "llvm/IR/Function.h"
29#include "llvm/IR/Intrinsics.h"
30#include "llvm/IR/LLVMContext.h"
Evan Cheng8e6b40a2010-05-04 20:39:49 +000031#include "llvm/Support/CommandLine.h"
Chris Lattner1770fb82008-02-03 05:43:57 +000032#include "llvm/Support/Compiler.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000033#include "llvm/Support/Debug.h"
Torok Edwinfb8d6d52009-07-08 20:53:28 +000034#include "llvm/Support/ErrorHandling.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000035#include "llvm/Target/TargetLowering.h"
36#include "llvm/Target/TargetOptions.h"
Torok Edwinfb8d6d52009-07-08 20:53:28 +000037
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000038using namespace llvm;
39
Evan Cheng59069ec2010-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 Cheng62c7b5b2010-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 Wilson0858c3a2011-04-19 18:11:57 +000048 cl::init(true));
Evan Cheng62c7b5b2010-12-05 22:04:16 +000049
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000050//===--------------------------------------------------------------------===//
51/// ARMDAGToDAGISel - ARM specific code to select ARM machine
52/// instructions for SelectionDAG operations.
53///
54namespace {
Jim Grosbach08605202010-09-29 19:03:54 +000055
56enum AddrMode2Type {
57 AM2_BASE, // Simple AM2 (+-imm12)
58 AM2_SHOP // Shifter-op AM2
59};
60
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000061class ARMDAGToDAGISel : public SelectionDAGISel {
Anton Korobeynikov99152f32009-06-26 21:28:53 +000062 ARMBaseTargetMachine &TM;
Evan Chengbc0d0ec2008-09-18 07:24:33 +000063
Evan Cheng10043e22007-01-19 07:51:42 +000064 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
65 /// make the right decision when generating code for different targets.
66 const ARMSubtarget *Subtarget;
67
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000068public:
Bob Wilson2dd957f2009-09-28 14:30:20 +000069 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm,
70 CodeGenOpt::Level OptLevel)
71 : SelectionDAGISel(tm, OptLevel), TM(tm),
Evan Cheng62c7b5b2010-12-05 22:04:16 +000072 Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000073 }
74
Craig Topper6bc27bf2014-03-10 02:09:33 +000075 const char *getPassName() const override {
Evan Cheng10043e22007-01-19 07:51:42 +000076 return "ARM Instruction Selection";
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000077 }
78
Craig Topper6bc27bf2014-03-10 02:09:33 +000079 void PreprocessISelDAG() override;
Evan Chengeae6d2c2012-12-19 20:16:09 +000080
Bob Wilson4facd962009-10-08 18:51:31 +000081 /// getI32Imm - Return a target constant of type i32 with the specified
82 /// value.
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000083 inline SDValue getI32Imm(unsigned Imm) {
Owen Anderson9f944592009-08-11 20:47:22 +000084 return CurDAG->getTargetConstant(Imm, MVT::i32);
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000085 }
86
Craig Topper6bc27bf2014-03-10 02:09:33 +000087 SDNode *Select(SDNode *N) override;
Evan Cheng5e73ff22010-02-15 19:41:07 +000088
Evan Cheng62c7b5b2010-12-05 22:04:16 +000089
90 bool hasNoVMLxHazardUse(SDNode *N) const;
Evan Cheng59bbc542010-10-27 23:41:30 +000091 bool isShifterOpProfitable(const SDValue &Shift,
92 ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt);
Owen Andersonb595ed02011-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 Anderson04912702011-07-21 23:38:37 +000097 SDValue &B, bool CheckProfitability = true);
98 bool SelectShiftRegShifterOperand(SDValue N, SDValue &A,
Owen Anderson6d557452011-03-18 19:46:58 +000099 SDValue &B, SDValue &C) {
100 // Don't apply the profitability check
Owen Anderson04912702011-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 Anderson6d557452011-03-18 19:46:58 +0000107 }
108
Jim Grosbach1e4d9a12010-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 Grosbach08605202010-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 Grosbach1e4d9a12010-10-26 22:37:02 +0000127// return SelectAddrMode2ShOp(N, Base, Offset, Opc);
Jim Grosbach08605202010-09-29 19:03:54 +0000128 // This always matches one way or another.
129 return true;
130 }
131
Tim Northover42180442013-08-22 09:57:11 +0000132 bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) {
133 const ConstantSDNode *CN = cast<ConstantSDNode>(N);
134 Pred = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
135 Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32);
136 return true;
137 }
138
Owen Anderson2aedba62011-07-26 20:54:26 +0000139 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
140 SDValue &Offset, SDValue &Opc);
141 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000142 SDValue &Offset, SDValue &Opc);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000143 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
144 SDValue &Offset, SDValue &Opc);
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000145 bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000146 bool SelectAddrMode3(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000147 SDValue &Offset, SDValue &Opc);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000148 bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000149 SDValue &Offset, SDValue &Opc);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000150 bool SelectAddrMode5(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000151 SDValue &Offset);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000152 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
Bob Wilsone3ecd5f2011-02-25 06:42:42 +0000153 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000154
Evan Chengdfce83c2011-01-17 08:03:18 +0000155 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
Evan Cheng10043e22007-01-19 07:51:42 +0000156
Bill Wendling092a7bd2010-12-14 03:36:38 +0000157 // Thumb Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000158 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
Bill Wendling092a7bd2010-12-14 03:36:38 +0000159 bool SelectThumbAddrModeRI(SDValue N, SDValue &Base, SDValue &Offset,
160 unsigned Scale);
161 bool SelectThumbAddrModeRI5S1(SDValue N, SDValue &Base, SDValue &Offset);
162 bool SelectThumbAddrModeRI5S2(SDValue N, SDValue &Base, SDValue &Offset);
163 bool SelectThumbAddrModeRI5S4(SDValue N, SDValue &Base, SDValue &Offset);
164 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
165 SDValue &OffImm);
166 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
167 SDValue &OffImm);
168 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
169 SDValue &OffImm);
170 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
171 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000172 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +0000173
Bill Wendling092a7bd2010-12-14 03:36:38 +0000174 // Thumb 2 Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000175 bool SelectT2ShifterOperandReg(SDValue N,
Evan Chengeab9ca72009-06-27 02:26:13 +0000176 SDValue &BaseReg, SDValue &Opc);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000177 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
178 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000179 SDValue &OffImm);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000180 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +0000181 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000182 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000183 SDValue &OffReg, SDValue &ShImm);
Tim Northovera7ecd242013-07-16 09:46:55 +0000184 bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Chengb23b50d2009-06-29 07:51:04 +0000185
Evan Cheng0fc80842010-11-12 22:42:47 +0000186 inline bool is_so_imm(unsigned Imm) const {
187 return ARM_AM::getSOImmVal(Imm) != -1;
188 }
189
190 inline bool is_so_imm_not(unsigned Imm) const {
191 return ARM_AM::getSOImmVal(~Imm) != -1;
192 }
193
194 inline bool is_t2_so_imm(unsigned Imm) const {
195 return ARM_AM::getT2SOImmVal(Imm) != -1;
196 }
197
198 inline bool is_t2_so_imm_not(unsigned Imm) const {
199 return ARM_AM::getT2SOImmVal(~Imm) != -1;
200 }
201
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000202 // Include the pieces autogenerated from the target description.
203#include "ARMGenDAGISel.inc"
Bob Wilsona2c462b2009-05-19 05:53:42 +0000204
205private:
Evan Cheng84c6cda2009-07-02 07:28:31 +0000206 /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
207 /// ARM.
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000208 SDNode *SelectARMIndexedLoad(SDNode *N);
209 SDNode *SelectT2IndexedLoad(SDNode *N);
Evan Cheng84c6cda2009-07-02 07:28:31 +0000210
Bob Wilson340861d2010-03-23 05:25:43 +0000211 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
212 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson12b47992009-10-14 17:28:52 +0000213 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson340861d2010-03-23 05:25:43 +0000214 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson06fce872011-02-07 17:43:21 +0000215 SDNode *SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000216 const uint16_t *DOpcodes,
217 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilson12b47992009-10-14 17:28:52 +0000218
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000219 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000220 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000221 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000222 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson06fce872011-02-07 17:43:21 +0000223 SDNode *SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000224 const uint16_t *DOpcodes,
225 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000226
Bob Wilson93117bc2009-10-14 16:46:45 +0000227 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilson4145e3a2009-10-14 16:19:03 +0000228 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsond5c57a52010-09-13 23:01:35 +0000229 /// load/store of D registers and Q registers.
Bob Wilson06fce872011-02-07 17:43:21 +0000230 SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad,
231 bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000232 const uint16_t *DOpcodes, const uint16_t *QOpcodes);
Bob Wilson4145e3a2009-10-14 16:19:03 +0000233
Bob Wilson2d790df2010-11-28 06:51:26 +0000234 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
235 /// should be 2, 3 or 4. The opcode array specifies the instructions used
236 /// for loading D registers. (Q registers are not supported.)
Bob Wilson06fce872011-02-07 17:43:21 +0000237 SDNode *SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000238 const uint16_t *Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +0000239
Bob Wilson5bc8a792010-07-07 00:08:54 +0000240 /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2,
241 /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be
242 /// generated to force the table registers to be consecutive.
243 SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc);
Bob Wilson3ed511b2010-07-06 23:36:25 +0000244
Sandeep Patel7460e082009-10-13 20:25:58 +0000245 /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
Jim Grosbach825cb292010-04-22 23:24:18 +0000246 SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000247
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000248 // Select special operations if node forms integer ABS pattern
249 SDNode *SelectABSOp(SDNode *N);
250
Weiming Zhaoc5987002013-02-14 18:10:21 +0000251 SDNode *SelectInlineAsm(SDNode *N);
252
Evan Chengd85631e2010-05-05 18:28:36 +0000253 SDNode *SelectConcatVector(SDNode *N);
254
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000255 SDNode *SelectAtomic(SDNode *N, unsigned Op8, unsigned Op16, unsigned Op32, unsigned Op64);
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +0000256
Evan Chengd9c55362009-07-02 01:23:32 +0000257 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
258 /// inline asm expressions.
Craig Topper6bc27bf2014-03-10 02:09:33 +0000259 bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
260 std::vector<SDValue> &OutOps) override;
Bob Wilsone6b778d2009-10-06 22:01:59 +0000261
Weiming Zhao95782222012-11-17 00:23:35 +0000262 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhao8f56f882012-11-16 21:55:34 +0000263 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao95782222012-11-17 00:23:35 +0000264 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
265 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
266 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Chengc2ae5f52010-05-10 17:34:18 +0000267
Bob Wilsond8a9a042010-06-04 00:04:02 +0000268 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +0000269 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
270 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
271 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000272
273 // Get the alignment operand for a NEON VLD or VST instruction.
274 SDValue GetVLDSTAlign(SDValue Align, unsigned NumVecs, bool is64BitVector);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000275};
Evan Cheng10043e22007-01-19 07:51:42 +0000276}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000277
Sandeep Patel423e42b2009-10-13 18:59:48 +0000278/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
279/// operand. If so Imm will receive the 32-bit value.
280static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
281 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
282 Imm = cast<ConstantSDNode>(N)->getZExtValue();
283 return true;
284 }
285 return false;
286}
287
288// isInt32Immediate - This method tests to see if a constant operand.
289// If so Imm will receive the 32 bit value.
290static bool isInt32Immediate(SDValue N, unsigned &Imm) {
291 return isInt32Immediate(N.getNode(), Imm);
292}
293
294// isOpcWithIntImmediate - This method tests to see if the node is a specific
295// opcode and that it has a immediate integer right operand.
296// If so Imm will receive the 32 bit value.
297static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
298 return N->getOpcode() == Opc &&
299 isInt32Immediate(N->getOperand(1).getNode(), Imm);
300}
301
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000302/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000303/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000304///
305/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000306static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000307 int RangeMin, int RangeMax,
308 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000309 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000310
311 // Check that this is a constant.
312 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
313 if (!C)
314 return false;
315
316 ScaledConstant = (int) C->getZExtValue();
317 if ((ScaledConstant % Scale) != 0)
318 return false;
319
320 ScaledConstant /= Scale;
321 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
322}
323
Evan Chengeae6d2c2012-12-19 20:16:09 +0000324void ARMDAGToDAGISel::PreprocessISelDAG() {
325 if (!Subtarget->hasV6T2Ops())
326 return;
327
328 bool isThumb2 = Subtarget->isThumb();
329 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
330 E = CurDAG->allnodes_end(); I != E; ) {
331 SDNode *N = I++; // Preincrement iterator to avoid invalidation issues.
332
333 if (N->getOpcode() != ISD::ADD)
334 continue;
335
336 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
337 // leading zeros, followed by consecutive set bits, followed by 1 or 2
338 // trailing zeros, e.g. 1020.
339 // Transform the expression to
340 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
341 // of trailing zeros of c2. The left shift would be folded as an shifter
342 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
343 // node (UBFX).
344
345 SDValue N0 = N->getOperand(0);
346 SDValue N1 = N->getOperand(1);
347 unsigned And_imm = 0;
348 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
349 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
350 std::swap(N0, N1);
351 }
352 if (!And_imm)
353 continue;
354
355 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000356 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000357 if (TZ != 1 && TZ != 2)
358 // Be conservative here. Shifter operands aren't always free. e.g. On
359 // Swift, left shifter operand of 1 / 2 for free but others are not.
360 // e.g.
361 // ubfx r3, r1, #16, #8
362 // ldr.w r3, [r0, r3, lsl #2]
363 // vs.
364 // mov.w r9, #1020
365 // and.w r2, r9, r1, lsr #14
366 // ldr r2, [r0, r2]
367 continue;
368 And_imm >>= TZ;
369 if (And_imm & (And_imm + 1))
370 continue;
371
372 // Look for (and (srl X, c1), c2).
373 SDValue Srl = N1.getOperand(0);
374 unsigned Srl_imm = 0;
375 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
376 (Srl_imm <= 2))
377 continue;
378
379 // Make sure first operand is not a shifter operand which would prevent
380 // folding of the left shift.
381 SDValue CPTmp0;
382 SDValue CPTmp1;
383 SDValue CPTmp2;
384 if (isThumb2) {
385 if (SelectT2ShifterOperandReg(N0, CPTmp0, CPTmp1))
386 continue;
387 } else {
388 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
389 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
390 continue;
391 }
392
393 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000394 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000395 Srl.getOperand(0),
396 CurDAG->getConstant(Srl_imm+TZ, MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000397 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000398 Srl, CurDAG->getConstant(And_imm, MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000399 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000400 N1, CurDAG->getConstant(TZ, MVT::i32));
401 CurDAG->UpdateNodeOperands(N, N0, N1);
402 }
403}
404
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000405/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
406/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
407/// least on current ARM implementations) which should be avoidded.
408bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
409 if (OptLevel == CodeGenOpt::None)
410 return true;
411
412 if (!CheckVMLxHazard)
413 return true;
Bob Wilsone8a549c2012-09-29 21:43:49 +0000414
Tim Northover0feb91e2014-04-01 14:10:07 +0000415 if (!Subtarget->isCortexA7() && !Subtarget->isCortexA8() &&
416 !Subtarget->isCortexA9() && !Subtarget->isSwift())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000417 return true;
418
419 if (!N->hasOneUse())
420 return false;
421
422 SDNode *Use = *N->use_begin();
423 if (Use->getOpcode() == ISD::CopyToReg)
424 return true;
425 if (Use->isMachineOpcode()) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000426 const ARMBaseInstrInfo *TII =
427 static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo());
428
Evan Cheng6cc775f2011-06-28 19:10:37 +0000429 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
430 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000431 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000432 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000433 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
434 return true;
435 // vmlx feeding into another vmlx. We actually want to unfold
436 // the use later in the MLxExpansion pass. e.g.
437 // vmla
438 // vmla (stall 8 cycles)
439 //
440 // vmul (5 cycles)
441 // vadd (5 cycles)
442 // vmla
443 // This adds up to about 18 - 19 cycles.
444 //
445 // vmla
446 // vmul (stall 4 cycles)
447 // vadd adds up to about 14 cycles.
448 return TII->isFpMLxInstruction(Opcode);
449 }
450
451 return false;
452}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000453
Evan Cheng59bbc542010-10-27 23:41:30 +0000454bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
455 ARM_AM::ShiftOpc ShOpcVal,
456 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000457 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000458 return true;
459 if (Shift.hasOneUse())
460 return true;
461 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000462 return ShOpcVal == ARM_AM::lsl &&
463 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000464}
465
Owen Andersonb595ed02011-07-21 18:54:16 +0000466bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000467 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000468 SDValue &Opc,
469 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000470 if (DisableShifterOp)
471 return false;
472
Evan Chenga20cde32011-07-20 23:34:39 +0000473 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000474
475 // Don't match base register only case. That is matched to a separate
476 // lower complexity pattern with explicit register operand.
477 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000478
Evan Chengb23b50d2009-06-29 07:51:04 +0000479 BaseReg = N.getOperand(0);
480 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000481 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
482 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000483 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000484 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
485 MVT::i32);
486 return true;
487}
488
Owen Andersonb595ed02011-07-21 18:54:16 +0000489bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
490 SDValue &BaseReg,
491 SDValue &ShReg,
492 SDValue &Opc,
493 bool CheckProfitability) {
494 if (DisableShifterOp)
495 return false;
496
497 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
498
499 // Don't match base register only case. That is matched to a separate
500 // lower complexity pattern with explicit register operand.
501 if (ShOpcVal == ARM_AM::no_shift) return false;
502
503 BaseReg = N.getOperand(0);
504 unsigned ShImmVal = 0;
505 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
506 if (RHS) return false;
507
508 ShReg = N.getOperand(1);
509 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
510 return false;
511 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
512 MVT::i32);
513 return true;
514}
515
516
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000517bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
518 SDValue &Base,
519 SDValue &OffImm) {
520 // Match simple R + imm12 operands.
521
522 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000523 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
524 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000525 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000526 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000527 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000528 Base = CurDAG->getTargetFrameIndex(FI,
529 getTargetLowering()->getPointerTy());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000530 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
531 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000532 }
Owen Anderson6d557452011-03-18 19:46:58 +0000533
Chris Lattner46c01a32011-02-13 22:25:43 +0000534 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northover72360d22013-12-02 10:35:41 +0000535 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000536 Base = N.getOperand(0);
537 } else
538 Base = N;
539 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
540 return true;
541 }
542
543 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
544 int RHSC = (int)RHS->getZExtValue();
545 if (N.getOpcode() == ISD::SUB)
546 RHSC = -RHSC;
547
548 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
549 Base = N.getOperand(0);
550 if (Base.getOpcode() == ISD::FrameIndex) {
551 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000552 Base = CurDAG->getTargetFrameIndex(FI,
553 getTargetLowering()->getPointerTy());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000554 }
555 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
556 return true;
557 }
558 }
559
560 // Base only.
561 Base = N;
562 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
563 return true;
564}
565
566
567
568bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
569 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000570 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000571 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000572 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
573 // X * [3,5,9] -> X + X * [2,4,8] etc.
574 int RHSC = (int)RHS->getZExtValue();
575 if (RHSC & 1) {
576 RHSC = RHSC & ~1;
577 ARM_AM::AddrOpc AddSub = ARM_AM::add;
578 if (RHSC < 0) {
579 AddSub = ARM_AM::sub;
580 RHSC = - RHSC;
581 }
582 if (isPowerOf2_32(RHSC)) {
583 unsigned ShAmt = Log2_32(RHSC);
584 Base = Offset = N.getOperand(0);
585 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
586 ARM_AM::lsl),
587 MVT::i32);
588 return true;
589 }
590 }
591 }
592 }
593
Chris Lattner46c01a32011-02-13 22:25:43 +0000594 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
595 // ISD::OR that is equivalent to an ISD::ADD.
596 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000597 return false;
598
599 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000600 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000601 int RHSC;
602 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
603 -0x1000+1, 0x1000, RHSC)) // 12 bits.
604 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000605 }
606
607 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000608 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000609 ARM_AM::ShiftOpc ShOpcVal =
610 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000611 unsigned ShAmt = 0;
612
613 Base = N.getOperand(0);
614 Offset = N.getOperand(1);
615
616 if (ShOpcVal != ARM_AM::no_shift) {
617 // Check to see if the RHS of the shift is a constant, if not, we can't fold
618 // it.
619 if (ConstantSDNode *Sh =
620 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
621 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000622 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
623 Offset = N.getOperand(1).getOperand(0);
624 else {
625 ShAmt = 0;
626 ShOpcVal = ARM_AM::no_shift;
627 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000628 } else {
629 ShOpcVal = ARM_AM::no_shift;
630 }
631 }
632
633 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000634 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000635 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
636 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000637 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000638 if (ShOpcVal != ARM_AM::no_shift) {
639 // Check to see if the RHS of the shift is a constant, if not, we can't
640 // fold it.
641 if (ConstantSDNode *Sh =
642 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
643 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000644 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000645 Offset = N.getOperand(0).getOperand(0);
646 Base = N.getOperand(1);
647 } else {
648 ShAmt = 0;
649 ShOpcVal = ARM_AM::no_shift;
650 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000651 } else {
652 ShOpcVal = ARM_AM::no_shift;
653 }
654 }
655 }
656
657 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
658 MVT::i32);
659 return true;
660}
661
662
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000663//-----
664
Jim Grosbach08605202010-09-29 19:03:54 +0000665AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
666 SDValue &Base,
667 SDValue &Offset,
668 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000669 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000670 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000671 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
672 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmaneffb8942008-09-12 16:56:44 +0000673 int RHSC = (int)RHS->getZExtValue();
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000674 if (RHSC & 1) {
675 RHSC = RHSC & ~1;
676 ARM_AM::AddrOpc AddSub = ARM_AM::add;
677 if (RHSC < 0) {
678 AddSub = ARM_AM::sub;
679 RHSC = - RHSC;
680 }
681 if (isPowerOf2_32(RHSC)) {
682 unsigned ShAmt = Log2_32(RHSC);
683 Base = Offset = N.getOperand(0);
684 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
685 ARM_AM::lsl),
Owen Anderson9f944592009-08-11 20:47:22 +0000686 MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000687 return AM2_SHOP;
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000688 }
689 }
690 }
691 }
692
Chris Lattner46c01a32011-02-13 22:25:43 +0000693 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
694 // ISD::OR that is equivalent to an ADD.
695 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000696 Base = N;
697 if (N.getOpcode() == ISD::FrameIndex) {
698 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000699 Base = CurDAG->getTargetFrameIndex(FI,
700 getTargetLowering()->getPointerTy());
Anton Korobeynikov25229082009-11-24 00:44:37 +0000701 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northover72360d22013-12-02 10:35:41 +0000702 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000703 Base = N.getOperand(0);
704 }
Owen Anderson9f944592009-08-11 20:47:22 +0000705 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000706 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
707 ARM_AM::no_shift),
Owen Anderson9f944592009-08-11 20:47:22 +0000708 MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000709 return AM2_BASE;
Rafael Espindola708cb602006-11-08 17:07:32 +0000710 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000711
Evan Cheng10043e22007-01-19 07:51:42 +0000712 // Match simple R +/- imm12 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +0000713 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000714 int RHSC;
715 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
716 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
717 Base = N.getOperand(0);
718 if (Base.getOpcode() == ISD::FrameIndex) {
719 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000720 Base = CurDAG->getTargetFrameIndex(FI,
721 getTargetLowering()->getPointerTy());
Rafael Espindola708cb602006-11-08 17:07:32 +0000722 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000723 Offset = CurDAG->getRegister(0, MVT::i32);
724
725 ARM_AM::AddrOpc AddSub = ARM_AM::add;
726 if (RHSC < 0) {
727 AddSub = ARM_AM::sub;
728 RHSC = - RHSC;
729 }
730 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
731 ARM_AM::no_shift),
732 MVT::i32);
733 return AM2_BASE;
Evan Cheng10043e22007-01-19 07:51:42 +0000734 }
Jim Grosbachc7b10f32010-09-29 17:32:29 +0000735 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000736
Bob Wilsone8a549c2012-09-29 21:43:49 +0000737 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000738 // Compute R +/- (R << N) and reuse it.
739 Base = N;
740 Offset = CurDAG->getRegister(0, MVT::i32);
741 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
742 ARM_AM::no_shift),
743 MVT::i32);
744 return AM2_BASE;
745 }
746
Johnny Chenb678a562009-10-27 17:25:15 +0000747 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000748 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chenga20cde32011-07-20 23:34:39 +0000749 ARM_AM::ShiftOpc ShOpcVal =
750 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000751 unsigned ShAmt = 0;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000752
Evan Cheng10043e22007-01-19 07:51:42 +0000753 Base = N.getOperand(0);
754 Offset = N.getOperand(1);
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000755
Evan Cheng10043e22007-01-19 07:51:42 +0000756 if (ShOpcVal != ARM_AM::no_shift) {
757 // Check to see if the RHS of the shift is a constant, if not, we can't fold
758 // it.
759 if (ConstantSDNode *Sh =
760 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000761 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000762 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
763 Offset = N.getOperand(1).getOperand(0);
764 else {
765 ShAmt = 0;
766 ShOpcVal = ARM_AM::no_shift;
767 }
Evan Cheng10043e22007-01-19 07:51:42 +0000768 } else {
769 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola708cb602006-11-08 17:07:32 +0000770 }
771 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000772
Evan Cheng10043e22007-01-19 07:51:42 +0000773 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000774 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000775 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
776 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000777 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000778 if (ShOpcVal != ARM_AM::no_shift) {
779 // Check to see if the RHS of the shift is a constant, if not, we can't
780 // fold it.
781 if (ConstantSDNode *Sh =
782 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000783 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000784 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000785 Offset = N.getOperand(0).getOperand(0);
786 Base = N.getOperand(1);
787 } else {
788 ShAmt = 0;
789 ShOpcVal = ARM_AM::no_shift;
790 }
Evan Cheng10043e22007-01-19 07:51:42 +0000791 } else {
792 ShOpcVal = ARM_AM::no_shift;
793 }
794 }
795 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000796
Evan Cheng10043e22007-01-19 07:51:42 +0000797 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson9f944592009-08-11 20:47:22 +0000798 MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000799 return AM2_SHOP;
Rafael Espindola708cb602006-11-08 17:07:32 +0000800}
801
Owen Anderson2aedba62011-07-26 20:54:26 +0000802bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000803 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000804 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000805 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
806 ? cast<LoadSDNode>(Op)->getAddressingMode()
807 : cast<StoreSDNode>(Op)->getAddressingMode();
808 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
809 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000810 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000811 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
812 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000813
814 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000815 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000816 unsigned ShAmt = 0;
817 if (ShOpcVal != ARM_AM::no_shift) {
818 // Check to see if the RHS of the shift is a constant, if not, we can't fold
819 // it.
820 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000821 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000822 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
823 Offset = N.getOperand(0);
824 else {
825 ShAmt = 0;
826 ShOpcVal = ARM_AM::no_shift;
827 }
Evan Cheng10043e22007-01-19 07:51:42 +0000828 } else {
829 ShOpcVal = ARM_AM::no_shift;
830 }
831 }
832
833 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson9f944592009-08-11 20:47:22 +0000834 MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000835 return true;
836}
837
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000838bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
839 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000840 unsigned Opcode = Op->getOpcode();
841 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
842 ? cast<LoadSDNode>(Op)->getAddressingMode()
843 : cast<StoreSDNode>(Op)->getAddressingMode();
844 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
845 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000846 int Val;
847 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000848 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000849 Offset = CurDAG->getRegister(0, MVT::i32);
850 Opc = CurDAG->getTargetConstant(Val, MVT::i32);
851 return true;
852 }
853
854 return false;
855}
856
857
Owen Anderson2aedba62011-07-26 20:54:26 +0000858bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
859 SDValue &Offset, SDValue &Opc) {
860 unsigned Opcode = Op->getOpcode();
861 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
862 ? cast<LoadSDNode>(Op)->getAddressingMode()
863 : cast<StoreSDNode>(Op)->getAddressingMode();
864 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
865 ? ARM_AM::add : ARM_AM::sub;
866 int Val;
867 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
868 Offset = CurDAG->getRegister(0, MVT::i32);
869 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
870 ARM_AM::no_shift),
871 MVT::i32);
872 return true;
873 }
874
875 return false;
876}
877
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000878bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
879 Base = N;
880 return true;
881}
Evan Cheng10043e22007-01-19 07:51:42 +0000882
Chris Lattner0e023ea2010-09-21 20:31:19 +0000883bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000884 SDValue &Base, SDValue &Offset,
885 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000886 if (N.getOpcode() == ISD::SUB) {
887 // X - C is canonicalize to X + -C, no need to handle it here.
888 Base = N.getOperand(0);
889 Offset = N.getOperand(1);
Owen Anderson9f944592009-08-11 20:47:22 +0000890 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000891 return true;
892 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000893
Chris Lattner46c01a32011-02-13 22:25:43 +0000894 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000895 Base = N;
896 if (N.getOpcode() == ISD::FrameIndex) {
897 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000898 Base = CurDAG->getTargetFrameIndex(FI,
899 getTargetLowering()->getPointerTy());
Evan Cheng10043e22007-01-19 07:51:42 +0000900 }
Owen Anderson9f944592009-08-11 20:47:22 +0000901 Offset = CurDAG->getRegister(0, MVT::i32);
902 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000903 return true;
904 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000905
Evan Cheng10043e22007-01-19 07:51:42 +0000906 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000907 int RHSC;
908 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
909 -256 + 1, 256, RHSC)) { // 8 bits.
910 Base = N.getOperand(0);
911 if (Base.getOpcode() == ISD::FrameIndex) {
912 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000913 Base = CurDAG->getTargetFrameIndex(FI,
914 getTargetLowering()->getPointerTy());
Evan Cheng10043e22007-01-19 07:51:42 +0000915 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000916 Offset = CurDAG->getRegister(0, MVT::i32);
917
918 ARM_AM::AddrOpc AddSub = ARM_AM::add;
919 if (RHSC < 0) {
920 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000921 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000922 }
923 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32);
924 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000925 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000926
Evan Cheng10043e22007-01-19 07:51:42 +0000927 Base = N.getOperand(0);
928 Offset = N.getOperand(1);
Owen Anderson9f944592009-08-11 20:47:22 +0000929 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000930 return true;
931}
932
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000933bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000934 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000935 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000936 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
937 ? cast<LoadSDNode>(Op)->getAddressingMode()
938 : cast<StoreSDNode>(Op)->getAddressingMode();
939 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
940 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000941 int Val;
942 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
943 Offset = CurDAG->getRegister(0, MVT::i32);
944 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32);
945 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000946 }
947
948 Offset = N;
Owen Anderson9f944592009-08-11 20:47:22 +0000949 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000950 return true;
951}
952
Jim Grosbachd37f0712010-10-21 19:38:40 +0000953bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000954 SDValue &Base, SDValue &Offset) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000955 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000956 Base = N;
957 if (N.getOpcode() == ISD::FrameIndex) {
958 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000959 Base = CurDAG->getTargetFrameIndex(FI,
960 getTargetLowering()->getPointerTy());
Anton Korobeynikov25229082009-11-24 00:44:37 +0000961 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northover72360d22013-12-02 10:35:41 +0000962 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000963 Base = N.getOperand(0);
964 }
965 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson9f944592009-08-11 20:47:22 +0000966 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000967 return true;
968 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000969
Evan Cheng10043e22007-01-19 07:51:42 +0000970 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000971 int RHSC;
972 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
973 -256 + 1, 256, RHSC)) {
974 Base = N.getOperand(0);
975 if (Base.getOpcode() == ISD::FrameIndex) {
976 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000977 Base = CurDAG->getTargetFrameIndex(FI,
978 getTargetLowering()->getPointerTy());
Evan Cheng10043e22007-01-19 07:51:42 +0000979 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000980
981 ARM_AM::AddrOpc AddSub = ARM_AM::add;
982 if (RHSC < 0) {
983 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000984 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000985 }
986 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
987 MVT::i32);
988 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000989 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000990
Evan Cheng10043e22007-01-19 07:51:42 +0000991 Base = N;
992 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson9f944592009-08-11 20:47:22 +0000993 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000994 return true;
995}
996
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000997bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
998 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +0000999 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001000
1001 unsigned Alignment = 0;
1002 if (LSBaseSDNode *LSN = dyn_cast<LSBaseSDNode>(Parent)) {
1003 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
1004 // The maximum alignment is equal to the memory size being referenced.
1005 unsigned LSNAlign = LSN->getAlignment();
1006 unsigned MemSize = LSN->getMemoryVT().getSizeInBits() / 8;
Jakob Stoklund Olesene5a6adc2011-10-27 22:39:16 +00001007 if (LSNAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001008 Alignment = MemSize;
1009 } else {
1010 // All other uses of addrmode6 are for intrinsics. For now just record
1011 // the raw alignment value; it will be refined later based on the legal
1012 // alignment operands for the intrinsic.
1013 Alignment = cast<MemIntrinsicSDNode>(Parent)->getAlignment();
1014 }
1015
1016 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001017 return true;
1018}
1019
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001020bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1021 SDValue &Offset) {
1022 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1023 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1024 if (AM != ISD::POST_INC)
1025 return false;
1026 Offset = N;
1027 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1028 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1029 Offset = CurDAG->getRegister(0, MVT::i32);
1030 }
1031 return true;
1032}
1033
Chris Lattner0e023ea2010-09-21 20:31:19 +00001034bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001035 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001036 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1037 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001038 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001039 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
1040 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001041 return true;
1042 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001043
Evan Cheng10043e22007-01-19 07:51:42 +00001044 return false;
1045}
1046
Bill Wendling092a7bd2010-12-14 03:36:38 +00001047
1048//===----------------------------------------------------------------------===//
1049// Thumb Addressing Modes
1050//===----------------------------------------------------------------------===//
1051
Chris Lattner0e023ea2010-09-21 20:31:19 +00001052bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001053 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001054 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001055 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001056 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001057 return false;
1058
1059 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001060 return true;
1061 }
1062
Evan Cheng10043e22007-01-19 07:51:42 +00001063 Base = N.getOperand(0);
1064 Offset = N.getOperand(1);
1065 return true;
1066}
1067
Evan Cheng139edae2007-01-24 02:21:22 +00001068bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001069ARMDAGToDAGISel::SelectThumbAddrModeRI(SDValue N, SDValue &Base,
1070 SDValue &Offset, unsigned Scale) {
Evan Cheng139edae2007-01-24 02:21:22 +00001071 if (Scale == 4) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001072 SDValue TmpBase, TmpOffImm;
Chris Lattner0e023ea2010-09-21 20:31:19 +00001073 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
Evan Cheng139edae2007-01-24 02:21:22 +00001074 return false; // We want to select tLDRspi / tSTRspi instead.
Bill Wendling092a7bd2010-12-14 03:36:38 +00001075
Evan Cheng1526ba52007-01-24 08:53:17 +00001076 if (N.getOpcode() == ARMISD::Wrapper &&
1077 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1078 return false; // We want to select tLDRpci instead.
Evan Cheng139edae2007-01-24 02:21:22 +00001079 }
1080
Chris Lattner46c01a32011-02-13 22:25:43 +00001081 if (!CurDAG->isBaseWithConstantOffset(N))
Bill Wendling832a5da2010-12-15 01:03:19 +00001082 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001083
Evan Cheng650d0672007-02-06 00:22:06 +00001084 // Thumb does not have [sp, r] address mode.
1085 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1086 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1087 if ((LHSR && LHSR->getReg() == ARM::SP) ||
Bill Wendling832a5da2010-12-15 01:03:19 +00001088 (RHSR && RHSR->getReg() == ARM::SP))
1089 return false;
Bill Wendling092a7bd2010-12-14 03:36:38 +00001090
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001091 // FIXME: Why do we explicitly check for a match here and then return false?
1092 // Presumably to allow something else to match, but shouldn't this be
1093 // documented?
1094 int RHSC;
1095 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC))
1096 return false;
Bill Wendling092a7bd2010-12-14 03:36:38 +00001097
1098 Base = N.getOperand(0);
1099 Offset = N.getOperand(1);
1100 return true;
1101}
1102
1103bool
1104ARMDAGToDAGISel::SelectThumbAddrModeRI5S1(SDValue N,
1105 SDValue &Base,
1106 SDValue &Offset) {
1107 return SelectThumbAddrModeRI(N, Base, Offset, 1);
1108}
1109
1110bool
1111ARMDAGToDAGISel::SelectThumbAddrModeRI5S2(SDValue N,
1112 SDValue &Base,
1113 SDValue &Offset) {
1114 return SelectThumbAddrModeRI(N, Base, Offset, 2);
1115}
1116
1117bool
1118ARMDAGToDAGISel::SelectThumbAddrModeRI5S4(SDValue N,
1119 SDValue &Base,
1120 SDValue &Offset) {
1121 return SelectThumbAddrModeRI(N, Base, Offset, 4);
1122}
1123
1124bool
1125ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1126 SDValue &Base, SDValue &OffImm) {
1127 if (Scale == 4) {
1128 SDValue TmpBase, TmpOffImm;
1129 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
1130 return false; // We want to select tLDRspi / tSTRspi instead.
1131
1132 if (N.getOpcode() == ARMISD::Wrapper &&
1133 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1134 return false; // We want to select tLDRpci instead.
1135 }
1136
Chris Lattner46c01a32011-02-13 22:25:43 +00001137 if (!CurDAG->isBaseWithConstantOffset(N)) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001138 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northover72360d22013-12-02 10:35:41 +00001139 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001140 Base = N.getOperand(0);
1141 } else {
1142 Base = N;
1143 }
1144
Owen Anderson9f944592009-08-11 20:47:22 +00001145 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001146 return true;
1147 }
1148
Bill Wendling832a5da2010-12-15 01:03:19 +00001149 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1150 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1151 if ((LHSR && LHSR->getReg() == ARM::SP) ||
1152 (RHSR && RHSR->getReg() == ARM::SP)) {
1153 ConstantSDNode *LHS = dyn_cast<ConstantSDNode>(N.getOperand(0));
1154 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1155 unsigned LHSC = LHS ? LHS->getZExtValue() : 0;
1156 unsigned RHSC = RHS ? RHS->getZExtValue() : 0;
1157
1158 // Thumb does not have [sp, #imm5] address mode for non-zero imm5.
1159 if (LHSC != 0 || RHSC != 0) return false;
1160
1161 Base = N;
1162 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
1163 return true;
1164 }
1165
Evan Cheng10043e22007-01-19 07:51:42 +00001166 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001167 int RHSC;
1168 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1169 Base = N.getOperand(0);
1170 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1171 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001172 }
1173
Evan Chengc0b73662007-01-23 22:59:13 +00001174 Base = N.getOperand(0);
Owen Anderson9f944592009-08-11 20:47:22 +00001175 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chengc0b73662007-01-23 22:59:13 +00001176 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001177}
1178
Bill Wendling092a7bd2010-12-14 03:36:38 +00001179bool
1180ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1181 SDValue &OffImm) {
1182 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001183}
1184
Bill Wendling092a7bd2010-12-14 03:36:38 +00001185bool
1186ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1187 SDValue &OffImm) {
1188 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001189}
1190
Bill Wendling092a7bd2010-12-14 03:36:38 +00001191bool
1192ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1193 SDValue &OffImm) {
1194 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001195}
1196
Chris Lattner0e023ea2010-09-21 20:31:19 +00001197bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1198 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001199 if (N.getOpcode() == ISD::FrameIndex) {
1200 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001201 Base = CurDAG->getTargetFrameIndex(FI,
1202 getTargetLowering()->getPointerTy());
Owen Anderson9f944592009-08-11 20:47:22 +00001203 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001204 return true;
1205 }
Evan Cheng139edae2007-01-24 02:21:22 +00001206
Chris Lattner46c01a32011-02-13 22:25:43 +00001207 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001208 return false;
1209
1210 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001211 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1212 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001213 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001214 int RHSC;
1215 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1216 Base = N.getOperand(0);
1217 if (Base.getOpcode() == ISD::FrameIndex) {
1218 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001219 Base = CurDAG->getTargetFrameIndex(FI,
1220 getTargetLowering()->getPointerTy());
Evan Cheng139edae2007-01-24 02:21:22 +00001221 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001222 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1223 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001224 }
1225 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001226
Evan Cheng10043e22007-01-19 07:51:42 +00001227 return false;
1228}
1229
Bill Wendling092a7bd2010-12-14 03:36:38 +00001230
1231//===----------------------------------------------------------------------===//
1232// Thumb 2 Addressing Modes
1233//===----------------------------------------------------------------------===//
1234
1235
Chris Lattner0e023ea2010-09-21 20:31:19 +00001236bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg,
Evan Chengeab9ca72009-06-27 02:26:13 +00001237 SDValue &Opc) {
Evan Cheng59069ec2010-07-30 23:33:54 +00001238 if (DisableShifterOp)
1239 return false;
1240
Evan Chenga20cde32011-07-20 23:34:39 +00001241 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengeab9ca72009-06-27 02:26:13 +00001242
1243 // Don't match base register only case. That is matched to a separate
1244 // lower complexity pattern with explicit register operand.
1245 if (ShOpcVal == ARM_AM::no_shift) return false;
1246
1247 BaseReg = N.getOperand(0);
1248 unsigned ShImmVal = 0;
1249 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1250 ShImmVal = RHS->getZExtValue() & 31;
1251 Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
1252 return true;
1253 }
1254
1255 return false;
1256}
1257
Chris Lattner0e023ea2010-09-21 20:31:19 +00001258bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001259 SDValue &Base, SDValue &OffImm) {
1260 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001261
Evan Cheng36064672009-08-11 08:52:18 +00001262 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001263 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1264 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001265 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001266 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001267 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001268 Base = CurDAG->getTargetFrameIndex(FI,
1269 getTargetLowering()->getPointerTy());
Owen Anderson9f944592009-08-11 20:47:22 +00001270 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001271 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001272 }
Owen Anderson6d557452011-03-18 19:46:58 +00001273
Chris Lattner46c01a32011-02-13 22:25:43 +00001274 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northover72360d22013-12-02 10:35:41 +00001275 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
Evan Cheng36064672009-08-11 08:52:18 +00001276 Base = N.getOperand(0);
1277 if (Base.getOpcode() == ISD::TargetConstantPool)
1278 return false; // We want to select t2LDRpci instead.
1279 } else
1280 Base = N;
Owen Anderson9f944592009-08-11 20:47:22 +00001281 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001282 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001283 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001284
1285 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001286 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001287 // Let t2LDRi8 handle (R - imm8).
1288 return false;
1289
Evan Chengb23b50d2009-06-29 07:51:04 +00001290 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001291 if (N.getOpcode() == ISD::SUB)
1292 RHSC = -RHSC;
1293
1294 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001295 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001296 if (Base.getOpcode() == ISD::FrameIndex) {
1297 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001298 Base = CurDAG->getTargetFrameIndex(FI,
1299 getTargetLowering()->getPointerTy());
David Goodwin79c079b2009-07-30 18:56:48 +00001300 }
Owen Anderson9f944592009-08-11 20:47:22 +00001301 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001302 return true;
1303 }
1304 }
1305
Evan Cheng36064672009-08-11 08:52:18 +00001306 // Base only.
1307 Base = N;
Owen Anderson9f944592009-08-11 20:47:22 +00001308 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001309 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001310}
1311
Chris Lattner0e023ea2010-09-21 20:31:19 +00001312bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001313 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001314 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001315 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1316 !CurDAG->isBaseWithConstantOffset(N))
1317 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001318
Chris Lattner46c01a32011-02-13 22:25:43 +00001319 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1320 int RHSC = (int)RHS->getSExtValue();
1321 if (N.getOpcode() == ISD::SUB)
1322 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001323
Chris Lattner46c01a32011-02-13 22:25:43 +00001324 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1325 Base = N.getOperand(0);
1326 if (Base.getOpcode() == ISD::FrameIndex) {
1327 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001328 Base = CurDAG->getTargetFrameIndex(FI,
1329 getTargetLowering()->getPointerTy());
Evan Chengb23b50d2009-06-29 07:51:04 +00001330 }
Chris Lattner46c01a32011-02-13 22:25:43 +00001331 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1332 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001333 }
1334 }
1335
1336 return false;
1337}
1338
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001339bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001340 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001341 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001342 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1343 ? cast<LoadSDNode>(Op)->getAddressingMode()
1344 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001345 int RHSC;
1346 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1347 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
1348 ? CurDAG->getTargetConstant(RHSC, MVT::i32)
1349 : CurDAG->getTargetConstant(-RHSC, MVT::i32);
1350 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001351 }
1352
1353 return false;
1354}
1355
Chris Lattner0e023ea2010-09-21 20:31:19 +00001356bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001357 SDValue &Base,
1358 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001359 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001360 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001361 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001362
Evan Cheng36064672009-08-11 08:52:18 +00001363 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1364 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1365 int RHSC = (int)RHS->getZExtValue();
1366 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1367 return false;
1368 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001369 return false;
1370 }
1371
Evan Chengb23b50d2009-06-29 07:51:04 +00001372 // Look for (R + R) or (R + (R << [1,2,3])).
1373 unsigned ShAmt = 0;
1374 Base = N.getOperand(0);
1375 OffReg = N.getOperand(1);
1376
1377 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001378 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001379 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001380 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001381 if (ShOpcVal == ARM_AM::lsl)
1382 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001383 }
1384
Evan Chengb23b50d2009-06-29 07:51:04 +00001385 if (ShOpcVal == ARM_AM::lsl) {
1386 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1387 // it.
1388 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1389 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001390 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1391 OffReg = OffReg.getOperand(0);
1392 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001393 ShAmt = 0;
1394 ShOpcVal = ARM_AM::no_shift;
Evan Cheng59bbc542010-10-27 23:41:30 +00001395 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001396 } else {
1397 ShOpcVal = ARM_AM::no_shift;
1398 }
David Goodwinf3912052009-07-15 15:50:19 +00001399 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001400
Owen Anderson9f944592009-08-11 20:47:22 +00001401 ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001402
1403 return true;
1404}
1405
Tim Northovera7ecd242013-07-16 09:46:55 +00001406bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1407 SDValue &OffImm) {
Alp Tokercb402912014-01-24 17:20:08 +00001408 // This *must* succeed since it's used for the irreplaceable ldrex and strex
Tim Northovera7ecd242013-07-16 09:46:55 +00001409 // instructions.
1410 Base = N;
1411 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
1412
1413 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1414 return true;
1415
1416 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1417 if (!RHS)
1418 return true;
1419
1420 uint32_t RHSC = (int)RHS->getZExtValue();
1421 if (RHSC > 1020 || RHSC % 4 != 0)
1422 return true;
1423
1424 Base = N.getOperand(0);
1425 if (Base.getOpcode() == ISD::FrameIndex) {
1426 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1427 Base = CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy());
1428 }
1429
1430 OffImm = CurDAG->getTargetConstant(RHSC / 4, MVT::i32);
1431 return true;
1432}
1433
Evan Chengb23b50d2009-06-29 07:51:04 +00001434//===--------------------------------------------------------------------===//
1435
Evan Cheng7e90b112007-07-05 07:15:27 +00001436/// getAL - Returns a ARMCC::AL immediate node.
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001437static inline SDValue getAL(SelectionDAG *CurDAG) {
Owen Anderson9f944592009-08-11 20:47:22 +00001438 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001439}
1440
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001441SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
1442 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001443 ISD::MemIndexedMode AM = LD->getAddressingMode();
1444 if (AM == ISD::UNINDEXED)
1445 return NULL;
1446
Owen Anderson53aa7a92009-08-10 22:56:29 +00001447 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001448 SDValue Offset, AMOpc;
1449 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1450 unsigned Opcode = 0;
1451 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001452 if (LoadedVT == MVT::i32 && isPre &&
1453 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1454 Opcode = ARM::LDR_PRE_IMM;
1455 Match = true;
1456 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001457 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001458 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001459 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001460 } else if (LoadedVT == MVT::i32 &&
1461 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001462 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001463 Match = true;
1464
Owen Anderson9f944592009-08-11 20:47:22 +00001465 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001466 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001467 Match = true;
1468 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1469 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1470 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001471 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001472 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001473 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001474 Match = true;
1475 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1476 }
1477 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001478 if (isPre &&
1479 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001480 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001481 Opcode = ARM::LDRB_PRE_IMM;
1482 } else if (!isPre &&
1483 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1484 Match = true;
1485 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001486 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1487 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001488 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001489 }
1490 }
1491 }
1492
1493 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001494 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1495 SDValue Chain = LD->getChain();
1496 SDValue Base = LD->getBasePtr();
1497 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG),
1498 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001499 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001500 MVT::i32, MVT::Other, Ops);
Owen Andersonfd60f602011-08-26 21:12:37 +00001501 } else {
1502 SDValue Chain = LD->getChain();
1503 SDValue Base = LD->getBasePtr();
1504 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG),
1505 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001506 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001507 MVT::i32, MVT::Other, Ops);
Owen Andersonfd60f602011-08-26 21:12:37 +00001508 }
Evan Chengd9c55362009-07-02 01:23:32 +00001509 }
1510
1511 return NULL;
1512}
1513
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001514SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
1515 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001516 ISD::MemIndexedMode AM = LD->getAddressingMode();
1517 if (AM == ISD::UNINDEXED)
1518 return NULL;
1519
Owen Anderson53aa7a92009-08-10 22:56:29 +00001520 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001521 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001522 SDValue Offset;
1523 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1524 unsigned Opcode = 0;
1525 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001526 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001527 switch (LoadedVT.getSimpleVT().SimpleTy) {
1528 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001529 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1530 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001531 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001532 if (isSExtLd)
1533 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1534 else
1535 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001536 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001537 case MVT::i8:
1538 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001539 if (isSExtLd)
1540 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1541 else
1542 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001543 break;
1544 default:
1545 return NULL;
1546 }
1547 Match = true;
1548 }
1549
1550 if (Match) {
1551 SDValue Chain = LD->getChain();
1552 SDValue Base = LD->getBasePtr();
1553 SDValue Ops[]= { Base, Offset, getAL(CurDAG),
Owen Anderson9f944592009-08-11 20:47:22 +00001554 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001555 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001556 MVT::Other, Ops);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001557 }
1558
1559 return NULL;
1560}
1561
Weiming Zhao8f56f882012-11-16 21:55:34 +00001562/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1563SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001564 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001565 SDValue RegClass =
1566 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, MVT::i32);
1567 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32);
1568 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32);
1569 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001570 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001571}
1572
Weiming Zhao95782222012-11-17 00:23:35 +00001573/// \brief Form a D register from a pair of S registers.
1574SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001575 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001576 SDValue RegClass =
1577 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, MVT::i32);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001578 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1579 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001580 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001581 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001582}
1583
Weiming Zhao95782222012-11-17 00:23:35 +00001584/// \brief Form a quad register from a pair of D registers.
1585SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001586 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001587 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, MVT::i32);
Jakob Stoklund Olesen6c47d642010-05-24 16:54:32 +00001588 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1589 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001590 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001591 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001592}
1593
Weiming Zhao95782222012-11-17 00:23:35 +00001594/// \brief Form 4 consecutive D registers from a pair of Q registers.
1595SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001596 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001597 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen6c47d642010-05-24 16:54:32 +00001598 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1599 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001600 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001601 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001602}
1603
Weiming Zhao95782222012-11-17 00:23:35 +00001604/// \brief Form 4 consecutive S registers.
1605SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001606 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001607 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001608 SDValue RegClass =
1609 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, MVT::i32);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001610 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1611 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
1612 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, MVT::i32);
1613 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001614 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1615 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001616 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001617}
1618
Weiming Zhao95782222012-11-17 00:23:35 +00001619/// \brief Form 4 consecutive D registers.
1620SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001621 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001622 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001623 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen6c47d642010-05-24 16:54:32 +00001624 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1625 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
1626 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32);
1627 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001628 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1629 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001630 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001631}
1632
Weiming Zhao95782222012-11-17 00:23:35 +00001633/// \brief Form 4 consecutive Q registers.
1634SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001635 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001636 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001637 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen6c47d642010-05-24 16:54:32 +00001638 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1639 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
1640 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32);
1641 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001642 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1643 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001644 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001645}
1646
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001647/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1648/// of a NEON VLD or VST instruction. The supported values depend on the
1649/// number of registers being loaded.
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001650SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, unsigned NumVecs,
1651 bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001652 unsigned NumRegs = NumVecs;
1653 if (!is64BitVector && NumVecs < 3)
1654 NumRegs *= 2;
1655
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001656 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001657 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001658 Alignment = 32;
1659 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1660 Alignment = 16;
1661 else if (Alignment >= 8)
1662 Alignment = 8;
1663 else
1664 Alignment = 0;
1665
1666 return CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001667}
1668
Jiangning Liu4df23632014-01-16 09:16:13 +00001669static bool isVLDfixed(unsigned Opc)
1670{
1671 switch (Opc) {
1672 default: return false;
1673 case ARM::VLD1d8wb_fixed : return true;
1674 case ARM::VLD1d16wb_fixed : return true;
1675 case ARM::VLD1d64Qwb_fixed : return true;
1676 case ARM::VLD1d32wb_fixed : return true;
1677 case ARM::VLD1d64wb_fixed : return true;
1678 case ARM::VLD1d64TPseudoWB_fixed : return true;
1679 case ARM::VLD1d64QPseudoWB_fixed : return true;
1680 case ARM::VLD1q8wb_fixed : return true;
1681 case ARM::VLD1q16wb_fixed : return true;
1682 case ARM::VLD1q32wb_fixed : return true;
1683 case ARM::VLD1q64wb_fixed : return true;
1684 case ARM::VLD2d8wb_fixed : return true;
1685 case ARM::VLD2d16wb_fixed : return true;
1686 case ARM::VLD2d32wb_fixed : return true;
1687 case ARM::VLD2q8PseudoWB_fixed : return true;
1688 case ARM::VLD2q16PseudoWB_fixed : return true;
1689 case ARM::VLD2q32PseudoWB_fixed : return true;
1690 case ARM::VLD2DUPd8wb_fixed : return true;
1691 case ARM::VLD2DUPd16wb_fixed : return true;
1692 case ARM::VLD2DUPd32wb_fixed : return true;
1693 }
1694}
1695
1696static bool isVSTfixed(unsigned Opc)
1697{
1698 switch (Opc) {
1699 default: return false;
1700 case ARM::VST1d8wb_fixed : return true;
1701 case ARM::VST1d16wb_fixed : return true;
1702 case ARM::VST1d32wb_fixed : return true;
1703 case ARM::VST1d64wb_fixed : return true;
1704 case ARM::VST1q8wb_fixed : return true;
1705 case ARM::VST1q16wb_fixed : return true;
1706 case ARM::VST1q32wb_fixed : return true;
1707 case ARM::VST1q64wb_fixed : return true;
1708 case ARM::VST1d64TPseudoWB_fixed : return true;
1709 case ARM::VST1d64QPseudoWB_fixed : return true;
1710 case ARM::VST2d8wb_fixed : return true;
1711 case ARM::VST2d16wb_fixed : return true;
1712 case ARM::VST2d32wb_fixed : return true;
1713 case ARM::VST2q8PseudoWB_fixed : return true;
1714 case ARM::VST2q16PseudoWB_fixed : return true;
1715 case ARM::VST2q32PseudoWB_fixed : return true;
1716 }
1717}
1718
Jim Grosbach2098cb12011-10-24 21:45:13 +00001719// Get the register stride update opcode of a VLD/VST instruction that
1720// is otherwise equivalent to the given fixed stride updating instruction.
1721static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
Jiangning Liu4df23632014-01-16 09:16:13 +00001722 assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1723 && "Incorrect fixed stride updating instruction.");
Jim Grosbach2098cb12011-10-24 21:45:13 +00001724 switch (Opc) {
1725 default: break;
1726 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1727 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1728 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1729 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1730 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1731 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1732 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1733 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jiangning Liu4df23632014-01-16 09:16:13 +00001734 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1735 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1736 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1737 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001738
1739 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1740 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1741 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1742 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1743 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1744 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1745 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1746 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001747 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001748 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001749
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001750 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1751 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1752 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001753 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1754 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1755 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1756
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001757 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1758 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1759 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001760 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1761 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1762 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001763
Jim Grosbach13a292c2012-03-06 22:01:44 +00001764 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1765 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1766 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001767 }
1768 return Opc; // If not one we handle, return it unchanged.
1769}
1770
Bob Wilson06fce872011-02-07 17:43:21 +00001771SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001772 const uint16_t *DOpcodes,
1773 const uint16_t *QOpcodes0,
1774 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001775 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001776 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001777
Bob Wilsonae08a732010-03-20 22:13:40 +00001778 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001779 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1780 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilson12b47992009-10-14 17:28:52 +00001781 return NULL;
1782
1783 SDValue Chain = N->getOperand(0);
1784 EVT VT = N->getValueType(0);
1785 bool is64BitVector = VT.is64BitVector();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001786 Align = GetVLDSTAlign(Align, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001787
Bob Wilson12b47992009-10-14 17:28:52 +00001788 unsigned OpcodeIndex;
1789 switch (VT.getSimpleVT().SimpleTy) {
1790 default: llvm_unreachable("unhandled vld type");
1791 // Double-register operations:
1792 case MVT::v8i8: OpcodeIndex = 0; break;
1793 case MVT::v4i16: OpcodeIndex = 1; break;
1794 case MVT::v2f32:
1795 case MVT::v2i32: OpcodeIndex = 2; break;
1796 case MVT::v1i64: OpcodeIndex = 3; break;
1797 // Quad-register operations:
1798 case MVT::v16i8: OpcodeIndex = 0; break;
1799 case MVT::v8i16: OpcodeIndex = 1; break;
1800 case MVT::v4f32:
1801 case MVT::v4i32: OpcodeIndex = 2; break;
Bob Wilson340861d2010-03-23 05:25:43 +00001802 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001803 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson340861d2010-03-23 05:25:43 +00001804 break;
Bob Wilson12b47992009-10-14 17:28:52 +00001805 }
1806
Bob Wilson35fafca2010-09-03 18:16:02 +00001807 EVT ResTy;
1808 if (NumVecs == 1)
1809 ResTy = VT;
1810 else {
1811 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1812 if (!is64BitVector)
1813 ResTyElts *= 2;
1814 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1815 }
Bob Wilson06fce872011-02-07 17:43:21 +00001816 std::vector<EVT> ResTys;
1817 ResTys.push_back(ResTy);
1818 if (isUpdating)
1819 ResTys.push_back(MVT::i32);
1820 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001821
Evan Cheng3da64f762010-04-16 05:46:06 +00001822 SDValue Pred = getAL(CurDAG);
Bob Wilsonae08a732010-03-20 22:13:40 +00001823 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001824 SDNode *VLd;
1825 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001826
Bob Wilson06fce872011-02-07 17:43:21 +00001827 // Double registers and VLD1/VLD2 quad registers are directly supported.
1828 if (is64BitVector || NumVecs <= 2) {
1829 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1830 QOpcodes0[OpcodeIndex]);
1831 Ops.push_back(MemAddr);
1832 Ops.push_back(Align);
1833 if (isUpdating) {
1834 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachd146a022011-12-09 21:28:25 +00001835 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach2098cb12011-10-24 21:45:13 +00001836 // case entirely when the rest are updated to that form, too.
Jiangning Liu4df23632014-01-16 09:16:13 +00001837 if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001838 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001839 // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001840 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00001841 if ((NumVecs > 2 && !isVLDfixed(Opc)) ||
Jim Grosbach05df4602011-10-31 21:50:31 +00001842 !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001843 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Evan Cheng630063a2010-05-10 21:26:24 +00001844 }
Bob Wilson06fce872011-02-07 17:43:21 +00001845 Ops.push_back(Pred);
1846 Ops.push_back(Reg0);
1847 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001848 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001849
Bob Wilson12b47992009-10-14 17:28:52 +00001850 } else {
1851 // Otherwise, quad registers are loaded with two separate instructions,
1852 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001853 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001854
Bob Wilson06fce872011-02-07 17:43:21 +00001855 // Load the even subregs. This is always an updating load, so that it
1856 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001857 SDValue ImplDef =
1858 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1859 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001860 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001861 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001862 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001863
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001864 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001865 Ops.push_back(SDValue(VLdA, 1));
1866 Ops.push_back(Align);
1867 if (isUpdating) {
1868 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1869 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1870 "only constant post-increment update allowed for VLD3/4");
1871 (void)Inc;
1872 Ops.push_back(Reg0);
1873 }
1874 Ops.push_back(SDValue(VLdA, 0));
1875 Ops.push_back(Pred);
1876 Ops.push_back(Reg0);
1877 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001878 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001879 }
Bob Wilson12b47992009-10-14 17:28:52 +00001880
Evan Cheng40791332011-04-19 00:04:03 +00001881 // Transfer memoperands.
1882 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1883 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1884 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1885
Bob Wilson06fce872011-02-07 17:43:21 +00001886 if (NumVecs == 1)
1887 return VLd;
1888
1889 // Extract out the subregisters.
1890 SDValue SuperReg = SDValue(VLd, 0);
1891 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
1892 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
1893 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1894 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1895 ReplaceUses(SDValue(N, Vec),
1896 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1897 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1898 if (isUpdating)
1899 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Bob Wilson12b47992009-10-14 17:28:52 +00001900 return NULL;
1901}
1902
Bob Wilson06fce872011-02-07 17:43:21 +00001903SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001904 const uint16_t *DOpcodes,
1905 const uint16_t *QOpcodes0,
1906 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001907 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001908 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001909
Bob Wilsonae08a732010-03-20 22:13:40 +00001910 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001911 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1912 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1913 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001914 return NULL;
1915
Evan Cheng40791332011-04-19 00:04:03 +00001916 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1917 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1918
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001919 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00001920 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001921 bool is64BitVector = VT.is64BitVector();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001922 Align = GetVLDSTAlign(Align, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001923
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001924 unsigned OpcodeIndex;
1925 switch (VT.getSimpleVT().SimpleTy) {
1926 default: llvm_unreachable("unhandled vst type");
1927 // Double-register operations:
1928 case MVT::v8i8: OpcodeIndex = 0; break;
1929 case MVT::v4i16: OpcodeIndex = 1; break;
1930 case MVT::v2f32:
1931 case MVT::v2i32: OpcodeIndex = 2; break;
1932 case MVT::v1i64: OpcodeIndex = 3; break;
1933 // Quad-register operations:
1934 case MVT::v16i8: OpcodeIndex = 0; break;
1935 case MVT::v8i16: OpcodeIndex = 1; break;
1936 case MVT::v4f32:
1937 case MVT::v4i32: OpcodeIndex = 2; break;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001938 case MVT::v2i64: OpcodeIndex = 3;
1939 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
1940 break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001941 }
1942
Bob Wilson06fce872011-02-07 17:43:21 +00001943 std::vector<EVT> ResTys;
1944 if (isUpdating)
1945 ResTys.push_back(MVT::i32);
1946 ResTys.push_back(MVT::Other);
1947
Evan Cheng3da64f762010-04-16 05:46:06 +00001948 SDValue Pred = getAL(CurDAG);
Bob Wilsonae08a732010-03-20 22:13:40 +00001949 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001950 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00001951
Bob Wilson06fce872011-02-07 17:43:21 +00001952 // Double registers and VST1/VST2 quad registers are directly supported.
1953 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00001954 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00001955 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00001956 SrcReg = N->getOperand(Vec0Idx);
1957 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00001958 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00001959 SDValue V0 = N->getOperand(Vec0Idx + 0);
1960 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00001961 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00001962 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001963 else {
Bob Wilson06fce872011-02-07 17:43:21 +00001964 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00001965 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00001966 // an undef.
1967 SDValue V3 = (NumVecs == 3)
1968 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00001969 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00001970 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001971 }
Bob Wilson950882b2010-08-28 05:12:57 +00001972 } else {
1973 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00001974 SDValue Q0 = N->getOperand(Vec0Idx);
1975 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00001976 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001977 }
Bob Wilson06fce872011-02-07 17:43:21 +00001978
1979 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1980 QOpcodes0[OpcodeIndex]);
1981 Ops.push_back(MemAddr);
1982 Ops.push_back(Align);
1983 if (isUpdating) {
1984 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbach88ac7612011-12-14 21:32:11 +00001985 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach05df4602011-10-31 21:50:31 +00001986 // case entirely when the rest are updated to that form, too.
Jim Grosbach88ac7612011-12-14 21:32:11 +00001987 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach05df4602011-10-31 21:50:31 +00001988 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001989 // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001990 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00001991 if (!isa<ConstantSDNode>(Inc.getNode()))
1992 Ops.push_back(Inc);
1993 else if (NumVecs > 2 && !isVSTfixed(Opc))
1994 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00001995 }
1996 Ops.push_back(SrcReg);
1997 Ops.push_back(Pred);
1998 Ops.push_back(Reg0);
1999 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00002000 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002001
2002 // Transfer memoperands.
2003 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
2004
2005 return VSt;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002006 }
2007
2008 // Otherwise, quad registers are stored with two separate instructions,
2009 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00002010
Bob Wilson01ac8f92010-06-16 21:34:01 +00002011 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00002012 SDValue V0 = N->getOperand(Vec0Idx + 0);
2013 SDValue V1 = N->getOperand(Vec0Idx + 1);
2014 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00002015 SDValue V3 = (NumVecs == 3)
2016 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002017 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002018 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002019
Bob Wilson06fce872011-02-07 17:43:21 +00002020 // Store the even D registers. This is always an updating store, so that it
2021 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00002022 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2023 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2024 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00002025 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00002026 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002027 Chain = SDValue(VStA, 1);
2028
2029 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00002030 Ops.push_back(SDValue(VStA, 0));
2031 Ops.push_back(Align);
2032 if (isUpdating) {
2033 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2034 assert(isa<ConstantSDNode>(Inc.getNode()) &&
2035 "only constant post-increment update allowed for VST3/4");
2036 (void)Inc;
2037 Ops.push_back(Reg0);
2038 }
2039 Ops.push_back(RegSeq);
2040 Ops.push_back(Pred);
2041 Ops.push_back(Reg0);
2042 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00002043 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00002044 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002045 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
2046 return VStB;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002047}
2048
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002049SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
Bob Wilson06fce872011-02-07 17:43:21 +00002050 bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00002051 const uint16_t *DOpcodes,
2052 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002053 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002054 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002055
Bob Wilsonae08a732010-03-20 22:13:40 +00002056 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00002057 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2058 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2059 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilson4145e3a2009-10-14 16:19:03 +00002060 return NULL;
2061
Evan Cheng40791332011-04-19 00:04:03 +00002062 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2063 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2064
Bob Wilson4145e3a2009-10-14 16:19:03 +00002065 SDValue Chain = N->getOperand(0);
2066 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002067 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2068 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002069 bool is64BitVector = VT.is64BitVector();
2070
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002071 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002072 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002073 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002074 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2075 if (Alignment > NumBytes)
2076 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002077 if (Alignment < 8 && Alignment < NumBytes)
2078 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002079 // Alignment must be a power of two; make sure of that.
2080 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002081 if (Alignment == 1)
2082 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002083 }
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002084 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002085
Bob Wilson4145e3a2009-10-14 16:19:03 +00002086 unsigned OpcodeIndex;
2087 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002088 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002089 // Double-register operations:
2090 case MVT::v8i8: OpcodeIndex = 0; break;
2091 case MVT::v4i16: OpcodeIndex = 1; break;
2092 case MVT::v2f32:
2093 case MVT::v2i32: OpcodeIndex = 2; break;
2094 // Quad-register operations:
2095 case MVT::v8i16: OpcodeIndex = 0; break;
2096 case MVT::v4f32:
2097 case MVT::v4i32: OpcodeIndex = 1; break;
2098 }
2099
Bob Wilson06fce872011-02-07 17:43:21 +00002100 std::vector<EVT> ResTys;
2101 if (IsLoad) {
2102 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2103 if (!is64BitVector)
2104 ResTyElts *= 2;
2105 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2106 MVT::i64, ResTyElts));
2107 }
2108 if (isUpdating)
2109 ResTys.push_back(MVT::i32);
2110 ResTys.push_back(MVT::Other);
2111
Evan Cheng3da64f762010-04-16 05:46:06 +00002112 SDValue Pred = getAL(CurDAG);
Bob Wilsonae08a732010-03-20 22:13:40 +00002113 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002114
Bob Wilson06fce872011-02-07 17:43:21 +00002115 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002116 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002117 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002118 if (isUpdating) {
2119 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2120 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
2121 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002122
Bob Wilsond5c57a52010-09-13 23:01:35 +00002123 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002124 SDValue V0 = N->getOperand(Vec0Idx + 0);
2125 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002126 if (NumVecs == 2) {
2127 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002128 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002129 else
Weiming Zhao95782222012-11-17 00:23:35 +00002130 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002131 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002132 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002133 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002134 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2135 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002136 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002137 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002138 else
Weiming Zhao95782222012-11-17 00:23:35 +00002139 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002140 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002141 Ops.push_back(SuperReg);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002142 Ops.push_back(getI32Imm(Lane));
Evan Chenga33fc862009-11-21 06:21:52 +00002143 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002144 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002145 Ops.push_back(Chain);
2146
Bob Wilson06fce872011-02-07 17:43:21 +00002147 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2148 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002149 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002150 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson93117bc2009-10-14 16:46:45 +00002151 if (!IsLoad)
Bob Wilson06fce872011-02-07 17:43:21 +00002152 return VLdLn;
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002153
Bob Wilsond5c57a52010-09-13 23:01:35 +00002154 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002155 SuperReg = SDValue(VLdLn, 0);
2156 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
2157 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
2158 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002159 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2160 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002161 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2162 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2163 if (isUpdating)
2164 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Bob Wilson4145e3a2009-10-14 16:19:03 +00002165 return NULL;
2166}
2167
Bob Wilson06fce872011-02-07 17:43:21 +00002168SDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating,
Craig Topper01736f82012-05-24 05:17:00 +00002169 unsigned NumVecs,
2170 const uint16_t *Opcodes) {
Bob Wilson2d790df2010-11-28 06:51:26 +00002171 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002172 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002173
2174 SDValue MemAddr, Align;
2175 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
2176 return NULL;
2177
Evan Cheng40791332011-04-19 00:04:03 +00002178 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2179 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2180
Bob Wilson2d790df2010-11-28 06:51:26 +00002181 SDValue Chain = N->getOperand(0);
2182 EVT VT = N->getValueType(0);
2183
2184 unsigned Alignment = 0;
2185 if (NumVecs != 3) {
2186 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2187 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2188 if (Alignment > NumBytes)
2189 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002190 if (Alignment < 8 && Alignment < NumBytes)
2191 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002192 // Alignment must be a power of two; make sure of that.
2193 Alignment = (Alignment & -Alignment);
2194 if (Alignment == 1)
2195 Alignment = 0;
2196 }
2197 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
2198
2199 unsigned OpcodeIndex;
2200 switch (VT.getSimpleVT().SimpleTy) {
2201 default: llvm_unreachable("unhandled vld-dup type");
2202 case MVT::v8i8: OpcodeIndex = 0; break;
2203 case MVT::v4i16: OpcodeIndex = 1; break;
2204 case MVT::v2f32:
2205 case MVT::v2i32: OpcodeIndex = 2; break;
2206 }
2207
2208 SDValue Pred = getAL(CurDAG);
2209 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2210 SDValue SuperReg;
2211 unsigned Opc = Opcodes[OpcodeIndex];
Bob Wilson06fce872011-02-07 17:43:21 +00002212 SmallVector<SDValue, 6> Ops;
2213 Ops.push_back(MemAddr);
2214 Ops.push_back(Align);
2215 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002216 // fixed-stride update instructions don't have an explicit writeback
2217 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002218 SDValue Inc = N->getOperand(2);
Jim Grosbachc80a2642011-12-21 19:40:55 +00002219 if (!isa<ConstantSDNode>(Inc.getNode()))
2220 Ops.push_back(Inc);
2221 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2222 else if (NumVecs > 2)
2223 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002224 }
2225 Ops.push_back(Pred);
2226 Ops.push_back(Reg0);
2227 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002228
2229 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002230 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002231 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002232 if (isUpdating)
2233 ResTys.push_back(MVT::i32);
2234 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002235 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002236 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002237 SuperReg = SDValue(VLdDup, 0);
Bob Wilson2d790df2010-11-28 06:51:26 +00002238
2239 // Extract the subregisters.
2240 assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
2241 unsigned SubIdx = ARM::dsub_0;
2242 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2243 ReplaceUses(SDValue(N, Vec),
2244 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Bob Wilson06fce872011-02-07 17:43:21 +00002245 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2246 if (isUpdating)
2247 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Bob Wilson2d790df2010-11-28 06:51:26 +00002248 return NULL;
2249}
2250
Bob Wilson5bc8a792010-07-07 00:08:54 +00002251SDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2252 unsigned Opc) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00002253 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002254 SDLoc dl(N);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002255 EVT VT = N->getValueType(0);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002256 unsigned FirstTblReg = IsExt ? 2 : 1;
Bob Wilson3ed511b2010-07-06 23:36:25 +00002257
2258 // Form a REG_SEQUENCE to force register allocation.
2259 SDValue RegSeq;
Bob Wilson5bc8a792010-07-07 00:08:54 +00002260 SDValue V0 = N->getOperand(FirstTblReg + 0);
2261 SDValue V1 = N->getOperand(FirstTblReg + 1);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002262 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002263 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002264 else {
Bob Wilson5bc8a792010-07-07 00:08:54 +00002265 SDValue V2 = N->getOperand(FirstTblReg + 2);
Jim Grosbachd37f0712010-10-21 19:38:40 +00002266 // If it's a vtbl3, form a quad D-register and leave the last part as
Bob Wilson3ed511b2010-07-06 23:36:25 +00002267 // an undef.
2268 SDValue V3 = (NumVecs == 3)
2269 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson5bc8a792010-07-07 00:08:54 +00002270 : N->getOperand(FirstTblReg + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002271 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002272 }
2273
Bob Wilson5bc8a792010-07-07 00:08:54 +00002274 SmallVector<SDValue, 6> Ops;
2275 if (IsExt)
2276 Ops.push_back(N->getOperand(1));
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00002277 Ops.push_back(RegSeq);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002278 Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
Bob Wilson3ed511b2010-07-06 23:36:25 +00002279 Ops.push_back(getAL(CurDAG)); // predicate
2280 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
Michael Liaob53d8962013-04-19 22:22:57 +00002281 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002282}
2283
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002284SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
Jim Grosbach825cb292010-04-22 23:24:18 +00002285 bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002286 if (!Subtarget->hasV6T2Ops())
2287 return NULL;
Bob Wilson93117bc2009-10-14 16:46:45 +00002288
Evan Chengeae6d2c2012-12-19 20:16:09 +00002289 unsigned Opc = isSigned
2290 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002291 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
2292
Jim Grosbach825cb292010-04-22 23:24:18 +00002293 // For unsigned extracts, check for a shift right and mask
2294 unsigned And_imm = 0;
2295 if (N->getOpcode() == ISD::AND) {
2296 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2297
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002298 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002299 if (And_imm & (And_imm + 1))
2300 return NULL;
2301
2302 unsigned Srl_imm = 0;
2303 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2304 Srl_imm)) {
2305 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2306
Jim Grosbach03f56d92011-07-27 21:09:25 +00002307 // Note: The width operand is encoded as width-1.
2308 unsigned Width = CountTrailingOnes_32(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002309 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002310
Jim Grosbach825cb292010-04-22 23:24:18 +00002311 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002312
2313 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2314 // It's cheaper to use a right shift to extract the top bits.
2315 if (Subtarget->isThumb()) {
2316 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2317 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2318 CurDAG->getTargetConstant(LSB, MVT::i32),
2319 getAL(CurDAG), Reg0, Reg0 };
2320 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
2321 }
2322
2323 // ARM models shift instructions as MOVsi with shifter operand.
2324 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2325 SDValue ShOpc =
2326 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB),
2327 MVT::i32);
2328 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
2329 getAL(CurDAG), Reg0, Reg0 };
2330 return CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops, 5);
2331 }
2332
Jim Grosbach825cb292010-04-22 23:24:18 +00002333 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2334 CurDAG->getTargetConstant(LSB, MVT::i32),
2335 CurDAG->getTargetConstant(Width, MVT::i32),
2336 getAL(CurDAG), Reg0 };
2337 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
2338 }
2339 }
2340 return NULL;
2341 }
2342
2343 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002344 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002345 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002346 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2347 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002348 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002349 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002350 // Note: The width operand is encoded as width-1.
2351 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002352 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002353 if (LSB < 0)
Sandeep Patel423e42b2009-10-13 18:59:48 +00002354 return NULL;
2355 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002356 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sandeep Patel423e42b2009-10-13 18:59:48 +00002357 CurDAG->getTargetConstant(LSB, MVT::i32),
2358 CurDAG->getTargetConstant(Width, MVT::i32),
2359 getAL(CurDAG), Reg0 };
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002360 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Sandeep Patel423e42b2009-10-13 18:59:48 +00002361 }
2362 }
2363 return NULL;
2364}
2365
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002366/// Target-specific DAG combining for ISD::XOR.
2367/// Target-independent combining lowers SELECT_CC nodes of the form
2368/// select_cc setg[ge] X, 0, X, -X
2369/// select_cc setgt X, -1, X, -X
2370/// select_cc setl[te] X, 0, -X, X
2371/// select_cc setlt X, 1, -X, X
2372/// which represent Integer ABS into:
2373/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2374/// ARM instruction selection detects the latter and matches it to
2375/// ARM::ABS or ARM::t2ABS machine node.
2376SDNode *ARMDAGToDAGISel::SelectABSOp(SDNode *N){
2377 SDValue XORSrc0 = N->getOperand(0);
2378 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002379 EVT VT = N->getValueType(0);
2380
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002381 if (Subtarget->isThumb1Only())
2382 return NULL;
2383
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002384 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002385 return NULL;
2386
2387 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2388 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2389 SDValue SRASrc0 = XORSrc1.getOperand(0);
2390 SDValue SRASrc1 = XORSrc1.getOperand(1);
2391 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2392 EVT XType = SRASrc0.getValueType();
2393 unsigned Size = XType.getSizeInBits() - 1;
2394
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002395 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
2396 XType.isInteger() && SRAConstant != NULL &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002397 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002398 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002399 return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2400 }
2401
2402 return NULL;
2403}
2404
Evan Chengd85631e2010-05-05 18:28:36 +00002405SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
2406 // The only time a CONCAT_VECTORS operation can have legal types is when
2407 // two 64-bit vectors are concatenated to a 128-bit vector.
2408 EVT VT = N->getValueType(0);
2409 if (!VT.is128BitVector() || N->getNumOperands() != 2)
2410 llvm_unreachable("unexpected CONCAT_VECTORS");
Weiming Zhao95782222012-11-17 00:23:35 +00002411 return createDRegPairNode(VT, N->getOperand(0), N->getOperand(1));
Evan Chengd85631e2010-05-05 18:28:36 +00002412}
2413
Amara Emersonb4ad2f32013-09-26 12:22:36 +00002414SDNode *ARMDAGToDAGISel::SelectAtomic(SDNode *Node, unsigned Op8,
2415 unsigned Op16,unsigned Op32,
2416 unsigned Op64) {
2417 // Mostly direct translation to the given operations, except that we preserve
2418 // the AtomicOrdering for use later on.
2419 AtomicSDNode *AN = cast<AtomicSDNode>(Node);
2420 EVT VT = AN->getMemoryVT();
2421
2422 unsigned Op;
2423 SDVTList VTs = CurDAG->getVTList(AN->getValueType(0), MVT::Other);
2424 if (VT == MVT::i8)
2425 Op = Op8;
2426 else if (VT == MVT::i16)
2427 Op = Op16;
2428 else if (VT == MVT::i32)
2429 Op = Op32;
2430 else if (VT == MVT::i64) {
2431 Op = Op64;
2432 VTs = CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other);
2433 } else
2434 llvm_unreachable("Unexpected atomic operation");
2435
Eli Friedman1ccecbb2011-08-31 17:52:22 +00002436 SmallVector<SDValue, 6> Ops;
Amara Emersonb4ad2f32013-09-26 12:22:36 +00002437 for (unsigned i = 1; i < AN->getNumOperands(); ++i)
2438 Ops.push_back(AN->getOperand(i));
2439
2440 Ops.push_back(CurDAG->getTargetConstant(AN->getOrdering(), MVT::i32));
2441 Ops.push_back(AN->getOperand(0)); // Chain moves to the end
2442
2443 return CurDAG->SelectNodeTo(Node, Op, VTs, &Ops[0], Ops.size());
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +00002444}
2445
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002446SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002447 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002448
Tim Northover31d093c2013-09-22 08:21:56 +00002449 if (N->isMachineOpcode()) {
2450 N->setNodeId(-1);
Evan Cheng10043e22007-01-19 07:51:42 +00002451 return NULL; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00002452 }
Rafael Espindola4e760152006-06-12 12:28:08 +00002453
2454 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002455 default: break;
Weiming Zhaoc5987002013-02-14 18:10:21 +00002456 case ISD::INLINEASM: {
2457 SDNode *ResNode = SelectInlineAsm(N);
2458 if (ResNode)
2459 return ResNode;
2460 break;
2461 }
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002462 case ISD::XOR: {
2463 // Select special operations if XOR node forms integer ABS pattern
2464 SDNode *ResNode = SelectABSOp(N);
2465 if (ResNode)
2466 return ResNode;
2467 // Other cases are autogenerated.
2468 break;
2469 }
Evan Cheng10043e22007-01-19 07:51:42 +00002470 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002471 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002472 bool UseCP = true;
Tim Northover55c625f2014-01-23 13:43:47 +00002473 if (Subtarget->useMovt())
Anton Korobeynikov7c2b1e72009-09-27 23:52:58 +00002474 // Thumb2-aware targets have the MOVT instruction, so all immediates can
2475 // be done with MOV + MOVT, at worst.
Tim Northover55c625f2014-01-23 13:43:47 +00002476 UseCP = false;
Anton Korobeynikov7c2b1e72009-09-27 23:52:58 +00002477 else {
2478 if (Subtarget->isThumb()) {
Tim Northover55c625f2014-01-23 13:43:47 +00002479 UseCP = (Val > 255 && // MOV
2480 ~Val > 255 && // MOV + MVN
2481 !ARM_AM::isThumbImmShiftedVal(Val) && // MOV + LSL
2482 !(Subtarget->hasV6T2Ops() && Val <= 0xffff)); // MOVW
Anton Korobeynikov7c2b1e72009-09-27 23:52:58 +00002483 } else
Tim Northover55c625f2014-01-23 13:43:47 +00002484 UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV
2485 ARM_AM::getSOImmVal(~Val) == -1 && // MVN
2486 !ARM_AM::isSOImmTwoPartVal(Val) && // two instrs.
2487 !(Subtarget->hasV6T2Ops() && Val <= 0xffff)); // MOVW
Anton Korobeynikov7c2b1e72009-09-27 23:52:58 +00002488 }
2489
Evan Cheng10043e22007-01-19 07:51:42 +00002490 if (UseCP) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002491 SDValue CPIdx =
Owen Anderson55f1c092009-08-13 21:58:54 +00002492 CurDAG->getTargetConstantPool(ConstantInt::get(
2493 Type::getInt32Ty(*CurDAG->getContext()), Val),
Bill Wendlinga3cd3502013-06-19 21:36:55 +00002494 getTargetLowering()->getPointerTy());
Evan Cheng1526ba52007-01-24 08:53:17 +00002495
2496 SDNode *ResNode;
Tim Northover55c625f2014-01-23 13:43:47 +00002497 if (Subtarget->isThumb()) {
Evan Cheng3da64f762010-04-16 05:46:06 +00002498 SDValue Pred = getAL(CurDAG);
Owen Anderson9f944592009-08-11 20:47:22 +00002499 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002500 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002501 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002502 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002503 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002504 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002505 CPIdx,
Owen Anderson9f944592009-08-11 20:47:22 +00002506 CurDAG->getTargetConstant(0, MVT::i32),
Evan Cheng7e90b112007-07-05 07:15:27 +00002507 getAL(CurDAG),
Owen Anderson9f944592009-08-11 20:47:22 +00002508 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002509 CurDAG->getEntryNode()
2510 };
Dan Gohman32f71d72009-09-25 18:54:59 +00002511 ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002512 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002513 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002514 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
Evan Cheng10043e22007-01-19 07:51:42 +00002515 return NULL;
2516 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002517
Evan Cheng10043e22007-01-19 07:51:42 +00002518 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002519 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002520 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002521 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002522 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002523 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00002524 SDValue TFI = CurDAG->getTargetFrameIndex(FI,
2525 getTargetLowering()->getPointerTy());
David Goodwin22c2fba2009-07-08 23:10:31 +00002526 if (Subtarget->isThumb1Only()) {
Jim Grosbach1b8457a2011-08-24 17:46:13 +00002527 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
2528 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2529 return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, Ops, 4);
Jim Grosbachfde21102009-04-07 20:34:09 +00002530 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002531 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2532 ARM::t2ADDri : ARM::ADDri);
Owen Anderson9f944592009-08-11 20:47:22 +00002533 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
2534 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2535 CurDAG->getRegister(0, MVT::i32) };
2536 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Cheng7e90b112007-07-05 07:15:27 +00002537 }
Evan Cheng10043e22007-01-19 07:51:42 +00002538 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002539 case ISD::SRL:
Jim Grosbach825cb292010-04-22 23:24:18 +00002540 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
Sandeep Patel423e42b2009-10-13 18:59:48 +00002541 return I;
2542 break;
2543 case ISD::SRA:
Jim Grosbach825cb292010-04-22 23:24:18 +00002544 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true))
Sandeep Patel423e42b2009-10-13 18:59:48 +00002545 return I;
2546 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002547 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002548 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002549 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002550 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002551 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002552 if (!RHSV) break;
2553 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002554 unsigned ShImm = Log2_32(RHSV-1);
2555 if (ShImm >= 32)
2556 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002557 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002558 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson9f944592009-08-11 20:47:22 +00002559 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
2560 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002561 if (Subtarget->isThumb()) {
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002562 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson9f944592009-08-11 20:47:22 +00002563 return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002564 } else {
2565 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Andersonb595ed02011-07-21 18:54:16 +00002566 return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops, 7);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002567 }
Evan Cheng10043e22007-01-19 07:51:42 +00002568 }
2569 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002570 unsigned ShImm = Log2_32(RHSV+1);
2571 if (ShImm >= 32)
2572 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002573 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002574 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson9f944592009-08-11 20:47:22 +00002575 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
2576 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002577 if (Subtarget->isThumb()) {
Bob Wilsonb6112e82010-05-28 00:27:15 +00002578 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
2579 return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 6);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002580 } else {
2581 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Andersonb595ed02011-07-21 18:54:16 +00002582 return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops, 7);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002583 }
Evan Cheng10043e22007-01-19 07:51:42 +00002584 }
2585 }
2586 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002587 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002588 // Check for unsigned bitfield extract
2589 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
2590 return I;
2591
Evan Cheng786b15f2009-10-21 08:15:52 +00002592 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2593 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2594 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2595 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2596 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002597 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002598 if (VT != MVT::i32)
2599 break;
2600 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2601 ? ARM::t2MOVTi16
2602 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2603 if (!Opc)
2604 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002605 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002606 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
2607 if (!N1C)
2608 break;
2609 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2610 SDValue N2 = N0.getOperand(1);
2611 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2612 if (!N2C)
2613 break;
2614 unsigned N1CVal = N1C->getZExtValue();
2615 unsigned N2CVal = N2C->getZExtValue();
2616 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2617 (N1CVal & 0xffffU) == 0xffffU &&
2618 (N2CVal & 0xffffU) == 0x0U) {
2619 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
2620 MVT::i32);
2621 SDValue Ops[] = { N0.getOperand(0), Imm16,
2622 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002623 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
Evan Cheng786b15f2009-10-21 08:15:52 +00002624 }
2625 }
2626 break;
2627 }
Jim Grosbachd7cf55c2009-11-09 00:11:35 +00002628 case ARMISD::VMOVRRD:
2629 return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002630 N->getOperand(0), getAL(CurDAG),
Dan Gohman32f71d72009-09-25 18:54:59 +00002631 CurDAG->getRegister(0, MVT::i32));
Dan Gohmana1603612007-10-08 18:33:35 +00002632 case ISD::UMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002633 if (Subtarget->isThumb1Only())
2634 break;
2635 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002636 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Michael Liaob53d8962013-04-19 22:22:57 +00002637 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2638 return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002639 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002640 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson9f944592009-08-11 20:47:22 +00002641 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2642 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov62acecd2011-01-01 20:38:38 +00002643 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2644 ARM::UMULL : ARM::UMULLv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002645 dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002646 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002647 }
Dan Gohmana1603612007-10-08 18:33:35 +00002648 case ISD::SMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002649 if (Subtarget->isThumb1Only())
2650 break;
2651 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002652 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson9f944592009-08-11 20:47:22 +00002653 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002654 return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002655 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002656 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson9f944592009-08-11 20:47:22 +00002657 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2658 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov62acecd2011-01-01 20:38:38 +00002659 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2660 ARM::SMULL : ARM::SMULLv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002661 dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002662 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002663 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002664 case ARMISD::UMLAL:{
2665 if (Subtarget->isThumb()) {
2666 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2667 N->getOperand(3), getAL(CurDAG),
2668 CurDAG->getRegister(0, MVT::i32)};
Michael Liaob53d8962013-04-19 22:22:57 +00002669 return CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002670 }else{
2671 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2672 N->getOperand(3), getAL(CurDAG),
2673 CurDAG->getRegister(0, MVT::i32),
2674 CurDAG->getRegister(0, MVT::i32) };
2675 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2676 ARM::UMLAL : ARM::UMLALv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002677 dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002678 }
2679 }
2680 case ARMISD::SMLAL:{
2681 if (Subtarget->isThumb()) {
2682 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2683 N->getOperand(3), getAL(CurDAG),
2684 CurDAG->getRegister(0, MVT::i32)};
Michael Liaob53d8962013-04-19 22:22:57 +00002685 return CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002686 }else{
2687 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2688 N->getOperand(3), getAL(CurDAG),
2689 CurDAG->getRegister(0, MVT::i32),
2690 CurDAG->getRegister(0, MVT::i32) };
2691 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2692 ARM::SMLAL : ARM::SMLALv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002693 dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002694 }
2695 }
Evan Cheng10043e22007-01-19 07:51:42 +00002696 case ISD::LOAD: {
Evan Cheng84c6cda2009-07-02 07:28:31 +00002697 SDNode *ResNode = 0;
Evan Chengb24e51e2009-07-07 01:17:28 +00002698 if (Subtarget->isThumb() && Subtarget->hasThumb2())
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002699 ResNode = SelectT2IndexedLoad(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00002700 else
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002701 ResNode = SelectARMIndexedLoad(N);
Evan Chengd9c55362009-07-02 01:23:32 +00002702 if (ResNode)
2703 return ResNode;
Evan Cheng10043e22007-01-19 07:51:42 +00002704 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002705 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00002706 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002707 case ARMISD::BRCOND: {
2708 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2709 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2710 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00002711
Evan Cheng7e90b112007-07-05 07:15:27 +00002712 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2713 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2714 // Pattern complexity = 6 cost = 1 size = 0
2715
David Goodwin27303cd2009-06-30 18:04:13 +00002716 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2717 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2718 // Pattern complexity = 6 cost = 1 size = 0
2719
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002720 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00002721 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002722 SDValue Chain = N->getOperand(0);
2723 SDValue N1 = N->getOperand(1);
2724 SDValue N2 = N->getOperand(2);
2725 SDValue N3 = N->getOperand(3);
2726 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00002727 assert(N1.getOpcode() == ISD::BasicBlock);
2728 assert(N2.getOpcode() == ISD::Constant);
2729 assert(N3.getOpcode() == ISD::Register);
2730
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002731 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Dan Gohmaneffb8942008-09-12 16:56:44 +00002732 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson9f944592009-08-11 20:47:22 +00002733 MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002734 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00002735 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002736 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002737 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002738 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002739 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002740 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00002741 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002742 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00002743 SDValue(Chain.getNode(), Chain.getResNo()));
Evan Cheng7e90b112007-07-05 07:15:27 +00002744 return NULL;
2745 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002746 case ARMISD::VZIP: {
2747 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002748 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002749 switch (VT.getSimpleVT().SimpleTy) {
2750 default: return NULL;
2751 case MVT::v8i8: Opc = ARM::VZIPd8; break;
2752 case MVT::v4i16: Opc = ARM::VZIPd16; break;
2753 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00002754 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2755 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002756 case MVT::v16i8: Opc = ARM::VZIPq8; break;
2757 case MVT::v8i16: Opc = ARM::VZIPq16; break;
2758 case MVT::v4f32:
2759 case MVT::v4i32: Opc = ARM::VZIPq32; break;
2760 }
Evan Cheng3da64f762010-04-16 05:46:06 +00002761 SDValue Pred = getAL(CurDAG);
Evan Chenga33fc862009-11-21 06:21:52 +00002762 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2763 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002764 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002765 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002766 case ARMISD::VUZP: {
2767 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002768 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002769 switch (VT.getSimpleVT().SimpleTy) {
2770 default: return NULL;
2771 case MVT::v8i8: Opc = ARM::VUZPd8; break;
2772 case MVT::v4i16: Opc = ARM::VUZPd16; break;
2773 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00002774 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2775 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002776 case MVT::v16i8: Opc = ARM::VUZPq8; break;
2777 case MVT::v8i16: Opc = ARM::VUZPq16; break;
2778 case MVT::v4f32:
2779 case MVT::v4i32: Opc = ARM::VUZPq32; break;
2780 }
Evan Cheng3da64f762010-04-16 05:46:06 +00002781 SDValue Pred = getAL(CurDAG);
Evan Chenga33fc862009-11-21 06:21:52 +00002782 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2783 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002784 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002785 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002786 case ARMISD::VTRN: {
2787 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002788 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002789 switch (VT.getSimpleVT().SimpleTy) {
2790 default: return NULL;
2791 case MVT::v8i8: Opc = ARM::VTRNd8; break;
2792 case MVT::v4i16: Opc = ARM::VTRNd16; break;
2793 case MVT::v2f32:
2794 case MVT::v2i32: Opc = ARM::VTRNd32; break;
2795 case MVT::v16i8: Opc = ARM::VTRNq8; break;
2796 case MVT::v8i16: Opc = ARM::VTRNq16; break;
2797 case MVT::v4f32:
2798 case MVT::v4i32: Opc = ARM::VTRNq32; break;
2799 }
Evan Cheng3da64f762010-04-16 05:46:06 +00002800 SDValue Pred = getAL(CurDAG);
Evan Chenga33fc862009-11-21 06:21:52 +00002801 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2802 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002803 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002804 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00002805 case ARMISD::BUILD_VECTOR: {
2806 EVT VecVT = N->getValueType(0);
2807 EVT EltVT = VecVT.getVectorElementType();
2808 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00002809 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00002810 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Weiming Zhao95782222012-11-17 00:23:35 +00002811 return createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilsond8a9a042010-06-04 00:04:02 +00002812 }
Duncan Sands14627772010-11-03 12:17:33 +00002813 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Bob Wilsond8a9a042010-06-04 00:04:02 +00002814 if (NumElts == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002815 return createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilsond8a9a042010-06-04 00:04:02 +00002816 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Weiming Zhao95782222012-11-17 00:23:35 +00002817 return createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
Bob Wilsond8a9a042010-06-04 00:04:02 +00002818 N->getOperand(2), N->getOperand(3));
2819 }
Bob Wilsone0636a72009-08-26 17:39:53 +00002820
Bob Wilson2d790df2010-11-28 06:51:26 +00002821 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002822 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
2823 ARM::VLD2DUPd32 };
Bob Wilson06fce872011-02-07 17:43:21 +00002824 return SelectVLDDup(N, false, 2, Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +00002825 }
2826
Bob Wilson77ab1652010-11-29 19:35:29 +00002827 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002828 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
2829 ARM::VLD3DUPd16Pseudo,
2830 ARM::VLD3DUPd32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00002831 return SelectVLDDup(N, false, 3, Opcodes);
Bob Wilson77ab1652010-11-29 19:35:29 +00002832 }
2833
Bob Wilson431ac4ef2010-11-30 00:00:35 +00002834 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002835 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
2836 ARM::VLD4DUPd16Pseudo,
2837 ARM::VLD4DUPd32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00002838 return SelectVLDDup(N, false, 4, Opcodes);
2839 }
2840
2841 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002842 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
2843 ARM::VLD2DUPd16wb_fixed,
2844 ARM::VLD2DUPd32wb_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00002845 return SelectVLDDup(N, true, 2, Opcodes);
2846 }
2847
2848 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002849 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
2850 ARM::VLD3DUPd16Pseudo_UPD,
2851 ARM::VLD3DUPd32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002852 return SelectVLDDup(N, true, 3, Opcodes);
2853 }
2854
2855 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002856 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
2857 ARM::VLD4DUPd16Pseudo_UPD,
2858 ARM::VLD4DUPd32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002859 return SelectVLDDup(N, true, 4, Opcodes);
2860 }
2861
2862 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002863 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
2864 ARM::VLD1d16wb_fixed,
2865 ARM::VLD1d32wb_fixed,
2866 ARM::VLD1d64wb_fixed };
2867 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
2868 ARM::VLD1q16wb_fixed,
2869 ARM::VLD1q32wb_fixed,
2870 ARM::VLD1q64wb_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00002871 return SelectVLD(N, true, 1, DOpcodes, QOpcodes, 0);
2872 }
2873
2874 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002875 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
2876 ARM::VLD2d16wb_fixed,
2877 ARM::VLD2d32wb_fixed,
2878 ARM::VLD1q64wb_fixed};
2879 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
2880 ARM::VLD2q16PseudoWB_fixed,
2881 ARM::VLD2q32PseudoWB_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00002882 return SelectVLD(N, true, 2, DOpcodes, QOpcodes, 0);
2883 }
2884
2885 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002886 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
2887 ARM::VLD3d16Pseudo_UPD,
2888 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00002889 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00002890 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
2891 ARM::VLD3q16Pseudo_UPD,
2892 ARM::VLD3q32Pseudo_UPD };
2893 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
2894 ARM::VLD3q16oddPseudo_UPD,
2895 ARM::VLD3q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002896 return SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
2897 }
2898
2899 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002900 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
2901 ARM::VLD4d16Pseudo_UPD,
2902 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00002903 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00002904 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
2905 ARM::VLD4q16Pseudo_UPD,
2906 ARM::VLD4q32Pseudo_UPD };
2907 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
2908 ARM::VLD4q16oddPseudo_UPD,
2909 ARM::VLD4q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002910 return SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
2911 }
2912
2913 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002914 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
2915 ARM::VLD2LNd16Pseudo_UPD,
2916 ARM::VLD2LNd32Pseudo_UPD };
2917 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
2918 ARM::VLD2LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002919 return SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
2920 }
2921
2922 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002923 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
2924 ARM::VLD3LNd16Pseudo_UPD,
2925 ARM::VLD3LNd32Pseudo_UPD };
2926 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
2927 ARM::VLD3LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002928 return SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
2929 }
2930
2931 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002932 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
2933 ARM::VLD4LNd16Pseudo_UPD,
2934 ARM::VLD4LNd32Pseudo_UPD };
2935 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
2936 ARM::VLD4LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002937 return SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
2938 }
2939
2940 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002941 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
2942 ARM::VST1d16wb_fixed,
2943 ARM::VST1d32wb_fixed,
2944 ARM::VST1d64wb_fixed };
2945 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
2946 ARM::VST1q16wb_fixed,
2947 ARM::VST1q32wb_fixed,
2948 ARM::VST1q64wb_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00002949 return SelectVST(N, true, 1, DOpcodes, QOpcodes, 0);
2950 }
2951
2952 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002953 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
2954 ARM::VST2d16wb_fixed,
2955 ARM::VST2d32wb_fixed,
2956 ARM::VST1q64wb_fixed};
2957 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
2958 ARM::VST2q16PseudoWB_fixed,
2959 ARM::VST2q32PseudoWB_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00002960 return SelectVST(N, true, 2, DOpcodes, QOpcodes, 0);
2961 }
2962
2963 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002964 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
2965 ARM::VST3d16Pseudo_UPD,
2966 ARM::VST3d32Pseudo_UPD,
2967 ARM::VST1d64TPseudoWB_fixed};
2968 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
2969 ARM::VST3q16Pseudo_UPD,
2970 ARM::VST3q32Pseudo_UPD };
2971 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
2972 ARM::VST3q16oddPseudo_UPD,
2973 ARM::VST3q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002974 return SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
2975 }
2976
2977 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002978 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
2979 ARM::VST4d16Pseudo_UPD,
2980 ARM::VST4d32Pseudo_UPD,
2981 ARM::VST1d64QPseudoWB_fixed};
2982 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
2983 ARM::VST4q16Pseudo_UPD,
2984 ARM::VST4q32Pseudo_UPD };
2985 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
2986 ARM::VST4q16oddPseudo_UPD,
2987 ARM::VST4q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002988 return SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
2989 }
2990
2991 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002992 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
2993 ARM::VST2LNd16Pseudo_UPD,
2994 ARM::VST2LNd32Pseudo_UPD };
2995 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
2996 ARM::VST2LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002997 return SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
2998 }
2999
3000 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003001 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3002 ARM::VST3LNd16Pseudo_UPD,
3003 ARM::VST3LNd32Pseudo_UPD };
3004 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3005 ARM::VST3LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003006 return SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3007 }
3008
3009 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003010 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3011 ARM::VST4LNd16Pseudo_UPD,
3012 ARM::VST4LNd32Pseudo_UPD };
3013 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3014 ARM::VST4LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003015 return SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003016 }
3017
Bob Wilsone0636a72009-08-26 17:39:53 +00003018 case ISD::INTRINSIC_VOID:
3019 case ISD::INTRINSIC_W_CHAIN: {
3020 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003021 switch (IntNo) {
3022 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003023 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003024
Tim Northover1ff5f292014-03-26 14:39:31 +00003025 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003026 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003027 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003028 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003029 SDValue MemAddr = N->getOperand(2);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003030 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
Tim Northover1ff5f292014-03-26 14:39:31 +00003031
3032 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3033 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3034 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003035
3036 // arm_ldrexd returns a i64 value in {i32, i32}
3037 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003038 if (isThumb) {
3039 ResTys.push_back(MVT::i32);
3040 ResTys.push_back(MVT::i32);
3041 } else
3042 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003043 ResTys.push_back(MVT::Other);
3044
Weiming Zhao8f56f882012-11-16 21:55:34 +00003045 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003046 SmallVector<SDValue, 7> Ops;
3047 Ops.push_back(MemAddr);
3048 Ops.push_back(getAL(CurDAG));
3049 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3050 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00003051 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003052 // Transfer memoperands.
3053 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3054 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3055 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3056
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003057 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003058 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003059 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003060 SDValue Result;
3061 if (isThumb)
3062 Result = SDValue(Ld, 0);
3063 else {
3064 SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32);
3065 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003066 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003067 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003068 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003069 ReplaceUses(SDValue(N, 0), Result);
3070 }
3071 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003072 SDValue Result;
3073 if (isThumb)
3074 Result = SDValue(Ld, 1);
3075 else {
3076 SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32);
3077 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003078 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003079 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003080 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003081 ReplaceUses(SDValue(N, 1), Result);
3082 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003083 ReplaceUses(SDValue(N, 2), OutChain);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003084 return NULL;
3085 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003086 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003087 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003088 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003089 SDValue Chain = N->getOperand(0);
3090 SDValue Val0 = N->getOperand(2);
3091 SDValue Val1 = N->getOperand(3);
3092 SDValue MemAddr = N->getOperand(4);
3093
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003094 // Store exclusive double return a i32 value which is the return status
3095 // of the issued store.
Benjamin Kramerfdf362b2013-03-07 20:33:29 +00003096 EVT ResTys[] = { MVT::i32, MVT::Other };
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003097
Weiming Zhao8f56f882012-11-16 21:55:34 +00003098 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3099 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003100 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003101 if (isThumb) {
3102 Ops.push_back(Val0);
3103 Ops.push_back(Val1);
3104 } else
3105 // arm_strexd uses GPRPair.
3106 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003107 Ops.push_back(MemAddr);
3108 Ops.push_back(getAL(CurDAG));
3109 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3110 Ops.push_back(Chain);
3111
Tim Northover1ff5f292014-03-26 14:39:31 +00003112 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3113 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3114 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003115
Michael Liaob53d8962013-04-19 22:22:57 +00003116 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003117 // Transfer memoperands.
3118 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3119 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3120 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3121
3122 return St;
3123 }
3124
Bob Wilson340861d2010-03-23 05:25:43 +00003125 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003126 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3127 ARM::VLD1d32, ARM::VLD1d64 };
3128 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3129 ARM::VLD1q32, ARM::VLD1q64};
Bob Wilson06fce872011-02-07 17:43:21 +00003130 return SelectVLD(N, false, 1, DOpcodes, QOpcodes, 0);
Bob Wilson340861d2010-03-23 05:25:43 +00003131 }
3132
Bob Wilsone0636a72009-08-26 17:39:53 +00003133 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003134 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3135 ARM::VLD2d32, ARM::VLD1q64 };
3136 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3137 ARM::VLD2q32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003138 return SelectVLD(N, false, 2, DOpcodes, QOpcodes, 0);
Bob Wilsone0636a72009-08-26 17:39:53 +00003139 }
3140
3141 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003142 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3143 ARM::VLD3d16Pseudo,
3144 ARM::VLD3d32Pseudo,
3145 ARM::VLD1d64TPseudo };
3146 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3147 ARM::VLD3q16Pseudo_UPD,
3148 ARM::VLD3q32Pseudo_UPD };
3149 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3150 ARM::VLD3q16oddPseudo,
3151 ARM::VLD3q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003152 return SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003153 }
3154
3155 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003156 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3157 ARM::VLD4d16Pseudo,
3158 ARM::VLD4d32Pseudo,
3159 ARM::VLD1d64QPseudo };
3160 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3161 ARM::VLD4q16Pseudo_UPD,
3162 ARM::VLD4q32Pseudo_UPD };
3163 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3164 ARM::VLD4q16oddPseudo,
3165 ARM::VLD4q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003166 return SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003167 }
3168
Bob Wilsonda9817c2009-09-01 04:26:28 +00003169 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003170 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3171 ARM::VLD2LNd16Pseudo,
3172 ARM::VLD2LNd32Pseudo };
3173 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3174 ARM::VLD2LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003175 return SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003176 }
3177
3178 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003179 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3180 ARM::VLD3LNd16Pseudo,
3181 ARM::VLD3LNd32Pseudo };
3182 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3183 ARM::VLD3LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003184 return SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003185 }
3186
3187 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003188 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3189 ARM::VLD4LNd16Pseudo,
3190 ARM::VLD4LNd32Pseudo };
3191 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3192 ARM::VLD4LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003193 return SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003194 }
3195
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003196 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003197 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3198 ARM::VST1d32, ARM::VST1d64 };
3199 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3200 ARM::VST1q32, ARM::VST1q64 };
Bob Wilson06fce872011-02-07 17:43:21 +00003201 return SelectVST(N, false, 1, DOpcodes, QOpcodes, 0);
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003202 }
3203
Bob Wilsone0636a72009-08-26 17:39:53 +00003204 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003205 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3206 ARM::VST2d32, ARM::VST1q64 };
3207 static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3208 ARM::VST2q32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003209 return SelectVST(N, false, 2, DOpcodes, QOpcodes, 0);
Bob Wilsone0636a72009-08-26 17:39:53 +00003210 }
3211
3212 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003213 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3214 ARM::VST3d16Pseudo,
3215 ARM::VST3d32Pseudo,
3216 ARM::VST1d64TPseudo };
3217 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3218 ARM::VST3q16Pseudo_UPD,
3219 ARM::VST3q32Pseudo_UPD };
3220 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3221 ARM::VST3q16oddPseudo,
3222 ARM::VST3q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003223 return SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003224 }
3225
3226 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003227 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3228 ARM::VST4d16Pseudo,
3229 ARM::VST4d32Pseudo,
3230 ARM::VST1d64QPseudo };
3231 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3232 ARM::VST4q16Pseudo_UPD,
3233 ARM::VST4q32Pseudo_UPD };
3234 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3235 ARM::VST4q16oddPseudo,
3236 ARM::VST4q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003237 return SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003238 }
Bob Wilsond7797752009-09-01 18:51:56 +00003239
3240 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003241 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3242 ARM::VST2LNd16Pseudo,
3243 ARM::VST2LNd32Pseudo };
3244 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3245 ARM::VST2LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003246 return SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003247 }
3248
3249 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003250 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3251 ARM::VST3LNd16Pseudo,
3252 ARM::VST3LNd32Pseudo };
3253 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3254 ARM::VST3LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003255 return SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003256 }
3257
3258 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003259 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3260 ARM::VST4LNd16Pseudo,
3261 ARM::VST4LNd32Pseudo };
3262 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3263 ARM::VST4LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003264 return SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003265 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003266 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003267 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003268 }
Evan Chengd85631e2010-05-05 18:28:36 +00003269
Bob Wilson3ed511b2010-07-06 23:36:25 +00003270 case ISD::INTRINSIC_WO_CHAIN: {
3271 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3272 switch (IntNo) {
3273 default:
3274 break;
3275
3276 case Intrinsic::arm_neon_vtbl2:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003277 return SelectVTBL(N, false, 2, ARM::VTBL2);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003278 case Intrinsic::arm_neon_vtbl3:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003279 return SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003280 case Intrinsic::arm_neon_vtbl4:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003281 return SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003282
3283 case Intrinsic::arm_neon_vtbx2:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003284 return SelectVTBL(N, true, 2, ARM::VTBX2);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003285 case Intrinsic::arm_neon_vtbx3:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003286 return SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003287 case Intrinsic::arm_neon_vtbx4:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003288 return SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003289 }
3290 break;
3291 }
3292
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003293 case ARMISD::VTBL1: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003294 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003295 EVT VT = N->getValueType(0);
3296 SmallVector<SDValue, 6> Ops;
3297
3298 Ops.push_back(N->getOperand(0));
3299 Ops.push_back(N->getOperand(1));
3300 Ops.push_back(getAL(CurDAG)); // Predicate
3301 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Michael Liaob53d8962013-04-19 22:22:57 +00003302 return CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003303 }
3304 case ARMISD::VTBL2: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003305 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003306 EVT VT = N->getValueType(0);
3307
3308 // Form a REG_SEQUENCE to force register allocation.
3309 SDValue V0 = N->getOperand(0);
3310 SDValue V1 = N->getOperand(1);
Weiming Zhao95782222012-11-17 00:23:35 +00003311 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003312
3313 SmallVector<SDValue, 6> Ops;
3314 Ops.push_back(RegSeq);
3315 Ops.push_back(N->getOperand(2));
3316 Ops.push_back(getAL(CurDAG)); // Predicate
3317 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Michael Liaob53d8962013-04-19 22:22:57 +00003318 return CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003319 }
3320
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003321 case ISD::CONCAT_VECTORS:
Evan Chengd85631e2010-05-05 18:28:36 +00003322 return SelectConcatVector(N);
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +00003323
Amara Emersonb4ad2f32013-09-26 12:22:36 +00003324 case ISD::ATOMIC_LOAD:
3325 if (cast<AtomicSDNode>(N)->getMemoryVT() == MVT::i64)
3326 return SelectAtomic(N, 0, 0, 0, ARM::ATOMIC_LOAD_I64);
3327 else
3328 break;
Silviu Baranga93aefa52012-11-29 14:41:25 +00003329
Amara Emersonb4ad2f32013-09-26 12:22:36 +00003330 case ISD::ATOMIC_LOAD_ADD:
3331 return SelectAtomic(N,
3332 ARM::ATOMIC_LOAD_ADD_I8,
3333 ARM::ATOMIC_LOAD_ADD_I16,
3334 ARM::ATOMIC_LOAD_ADD_I32,
3335 ARM::ATOMIC_LOAD_ADD_I64);
3336 case ISD::ATOMIC_LOAD_SUB:
3337 return SelectAtomic(N,
3338 ARM::ATOMIC_LOAD_SUB_I8,
3339 ARM::ATOMIC_LOAD_SUB_I16,
3340 ARM::ATOMIC_LOAD_SUB_I32,
3341 ARM::ATOMIC_LOAD_SUB_I64);
3342 case ISD::ATOMIC_LOAD_AND:
3343 return SelectAtomic(N,
3344 ARM::ATOMIC_LOAD_AND_I8,
3345 ARM::ATOMIC_LOAD_AND_I16,
3346 ARM::ATOMIC_LOAD_AND_I32,
3347 ARM::ATOMIC_LOAD_AND_I64);
3348 case ISD::ATOMIC_LOAD_OR:
3349 return SelectAtomic(N,
3350 ARM::ATOMIC_LOAD_OR_I8,
3351 ARM::ATOMIC_LOAD_OR_I16,
3352 ARM::ATOMIC_LOAD_OR_I32,
3353 ARM::ATOMIC_LOAD_OR_I64);
3354 case ISD::ATOMIC_LOAD_XOR:
3355 return SelectAtomic(N,
3356 ARM::ATOMIC_LOAD_XOR_I8,
3357 ARM::ATOMIC_LOAD_XOR_I16,
3358 ARM::ATOMIC_LOAD_XOR_I32,
3359 ARM::ATOMIC_LOAD_XOR_I64);
3360 case ISD::ATOMIC_LOAD_NAND:
3361 return SelectAtomic(N,
3362 ARM::ATOMIC_LOAD_NAND_I8,
3363 ARM::ATOMIC_LOAD_NAND_I16,
3364 ARM::ATOMIC_LOAD_NAND_I32,
3365 ARM::ATOMIC_LOAD_NAND_I64);
3366 case ISD::ATOMIC_LOAD_MIN:
3367 return SelectAtomic(N,
3368 ARM::ATOMIC_LOAD_MIN_I8,
3369 ARM::ATOMIC_LOAD_MIN_I16,
3370 ARM::ATOMIC_LOAD_MIN_I32,
3371 ARM::ATOMIC_LOAD_MIN_I64);
3372 case ISD::ATOMIC_LOAD_MAX:
3373 return SelectAtomic(N,
3374 ARM::ATOMIC_LOAD_MAX_I8,
3375 ARM::ATOMIC_LOAD_MAX_I16,
3376 ARM::ATOMIC_LOAD_MAX_I32,
3377 ARM::ATOMIC_LOAD_MAX_I64);
3378 case ISD::ATOMIC_LOAD_UMIN:
3379 return SelectAtomic(N,
3380 ARM::ATOMIC_LOAD_UMIN_I8,
3381 ARM::ATOMIC_LOAD_UMIN_I16,
3382 ARM::ATOMIC_LOAD_UMIN_I32,
3383 ARM::ATOMIC_LOAD_UMIN_I64);
3384 case ISD::ATOMIC_LOAD_UMAX:
3385 return SelectAtomic(N,
3386 ARM::ATOMIC_LOAD_UMAX_I8,
3387 ARM::ATOMIC_LOAD_UMAX_I16,
3388 ARM::ATOMIC_LOAD_UMAX_I32,
3389 ARM::ATOMIC_LOAD_UMAX_I64);
3390 case ISD::ATOMIC_SWAP:
3391 return SelectAtomic(N,
3392 ARM::ATOMIC_SWAP_I8,
3393 ARM::ATOMIC_SWAP_I16,
3394 ARM::ATOMIC_SWAP_I32,
3395 ARM::ATOMIC_SWAP_I64);
3396 case ISD::ATOMIC_CMP_SWAP:
3397 return SelectAtomic(N,
3398 ARM::ATOMIC_CMP_SWAP_I8,
3399 ARM::ATOMIC_CMP_SWAP_I16,
3400 ARM::ATOMIC_CMP_SWAP_I32,
3401 ARM::ATOMIC_CMP_SWAP_I64);
Evan Chengd85631e2010-05-05 18:28:36 +00003402 }
Evan Chengd5021732008-12-10 21:54:21 +00003403
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003404 return SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003405}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003406
Weiming Zhaoc5987002013-02-14 18:10:21 +00003407SDNode *ARMDAGToDAGISel::SelectInlineAsm(SDNode *N){
3408 std::vector<SDValue> AsmNodeOperands;
3409 unsigned Flag, Kind;
3410 bool Changed = false;
3411 unsigned NumOps = N->getNumOperands();
3412
Weiming Zhaoc5987002013-02-14 18:10:21 +00003413 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
3414 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
3415 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
3416 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003417 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
3418 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
3419 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00003420
Andrew Trickef9de2a2013-05-25 02:42:55 +00003421 SDLoc dl(N);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003422 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1) : SDValue(0,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003423
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003424 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003425 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003426 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00003427 SDValue op = N->getOperand(i);
3428 AsmNodeOperands.push_back(op);
3429
3430 if (i < InlineAsm::Op_FirstOperand)
3431 continue;
3432
3433 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
3434 Flag = C->getZExtValue();
3435 Kind = InlineAsm::getKind(Flag);
3436 }
3437 else
3438 continue;
3439
Joey Gouly392cdad2013-07-08 19:52:51 +00003440 // Immediate operands to inline asm in the SelectionDAG are modeled with
3441 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
3442 // the second is a constant with the value of the immediate. If we get here
3443 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00003444 if (Kind == InlineAsm::Kind_Imm) {
3445 SDValue op = N->getOperand(++i);
3446 AsmNodeOperands.push_back(op);
3447 continue;
3448 }
3449
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003450 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
3451 if (NumRegs)
3452 OpChanged.push_back(false);
3453
3454 unsigned DefIdx = 0;
3455 bool IsTiedToChangedOp = false;
3456 // If it's a use that is tied with a previous def, it has no
3457 // reg class constraint.
3458 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
3459 IsTiedToChangedOp = OpChanged[DefIdx];
3460
Weiming Zhaoc5987002013-02-14 18:10:21 +00003461 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
3462 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
3463 continue;
3464
Weiming Zhaoc5987002013-02-14 18:10:21 +00003465 unsigned RC;
3466 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003467 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
3468 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00003469 continue;
3470
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003471 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00003472 SDValue V0 = N->getOperand(i+1);
3473 SDValue V1 = N->getOperand(i+2);
3474 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
3475 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
3476 SDValue PairedReg;
3477 MachineRegisterInfo &MRI = MF->getRegInfo();
3478
3479 if (Kind == InlineAsm::Kind_RegDef ||
3480 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
3481 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
3482 // the original GPRs.
3483
3484 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3485 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3486 SDValue Chain = SDValue(N,0);
3487
3488 SDNode *GU = N->getGluedUser();
3489 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
3490 Chain.getValue(1));
3491
3492 // Extract values from a GPRPair reg and copy to the original GPR reg.
3493 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
3494 RegCopy);
3495 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
3496 RegCopy);
3497 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
3498 RegCopy.getValue(1));
3499 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
3500
3501 // Update the original glue user.
3502 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
3503 Ops.push_back(T1.getValue(1));
3504 CurDAG->UpdateNodeOperands(GU, &Ops[0], Ops.size());
3505 GU = T1.getNode();
3506 }
3507 else {
3508 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
3509 // GPRPair and then pass the GPRPair to the inline asm.
3510 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
3511
3512 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
3513 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
3514 Chain.getValue(1));
3515 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
3516 T0.getValue(1));
3517 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
3518
3519 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
3520 // i32 VRs of inline asm with it.
3521 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3522 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3523 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
3524
3525 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
3526 Glue = Chain.getValue(1);
3527 }
3528
3529 Changed = true;
3530
3531 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003532 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003533 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00003534 if (IsTiedToChangedOp)
3535 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
3536 else
3537 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003538 // Replace the current flag.
3539 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
3540 Flag, MVT::i32);
3541 // Add the new register node and skip the original two GPRs.
3542 AsmNodeOperands.push_back(PairedReg);
3543 // Skip the next two GPRs.
3544 i += 2;
3545 }
3546 }
3547
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003548 if (Glue.getNode())
3549 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003550 if (!Changed)
3551 return NULL;
3552
Andrew Trickef9de2a2013-05-25 02:42:55 +00003553 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Weiming Zhaoc5987002013-02-14 18:10:21 +00003554 CurDAG->getVTList(MVT::Other, MVT::Glue), &AsmNodeOperands[0],
3555 AsmNodeOperands.size());
3556 New->setNodeId(-1);
3557 return New.getNode();
3558}
3559
3560
Bob Wilsona2c462b2009-05-19 05:53:42 +00003561bool ARMDAGToDAGISel::
3562SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
3563 std::vector<SDValue> &OutOps) {
3564 assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
Bob Wilson3b515602009-10-13 20:50:28 +00003565 // Require the address to be in a register. That is safe for all ARM
3566 // variants and it is hard to do anything much smarter without knowing
3567 // how the operand is used.
3568 OutOps.push_back(Op);
Bob Wilsona2c462b2009-05-19 05:53:42 +00003569 return false;
3570}
3571
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003572/// createARMISelDag - This pass converts a legalized DAG into a
3573/// ARM-specific DAG, ready for instruction scheduling.
3574///
Bob Wilson2dd957f2009-09-28 14:30:20 +00003575FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
3576 CodeGenOpt::Level OptLevel) {
3577 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003578}