blob: b4a438b05389d84f5ff8b376eef8566b6a9e7bc2 [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
14#include "ARM.h"
Evan Cheng62c7b5b2010-12-05 22:04:16 +000015#include "ARMBaseInstrInfo.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000016#include "ARMTargetMachine.h"
Evan Chenga20cde32011-07-20 23:34:39 +000017#include "MCTargetDesc/ARMAddressingModes.h"
Luke Cheeseman85fd06d2015-06-01 12:02:47 +000018#include "llvm/ADT/StringSwitch.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
Chandler Carruth84e68b22014-04-22 02:41:26 +000040#define DEBUG_TYPE "arm-isel"
41
Evan Cheng59069ec2010-07-30 23:33:54 +000042static cl::opt<bool>
43DisableShifterOp("disable-shifter-op", cl::Hidden,
44 cl::desc("Disable isel of shifter-op"),
45 cl::init(false));
46
Evan Cheng62c7b5b2010-12-05 22:04:16 +000047static cl::opt<bool>
48CheckVMLxHazard("check-vmlx-hazard", cl::Hidden,
49 cl::desc("Check fp vmla / vmls hazard at isel time"),
Bob Wilson0858c3a2011-04-19 18:11:57 +000050 cl::init(true));
Evan Cheng62c7b5b2010-12-05 22:04:16 +000051
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000052//===--------------------------------------------------------------------===//
53/// ARMDAGToDAGISel - ARM specific code to select ARM machine
54/// instructions for SelectionDAG operations.
55///
56namespace {
Jim Grosbach08605202010-09-29 19:03:54 +000057
58enum AddrMode2Type {
59 AM2_BASE, // Simple AM2 (+-imm12)
60 AM2_SHOP // Shifter-op AM2
61};
62
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000063class ARMDAGToDAGISel : public SelectionDAGISel {
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:
Eric Christopher2f991c92014-07-03 22:24:49 +000069 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, CodeGenOpt::Level OptLevel)
70 : SelectionDAGISel(tm, OptLevel) {}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000071
Eric Christopher0e6e7cf2014-05-22 02:00:27 +000072 bool runOnMachineFunction(MachineFunction &MF) override {
73 // Reset the subtarget each time through.
Eric Christopher22b2ad22015-02-20 08:24:37 +000074 Subtarget = &MF.getSubtarget<ARMSubtarget>();
Eric Christopher0e6e7cf2014-05-22 02:00:27 +000075 SelectionDAGISel::runOnMachineFunction(MF);
76 return true;
77 }
78
Craig Topper6bc27bf2014-03-10 02:09:33 +000079 const char *getPassName() const override {
Evan Cheng10043e22007-01-19 07:51:42 +000080 return "ARM Instruction Selection";
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000081 }
82
Craig Topper6bc27bf2014-03-10 02:09:33 +000083 void PreprocessISelDAG() override;
Evan Chengeae6d2c2012-12-19 20:16:09 +000084
Bob Wilson4facd962009-10-08 18:51:31 +000085 /// getI32Imm - Return a target constant of type i32 with the specified
86 /// value.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +000087 inline SDValue getI32Imm(unsigned Imm, SDLoc dl) {
88 return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000089 }
90
Craig Topper6bc27bf2014-03-10 02:09:33 +000091 SDNode *Select(SDNode *N) override;
Evan Cheng5e73ff22010-02-15 19:41:07 +000092
Evan Cheng62c7b5b2010-12-05 22:04:16 +000093
94 bool hasNoVMLxHazardUse(SDNode *N) const;
Evan Cheng59bbc542010-10-27 23:41:30 +000095 bool isShifterOpProfitable(const SDValue &Shift,
96 ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt);
Owen Andersonb595ed02011-07-21 18:54:16 +000097 bool SelectRegShifterOperand(SDValue N, SDValue &A,
98 SDValue &B, SDValue &C,
99 bool CheckProfitability = true);
100 bool SelectImmShifterOperand(SDValue N, SDValue &A,
Owen Anderson04912702011-07-21 23:38:37 +0000101 SDValue &B, bool CheckProfitability = true);
102 bool SelectShiftRegShifterOperand(SDValue N, SDValue &A,
Owen Anderson6d557452011-03-18 19:46:58 +0000103 SDValue &B, SDValue &C) {
104 // Don't apply the profitability check
Owen Anderson04912702011-07-21 23:38:37 +0000105 return SelectRegShifterOperand(N, A, B, C, false);
106 }
107 bool SelectShiftImmShifterOperand(SDValue N, SDValue &A,
108 SDValue &B) {
109 // Don't apply the profitability check
110 return SelectImmShifterOperand(N, A, B, false);
Owen Anderson6d557452011-03-18 19:46:58 +0000111 }
112
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000113 bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
114 bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);
115
Jim Grosbach08605202010-09-29 19:03:54 +0000116 AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base,
117 SDValue &Offset, SDValue &Opc);
118 bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset,
119 SDValue &Opc) {
120 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE;
121 }
122
123 bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset,
124 SDValue &Opc) {
125 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP;
126 }
127
128 bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset,
129 SDValue &Opc) {
130 SelectAddrMode2Worker(N, Base, Offset, Opc);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000131// return SelectAddrMode2ShOp(N, Base, Offset, Opc);
Jim Grosbach08605202010-09-29 19:03:54 +0000132 // This always matches one way or another.
133 return true;
134 }
135
Tim Northover42180442013-08-22 09:57:11 +0000136 bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) {
137 const ConstantSDNode *CN = cast<ConstantSDNode>(N);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000138 Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32);
Tim Northover42180442013-08-22 09:57:11 +0000139 Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32);
140 return true;
141 }
142
Owen Anderson2aedba62011-07-26 20:54:26 +0000143 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
144 SDValue &Offset, SDValue &Opc);
145 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000146 SDValue &Offset, SDValue &Opc);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000147 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
148 SDValue &Offset, SDValue &Opc);
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000149 bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000150 bool SelectAddrMode3(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000151 SDValue &Offset, SDValue &Opc);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000152 bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000153 SDValue &Offset, SDValue &Opc);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000154 bool SelectAddrMode5(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000155 SDValue &Offset);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000156 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
Bob Wilsone3ecd5f2011-02-25 06:42:42 +0000157 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000158
Evan Chengdfce83c2011-01-17 08:03:18 +0000159 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
Evan Cheng10043e22007-01-19 07:51:42 +0000160
Bill Wendling092a7bd2010-12-14 03:36:38 +0000161 // Thumb Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000162 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
Bill Wendling092a7bd2010-12-14 03:36:38 +0000163 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
164 SDValue &OffImm);
165 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
166 SDValue &OffImm);
167 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
168 SDValue &OffImm);
169 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
170 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000171 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +0000172
Bill Wendling092a7bd2010-12-14 03:36:38 +0000173 // Thumb 2 Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000174 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
175 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000176 SDValue &OffImm);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000177 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +0000178 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000179 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000180 SDValue &OffReg, SDValue &ShImm);
Tim Northovera7ecd242013-07-16 09:46:55 +0000181 bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Chengb23b50d2009-06-29 07:51:04 +0000182
Evan Cheng0fc80842010-11-12 22:42:47 +0000183 inline bool is_so_imm(unsigned Imm) const {
184 return ARM_AM::getSOImmVal(Imm) != -1;
185 }
186
187 inline bool is_so_imm_not(unsigned Imm) const {
188 return ARM_AM::getSOImmVal(~Imm) != -1;
189 }
190
191 inline bool is_t2_so_imm(unsigned Imm) const {
192 return ARM_AM::getT2SOImmVal(Imm) != -1;
193 }
194
195 inline bool is_t2_so_imm_not(unsigned Imm) const {
196 return ARM_AM::getT2SOImmVal(~Imm) != -1;
197 }
198
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000199 // Include the pieces autogenerated from the target description.
200#include "ARMGenDAGISel.inc"
Bob Wilsona2c462b2009-05-19 05:53:42 +0000201
202private:
Evan Cheng84c6cda2009-07-02 07:28:31 +0000203 /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
204 /// ARM.
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000205 SDNode *SelectARMIndexedLoad(SDNode *N);
206 SDNode *SelectT2IndexedLoad(SDNode *N);
Evan Cheng84c6cda2009-07-02 07:28:31 +0000207
Bob Wilson340861d2010-03-23 05:25:43 +0000208 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
209 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson12b47992009-10-14 17:28:52 +0000210 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson340861d2010-03-23 05:25:43 +0000211 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson06fce872011-02-07 17:43:21 +0000212 SDNode *SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000213 const uint16_t *DOpcodes,
214 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilson12b47992009-10-14 17:28:52 +0000215
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000216 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000217 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000218 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000219 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson06fce872011-02-07 17:43:21 +0000220 SDNode *SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000221 const uint16_t *DOpcodes,
222 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000223
Bob Wilson93117bc2009-10-14 16:46:45 +0000224 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilson4145e3a2009-10-14 16:19:03 +0000225 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsond5c57a52010-09-13 23:01:35 +0000226 /// load/store of D registers and Q registers.
Bob Wilson06fce872011-02-07 17:43:21 +0000227 SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad,
228 bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000229 const uint16_t *DOpcodes, const uint16_t *QOpcodes);
Bob Wilson4145e3a2009-10-14 16:19:03 +0000230
Bob Wilson2d790df2010-11-28 06:51:26 +0000231 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
232 /// should be 2, 3 or 4. The opcode array specifies the instructions used
233 /// for loading D registers. (Q registers are not supported.)
Bob Wilson06fce872011-02-07 17:43:21 +0000234 SDNode *SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000235 const uint16_t *Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +0000236
Bob Wilson5bc8a792010-07-07 00:08:54 +0000237 /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2,
238 /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be
239 /// generated to force the table registers to be consecutive.
240 SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc);
Bob Wilson3ed511b2010-07-06 23:36:25 +0000241
Sandeep Patel7460e082009-10-13 20:25:58 +0000242 /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
Jim Grosbach825cb292010-04-22 23:24:18 +0000243 SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000244
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000245 // Select special operations if node forms integer ABS pattern
246 SDNode *SelectABSOp(SDNode *N);
247
Luke Cheeseman85fd06d2015-06-01 12:02:47 +0000248 SDNode *SelectReadRegister(SDNode *N);
249 SDNode *SelectWriteRegister(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
Sam Parker2d5126c2016-04-08 16:02:53 +0000255 SDNode *SelectSMLAWSMULW(SDNode *N);
256
Evan Chengd9c55362009-07-02 01:23:32 +0000257 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
258 /// inline asm expressions.
Daniel Sanders60f1db02015-03-13 12:45:09 +0000259 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Craig Topper6bc27bf2014-03-10 02:09:33 +0000260 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.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000274 SDValue GetVLDSTAlign(SDValue Align, SDLoc dl, unsigned NumVecs,
275 bool is64BitVector);
John Brawn056e6782015-09-14 15:19:41 +0000276
277 /// Returns the number of instructions required to materialize the given
278 /// constant in a register, or 3 if a literal pool load is needed.
279 unsigned ConstantMaterializationCost(unsigned Val) const;
280
281 /// Checks if N is a multiplication by a constant where we can extract out a
282 /// power of two from the constant so that it can be used in a shift, but only
283 /// if it simplifies the materialization of the constant. Returns true if it
284 /// is, and assigns to PowerOfTwo the power of two that should be extracted
285 /// out and to NewMulConst the new constant to be multiplied by.
286 bool canExtractShiftFromMul(const SDValue &N, unsigned MaxShift,
287 unsigned &PowerOfTwo, SDValue &NewMulConst) const;
288
289 /// Replace N with M in CurDAG, in a way that also ensures that M gets
290 /// selected when N would have been selected.
291 void replaceDAGValue(const SDValue &N, SDValue M);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000292};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000293}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000294
Sandeep Patel423e42b2009-10-13 18:59:48 +0000295/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
296/// operand. If so Imm will receive the 32-bit value.
297static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
298 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
299 Imm = cast<ConstantSDNode>(N)->getZExtValue();
300 return true;
301 }
302 return false;
303}
304
305// isInt32Immediate - This method tests to see if a constant operand.
306// If so Imm will receive the 32 bit value.
307static bool isInt32Immediate(SDValue N, unsigned &Imm) {
308 return isInt32Immediate(N.getNode(), Imm);
309}
310
311// isOpcWithIntImmediate - This method tests to see if the node is a specific
312// opcode and that it has a immediate integer right operand.
313// If so Imm will receive the 32 bit value.
314static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
315 return N->getOpcode() == Opc &&
316 isInt32Immediate(N->getOperand(1).getNode(), Imm);
317}
318
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000319/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000320/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000321///
322/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000323static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000324 int RangeMin, int RangeMax,
325 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000326 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000327
328 // Check that this is a constant.
329 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
330 if (!C)
331 return false;
332
333 ScaledConstant = (int) C->getZExtValue();
334 if ((ScaledConstant % Scale) != 0)
335 return false;
336
337 ScaledConstant /= Scale;
338 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
339}
340
Evan Chengeae6d2c2012-12-19 20:16:09 +0000341void ARMDAGToDAGISel::PreprocessISelDAG() {
342 if (!Subtarget->hasV6T2Ops())
343 return;
344
345 bool isThumb2 = Subtarget->isThumb();
346 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
347 E = CurDAG->allnodes_end(); I != E; ) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000348 SDNode *N = &*I++; // Preincrement iterator to avoid invalidation issues.
Evan Chengeae6d2c2012-12-19 20:16:09 +0000349
350 if (N->getOpcode() != ISD::ADD)
351 continue;
352
353 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
354 // leading zeros, followed by consecutive set bits, followed by 1 or 2
355 // trailing zeros, e.g. 1020.
356 // Transform the expression to
357 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
358 // of trailing zeros of c2. The left shift would be folded as an shifter
359 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
360 // node (UBFX).
361
362 SDValue N0 = N->getOperand(0);
363 SDValue N1 = N->getOperand(1);
364 unsigned And_imm = 0;
365 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
366 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
367 std::swap(N0, N1);
368 }
369 if (!And_imm)
370 continue;
371
372 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000373 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000374 if (TZ != 1 && TZ != 2)
375 // Be conservative here. Shifter operands aren't always free. e.g. On
376 // Swift, left shifter operand of 1 / 2 for free but others are not.
377 // e.g.
378 // ubfx r3, r1, #16, #8
379 // ldr.w r3, [r0, r3, lsl #2]
380 // vs.
381 // mov.w r9, #1020
382 // and.w r2, r9, r1, lsr #14
383 // ldr r2, [r0, r2]
384 continue;
385 And_imm >>= TZ;
386 if (And_imm & (And_imm + 1))
387 continue;
388
389 // Look for (and (srl X, c1), c2).
390 SDValue Srl = N1.getOperand(0);
391 unsigned Srl_imm = 0;
392 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
393 (Srl_imm <= 2))
394 continue;
395
396 // Make sure first operand is not a shifter operand which would prevent
397 // folding of the left shift.
398 SDValue CPTmp0;
399 SDValue CPTmp1;
400 SDValue CPTmp2;
401 if (isThumb2) {
John Brawnd8b405a2015-09-07 11:45:18 +0000402 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
Evan Chengeae6d2c2012-12-19 20:16:09 +0000403 continue;
404 } else {
405 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
406 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
407 continue;
408 }
409
410 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000411 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000412 Srl.getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000413 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl),
414 MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000415 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000416 Srl,
417 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000418 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000419 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32));
Evan Chengeae6d2c2012-12-19 20:16:09 +0000420 CurDAG->UpdateNodeOperands(N, N0, N1);
Jim Grosbach1a597112014-04-03 23:43:18 +0000421 }
Evan Chengeae6d2c2012-12-19 20:16:09 +0000422}
423
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000424/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
425/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
426/// least on current ARM implementations) which should be avoidded.
427bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
428 if (OptLevel == CodeGenOpt::None)
429 return true;
430
431 if (!CheckVMLxHazard)
432 return true;
Bob Wilsone8a549c2012-09-29 21:43:49 +0000433
Tim Northover0feb91e2014-04-01 14:10:07 +0000434 if (!Subtarget->isCortexA7() && !Subtarget->isCortexA8() &&
435 !Subtarget->isCortexA9() && !Subtarget->isSwift())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000436 return true;
437
438 if (!N->hasOneUse())
439 return false;
440
441 SDNode *Use = *N->use_begin();
442 if (Use->getOpcode() == ISD::CopyToReg)
443 return true;
444 if (Use->isMachineOpcode()) {
Eric Christopher2f991c92014-07-03 22:24:49 +0000445 const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>(
Eric Christopherfc6de422014-08-05 02:39:49 +0000446 CurDAG->getSubtarget().getInstrInfo());
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000447
Evan Cheng6cc775f2011-06-28 19:10:37 +0000448 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
449 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000450 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000451 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000452 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
453 return true;
454 // vmlx feeding into another vmlx. We actually want to unfold
455 // the use later in the MLxExpansion pass. e.g.
456 // vmla
457 // vmla (stall 8 cycles)
458 //
459 // vmul (5 cycles)
460 // vadd (5 cycles)
461 // vmla
462 // This adds up to about 18 - 19 cycles.
463 //
464 // vmla
465 // vmul (stall 4 cycles)
466 // vadd adds up to about 14 cycles.
467 return TII->isFpMLxInstruction(Opcode);
468 }
469
470 return false;
471}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000472
Evan Cheng59bbc542010-10-27 23:41:30 +0000473bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
474 ARM_AM::ShiftOpc ShOpcVal,
475 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000476 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000477 return true;
478 if (Shift.hasOneUse())
479 return true;
480 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000481 return ShOpcVal == ARM_AM::lsl &&
482 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000483}
484
John Brawn056e6782015-09-14 15:19:41 +0000485unsigned ARMDAGToDAGISel::ConstantMaterializationCost(unsigned Val) const {
486 if (Subtarget->isThumb()) {
487 if (Val <= 255) return 1; // MOV
488 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
489 if (~Val <= 255) return 2; // MOV + MVN
490 if (ARM_AM::isThumbImmShiftedVal(Val)) return 2; // MOV + LSL
491 } else {
492 if (ARM_AM::getSOImmVal(Val) != -1) return 1; // MOV
493 if (ARM_AM::getSOImmVal(~Val) != -1) return 1; // MVN
494 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
495 if (ARM_AM::isSOImmTwoPartVal(Val)) return 2; // two instrs
496 }
497 if (Subtarget->useMovt(*MF)) return 2; // MOVW + MOVT
498 return 3; // Literal pool load
499}
500
501bool ARMDAGToDAGISel::canExtractShiftFromMul(const SDValue &N,
502 unsigned MaxShift,
503 unsigned &PowerOfTwo,
504 SDValue &NewMulConst) const {
505 assert(N.getOpcode() == ISD::MUL);
506 assert(MaxShift > 0);
507
508 // If the multiply is used in more than one place then changing the constant
509 // will make other uses incorrect, so don't.
510 if (!N.hasOneUse()) return false;
511 // Check if the multiply is by a constant
512 ConstantSDNode *MulConst = dyn_cast<ConstantSDNode>(N.getOperand(1));
513 if (!MulConst) return false;
514 // If the constant is used in more than one place then modifying it will mean
515 // we need to materialize two constants instead of one, which is a bad idea.
516 if (!MulConst->hasOneUse()) return false;
517 unsigned MulConstVal = MulConst->getZExtValue();
518 if (MulConstVal == 0) return false;
519
520 // Find the largest power of 2 that MulConstVal is a multiple of
521 PowerOfTwo = MaxShift;
522 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
523 --PowerOfTwo;
524 if (PowerOfTwo == 0) return false;
525 }
526
527 // Only optimise if the new cost is better
528 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
529 NewMulConst = CurDAG->getConstant(NewMulConstVal, SDLoc(N), MVT::i32);
530 unsigned OldCost = ConstantMaterializationCost(MulConstVal);
531 unsigned NewCost = ConstantMaterializationCost(NewMulConstVal);
532 return NewCost < OldCost;
533}
534
535void ARMDAGToDAGISel::replaceDAGValue(const SDValue &N, SDValue M) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000536 CurDAG->RepositionNode(N.getNode()->getIterator(), M.getNode());
John Brawn056e6782015-09-14 15:19:41 +0000537 CurDAG->ReplaceAllUsesWith(N, M);
538}
539
Owen Andersonb595ed02011-07-21 18:54:16 +0000540bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000541 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000542 SDValue &Opc,
543 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000544 if (DisableShifterOp)
545 return false;
546
John Brawn056e6782015-09-14 15:19:41 +0000547 // If N is a multiply-by-constant and it's profitable to extract a shift and
548 // use it in a shifted operand do so.
549 if (N.getOpcode() == ISD::MUL) {
550 unsigned PowerOfTwo = 0;
551 SDValue NewMulConst;
552 if (canExtractShiftFromMul(N, 31, PowerOfTwo, NewMulConst)) {
Tim Northoverd91d6352015-12-09 15:54:50 +0000553 BaseReg = SDValue(Select(CurDAG->getNode(ISD::MUL, SDLoc(N), MVT::i32,
554 N.getOperand(0), NewMulConst)
555 .getNode()),
556 0);
John Brawn056e6782015-09-14 15:19:41 +0000557 replaceDAGValue(N.getOperand(1), NewMulConst);
John Brawn056e6782015-09-14 15:19:41 +0000558 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ARM_AM::lsl,
559 PowerOfTwo),
560 SDLoc(N), MVT::i32);
561 return true;
562 }
563 }
564
Evan Chenga20cde32011-07-20 23:34:39 +0000565 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000566
567 // Don't match base register only case. That is matched to a separate
568 // lower complexity pattern with explicit register operand.
569 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000570
Evan Chengb23b50d2009-06-29 07:51:04 +0000571 BaseReg = N.getOperand(0);
572 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000573 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
574 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000575 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000576 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000577 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000578 return true;
579}
580
Owen Andersonb595ed02011-07-21 18:54:16 +0000581bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
582 SDValue &BaseReg,
583 SDValue &ShReg,
584 SDValue &Opc,
585 bool CheckProfitability) {
586 if (DisableShifterOp)
587 return false;
588
589 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
590
591 // Don't match base register only case. That is matched to a separate
592 // lower complexity pattern with explicit register operand.
593 if (ShOpcVal == ARM_AM::no_shift) return false;
594
595 BaseReg = N.getOperand(0);
596 unsigned ShImmVal = 0;
597 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
598 if (RHS) return false;
599
600 ShReg = N.getOperand(1);
601 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
602 return false;
603 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000604 SDLoc(N), MVT::i32);
Owen Andersonb595ed02011-07-21 18:54:16 +0000605 return true;
606}
607
608
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000609bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
610 SDValue &Base,
611 SDValue &OffImm) {
612 // Match simple R + imm12 operands.
613
614 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000615 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
616 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000617 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000618 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000619 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000620 Base = CurDAG->getTargetFrameIndex(
621 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000622 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000623 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000624 }
Owen Anderson6d557452011-03-18 19:46:58 +0000625
Chris Lattner46c01a32011-02-13 22:25:43 +0000626 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000627 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000628 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000629 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000630 Base = N.getOperand(0);
631 } else
632 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000633 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000634 return true;
635 }
636
637 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Renato Golin63e27982014-09-09 09:57:59 +0000638 int RHSC = (int)RHS->getSExtValue();
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000639 if (N.getOpcode() == ISD::SUB)
640 RHSC = -RHSC;
641
Renato Golin63e27982014-09-09 09:57:59 +0000642 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000643 Base = N.getOperand(0);
644 if (Base.getOpcode() == ISD::FrameIndex) {
645 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000646 Base = CurDAG->getTargetFrameIndex(
647 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000648 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000649 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000650 return true;
651 }
652 }
653
654 // Base only.
655 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000656 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000657 return true;
658}
659
660
661
662bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
663 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000664 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000665 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000666 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
667 // X * [3,5,9] -> X + X * [2,4,8] etc.
668 int RHSC = (int)RHS->getZExtValue();
669 if (RHSC & 1) {
670 RHSC = RHSC & ~1;
671 ARM_AM::AddrOpc AddSub = ARM_AM::add;
672 if (RHSC < 0) {
673 AddSub = ARM_AM::sub;
674 RHSC = - RHSC;
675 }
676 if (isPowerOf2_32(RHSC)) {
677 unsigned ShAmt = Log2_32(RHSC);
678 Base = Offset = N.getOperand(0);
679 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
680 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000681 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000682 return true;
683 }
684 }
685 }
686 }
687
Chris Lattner46c01a32011-02-13 22:25:43 +0000688 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
689 // ISD::OR that is equivalent to an ISD::ADD.
690 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000691 return false;
692
693 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000694 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000695 int RHSC;
696 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
697 -0x1000+1, 0x1000, RHSC)) // 12 bits.
698 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000699 }
700
701 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000702 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000703 ARM_AM::ShiftOpc ShOpcVal =
704 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000705 unsigned ShAmt = 0;
706
707 Base = N.getOperand(0);
708 Offset = N.getOperand(1);
709
710 if (ShOpcVal != ARM_AM::no_shift) {
711 // Check to see if the RHS of the shift is a constant, if not, we can't fold
712 // it.
713 if (ConstantSDNode *Sh =
714 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
715 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000716 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
717 Offset = N.getOperand(1).getOperand(0);
718 else {
719 ShAmt = 0;
720 ShOpcVal = ARM_AM::no_shift;
721 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000722 } else {
723 ShOpcVal = ARM_AM::no_shift;
724 }
725 }
726
727 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000728 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000729 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
730 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000731 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000732 if (ShOpcVal != ARM_AM::no_shift) {
733 // Check to see if the RHS of the shift is a constant, if not, we can't
734 // fold it.
735 if (ConstantSDNode *Sh =
736 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
737 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000738 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000739 Offset = N.getOperand(0).getOperand(0);
740 Base = N.getOperand(1);
741 } else {
742 ShAmt = 0;
743 ShOpcVal = ARM_AM::no_shift;
744 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000745 } else {
746 ShOpcVal = ARM_AM::no_shift;
747 }
748 }
749 }
750
John Brawn056e6782015-09-14 15:19:41 +0000751 // If Offset is a multiply-by-constant and it's profitable to extract a shift
752 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +0000753 if (Offset.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +0000754 unsigned PowerOfTwo = 0;
755 SDValue NewMulConst;
756 if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) {
757 replaceDAGValue(Offset.getOperand(1), NewMulConst);
758 ShAmt = PowerOfTwo;
759 ShOpcVal = ARM_AM::lsl;
760 }
761 }
762
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000763 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000764 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000765 return true;
766}
767
768
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000769//-----
770
Jim Grosbach08605202010-09-29 19:03:54 +0000771AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
772 SDValue &Base,
773 SDValue &Offset,
774 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000775 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000776 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000777 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
778 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmaneffb8942008-09-12 16:56:44 +0000779 int RHSC = (int)RHS->getZExtValue();
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000780 if (RHSC & 1) {
781 RHSC = RHSC & ~1;
782 ARM_AM::AddrOpc AddSub = ARM_AM::add;
783 if (RHSC < 0) {
784 AddSub = ARM_AM::sub;
785 RHSC = - RHSC;
786 }
787 if (isPowerOf2_32(RHSC)) {
788 unsigned ShAmt = Log2_32(RHSC);
789 Base = Offset = N.getOperand(0);
790 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
791 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000792 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000793 return AM2_SHOP;
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000794 }
795 }
796 }
797 }
798
Chris Lattner46c01a32011-02-13 22:25:43 +0000799 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
800 // ISD::OR that is equivalent to an ADD.
801 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000802 Base = N;
803 if (N.getOpcode() == ISD::FrameIndex) {
804 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000805 Base = CurDAG->getTargetFrameIndex(
806 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +0000807 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000808 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000809 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000810 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000811 Base = N.getOperand(0);
812 }
Owen Anderson9f944592009-08-11 20:47:22 +0000813 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000814 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
815 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000816 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000817 return AM2_BASE;
Rafael Espindola708cb602006-11-08 17:07:32 +0000818 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000819
Evan Cheng10043e22007-01-19 07:51:42 +0000820 // Match simple R +/- imm12 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +0000821 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000822 int RHSC;
823 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
824 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
825 Base = N.getOperand(0);
826 if (Base.getOpcode() == ISD::FrameIndex) {
827 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000828 Base = CurDAG->getTargetFrameIndex(
829 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Rafael Espindola708cb602006-11-08 17:07:32 +0000830 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000831 Offset = CurDAG->getRegister(0, MVT::i32);
832
833 ARM_AM::AddrOpc AddSub = ARM_AM::add;
834 if (RHSC < 0) {
835 AddSub = ARM_AM::sub;
836 RHSC = - RHSC;
837 }
838 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
839 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000840 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000841 return AM2_BASE;
Evan Cheng10043e22007-01-19 07:51:42 +0000842 }
Jim Grosbachc7b10f32010-09-29 17:32:29 +0000843 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000844
Bob Wilsone8a549c2012-09-29 21:43:49 +0000845 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000846 // Compute R +/- (R << N) and reuse it.
847 Base = N;
848 Offset = CurDAG->getRegister(0, MVT::i32);
849 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
850 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000851 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000852 return AM2_BASE;
853 }
854
Johnny Chenb678a562009-10-27 17:25:15 +0000855 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000856 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chenga20cde32011-07-20 23:34:39 +0000857 ARM_AM::ShiftOpc ShOpcVal =
858 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000859 unsigned ShAmt = 0;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000860
Evan Cheng10043e22007-01-19 07:51:42 +0000861 Base = N.getOperand(0);
862 Offset = N.getOperand(1);
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000863
Evan Cheng10043e22007-01-19 07:51:42 +0000864 if (ShOpcVal != ARM_AM::no_shift) {
865 // Check to see if the RHS of the shift is a constant, if not, we can't fold
866 // it.
867 if (ConstantSDNode *Sh =
868 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000869 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000870 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
871 Offset = N.getOperand(1).getOperand(0);
872 else {
873 ShAmt = 0;
874 ShOpcVal = ARM_AM::no_shift;
875 }
Evan Cheng10043e22007-01-19 07:51:42 +0000876 } else {
877 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola708cb602006-11-08 17:07:32 +0000878 }
879 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000880
Evan Cheng10043e22007-01-19 07:51:42 +0000881 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000882 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000883 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
884 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000885 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000886 if (ShOpcVal != ARM_AM::no_shift) {
887 // Check to see if the RHS of the shift is a constant, if not, we can't
888 // fold it.
889 if (ConstantSDNode *Sh =
890 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000891 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000892 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000893 Offset = N.getOperand(0).getOperand(0);
894 Base = N.getOperand(1);
895 } else {
896 ShAmt = 0;
897 ShOpcVal = ARM_AM::no_shift;
898 }
Evan Cheng10043e22007-01-19 07:51:42 +0000899 } else {
900 ShOpcVal = ARM_AM::no_shift;
901 }
902 }
903 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000904
Evan Cheng10043e22007-01-19 07:51:42 +0000905 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000906 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000907 return AM2_SHOP;
Rafael Espindola708cb602006-11-08 17:07:32 +0000908}
909
Owen Anderson2aedba62011-07-26 20:54:26 +0000910bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000911 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000912 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000913 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
914 ? cast<LoadSDNode>(Op)->getAddressingMode()
915 : cast<StoreSDNode>(Op)->getAddressingMode();
916 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
917 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000918 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000919 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
920 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000921
922 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000923 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000924 unsigned ShAmt = 0;
925 if (ShOpcVal != ARM_AM::no_shift) {
926 // Check to see if the RHS of the shift is a constant, if not, we can't fold
927 // it.
928 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000929 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000930 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
931 Offset = N.getOperand(0);
932 else {
933 ShAmt = 0;
934 ShOpcVal = ARM_AM::no_shift;
935 }
Evan Cheng10043e22007-01-19 07:51:42 +0000936 } else {
937 ShOpcVal = ARM_AM::no_shift;
938 }
939 }
940
941 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000942 SDLoc(N), MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000943 return true;
944}
945
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000946bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
947 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000948 unsigned Opcode = Op->getOpcode();
949 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
950 ? cast<LoadSDNode>(Op)->getAddressingMode()
951 : cast<StoreSDNode>(Op)->getAddressingMode();
952 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
953 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000954 int Val;
955 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000956 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000957 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000958 Opc = CurDAG->getTargetConstant(Val, SDLoc(Op), MVT::i32);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000959 return true;
960 }
961
962 return false;
963}
964
965
Owen Anderson2aedba62011-07-26 20:54:26 +0000966bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
967 SDValue &Offset, SDValue &Opc) {
968 unsigned Opcode = Op->getOpcode();
969 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
970 ? cast<LoadSDNode>(Op)->getAddressingMode()
971 : cast<StoreSDNode>(Op)->getAddressingMode();
972 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
973 ? ARM_AM::add : ARM_AM::sub;
974 int Val;
975 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
976 Offset = CurDAG->getRegister(0, MVT::i32);
977 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
978 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000979 SDLoc(Op), MVT::i32);
Owen Anderson2aedba62011-07-26 20:54:26 +0000980 return true;
981 }
982
983 return false;
984}
985
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000986bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
987 Base = N;
988 return true;
989}
Evan Cheng10043e22007-01-19 07:51:42 +0000990
Chris Lattner0e023ea2010-09-21 20:31:19 +0000991bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000992 SDValue &Base, SDValue &Offset,
993 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000994 if (N.getOpcode() == ISD::SUB) {
995 // X - C is canonicalize to X + -C, no need to handle it here.
996 Base = N.getOperand(0);
997 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000998 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0), SDLoc(N),
999 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001000 return true;
1001 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001002
Chris Lattner46c01a32011-02-13 22:25:43 +00001003 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +00001004 Base = N;
1005 if (N.getOpcode() == ISD::FrameIndex) {
1006 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001007 Base = CurDAG->getTargetFrameIndex(
1008 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001009 }
Owen Anderson9f944592009-08-11 20:47:22 +00001010 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001011 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1012 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001013 return true;
1014 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001015
Evan Cheng10043e22007-01-19 07:51:42 +00001016 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001017 int RHSC;
1018 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
1019 -256 + 1, 256, RHSC)) { // 8 bits.
1020 Base = N.getOperand(0);
1021 if (Base.getOpcode() == ISD::FrameIndex) {
1022 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001023 Base = CurDAG->getTargetFrameIndex(
1024 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001025 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001026 Offset = CurDAG->getRegister(0, MVT::i32);
1027
1028 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1029 if (RHSC < 0) {
1030 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001031 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001032 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001033 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC), SDLoc(N),
1034 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001035 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001036 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001037
Evan Cheng10043e22007-01-19 07:51:42 +00001038 Base = N.getOperand(0);
1039 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001040 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1041 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001042 return true;
1043}
1044
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001045bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001046 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001047 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +00001048 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1049 ? cast<LoadSDNode>(Op)->getAddressingMode()
1050 : cast<StoreSDNode>(Op)->getAddressingMode();
1051 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
1052 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001053 int Val;
1054 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
1055 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001056 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), SDLoc(Op),
1057 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001058 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001059 }
1060
1061 Offset = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001062 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), SDLoc(Op),
1063 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001064 return true;
1065}
1066
Jim Grosbachd37f0712010-10-21 19:38:40 +00001067bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001068 SDValue &Base, SDValue &Offset) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001069 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +00001070 Base = N;
1071 if (N.getOpcode() == ISD::FrameIndex) {
1072 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001073 Base = CurDAG->getTargetFrameIndex(
1074 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +00001075 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001076 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001077 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001078 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +00001079 Base = N.getOperand(0);
1080 }
1081 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001082 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001083 return true;
1084 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001085
Evan Cheng10043e22007-01-19 07:51:42 +00001086 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001087 int RHSC;
1088 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
1089 -256 + 1, 256, RHSC)) {
1090 Base = N.getOperand(0);
1091 if (Base.getOpcode() == ISD::FrameIndex) {
1092 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001093 Base = CurDAG->getTargetFrameIndex(
1094 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001095 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001096
1097 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1098 if (RHSC < 0) {
1099 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001100 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001101 }
1102 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001103 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001104 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001105 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001106
Evan Cheng10043e22007-01-19 07:51:42 +00001107 Base = N;
1108 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001109 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001110 return true;
1111}
1112
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001113bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
1114 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +00001115 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001116
1117 unsigned Alignment = 0;
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001118
1119 MemSDNode *MemN = cast<MemSDNode>(Parent);
1120
1121 if (isa<LSBaseSDNode>(MemN) ||
1122 ((MemN->getOpcode() == ARMISD::VST1_UPD ||
1123 MemN->getOpcode() == ARMISD::VLD1_UPD) &&
1124 MemN->getConstantOperandVal(MemN->getNumOperands() - 1) == 1)) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001125 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
1126 // The maximum alignment is equal to the memory size being referenced.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001127 unsigned MMOAlign = MemN->getAlignment();
1128 unsigned MemSize = MemN->getMemoryVT().getSizeInBits() / 8;
1129 if (MMOAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001130 Alignment = MemSize;
1131 } else {
1132 // All other uses of addrmode6 are for intrinsics. For now just record
1133 // the raw alignment value; it will be refined later based on the legal
1134 // alignment operands for the intrinsic.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001135 Alignment = MemN->getAlignment();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001136 }
1137
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001138 Align = CurDAG->getTargetConstant(Alignment, SDLoc(N), MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001139 return true;
1140}
1141
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001142bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1143 SDValue &Offset) {
1144 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1145 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1146 if (AM != ISD::POST_INC)
1147 return false;
1148 Offset = N;
1149 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1150 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1151 Offset = CurDAG->getRegister(0, MVT::i32);
1152 }
1153 return true;
1154}
1155
Chris Lattner0e023ea2010-09-21 20:31:19 +00001156bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001157 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001158 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1159 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001160 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001161 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001162 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001163 return true;
1164 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001165
Evan Cheng10043e22007-01-19 07:51:42 +00001166 return false;
1167}
1168
Bill Wendling092a7bd2010-12-14 03:36:38 +00001169
1170//===----------------------------------------------------------------------===//
1171// Thumb Addressing Modes
1172//===----------------------------------------------------------------------===//
1173
Chris Lattner0e023ea2010-09-21 20:31:19 +00001174bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001175 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001176 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001177 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001178 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001179 return false;
1180
1181 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001182 return true;
1183 }
1184
Evan Cheng10043e22007-01-19 07:51:42 +00001185 Base = N.getOperand(0);
1186 Offset = N.getOperand(1);
1187 return true;
1188}
1189
Evan Cheng139edae2007-01-24 02:21:22 +00001190bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001191ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1192 SDValue &Base, SDValue &OffImm) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001193 if (!CurDAG->isBaseWithConstantOffset(N)) {
John Brawn68acdcb2015-08-13 10:48:22 +00001194 if (N.getOpcode() == ISD::ADD) {
1195 return false; // We want to select register offset instead
1196 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001197 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001198 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001199 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001200 Base = N.getOperand(0);
1201 } else {
1202 Base = N;
1203 }
1204
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001205 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001206 return true;
1207 }
1208
Evan Cheng10043e22007-01-19 07:51:42 +00001209 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001210 int RHSC;
1211 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1212 Base = N.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001213 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001214 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001215 }
1216
John Brawn68acdcb2015-08-13 10:48:22 +00001217 // Offset is too large, so use register offset instead.
1218 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001219}
1220
Bill Wendling092a7bd2010-12-14 03:36:38 +00001221bool
1222ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1223 SDValue &OffImm) {
1224 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001225}
1226
Bill Wendling092a7bd2010-12-14 03:36:38 +00001227bool
1228ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1229 SDValue &OffImm) {
1230 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001231}
1232
Bill Wendling092a7bd2010-12-14 03:36:38 +00001233bool
1234ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1235 SDValue &OffImm) {
1236 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001237}
1238
Chris Lattner0e023ea2010-09-21 20:31:19 +00001239bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1240 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001241 if (N.getOpcode() == ISD::FrameIndex) {
1242 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001243 // Only multiples of 4 are allowed for the offset, so the frame object
1244 // alignment must be at least 4.
1245 MachineFrameInfo *MFI = MF->getFrameInfo();
1246 if (MFI->getObjectAlignment(FI) < 4)
1247 MFI->setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001248 Base = CurDAG->getTargetFrameIndex(
1249 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001250 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001251 return true;
1252 }
Evan Cheng139edae2007-01-24 02:21:22 +00001253
Chris Lattner46c01a32011-02-13 22:25:43 +00001254 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001255 return false;
1256
1257 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001258 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1259 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001260 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001261 int RHSC;
1262 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1263 Base = N.getOperand(0);
1264 if (Base.getOpcode() == ISD::FrameIndex) {
1265 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001266 // For LHS+RHS to result in an offset that's a multiple of 4 the object
1267 // indexed by the LHS must be 4-byte aligned.
1268 MachineFrameInfo *MFI = MF->getFrameInfo();
1269 if (MFI->getObjectAlignment(FI) < 4)
1270 MFI->setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001271 Base = CurDAG->getTargetFrameIndex(
1272 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng139edae2007-01-24 02:21:22 +00001273 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001274 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001275 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001276 }
1277 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001278
Evan Cheng10043e22007-01-19 07:51:42 +00001279 return false;
1280}
1281
Bill Wendling092a7bd2010-12-14 03:36:38 +00001282
1283//===----------------------------------------------------------------------===//
1284// Thumb 2 Addressing Modes
1285//===----------------------------------------------------------------------===//
1286
1287
Chris Lattner0e023ea2010-09-21 20:31:19 +00001288bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001289 SDValue &Base, SDValue &OffImm) {
1290 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001291
Evan Cheng36064672009-08-11 08:52:18 +00001292 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001293 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1294 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001295 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001296 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001297 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001298 Base = CurDAG->getTargetFrameIndex(
1299 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001300 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001301 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001302 }
Owen Anderson6d557452011-03-18 19:46:58 +00001303
Chris Lattner46c01a32011-02-13 22:25:43 +00001304 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001305 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001306 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001307 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng36064672009-08-11 08:52:18 +00001308 Base = N.getOperand(0);
1309 if (Base.getOpcode() == ISD::TargetConstantPool)
1310 return false; // We want to select t2LDRpci instead.
1311 } else
1312 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001313 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001314 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001315 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001316
1317 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001318 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001319 // Let t2LDRi8 handle (R - imm8).
1320 return false;
1321
Evan Chengb23b50d2009-06-29 07:51:04 +00001322 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001323 if (N.getOpcode() == ISD::SUB)
1324 RHSC = -RHSC;
1325
1326 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001327 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001328 if (Base.getOpcode() == ISD::FrameIndex) {
1329 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001330 Base = CurDAG->getTargetFrameIndex(
1331 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin79c079b2009-07-30 18:56:48 +00001332 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001333 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001334 return true;
1335 }
1336 }
1337
Evan Cheng36064672009-08-11 08:52:18 +00001338 // Base only.
1339 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001340 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001341 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001342}
1343
Chris Lattner0e023ea2010-09-21 20:31:19 +00001344bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001345 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001346 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001347 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1348 !CurDAG->isBaseWithConstantOffset(N))
1349 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001350
Chris Lattner46c01a32011-02-13 22:25:43 +00001351 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1352 int RHSC = (int)RHS->getSExtValue();
1353 if (N.getOpcode() == ISD::SUB)
1354 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001355
Chris Lattner46c01a32011-02-13 22:25:43 +00001356 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1357 Base = N.getOperand(0);
1358 if (Base.getOpcode() == ISD::FrameIndex) {
1359 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001360 Base = CurDAG->getTargetFrameIndex(
1361 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Chengb23b50d2009-06-29 07:51:04 +00001362 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001363 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Chris Lattner46c01a32011-02-13 22:25:43 +00001364 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001365 }
1366 }
1367
1368 return false;
1369}
1370
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001371bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001372 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001373 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001374 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1375 ? cast<LoadSDNode>(Op)->getAddressingMode()
1376 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001377 int RHSC;
1378 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1379 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001380 ? CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32)
1381 : CurDAG->getTargetConstant(-RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001382 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001383 }
1384
1385 return false;
1386}
1387
Chris Lattner0e023ea2010-09-21 20:31:19 +00001388bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001389 SDValue &Base,
1390 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001391 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001392 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001393 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001394
Evan Cheng36064672009-08-11 08:52:18 +00001395 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1396 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1397 int RHSC = (int)RHS->getZExtValue();
1398 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1399 return false;
1400 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001401 return false;
1402 }
1403
Evan Chengb23b50d2009-06-29 07:51:04 +00001404 // Look for (R + R) or (R + (R << [1,2,3])).
1405 unsigned ShAmt = 0;
1406 Base = N.getOperand(0);
1407 OffReg = N.getOperand(1);
1408
1409 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001410 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001411 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001412 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001413 if (ShOpcVal == ARM_AM::lsl)
1414 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001415 }
1416
Evan Chengb23b50d2009-06-29 07:51:04 +00001417 if (ShOpcVal == ARM_AM::lsl) {
1418 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1419 // it.
1420 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1421 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001422 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1423 OffReg = OffReg.getOperand(0);
1424 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001425 ShAmt = 0;
Evan Cheng59bbc542010-10-27 23:41:30 +00001426 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001427 }
David Goodwinf3912052009-07-15 15:50:19 +00001428 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001429
John Brawn056e6782015-09-14 15:19:41 +00001430 // If OffReg is a multiply-by-constant and it's profitable to extract a shift
1431 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +00001432 if (OffReg.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +00001433 unsigned PowerOfTwo = 0;
1434 SDValue NewMulConst;
1435 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
1436 replaceDAGValue(OffReg.getOperand(1), NewMulConst);
1437 ShAmt = PowerOfTwo;
1438 }
1439 }
1440
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001441 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001442
1443 return true;
1444}
1445
Tim Northovera7ecd242013-07-16 09:46:55 +00001446bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1447 SDValue &OffImm) {
Alp Tokercb402912014-01-24 17:20:08 +00001448 // This *must* succeed since it's used for the irreplaceable ldrex and strex
Tim Northovera7ecd242013-07-16 09:46:55 +00001449 // instructions.
1450 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001451 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001452
1453 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1454 return true;
1455
1456 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1457 if (!RHS)
1458 return true;
1459
1460 uint32_t RHSC = (int)RHS->getZExtValue();
1461 if (RHSC > 1020 || RHSC % 4 != 0)
1462 return true;
1463
1464 Base = N.getOperand(0);
1465 if (Base.getOpcode() == ISD::FrameIndex) {
1466 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001467 Base = CurDAG->getTargetFrameIndex(
1468 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Tim Northovera7ecd242013-07-16 09:46:55 +00001469 }
1470
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001471 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001472 return true;
1473}
1474
Evan Chengb23b50d2009-06-29 07:51:04 +00001475//===--------------------------------------------------------------------===//
1476
Evan Cheng7e90b112007-07-05 07:15:27 +00001477/// getAL - Returns a ARMCC::AL immediate node.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001478static inline SDValue getAL(SelectionDAG *CurDAG, SDLoc dl) {
1479 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001480}
1481
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001482SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
1483 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001484 ISD::MemIndexedMode AM = LD->getAddressingMode();
1485 if (AM == ISD::UNINDEXED)
Craig Topper062a2ba2014-04-25 05:30:21 +00001486 return nullptr;
Evan Chengd9c55362009-07-02 01:23:32 +00001487
Owen Anderson53aa7a92009-08-10 22:56:29 +00001488 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001489 SDValue Offset, AMOpc;
1490 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1491 unsigned Opcode = 0;
1492 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001493 if (LoadedVT == MVT::i32 && isPre &&
1494 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1495 Opcode = ARM::LDR_PRE_IMM;
1496 Match = true;
1497 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001498 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001499 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001500 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001501 } else if (LoadedVT == MVT::i32 &&
1502 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001503 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001504 Match = true;
1505
Owen Anderson9f944592009-08-11 20:47:22 +00001506 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001507 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001508 Match = true;
1509 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1510 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1511 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001512 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001513 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001514 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001515 Match = true;
1516 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1517 }
1518 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001519 if (isPre &&
1520 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001521 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001522 Opcode = ARM::LDRB_PRE_IMM;
1523 } else if (!isPre &&
1524 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1525 Match = true;
1526 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001527 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1528 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001529 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001530 }
1531 }
1532 }
1533
1534 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001535 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1536 SDValue Chain = LD->getChain();
1537 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001538 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001539 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001540 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001541 MVT::i32, MVT::Other, Ops);
Owen Andersonfd60f602011-08-26 21:12:37 +00001542 } else {
1543 SDValue Chain = LD->getChain();
1544 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001545 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001546 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001547 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001548 MVT::i32, MVT::Other, Ops);
Owen Andersonfd60f602011-08-26 21:12:37 +00001549 }
Evan Chengd9c55362009-07-02 01:23:32 +00001550 }
1551
Craig Topper062a2ba2014-04-25 05:30:21 +00001552 return nullptr;
Evan Chengd9c55362009-07-02 01:23:32 +00001553}
1554
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001555SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
1556 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001557 ISD::MemIndexedMode AM = LD->getAddressingMode();
1558 if (AM == ISD::UNINDEXED)
Craig Topper062a2ba2014-04-25 05:30:21 +00001559 return nullptr;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001560
Owen Anderson53aa7a92009-08-10 22:56:29 +00001561 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001562 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001563 SDValue Offset;
1564 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1565 unsigned Opcode = 0;
1566 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001567 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001568 switch (LoadedVT.getSimpleVT().SimpleTy) {
1569 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001570 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1571 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001572 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001573 if (isSExtLd)
1574 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1575 else
1576 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001577 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001578 case MVT::i8:
1579 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001580 if (isSExtLd)
1581 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1582 else
1583 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001584 break;
1585 default:
Craig Topper062a2ba2014-04-25 05:30:21 +00001586 return nullptr;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001587 }
1588 Match = true;
1589 }
1590
1591 if (Match) {
1592 SDValue Chain = LD->getChain();
1593 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001594 SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)),
Owen Anderson9f944592009-08-11 20:47:22 +00001595 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001596 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001597 MVT::Other, Ops);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001598 }
1599
Craig Topper062a2ba2014-04-25 05:30:21 +00001600 return nullptr;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001601}
1602
Weiming Zhao8f56f882012-11-16 21:55:34 +00001603/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1604SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001605 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001606 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001607 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1608 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1609 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001610 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001611 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001612}
1613
Weiming Zhao95782222012-11-17 00:23:35 +00001614/// \brief Form a D register from a pair of S registers.
1615SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001616 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001617 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001618 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1619 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1620 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001621 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001622 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001623}
1624
Weiming Zhao95782222012-11-17 00:23:35 +00001625/// \brief Form a quad register from a pair of D registers.
1626SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001627 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001628 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1629 MVT::i32);
1630 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1631 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001632 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001633 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001634}
1635
Weiming Zhao95782222012-11-17 00:23:35 +00001636/// \brief Form 4 consecutive D registers from a pair of Q registers.
1637SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001638 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001639 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1640 MVT::i32);
1641 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1642 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001643 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001644 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001645}
1646
Weiming Zhao95782222012-11-17 00:23:35 +00001647/// \brief Form 4 consecutive S registers.
1648SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001649 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001650 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001651 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001652 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1653 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1654 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1655 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1656 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001657 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1658 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001659 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001660}
1661
Weiming Zhao95782222012-11-17 00:23:35 +00001662/// \brief Form 4 consecutive D registers.
1663SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001664 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001665 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001666 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1667 MVT::i32);
1668 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1669 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1670 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1671 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001672 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1673 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001674 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001675}
1676
Weiming Zhao95782222012-11-17 00:23:35 +00001677/// \brief Form 4 consecutive Q registers.
1678SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001679 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001680 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001681 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1682 MVT::i32);
1683 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1684 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1685 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1686 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001687 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1688 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001689 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001690}
1691
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001692/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1693/// of a NEON VLD or VST instruction. The supported values depend on the
1694/// number of registers being loaded.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001695SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, SDLoc dl,
1696 unsigned NumVecs, bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001697 unsigned NumRegs = NumVecs;
1698 if (!is64BitVector && NumVecs < 3)
1699 NumRegs *= 2;
1700
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001701 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001702 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001703 Alignment = 32;
1704 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1705 Alignment = 16;
1706 else if (Alignment >= 8)
1707 Alignment = 8;
1708 else
1709 Alignment = 0;
1710
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001711 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001712}
1713
Jiangning Liu4df23632014-01-16 09:16:13 +00001714static bool isVLDfixed(unsigned Opc)
1715{
1716 switch (Opc) {
1717 default: return false;
1718 case ARM::VLD1d8wb_fixed : return true;
1719 case ARM::VLD1d16wb_fixed : return true;
1720 case ARM::VLD1d64Qwb_fixed : return true;
1721 case ARM::VLD1d32wb_fixed : return true;
1722 case ARM::VLD1d64wb_fixed : return true;
1723 case ARM::VLD1d64TPseudoWB_fixed : return true;
1724 case ARM::VLD1d64QPseudoWB_fixed : return true;
1725 case ARM::VLD1q8wb_fixed : return true;
1726 case ARM::VLD1q16wb_fixed : return true;
1727 case ARM::VLD1q32wb_fixed : return true;
1728 case ARM::VLD1q64wb_fixed : return true;
1729 case ARM::VLD2d8wb_fixed : return true;
1730 case ARM::VLD2d16wb_fixed : return true;
1731 case ARM::VLD2d32wb_fixed : return true;
1732 case ARM::VLD2q8PseudoWB_fixed : return true;
1733 case ARM::VLD2q16PseudoWB_fixed : return true;
1734 case ARM::VLD2q32PseudoWB_fixed : return true;
1735 case ARM::VLD2DUPd8wb_fixed : return true;
1736 case ARM::VLD2DUPd16wb_fixed : return true;
1737 case ARM::VLD2DUPd32wb_fixed : return true;
1738 }
1739}
1740
1741static bool isVSTfixed(unsigned Opc)
1742{
1743 switch (Opc) {
1744 default: return false;
1745 case ARM::VST1d8wb_fixed : return true;
1746 case ARM::VST1d16wb_fixed : return true;
1747 case ARM::VST1d32wb_fixed : return true;
1748 case ARM::VST1d64wb_fixed : return true;
Jim Grosbach1a597112014-04-03 23:43:18 +00001749 case ARM::VST1q8wb_fixed : return true;
1750 case ARM::VST1q16wb_fixed : return true;
1751 case ARM::VST1q32wb_fixed : return true;
1752 case ARM::VST1q64wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001753 case ARM::VST1d64TPseudoWB_fixed : return true;
1754 case ARM::VST1d64QPseudoWB_fixed : return true;
1755 case ARM::VST2d8wb_fixed : return true;
1756 case ARM::VST2d16wb_fixed : return true;
1757 case ARM::VST2d32wb_fixed : return true;
1758 case ARM::VST2q8PseudoWB_fixed : return true;
1759 case ARM::VST2q16PseudoWB_fixed : return true;
1760 case ARM::VST2q32PseudoWB_fixed : return true;
1761 }
1762}
1763
Jim Grosbach2098cb12011-10-24 21:45:13 +00001764// Get the register stride update opcode of a VLD/VST instruction that
1765// is otherwise equivalent to the given fixed stride updating instruction.
1766static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
Jiangning Liu4df23632014-01-16 09:16:13 +00001767 assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1768 && "Incorrect fixed stride updating instruction.");
Jim Grosbach2098cb12011-10-24 21:45:13 +00001769 switch (Opc) {
1770 default: break;
1771 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1772 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1773 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1774 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1775 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1776 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1777 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1778 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jiangning Liu4df23632014-01-16 09:16:13 +00001779 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1780 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1781 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1782 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001783
1784 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1785 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1786 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1787 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1788 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1789 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1790 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1791 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001792 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001793 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001794
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001795 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1796 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1797 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001798 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1799 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1800 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1801
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001802 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1803 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1804 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001805 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1806 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1807 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001808
Jim Grosbach13a292c2012-03-06 22:01:44 +00001809 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1810 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1811 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001812 }
1813 return Opc; // If not one we handle, return it unchanged.
1814}
1815
Bob Wilson06fce872011-02-07 17:43:21 +00001816SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001817 const uint16_t *DOpcodes,
1818 const uint16_t *QOpcodes0,
1819 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001820 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001821 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001822
Bob Wilsonae08a732010-03-20 22:13:40 +00001823 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001824 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1825 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Craig Topper062a2ba2014-04-25 05:30:21 +00001826 return nullptr;
Bob Wilson12b47992009-10-14 17:28:52 +00001827
1828 SDValue Chain = N->getOperand(0);
1829 EVT VT = N->getValueType(0);
1830 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001831 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001832
Bob Wilson12b47992009-10-14 17:28:52 +00001833 unsigned OpcodeIndex;
1834 switch (VT.getSimpleVT().SimpleTy) {
1835 default: llvm_unreachable("unhandled vld type");
1836 // Double-register operations:
1837 case MVT::v8i8: OpcodeIndex = 0; break;
1838 case MVT::v4i16: OpcodeIndex = 1; break;
1839 case MVT::v2f32:
1840 case MVT::v2i32: OpcodeIndex = 2; break;
1841 case MVT::v1i64: OpcodeIndex = 3; break;
1842 // Quad-register operations:
1843 case MVT::v16i8: OpcodeIndex = 0; break;
1844 case MVT::v8i16: OpcodeIndex = 1; break;
1845 case MVT::v4f32:
1846 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001847 case MVT::v2f64:
Bob Wilson340861d2010-03-23 05:25:43 +00001848 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001849 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson340861d2010-03-23 05:25:43 +00001850 break;
Bob Wilson12b47992009-10-14 17:28:52 +00001851 }
1852
Bob Wilson35fafca2010-09-03 18:16:02 +00001853 EVT ResTy;
1854 if (NumVecs == 1)
1855 ResTy = VT;
1856 else {
1857 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1858 if (!is64BitVector)
1859 ResTyElts *= 2;
1860 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1861 }
Bob Wilson06fce872011-02-07 17:43:21 +00001862 std::vector<EVT> ResTys;
1863 ResTys.push_back(ResTy);
1864 if (isUpdating)
1865 ResTys.push_back(MVT::i32);
1866 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001867
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001868 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001869 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001870 SDNode *VLd;
1871 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001872
Bob Wilson06fce872011-02-07 17:43:21 +00001873 // Double registers and VLD1/VLD2 quad registers are directly supported.
1874 if (is64BitVector || NumVecs <= 2) {
1875 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1876 QOpcodes0[OpcodeIndex]);
1877 Ops.push_back(MemAddr);
1878 Ops.push_back(Align);
1879 if (isUpdating) {
1880 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachd146a022011-12-09 21:28:25 +00001881 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach2098cb12011-10-24 21:45:13 +00001882 // case entirely when the rest are updated to that form, too.
Jiangning Liu4df23632014-01-16 09:16:13 +00001883 if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001884 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001885 // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001886 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00001887 if ((NumVecs > 2 && !isVLDfixed(Opc)) ||
Jim Grosbach05df4602011-10-31 21:50:31 +00001888 !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001889 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Evan Cheng630063a2010-05-10 21:26:24 +00001890 }
Bob Wilson06fce872011-02-07 17:43:21 +00001891 Ops.push_back(Pred);
1892 Ops.push_back(Reg0);
1893 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001894 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001895
Bob Wilson12b47992009-10-14 17:28:52 +00001896 } else {
1897 // Otherwise, quad registers are loaded with two separate instructions,
1898 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001899 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001900
Bob Wilson06fce872011-02-07 17:43:21 +00001901 // Load the even subregs. This is always an updating load, so that it
1902 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001903 SDValue ImplDef =
1904 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1905 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001906 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001907 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001908 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001909
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001910 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001911 Ops.push_back(SDValue(VLdA, 1));
1912 Ops.push_back(Align);
1913 if (isUpdating) {
1914 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1915 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1916 "only constant post-increment update allowed for VLD3/4");
1917 (void)Inc;
1918 Ops.push_back(Reg0);
1919 }
1920 Ops.push_back(SDValue(VLdA, 0));
1921 Ops.push_back(Pred);
1922 Ops.push_back(Reg0);
1923 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001924 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001925 }
Bob Wilson12b47992009-10-14 17:28:52 +00001926
Evan Cheng40791332011-04-19 00:04:03 +00001927 // Transfer memoperands.
1928 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1929 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1930 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1931
Bob Wilson06fce872011-02-07 17:43:21 +00001932 if (NumVecs == 1)
1933 return VLd;
1934
1935 // Extract out the subregisters.
1936 SDValue SuperReg = SDValue(VLd, 0);
1937 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
1938 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
1939 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1940 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1941 ReplaceUses(SDValue(N, Vec),
1942 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1943 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1944 if (isUpdating)
1945 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Craig Topper062a2ba2014-04-25 05:30:21 +00001946 return nullptr;
Bob Wilson12b47992009-10-14 17:28:52 +00001947}
1948
Bob Wilson06fce872011-02-07 17:43:21 +00001949SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001950 const uint16_t *DOpcodes,
1951 const uint16_t *QOpcodes0,
1952 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001953 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001954 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001955
Bob Wilsonae08a732010-03-20 22:13:40 +00001956 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001957 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1958 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1959 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Craig Topper062a2ba2014-04-25 05:30:21 +00001960 return nullptr;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001961
Evan Cheng40791332011-04-19 00:04:03 +00001962 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1963 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1964
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001965 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00001966 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001967 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001968 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001969
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001970 unsigned OpcodeIndex;
1971 switch (VT.getSimpleVT().SimpleTy) {
1972 default: llvm_unreachable("unhandled vst type");
1973 // Double-register operations:
1974 case MVT::v8i8: OpcodeIndex = 0; break;
1975 case MVT::v4i16: OpcodeIndex = 1; break;
1976 case MVT::v2f32:
1977 case MVT::v2i32: OpcodeIndex = 2; break;
1978 case MVT::v1i64: OpcodeIndex = 3; break;
1979 // Quad-register operations:
1980 case MVT::v16i8: OpcodeIndex = 0; break;
1981 case MVT::v8i16: OpcodeIndex = 1; break;
1982 case MVT::v4f32:
1983 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001984 case MVT::v2f64:
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001985 case MVT::v2i64: OpcodeIndex = 3;
1986 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
1987 break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001988 }
1989
Bob Wilson06fce872011-02-07 17:43:21 +00001990 std::vector<EVT> ResTys;
1991 if (isUpdating)
1992 ResTys.push_back(MVT::i32);
1993 ResTys.push_back(MVT::Other);
1994
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001995 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001996 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001997 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00001998
Bob Wilson06fce872011-02-07 17:43:21 +00001999 // Double registers and VST1/VST2 quad registers are directly supported.
2000 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00002001 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00002002 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00002003 SrcReg = N->getOperand(Vec0Idx);
2004 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00002005 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00002006 SDValue V0 = N->getOperand(Vec0Idx + 0);
2007 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00002008 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002009 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002010 else {
Bob Wilson06fce872011-02-07 17:43:21 +00002011 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00002012 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00002013 // an undef.
2014 SDValue V3 = (NumVecs == 3)
2015 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002016 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002017 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002018 }
Bob Wilson950882b2010-08-28 05:12:57 +00002019 } else {
2020 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00002021 SDValue Q0 = N->getOperand(Vec0Idx);
2022 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00002023 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002024 }
Bob Wilson06fce872011-02-07 17:43:21 +00002025
2026 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2027 QOpcodes0[OpcodeIndex]);
2028 Ops.push_back(MemAddr);
2029 Ops.push_back(Align);
2030 if (isUpdating) {
2031 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbach88ac7612011-12-14 21:32:11 +00002032 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach05df4602011-10-31 21:50:31 +00002033 // case entirely when the rest are updated to that form, too.
Jim Grosbach88ac7612011-12-14 21:32:11 +00002034 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach05df4602011-10-31 21:50:31 +00002035 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00002036 // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00002037 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00002038 if (!isa<ConstantSDNode>(Inc.getNode()))
2039 Ops.push_back(Inc);
2040 else if (NumVecs > 2 && !isVSTfixed(Opc))
2041 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002042 }
2043 Ops.push_back(SrcReg);
2044 Ops.push_back(Pred);
2045 Ops.push_back(Reg0);
2046 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00002047 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002048
2049 // Transfer memoperands.
2050 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
2051
2052 return VSt;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002053 }
2054
2055 // Otherwise, quad registers are stored with two separate instructions,
2056 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00002057
Bob Wilson01ac8f92010-06-16 21:34:01 +00002058 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00002059 SDValue V0 = N->getOperand(Vec0Idx + 0);
2060 SDValue V1 = N->getOperand(Vec0Idx + 1);
2061 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00002062 SDValue V3 = (NumVecs == 3)
2063 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002064 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002065 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002066
Bob Wilson06fce872011-02-07 17:43:21 +00002067 // Store the even D registers. This is always an updating store, so that it
2068 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00002069 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2070 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2071 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00002072 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00002073 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002074 Chain = SDValue(VStA, 1);
2075
2076 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00002077 Ops.push_back(SDValue(VStA, 0));
2078 Ops.push_back(Align);
2079 if (isUpdating) {
2080 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2081 assert(isa<ConstantSDNode>(Inc.getNode()) &&
2082 "only constant post-increment update allowed for VST3/4");
2083 (void)Inc;
2084 Ops.push_back(Reg0);
2085 }
2086 Ops.push_back(RegSeq);
2087 Ops.push_back(Pred);
2088 Ops.push_back(Reg0);
2089 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00002090 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00002091 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002092 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
2093 return VStB;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002094}
2095
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002096SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
Bob Wilson06fce872011-02-07 17:43:21 +00002097 bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00002098 const uint16_t *DOpcodes,
2099 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002100 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002101 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002102
Bob Wilsonae08a732010-03-20 22:13:40 +00002103 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00002104 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2105 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2106 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Craig Topper062a2ba2014-04-25 05:30:21 +00002107 return nullptr;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002108
Evan Cheng40791332011-04-19 00:04:03 +00002109 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2110 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2111
Bob Wilson4145e3a2009-10-14 16:19:03 +00002112 SDValue Chain = N->getOperand(0);
2113 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002114 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2115 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002116 bool is64BitVector = VT.is64BitVector();
2117
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002118 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002119 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002120 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002121 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2122 if (Alignment > NumBytes)
2123 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002124 if (Alignment < 8 && Alignment < NumBytes)
2125 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002126 // Alignment must be a power of two; make sure of that.
2127 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002128 if (Alignment == 1)
2129 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002130 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002131 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002132
Bob Wilson4145e3a2009-10-14 16:19:03 +00002133 unsigned OpcodeIndex;
2134 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002135 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002136 // Double-register operations:
2137 case MVT::v8i8: OpcodeIndex = 0; break;
2138 case MVT::v4i16: OpcodeIndex = 1; break;
2139 case MVT::v2f32:
2140 case MVT::v2i32: OpcodeIndex = 2; break;
2141 // Quad-register operations:
2142 case MVT::v8i16: OpcodeIndex = 0; break;
2143 case MVT::v4f32:
2144 case MVT::v4i32: OpcodeIndex = 1; break;
2145 }
2146
Bob Wilson06fce872011-02-07 17:43:21 +00002147 std::vector<EVT> ResTys;
2148 if (IsLoad) {
2149 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2150 if (!is64BitVector)
2151 ResTyElts *= 2;
2152 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2153 MVT::i64, ResTyElts));
2154 }
2155 if (isUpdating)
2156 ResTys.push_back(MVT::i32);
2157 ResTys.push_back(MVT::Other);
2158
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002159 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002160 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002161
Bob Wilson06fce872011-02-07 17:43:21 +00002162 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002163 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002164 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002165 if (isUpdating) {
2166 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2167 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
2168 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002169
Bob Wilsond5c57a52010-09-13 23:01:35 +00002170 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002171 SDValue V0 = N->getOperand(Vec0Idx + 0);
2172 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002173 if (NumVecs == 2) {
2174 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002175 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002176 else
Weiming Zhao95782222012-11-17 00:23:35 +00002177 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002178 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002179 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002180 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002181 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2182 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002183 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002184 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002185 else
Weiming Zhao95782222012-11-17 00:23:35 +00002186 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002187 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002188 Ops.push_back(SuperReg);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002189 Ops.push_back(getI32Imm(Lane, dl));
Evan Chenga33fc862009-11-21 06:21:52 +00002190 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002191 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002192 Ops.push_back(Chain);
2193
Bob Wilson06fce872011-02-07 17:43:21 +00002194 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2195 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002196 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002197 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson93117bc2009-10-14 16:46:45 +00002198 if (!IsLoad)
Bob Wilson06fce872011-02-07 17:43:21 +00002199 return VLdLn;
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002200
Bob Wilsond5c57a52010-09-13 23:01:35 +00002201 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002202 SuperReg = SDValue(VLdLn, 0);
2203 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
2204 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
2205 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002206 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2207 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002208 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2209 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2210 if (isUpdating)
2211 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Craig Topper062a2ba2014-04-25 05:30:21 +00002212 return nullptr;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002213}
2214
Bob Wilson06fce872011-02-07 17:43:21 +00002215SDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating,
Craig Topper01736f82012-05-24 05:17:00 +00002216 unsigned NumVecs,
2217 const uint16_t *Opcodes) {
Bob Wilson2d790df2010-11-28 06:51:26 +00002218 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002219 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002220
2221 SDValue MemAddr, Align;
2222 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
Craig Topper062a2ba2014-04-25 05:30:21 +00002223 return nullptr;
Bob Wilson2d790df2010-11-28 06:51:26 +00002224
Evan Cheng40791332011-04-19 00:04:03 +00002225 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2226 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2227
Bob Wilson2d790df2010-11-28 06:51:26 +00002228 SDValue Chain = N->getOperand(0);
2229 EVT VT = N->getValueType(0);
2230
2231 unsigned Alignment = 0;
2232 if (NumVecs != 3) {
2233 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2234 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2235 if (Alignment > NumBytes)
2236 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002237 if (Alignment < 8 && Alignment < NumBytes)
2238 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002239 // Alignment must be a power of two; make sure of that.
2240 Alignment = (Alignment & -Alignment);
2241 if (Alignment == 1)
2242 Alignment = 0;
2243 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002244 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson2d790df2010-11-28 06:51:26 +00002245
2246 unsigned OpcodeIndex;
2247 switch (VT.getSimpleVT().SimpleTy) {
2248 default: llvm_unreachable("unhandled vld-dup type");
2249 case MVT::v8i8: OpcodeIndex = 0; break;
2250 case MVT::v4i16: OpcodeIndex = 1; break;
2251 case MVT::v2f32:
2252 case MVT::v2i32: OpcodeIndex = 2; break;
2253 }
2254
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002255 SDValue Pred = getAL(CurDAG, dl);
Bob Wilson2d790df2010-11-28 06:51:26 +00002256 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2257 SDValue SuperReg;
2258 unsigned Opc = Opcodes[OpcodeIndex];
Bob Wilson06fce872011-02-07 17:43:21 +00002259 SmallVector<SDValue, 6> Ops;
2260 Ops.push_back(MemAddr);
2261 Ops.push_back(Align);
2262 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002263 // fixed-stride update instructions don't have an explicit writeback
2264 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002265 SDValue Inc = N->getOperand(2);
Jim Grosbachc80a2642011-12-21 19:40:55 +00002266 if (!isa<ConstantSDNode>(Inc.getNode()))
2267 Ops.push_back(Inc);
2268 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2269 else if (NumVecs > 2)
2270 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002271 }
2272 Ops.push_back(Pred);
2273 Ops.push_back(Reg0);
2274 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002275
2276 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002277 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002278 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002279 if (isUpdating)
2280 ResTys.push_back(MVT::i32);
2281 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002282 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002283 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002284 SuperReg = SDValue(VLdDup, 0);
Bob Wilson2d790df2010-11-28 06:51:26 +00002285
2286 // Extract the subregisters.
2287 assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
2288 unsigned SubIdx = ARM::dsub_0;
2289 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2290 ReplaceUses(SDValue(N, Vec),
2291 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Bob Wilson06fce872011-02-07 17:43:21 +00002292 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2293 if (isUpdating)
2294 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Craig Topper062a2ba2014-04-25 05:30:21 +00002295 return nullptr;
Bob Wilson2d790df2010-11-28 06:51:26 +00002296}
2297
Bob Wilson5bc8a792010-07-07 00:08:54 +00002298SDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2299 unsigned Opc) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00002300 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002301 SDLoc dl(N);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002302 EVT VT = N->getValueType(0);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002303 unsigned FirstTblReg = IsExt ? 2 : 1;
Bob Wilson3ed511b2010-07-06 23:36:25 +00002304
2305 // Form a REG_SEQUENCE to force register allocation.
2306 SDValue RegSeq;
Bob Wilson5bc8a792010-07-07 00:08:54 +00002307 SDValue V0 = N->getOperand(FirstTblReg + 0);
2308 SDValue V1 = N->getOperand(FirstTblReg + 1);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002309 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002310 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002311 else {
Bob Wilson5bc8a792010-07-07 00:08:54 +00002312 SDValue V2 = N->getOperand(FirstTblReg + 2);
Jim Grosbachd37f0712010-10-21 19:38:40 +00002313 // If it's a vtbl3, form a quad D-register and leave the last part as
Bob Wilson3ed511b2010-07-06 23:36:25 +00002314 // an undef.
2315 SDValue V3 = (NumVecs == 3)
2316 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson5bc8a792010-07-07 00:08:54 +00002317 : N->getOperand(FirstTblReg + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002318 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002319 }
2320
Bob Wilson5bc8a792010-07-07 00:08:54 +00002321 SmallVector<SDValue, 6> Ops;
2322 if (IsExt)
2323 Ops.push_back(N->getOperand(1));
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00002324 Ops.push_back(RegSeq);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002325 Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002326 Ops.push_back(getAL(CurDAG, dl)); // predicate
Bob Wilson3ed511b2010-07-06 23:36:25 +00002327 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
Michael Liaob53d8962013-04-19 22:22:57 +00002328 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002329}
2330
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002331SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
Jim Grosbach825cb292010-04-22 23:24:18 +00002332 bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002333 if (!Subtarget->hasV6T2Ops())
Craig Topper062a2ba2014-04-25 05:30:21 +00002334 return nullptr;
Bob Wilson93117bc2009-10-14 16:46:45 +00002335
Evan Chengeae6d2c2012-12-19 20:16:09 +00002336 unsigned Opc = isSigned
2337 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002338 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002339 SDLoc dl(N);
Jim Grosbach825cb292010-04-22 23:24:18 +00002340
Jim Grosbach825cb292010-04-22 23:24:18 +00002341 // For unsigned extracts, check for a shift right and mask
2342 unsigned And_imm = 0;
2343 if (N->getOpcode() == ISD::AND) {
2344 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2345
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002346 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002347 if (And_imm & (And_imm + 1))
Craig Topper062a2ba2014-04-25 05:30:21 +00002348 return nullptr;
Jim Grosbach825cb292010-04-22 23:24:18 +00002349
2350 unsigned Srl_imm = 0;
2351 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2352 Srl_imm)) {
2353 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2354
Jim Grosbach03f56d92011-07-27 21:09:25 +00002355 // Note: The width operand is encoded as width-1.
Benjamin Kramer5f6a9072015-02-12 15:35:40 +00002356 unsigned Width = countTrailingOnes(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002357 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002358
Jim Grosbach825cb292010-04-22 23:24:18 +00002359 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002360
2361 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2362 // It's cheaper to use a right shift to extract the top bits.
2363 if (Subtarget->isThumb()) {
2364 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2365 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002366 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2367 getAL(CurDAG, dl), Reg0, Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002368 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002369 }
2370
2371 // ARM models shift instructions as MOVsi with shifter operand.
2372 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2373 SDValue ShOpc =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002374 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), dl,
Evan Chengeae6d2c2012-12-19 20:16:09 +00002375 MVT::i32);
2376 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002377 getAL(CurDAG, dl), Reg0, Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002378 return CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002379 }
2380
Jim Grosbach825cb292010-04-22 23:24:18 +00002381 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002382 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2383 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2384 getAL(CurDAG, dl), Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002385 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
Jim Grosbach825cb292010-04-22 23:24:18 +00002386 }
2387 }
Craig Topper062a2ba2014-04-25 05:30:21 +00002388 return nullptr;
Jim Grosbach825cb292010-04-22 23:24:18 +00002389 }
2390
2391 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002392 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002393 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002394 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2395 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002396 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002397 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002398 // Note: The width operand is encoded as width-1.
2399 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002400 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002401 if (LSB < 0)
Craig Topper062a2ba2014-04-25 05:30:21 +00002402 return nullptr;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002403 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002404 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002405 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2406 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2407 getAL(CurDAG, dl), Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002408 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
Sandeep Patel423e42b2009-10-13 18:59:48 +00002409 }
2410 }
Tim Northover14ff2df2014-07-23 13:59:12 +00002411
2412 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
2413 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2414 unsigned LSB = 0;
2415 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) &&
2416 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB))
2417 return nullptr;
2418
2419 if (LSB + Width > 32)
2420 return nullptr;
2421
2422 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2423 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002424 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2425 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
2426 getAL(CurDAG, dl), Reg0 };
Tim Northover14ff2df2014-07-23 13:59:12 +00002427 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2428 }
2429
Craig Topper062a2ba2014-04-25 05:30:21 +00002430 return nullptr;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002431}
2432
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002433/// Target-specific DAG combining for ISD::XOR.
2434/// Target-independent combining lowers SELECT_CC nodes of the form
2435/// select_cc setg[ge] X, 0, X, -X
2436/// select_cc setgt X, -1, X, -X
2437/// select_cc setl[te] X, 0, -X, X
2438/// select_cc setlt X, 1, -X, X
2439/// which represent Integer ABS into:
2440/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2441/// ARM instruction selection detects the latter and matches it to
2442/// ARM::ABS or ARM::t2ABS machine node.
2443SDNode *ARMDAGToDAGISel::SelectABSOp(SDNode *N){
2444 SDValue XORSrc0 = N->getOperand(0);
2445 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002446 EVT VT = N->getValueType(0);
2447
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002448 if (Subtarget->isThumb1Only())
Craig Topper062a2ba2014-04-25 05:30:21 +00002449 return nullptr;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002450
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002451 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Craig Topper062a2ba2014-04-25 05:30:21 +00002452 return nullptr;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002453
2454 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2455 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2456 SDValue SRASrc0 = XORSrc1.getOperand(0);
2457 SDValue SRASrc1 = XORSrc1.getOperand(1);
2458 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2459 EVT XType = SRASrc0.getValueType();
2460 unsigned Size = XType.getSizeInBits() - 1;
2461
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002462 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
Craig Topper062a2ba2014-04-25 05:30:21 +00002463 XType.isInteger() && SRAConstant != nullptr &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002464 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002465 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002466 return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2467 }
2468
Craig Topper062a2ba2014-04-25 05:30:21 +00002469 return nullptr;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002470}
2471
Sam Parker2d5126c2016-04-08 16:02:53 +00002472static bool SearchSignedMulShort(SDValue SignExt, unsigned *Opc, SDValue &Src1,
2473 bool Accumulate) {
2474 // For SM*WB, we need to some form of sext.
2475 // For SM*WT, we need to search for (sra X, 16)
2476 // Src1 then gets set to X.
2477 if ((SignExt.getOpcode() == ISD::SIGN_EXTEND ||
2478 SignExt.getOpcode() == ISD::SIGN_EXTEND_INREG ||
2479 SignExt.getOpcode() == ISD::AssertSext) &&
2480 SignExt.getValueType() == MVT::i32) {
2481
2482 *Opc = Accumulate ? ARM::SMLAWB : ARM::SMULWB;
2483 Src1 = SignExt.getOperand(0);
2484 return true;
2485 }
2486
2487 if (SignExt.getOpcode() != ISD::SRA)
2488 return false;
2489
2490 ConstantSDNode *SRASrc1 = dyn_cast<ConstantSDNode>(SignExt.getOperand(1));
2491 if (!SRASrc1 || SRASrc1->getZExtValue() != 16)
2492 return false;
2493
2494 SDValue Op0 = SignExt.getOperand(0);
2495
2496 // The sign extend operand for SM*WB could be generated by a shl and ashr.
2497 if (Op0.getOpcode() == ISD::SHL) {
2498 SDValue SHL = Op0;
2499 ConstantSDNode *SHLSrc1 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
2500 if (!SHLSrc1 || SHLSrc1->getZExtValue() != 16)
2501 return false;
2502
2503 *Opc = Accumulate ? ARM::SMLAWB : ARM::SMULWB;
2504 Src1 = Op0.getOperand(0);
2505 return true;
2506 }
2507 *Opc = Accumulate ? ARM::SMLAWT : ARM::SMULWT;
2508 Src1 = SignExt.getOperand(0);
2509 return true;
2510}
2511
2512static bool SearchSignedMulLong(SDValue OR, unsigned *Opc, SDValue &Src0,
2513 SDValue &Src1, bool Accumulate) {
2514 // First we look for:
2515 // (add (or (srl ?, 16), (shl ?, 16)))
2516 if (OR.getOpcode() != ISD::OR)
2517 return false;
2518
2519 SDValue SRL = OR.getOperand(0);
2520 SDValue SHL = OR.getOperand(1);
2521
2522 if (SRL.getOpcode() != ISD::SRL || SHL.getOpcode() != ISD::SHL) {
2523 SRL = OR.getOperand(1);
2524 SHL = OR.getOperand(0);
2525 if (SRL.getOpcode() != ISD::SRL || SHL.getOpcode() != ISD::SHL)
2526 return false;
2527 }
2528
2529 ConstantSDNode *SRLSrc1 = dyn_cast<ConstantSDNode>(SRL.getOperand(1));
2530 ConstantSDNode *SHLSrc1 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
2531 if (!SRLSrc1 || !SHLSrc1 || SRLSrc1->getZExtValue() != 16 ||
2532 SHLSrc1->getZExtValue() != 16)
2533 return false;
2534
2535 // The first operands to the shifts need to be the two results from the
2536 // same smul_lohi node.
2537 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
2538 SRL.getOperand(0).getOpcode() != ISD::SMUL_LOHI)
2539 return false;
2540
2541 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
2542 if (SRL.getOperand(0) != SDValue(SMULLOHI, 0) ||
2543 SHL.getOperand(0) != SDValue(SMULLOHI, 1))
2544 return false;
2545
2546 // Now we have:
2547 // (add (or (srl (smul_lohi ?, ?), 16), (shl (smul_lohi ?, ?), 16)))
2548 // For SMLAW[B|T] smul_lohi will take a 32-bit and a 16-bit arguments.
2549 // For SMLAWB the 16-bit value will signed extended somehow.
2550 // For SMLAWT only the SRA is required.
2551
2552 // Check both sides of SMUL_LOHI
2553 if (SearchSignedMulShort(SMULLOHI->getOperand(0), Opc, Src1, Accumulate)) {
2554 Src0 = SMULLOHI->getOperand(1);
2555 } else if (SearchSignedMulShort(SMULLOHI->getOperand(1), Opc, Src1,
2556 Accumulate)) {
2557 Src0 = SMULLOHI->getOperand(0);
2558 } else {
2559 return false;
2560 }
2561 return true;
2562}
2563
2564SDNode *ARMDAGToDAGISel::SelectSMLAWSMULW(SDNode *N) {
2565 SDLoc dl(N);
2566 SDValue Src0 = N->getOperand(0);
2567 SDValue Src1 = N->getOperand(1);
2568 SDValue A, B;
2569 unsigned Opc = 0;
2570
2571 if (N->getOpcode() == ISD::ADD) {
2572 if (Src0.getOpcode() != ISD::OR && Src1.getOpcode() != ISD::OR)
2573 return nullptr;
2574
2575 SDValue Acc;
2576 if (SearchSignedMulLong(Src0, &Opc, A, B, true)) {
2577 Acc = Src1;
2578 } else if (SearchSignedMulLong(Src1, &Opc, A, B, true)) {
2579 Acc = Src0;
2580 } else {
2581 return nullptr;
2582 }
2583 if (Opc == 0)
2584 return nullptr;
2585
2586 SDValue Ops[] = { A, B, Acc, getAL(CurDAG, dl),
2587 CurDAG->getRegister(0, MVT::i32) };
2588 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, MVT::Other, Ops);
2589 } else if (N->getOpcode() == ISD::OR &&
2590 SearchSignedMulLong(SDValue(N, 0), &Opc, A, B, false)) {
2591 if (Opc == 0)
2592 return nullptr;
2593
2594 SDValue Ops[] = { A, B, getAL(CurDAG, dl),
2595 CurDAG->getRegister(0, MVT::i32)};
2596 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2597 }
2598 return nullptr;
2599}
2600
Evan Chengd85631e2010-05-05 18:28:36 +00002601SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
2602 // The only time a CONCAT_VECTORS operation can have legal types is when
2603 // two 64-bit vectors are concatenated to a 128-bit vector.
2604 EVT VT = N->getValueType(0);
2605 if (!VT.is128BitVector() || N->getNumOperands() != 2)
2606 llvm_unreachable("unexpected CONCAT_VECTORS");
Weiming Zhao95782222012-11-17 00:23:35 +00002607 return createDRegPairNode(VT, N->getOperand(0), N->getOperand(1));
Evan Chengd85631e2010-05-05 18:28:36 +00002608}
2609
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002610SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002611 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002612
Tim Northover31d093c2013-09-22 08:21:56 +00002613 if (N->isMachineOpcode()) {
2614 N->setNodeId(-1);
Craig Topper062a2ba2014-04-25 05:30:21 +00002615 return nullptr; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00002616 }
Rafael Espindola4e760152006-06-12 12:28:08 +00002617
2618 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002619 default: break;
Sam Parker2d5126c2016-04-08 16:02:53 +00002620 case ISD::ADD:
2621 case ISD::OR: {
2622 SDNode *ResNode = SelectSMLAWSMULW(N);
2623 if (ResNode)
2624 return ResNode;
2625 break;
2626 }
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002627 case ISD::WRITE_REGISTER: {
2628 SDNode *ResNode = SelectWriteRegister(N);
2629 if (ResNode)
2630 return ResNode;
2631 break;
2632 }
2633 case ISD::READ_REGISTER: {
2634 SDNode *ResNode = SelectReadRegister(N);
2635 if (ResNode)
2636 return ResNode;
2637 break;
2638 }
Weiming Zhaoc5987002013-02-14 18:10:21 +00002639 case ISD::INLINEASM: {
2640 SDNode *ResNode = SelectInlineAsm(N);
2641 if (ResNode)
2642 return ResNode;
2643 break;
2644 }
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002645 case ISD::XOR: {
2646 // Select special operations if XOR node forms integer ABS pattern
2647 SDNode *ResNode = SelectABSOp(N);
2648 if (ResNode)
2649 return ResNode;
2650 // Other cases are autogenerated.
2651 break;
2652 }
Evan Cheng10043e22007-01-19 07:51:42 +00002653 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002654 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
John Brawn056e6782015-09-14 15:19:41 +00002655 // If we can't materialize the constant we need to use a literal pool
2656 if (ConstantMaterializationCost(Val) > 2) {
Eric Christopherb17140d2014-10-08 07:32:17 +00002657 SDValue CPIdx = CurDAG->getTargetConstantPool(
2658 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
Mehdi Amini44ede332015-07-09 02:09:04 +00002659 TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng1526ba52007-01-24 08:53:17 +00002660
2661 SDNode *ResNode;
Tim Northover55c625f2014-01-23 13:43:47 +00002662 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002663 SDValue Pred = getAL(CurDAG, dl);
Owen Anderson9f944592009-08-11 20:47:22 +00002664 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002665 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002666 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002667 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002668 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002669 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002670 CPIdx,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002671 CurDAG->getTargetConstant(0, dl, MVT::i32),
2672 getAL(CurDAG, dl),
Owen Anderson9f944592009-08-11 20:47:22 +00002673 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002674 CurDAG->getEntryNode()
2675 };
Dan Gohman32f71d72009-09-25 18:54:59 +00002676 ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002677 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002678 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002679 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
Craig Topper062a2ba2014-04-25 05:30:21 +00002680 return nullptr;
Evan Cheng10043e22007-01-19 07:51:42 +00002681 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002682
Evan Cheng10043e22007-01-19 07:51:42 +00002683 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002684 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002685 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002686 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002687 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002688 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00002689 SDValue TFI = CurDAG->getTargetFrameIndex(
2690 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin22c2fba2009-07-08 23:10:31 +00002691 if (Subtarget->isThumb1Only()) {
Renato Golinb9887ef2015-02-25 14:41:06 +00002692 // Set the alignment of the frame object to 4, to avoid having to generate
2693 // more than one ADD
2694 MachineFrameInfo *MFI = MF->getFrameInfo();
2695 if (MFI->getObjectAlignment(FI) < 4)
2696 MFI->setObjectAlignment(FI, 4);
Tim Northover23075cc2014-10-20 21:28:41 +00002697 return CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002698 CurDAG->getTargetConstant(0, dl, MVT::i32));
Jim Grosbachfde21102009-04-07 20:34:09 +00002699 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002700 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2701 ARM::t2ADDri : ARM::ADDri);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002702 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
2703 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002704 CurDAG->getRegister(0, MVT::i32) };
Craig Topper481fb282014-04-27 19:21:11 +00002705 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
Evan Cheng7e90b112007-07-05 07:15:27 +00002706 }
Evan Cheng10043e22007-01-19 07:51:42 +00002707 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002708 case ISD::SRL:
Jim Grosbach825cb292010-04-22 23:24:18 +00002709 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
Sandeep Patel423e42b2009-10-13 18:59:48 +00002710 return I;
2711 break;
Tim Northover14ff2df2014-07-23 13:59:12 +00002712 case ISD::SIGN_EXTEND_INREG:
Sandeep Patel423e42b2009-10-13 18:59:48 +00002713 case ISD::SRA:
Jim Grosbach825cb292010-04-22 23:24:18 +00002714 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true))
Sandeep Patel423e42b2009-10-13 18:59:48 +00002715 return I;
2716 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002717 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002718 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002719 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002720 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002721 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002722 if (!RHSV) break;
2723 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002724 unsigned ShImm = Log2_32(RHSV-1);
2725 if (ShImm >= 32)
2726 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002727 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002728 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002729 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002730 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002731 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002732 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002733 return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002734 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002735 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2736 Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002737 return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002738 }
Evan Cheng10043e22007-01-19 07:51:42 +00002739 }
2740 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002741 unsigned ShImm = Log2_32(RHSV+1);
2742 if (ShImm >= 32)
2743 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002744 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002745 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002746 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002747 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002748 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002749 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002750 return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002751 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002752 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2753 Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002754 return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002755 }
Evan Cheng10043e22007-01-19 07:51:42 +00002756 }
2757 }
2758 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002759 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002760 // Check for unsigned bitfield extract
2761 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
2762 return I;
2763
Evan Cheng786b15f2009-10-21 08:15:52 +00002764 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2765 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2766 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2767 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2768 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002769 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002770 if (VT != MVT::i32)
2771 break;
2772 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2773 ? ARM::t2MOVTi16
2774 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2775 if (!Opc)
2776 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002777 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002778 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
2779 if (!N1C)
2780 break;
2781 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2782 SDValue N2 = N0.getOperand(1);
2783 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2784 if (!N2C)
2785 break;
2786 unsigned N1CVal = N1C->getZExtValue();
2787 unsigned N2CVal = N2C->getZExtValue();
2788 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2789 (N1CVal & 0xffffU) == 0xffffU &&
2790 (N2CVal & 0xffffU) == 0x0U) {
2791 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002792 dl, MVT::i32);
Evan Cheng786b15f2009-10-21 08:15:52 +00002793 SDValue Ops[] = { N0.getOperand(0), Imm16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002794 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002795 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
Evan Cheng786b15f2009-10-21 08:15:52 +00002796 }
2797 }
2798 break;
2799 }
Jim Grosbachd7cf55c2009-11-09 00:11:35 +00002800 case ARMISD::VMOVRRD:
2801 return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002802 N->getOperand(0), getAL(CurDAG, dl),
Dan Gohman32f71d72009-09-25 18:54:59 +00002803 CurDAG->getRegister(0, MVT::i32));
Dan Gohmana1603612007-10-08 18:33:35 +00002804 case ISD::UMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002805 if (Subtarget->isThumb1Only())
2806 break;
2807 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002808 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002809 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002810 return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002811 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002812 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002813 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002814 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov62acecd2011-01-01 20:38:38 +00002815 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2816 ARM::UMULL : ARM::UMULLv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002817 dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002818 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002819 }
Dan Gohmana1603612007-10-08 18:33:35 +00002820 case ISD::SMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002821 if (Subtarget->isThumb1Only())
2822 break;
2823 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002824 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002825 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002826 return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002827 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002828 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002829 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002830 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov62acecd2011-01-01 20:38:38 +00002831 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2832 ARM::SMULL : ARM::SMULLv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002833 dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002834 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002835 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002836 case ARMISD::UMLAL:{
2837 if (Subtarget->isThumb()) {
2838 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002839 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002840 CurDAG->getRegister(0, MVT::i32)};
Michael Liaob53d8962013-04-19 22:22:57 +00002841 return CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002842 }else{
2843 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002844 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002845 CurDAG->getRegister(0, MVT::i32),
2846 CurDAG->getRegister(0, MVT::i32) };
2847 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2848 ARM::UMLAL : ARM::UMLALv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002849 dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002850 }
2851 }
2852 case ARMISD::SMLAL:{
2853 if (Subtarget->isThumb()) {
2854 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002855 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002856 CurDAG->getRegister(0, MVT::i32)};
Michael Liaob53d8962013-04-19 22:22:57 +00002857 return CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002858 }else{
2859 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002860 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002861 CurDAG->getRegister(0, MVT::i32),
2862 CurDAG->getRegister(0, MVT::i32) };
2863 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2864 ARM::SMLAL : ARM::SMLALv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002865 dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002866 }
2867 }
Evan Cheng10043e22007-01-19 07:51:42 +00002868 case ISD::LOAD: {
Craig Topper062a2ba2014-04-25 05:30:21 +00002869 SDNode *ResNode = nullptr;
Evan Chengb24e51e2009-07-07 01:17:28 +00002870 if (Subtarget->isThumb() && Subtarget->hasThumb2())
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002871 ResNode = SelectT2IndexedLoad(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00002872 else
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002873 ResNode = SelectARMIndexedLoad(N);
Evan Chengd9c55362009-07-02 01:23:32 +00002874 if (ResNode)
2875 return ResNode;
Evan Cheng10043e22007-01-19 07:51:42 +00002876 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002877 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00002878 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002879 case ARMISD::BRCOND: {
2880 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2881 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2882 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00002883
Evan Cheng7e90b112007-07-05 07:15:27 +00002884 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2885 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2886 // Pattern complexity = 6 cost = 1 size = 0
2887
David Goodwin27303cd2009-06-30 18:04:13 +00002888 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2889 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2890 // Pattern complexity = 6 cost = 1 size = 0
2891
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002892 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00002893 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002894 SDValue Chain = N->getOperand(0);
2895 SDValue N1 = N->getOperand(1);
2896 SDValue N2 = N->getOperand(2);
2897 SDValue N3 = N->getOperand(3);
2898 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00002899 assert(N1.getOpcode() == ISD::BasicBlock);
2900 assert(N2.getOpcode() == ISD::Constant);
2901 assert(N3.getOpcode() == ISD::Register);
2902
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002903 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002904 cast<ConstantSDNode>(N2)->getZExtValue()), dl,
Owen Anderson9f944592009-08-11 20:47:22 +00002905 MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002906 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00002907 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002908 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002909 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002910 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002911 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002912 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00002913 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002914 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00002915 SDValue(Chain.getNode(), Chain.getResNo()));
Craig Topper062a2ba2014-04-25 05:30:21 +00002916 return nullptr;
Evan Cheng7e90b112007-07-05 07:15:27 +00002917 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002918 case ARMISD::VZIP: {
2919 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002920 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002921 switch (VT.getSimpleVT().SimpleTy) {
Craig Topper062a2ba2014-04-25 05:30:21 +00002922 default: return nullptr;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002923 case MVT::v8i8: Opc = ARM::VZIPd8; break;
2924 case MVT::v4i16: Opc = ARM::VZIPd16; break;
2925 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00002926 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2927 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002928 case MVT::v16i8: Opc = ARM::VZIPq8; break;
2929 case MVT::v8i16: Opc = ARM::VZIPq16; break;
2930 case MVT::v4f32:
2931 case MVT::v4i32: Opc = ARM::VZIPq32; break;
2932 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002933 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002934 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2935 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002936 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002937 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002938 case ARMISD::VUZP: {
2939 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002940 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002941 switch (VT.getSimpleVT().SimpleTy) {
Craig Topper062a2ba2014-04-25 05:30:21 +00002942 default: return nullptr;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002943 case MVT::v8i8: Opc = ARM::VUZPd8; break;
2944 case MVT::v4i16: Opc = ARM::VUZPd16; break;
2945 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00002946 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2947 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002948 case MVT::v16i8: Opc = ARM::VUZPq8; break;
2949 case MVT::v8i16: Opc = ARM::VUZPq16; break;
2950 case MVT::v4f32:
2951 case MVT::v4i32: Opc = ARM::VUZPq32; break;
2952 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002953 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002954 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2955 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002956 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002957 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002958 case ARMISD::VTRN: {
2959 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002960 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002961 switch (VT.getSimpleVT().SimpleTy) {
Craig Topper062a2ba2014-04-25 05:30:21 +00002962 default: return nullptr;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002963 case MVT::v8i8: Opc = ARM::VTRNd8; break;
2964 case MVT::v4i16: Opc = ARM::VTRNd16; break;
2965 case MVT::v2f32:
2966 case MVT::v2i32: Opc = ARM::VTRNd32; break;
2967 case MVT::v16i8: Opc = ARM::VTRNq8; break;
2968 case MVT::v8i16: Opc = ARM::VTRNq16; break;
2969 case MVT::v4f32:
2970 case MVT::v4i32: Opc = ARM::VTRNq32; break;
2971 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002972 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002973 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2974 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002975 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002976 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00002977 case ARMISD::BUILD_VECTOR: {
2978 EVT VecVT = N->getValueType(0);
2979 EVT EltVT = VecVT.getVectorElementType();
2980 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00002981 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00002982 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Weiming Zhao95782222012-11-17 00:23:35 +00002983 return createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilsond8a9a042010-06-04 00:04:02 +00002984 }
Duncan Sands14627772010-11-03 12:17:33 +00002985 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Bob Wilsond8a9a042010-06-04 00:04:02 +00002986 if (NumElts == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002987 return createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilsond8a9a042010-06-04 00:04:02 +00002988 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Weiming Zhao95782222012-11-17 00:23:35 +00002989 return createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
Bob Wilsond8a9a042010-06-04 00:04:02 +00002990 N->getOperand(2), N->getOperand(3));
2991 }
Bob Wilsone0636a72009-08-26 17:39:53 +00002992
Bob Wilson2d790df2010-11-28 06:51:26 +00002993 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002994 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
2995 ARM::VLD2DUPd32 };
Bob Wilson06fce872011-02-07 17:43:21 +00002996 return SelectVLDDup(N, false, 2, Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +00002997 }
2998
Bob Wilson77ab1652010-11-29 19:35:29 +00002999 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003000 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
3001 ARM::VLD3DUPd16Pseudo,
3002 ARM::VLD3DUPd32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003003 return SelectVLDDup(N, false, 3, Opcodes);
Bob Wilson77ab1652010-11-29 19:35:29 +00003004 }
3005
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003006 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003007 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
3008 ARM::VLD4DUPd16Pseudo,
3009 ARM::VLD4DUPd32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003010 return SelectVLDDup(N, false, 4, Opcodes);
3011 }
3012
3013 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003014 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
3015 ARM::VLD2DUPd16wb_fixed,
3016 ARM::VLD2DUPd32wb_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00003017 return SelectVLDDup(N, true, 2, Opcodes);
3018 }
3019
3020 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003021 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
3022 ARM::VLD3DUPd16Pseudo_UPD,
3023 ARM::VLD3DUPd32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003024 return SelectVLDDup(N, true, 3, Opcodes);
3025 }
3026
3027 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003028 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
3029 ARM::VLD4DUPd16Pseudo_UPD,
3030 ARM::VLD4DUPd32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003031 return SelectVLDDup(N, true, 4, Opcodes);
3032 }
3033
3034 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003035 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
3036 ARM::VLD1d16wb_fixed,
3037 ARM::VLD1d32wb_fixed,
3038 ARM::VLD1d64wb_fixed };
3039 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
3040 ARM::VLD1q16wb_fixed,
3041 ARM::VLD1q32wb_fixed,
3042 ARM::VLD1q64wb_fixed };
Craig Topper062a2ba2014-04-25 05:30:21 +00003043 return SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
Bob Wilson06fce872011-02-07 17:43:21 +00003044 }
3045
3046 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003047 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
3048 ARM::VLD2d16wb_fixed,
3049 ARM::VLD2d32wb_fixed,
3050 ARM::VLD1q64wb_fixed};
3051 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
3052 ARM::VLD2q16PseudoWB_fixed,
3053 ARM::VLD2q32PseudoWB_fixed };
Craig Topper062a2ba2014-04-25 05:30:21 +00003054 return SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
Bob Wilson06fce872011-02-07 17:43:21 +00003055 }
3056
3057 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003058 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
3059 ARM::VLD3d16Pseudo_UPD,
3060 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003061 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003062 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3063 ARM::VLD3q16Pseudo_UPD,
3064 ARM::VLD3q32Pseudo_UPD };
3065 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3066 ARM::VLD3q16oddPseudo_UPD,
3067 ARM::VLD3q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003068 return SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3069 }
3070
3071 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003072 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3073 ARM::VLD4d16Pseudo_UPD,
3074 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003075 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003076 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3077 ARM::VLD4q16Pseudo_UPD,
3078 ARM::VLD4q32Pseudo_UPD };
3079 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3080 ARM::VLD4q16oddPseudo_UPD,
3081 ARM::VLD4q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003082 return SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3083 }
3084
3085 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003086 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3087 ARM::VLD2LNd16Pseudo_UPD,
3088 ARM::VLD2LNd32Pseudo_UPD };
3089 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3090 ARM::VLD2LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003091 return SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3092 }
3093
3094 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003095 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3096 ARM::VLD3LNd16Pseudo_UPD,
3097 ARM::VLD3LNd32Pseudo_UPD };
3098 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3099 ARM::VLD3LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003100 return SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3101 }
3102
3103 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003104 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3105 ARM::VLD4LNd16Pseudo_UPD,
3106 ARM::VLD4LNd32Pseudo_UPD };
3107 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3108 ARM::VLD4LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003109 return SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3110 }
3111
3112 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003113 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3114 ARM::VST1d16wb_fixed,
3115 ARM::VST1d32wb_fixed,
3116 ARM::VST1d64wb_fixed };
3117 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3118 ARM::VST1q16wb_fixed,
3119 ARM::VST1q32wb_fixed,
3120 ARM::VST1q64wb_fixed };
Craig Topper062a2ba2014-04-25 05:30:21 +00003121 return SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
Bob Wilson06fce872011-02-07 17:43:21 +00003122 }
3123
3124 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003125 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3126 ARM::VST2d16wb_fixed,
3127 ARM::VST2d32wb_fixed,
3128 ARM::VST1q64wb_fixed};
3129 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3130 ARM::VST2q16PseudoWB_fixed,
3131 ARM::VST2q32PseudoWB_fixed };
Craig Topper062a2ba2014-04-25 05:30:21 +00003132 return SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
Bob Wilson06fce872011-02-07 17:43:21 +00003133 }
3134
3135 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003136 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3137 ARM::VST3d16Pseudo_UPD,
3138 ARM::VST3d32Pseudo_UPD,
3139 ARM::VST1d64TPseudoWB_fixed};
3140 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3141 ARM::VST3q16Pseudo_UPD,
3142 ARM::VST3q32Pseudo_UPD };
3143 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3144 ARM::VST3q16oddPseudo_UPD,
3145 ARM::VST3q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003146 return SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3147 }
3148
3149 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003150 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3151 ARM::VST4d16Pseudo_UPD,
3152 ARM::VST4d32Pseudo_UPD,
3153 ARM::VST1d64QPseudoWB_fixed};
3154 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3155 ARM::VST4q16Pseudo_UPD,
3156 ARM::VST4q32Pseudo_UPD };
3157 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3158 ARM::VST4q16oddPseudo_UPD,
3159 ARM::VST4q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003160 return SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3161 }
3162
3163 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003164 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3165 ARM::VST2LNd16Pseudo_UPD,
3166 ARM::VST2LNd32Pseudo_UPD };
3167 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3168 ARM::VST2LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003169 return SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3170 }
3171
3172 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003173 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3174 ARM::VST3LNd16Pseudo_UPD,
3175 ARM::VST3LNd32Pseudo_UPD };
3176 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3177 ARM::VST3LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003178 return SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3179 }
3180
3181 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003182 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3183 ARM::VST4LNd16Pseudo_UPD,
3184 ARM::VST4LNd32Pseudo_UPD };
3185 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3186 ARM::VST4LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003187 return SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003188 }
3189
Bob Wilsone0636a72009-08-26 17:39:53 +00003190 case ISD::INTRINSIC_VOID:
3191 case ISD::INTRINSIC_W_CHAIN: {
3192 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003193 switch (IntNo) {
3194 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003195 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003196
Tim Northover1ff5f292014-03-26 14:39:31 +00003197 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003198 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003199 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003200 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003201 SDValue MemAddr = N->getOperand(2);
Bradley Smith433c22e2016-01-15 10:26:51 +00003202 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
Tim Northover1ff5f292014-03-26 14:39:31 +00003203
3204 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3205 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3206 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003207
3208 // arm_ldrexd returns a i64 value in {i32, i32}
3209 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003210 if (isThumb) {
3211 ResTys.push_back(MVT::i32);
3212 ResTys.push_back(MVT::i32);
3213 } else
3214 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003215 ResTys.push_back(MVT::Other);
3216
Weiming Zhao8f56f882012-11-16 21:55:34 +00003217 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003218 SmallVector<SDValue, 7> Ops;
3219 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003220 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003221 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3222 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00003223 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003224 // Transfer memoperands.
3225 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3226 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3227 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3228
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003229 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003230 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003231 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003232 SDValue Result;
3233 if (isThumb)
3234 Result = SDValue(Ld, 0);
3235 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003236 SDValue SubRegIdx =
3237 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003238 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003239 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003240 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003241 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003242 ReplaceUses(SDValue(N, 0), Result);
3243 }
3244 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003245 SDValue Result;
3246 if (isThumb)
3247 Result = SDValue(Ld, 1);
3248 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003249 SDValue SubRegIdx =
3250 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003251 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003252 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003253 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003254 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003255 ReplaceUses(SDValue(N, 1), Result);
3256 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003257 ReplaceUses(SDValue(N, 2), OutChain);
Craig Topper062a2ba2014-04-25 05:30:21 +00003258 return nullptr;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003259 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003260 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003261 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003262 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003263 SDValue Chain = N->getOperand(0);
3264 SDValue Val0 = N->getOperand(2);
3265 SDValue Val1 = N->getOperand(3);
3266 SDValue MemAddr = N->getOperand(4);
3267
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003268 // Store exclusive double return a i32 value which is the return status
3269 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003270 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003271
Weiming Zhao8f56f882012-11-16 21:55:34 +00003272 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3273 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003274 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003275 if (isThumb) {
3276 Ops.push_back(Val0);
3277 Ops.push_back(Val1);
3278 } else
3279 // arm_strexd uses GPRPair.
3280 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003281 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003282 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003283 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3284 Ops.push_back(Chain);
3285
Tim Northover1ff5f292014-03-26 14:39:31 +00003286 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3287 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3288 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003289
Michael Liaob53d8962013-04-19 22:22:57 +00003290 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003291 // Transfer memoperands.
3292 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3293 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3294 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3295
3296 return St;
3297 }
3298
Bob Wilson340861d2010-03-23 05:25:43 +00003299 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003300 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3301 ARM::VLD1d32, ARM::VLD1d64 };
3302 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3303 ARM::VLD1q32, ARM::VLD1q64};
Craig Topper062a2ba2014-04-25 05:30:21 +00003304 return SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
Bob Wilson340861d2010-03-23 05:25:43 +00003305 }
3306
Bob Wilsone0636a72009-08-26 17:39:53 +00003307 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003308 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3309 ARM::VLD2d32, ARM::VLD1q64 };
3310 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3311 ARM::VLD2q32Pseudo };
Craig Topper062a2ba2014-04-25 05:30:21 +00003312 return SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
Bob Wilsone0636a72009-08-26 17:39:53 +00003313 }
3314
3315 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003316 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3317 ARM::VLD3d16Pseudo,
3318 ARM::VLD3d32Pseudo,
3319 ARM::VLD1d64TPseudo };
3320 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3321 ARM::VLD3q16Pseudo_UPD,
3322 ARM::VLD3q32Pseudo_UPD };
3323 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3324 ARM::VLD3q16oddPseudo,
3325 ARM::VLD3q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003326 return SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003327 }
3328
3329 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003330 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3331 ARM::VLD4d16Pseudo,
3332 ARM::VLD4d32Pseudo,
3333 ARM::VLD1d64QPseudo };
3334 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3335 ARM::VLD4q16Pseudo_UPD,
3336 ARM::VLD4q32Pseudo_UPD };
3337 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3338 ARM::VLD4q16oddPseudo,
3339 ARM::VLD4q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003340 return SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003341 }
3342
Bob Wilsonda9817c2009-09-01 04:26:28 +00003343 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003344 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3345 ARM::VLD2LNd16Pseudo,
3346 ARM::VLD2LNd32Pseudo };
3347 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3348 ARM::VLD2LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003349 return SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003350 }
3351
3352 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003353 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3354 ARM::VLD3LNd16Pseudo,
3355 ARM::VLD3LNd32Pseudo };
3356 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3357 ARM::VLD3LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003358 return SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003359 }
3360
3361 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003362 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3363 ARM::VLD4LNd16Pseudo,
3364 ARM::VLD4LNd32Pseudo };
3365 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3366 ARM::VLD4LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003367 return SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003368 }
3369
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003370 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003371 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3372 ARM::VST1d32, ARM::VST1d64 };
3373 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3374 ARM::VST1q32, ARM::VST1q64 };
Craig Topper062a2ba2014-04-25 05:30:21 +00003375 return SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003376 }
3377
Bob Wilsone0636a72009-08-26 17:39:53 +00003378 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003379 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3380 ARM::VST2d32, ARM::VST1q64 };
3381 static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3382 ARM::VST2q32Pseudo };
Craig Topper062a2ba2014-04-25 05:30:21 +00003383 return SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
Bob Wilsone0636a72009-08-26 17:39:53 +00003384 }
3385
3386 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003387 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3388 ARM::VST3d16Pseudo,
3389 ARM::VST3d32Pseudo,
3390 ARM::VST1d64TPseudo };
3391 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3392 ARM::VST3q16Pseudo_UPD,
3393 ARM::VST3q32Pseudo_UPD };
3394 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3395 ARM::VST3q16oddPseudo,
3396 ARM::VST3q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003397 return SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003398 }
3399
3400 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003401 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3402 ARM::VST4d16Pseudo,
3403 ARM::VST4d32Pseudo,
3404 ARM::VST1d64QPseudo };
3405 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3406 ARM::VST4q16Pseudo_UPD,
3407 ARM::VST4q32Pseudo_UPD };
3408 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3409 ARM::VST4q16oddPseudo,
3410 ARM::VST4q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003411 return SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003412 }
Bob Wilsond7797752009-09-01 18:51:56 +00003413
3414 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003415 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3416 ARM::VST2LNd16Pseudo,
3417 ARM::VST2LNd32Pseudo };
3418 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3419 ARM::VST2LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003420 return SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003421 }
3422
3423 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003424 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3425 ARM::VST3LNd16Pseudo,
3426 ARM::VST3LNd32Pseudo };
3427 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3428 ARM::VST3LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003429 return SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003430 }
3431
3432 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003433 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3434 ARM::VST4LNd16Pseudo,
3435 ARM::VST4LNd32Pseudo };
3436 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3437 ARM::VST4LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003438 return SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003439 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003440 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003441 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003442 }
Evan Chengd85631e2010-05-05 18:28:36 +00003443
Bob Wilson3ed511b2010-07-06 23:36:25 +00003444 case ISD::INTRINSIC_WO_CHAIN: {
3445 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3446 switch (IntNo) {
3447 default:
3448 break;
3449
3450 case Intrinsic::arm_neon_vtbl2:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003451 return SelectVTBL(N, false, 2, ARM::VTBL2);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003452 case Intrinsic::arm_neon_vtbl3:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003453 return SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003454 case Intrinsic::arm_neon_vtbl4:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003455 return SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003456
3457 case Intrinsic::arm_neon_vtbx2:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003458 return SelectVTBL(N, true, 2, ARM::VTBX2);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003459 case Intrinsic::arm_neon_vtbx3:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003460 return SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003461 case Intrinsic::arm_neon_vtbx4:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003462 return SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003463 }
3464 break;
3465 }
3466
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003467 case ARMISD::VTBL1: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003468 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003469 EVT VT = N->getValueType(0);
3470 SmallVector<SDValue, 6> Ops;
3471
3472 Ops.push_back(N->getOperand(0));
3473 Ops.push_back(N->getOperand(1));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003474 Ops.push_back(getAL(CurDAG, dl)); // Predicate
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003475 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Michael Liaob53d8962013-04-19 22:22:57 +00003476 return CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003477 }
3478 case ARMISD::VTBL2: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003479 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003480 EVT VT = N->getValueType(0);
3481
3482 // Form a REG_SEQUENCE to force register allocation.
3483 SDValue V0 = N->getOperand(0);
3484 SDValue V1 = N->getOperand(1);
Weiming Zhao95782222012-11-17 00:23:35 +00003485 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003486
3487 SmallVector<SDValue, 6> Ops;
3488 Ops.push_back(RegSeq);
3489 Ops.push_back(N->getOperand(2));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003490 Ops.push_back(getAL(CurDAG, dl)); // Predicate
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003491 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Michael Liaob53d8962013-04-19 22:22:57 +00003492 return CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003493 }
3494
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003495 case ISD::CONCAT_VECTORS:
Evan Chengd85631e2010-05-05 18:28:36 +00003496 return SelectConcatVector(N);
3497 }
Evan Chengd5021732008-12-10 21:54:21 +00003498
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003499 return SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003500}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003501
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003502// Inspect a register string of the form
3503// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3504// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3505// and obtain the integer operands from them, adding these operands to the
3506// provided vector.
3507static void getIntOperandsFromRegisterString(StringRef RegString,
3508 SelectionDAG *CurDAG, SDLoc DL,
3509 std::vector<SDValue>& Ops) {
3510 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003511 RegString.split(Fields, ':');
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003512
3513 if (Fields.size() > 1) {
3514 bool AllIntFields = true;
3515
3516 for (StringRef Field : Fields) {
3517 // Need to trim out leading 'cp' characters and get the integer field.
3518 unsigned IntField;
3519 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3520 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3521 }
3522
3523 assert(AllIntFields &&
3524 "Unexpected non-integer value in special register string.");
3525 }
3526}
3527
3528// Maps a Banked Register string to its mask value. The mask value returned is
3529// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3530// mask operand, which expresses which register is to be used, e.g. r8, and in
3531// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3532// was invalid.
3533static inline int getBankedRegisterMask(StringRef RegString) {
3534 return StringSwitch<int>(RegString.lower())
3535 .Case("r8_usr", 0x00)
3536 .Case("r9_usr", 0x01)
3537 .Case("r10_usr", 0x02)
3538 .Case("r11_usr", 0x03)
3539 .Case("r12_usr", 0x04)
3540 .Case("sp_usr", 0x05)
3541 .Case("lr_usr", 0x06)
3542 .Case("r8_fiq", 0x08)
3543 .Case("r9_fiq", 0x09)
3544 .Case("r10_fiq", 0x0a)
3545 .Case("r11_fiq", 0x0b)
3546 .Case("r12_fiq", 0x0c)
3547 .Case("sp_fiq", 0x0d)
3548 .Case("lr_fiq", 0x0e)
3549 .Case("lr_irq", 0x10)
3550 .Case("sp_irq", 0x11)
3551 .Case("lr_svc", 0x12)
3552 .Case("sp_svc", 0x13)
3553 .Case("lr_abt", 0x14)
3554 .Case("sp_abt", 0x15)
3555 .Case("lr_und", 0x16)
3556 .Case("sp_und", 0x17)
3557 .Case("lr_mon", 0x1c)
3558 .Case("sp_mon", 0x1d)
3559 .Case("elr_hyp", 0x1e)
3560 .Case("sp_hyp", 0x1f)
3561 .Case("spsr_fiq", 0x2e)
3562 .Case("spsr_irq", 0x30)
3563 .Case("spsr_svc", 0x32)
3564 .Case("spsr_abt", 0x34)
3565 .Case("spsr_und", 0x36)
3566 .Case("spsr_mon", 0x3c)
3567 .Case("spsr_hyp", 0x3e)
3568 .Default(-1);
3569}
3570
3571// Maps a MClass special register string to its value for use in the
3572// t2MRS_M / t2MSR_M instruction nodes as the SYSm value operand.
3573// Returns -1 to signify that the string was invalid.
3574static inline int getMClassRegisterSYSmValueMask(StringRef RegString) {
3575 return StringSwitch<int>(RegString.lower())
3576 .Case("apsr", 0x0)
3577 .Case("iapsr", 0x1)
3578 .Case("eapsr", 0x2)
3579 .Case("xpsr", 0x3)
3580 .Case("ipsr", 0x5)
3581 .Case("epsr", 0x6)
3582 .Case("iepsr", 0x7)
3583 .Case("msp", 0x8)
3584 .Case("psp", 0x9)
3585 .Case("primask", 0x10)
3586 .Case("basepri", 0x11)
3587 .Case("basepri_max", 0x12)
3588 .Case("faultmask", 0x13)
3589 .Case("control", 0x14)
Bradley Smithf277c8a2016-01-25 11:25:36 +00003590 .Case("msplim", 0x0a)
3591 .Case("psplim", 0x0b)
3592 .Case("sp", 0x18)
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003593 .Default(-1);
3594}
3595
3596// The flags here are common to those allowed for apsr in the A class cores and
3597// those allowed for the special registers in the M class cores. Returns a
3598// value representing which flags were present, -1 if invalid.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003599static inline int getMClassFlagsMask(StringRef Flags, bool hasDSP) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003600 if (Flags.empty())
Artyom Skrobovcf296442015-09-24 17:31:16 +00003601 return 0x2 | (int)hasDSP;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003602
3603 return StringSwitch<int>(Flags)
3604 .Case("g", 0x1)
3605 .Case("nzcvq", 0x2)
3606 .Case("nzcvqg", 0x3)
3607 .Default(-1);
3608}
3609
3610static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead,
3611 const ARMSubtarget *Subtarget) {
3612 // Ensure that the register (without flags) was a valid M Class special
3613 // register.
3614 int SYSmvalue = getMClassRegisterSYSmValueMask(Reg);
3615 if (SYSmvalue == -1)
3616 return -1;
3617
3618 // basepri, basepri_max and faultmask are only valid for V7m.
3619 if (!Subtarget->hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
3620 return -1;
3621
Bradley Smithf277c8a2016-01-25 11:25:36 +00003622 if (Subtarget->has8MSecExt() && Flags.lower() == "ns") {
3623 Flags = "";
3624 SYSmvalue |= 0x80;
3625 }
3626
3627 if (!Subtarget->has8MSecExt() &&
3628 (SYSmvalue == 0xa || SYSmvalue == 0xb || SYSmvalue > 0x14))
3629 return -1;
3630
3631 if (!Subtarget->hasV8MMainlineOps() &&
3632 (SYSmvalue == 0x8a || SYSmvalue == 0x8b || SYSmvalue == 0x91 ||
3633 SYSmvalue == 0x93))
3634 return -1;
3635
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003636 // If it was a read then we won't be expecting flags and so at this point
3637 // we can return the mask.
3638 if (IsRead) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00003639 if (Flags.empty())
3640 return SYSmvalue;
3641 else
3642 return -1;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003643 }
3644
3645 // We know we are now handling a write so need to get the mask for the flags.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003646 int Mask = getMClassFlagsMask(Flags, Subtarget->hasDSP());
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003647
3648 // Only apsr, iapsr, eapsr, xpsr can have flags. The other register values
3649 // shouldn't have flags present.
3650 if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.empty()))
3651 return -1;
3652
3653 // The _g and _nzcvqg versions are only valid if the DSP extension is
3654 // available.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003655 if (!Subtarget->hasDSP() && (Mask & 0x1))
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003656 return -1;
3657
3658 // The register was valid so need to put the mask in the correct place
3659 // (the flags need to be in bits 11-10) and combine with the SYSmvalue to
3660 // construct the operand for the instruction node.
3661 if (SYSmvalue < 0x4)
3662 return SYSmvalue | Mask << 10;
3663
3664 return SYSmvalue;
3665}
3666
3667static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
3668 // The mask operand contains the special register (R Bit) in bit 4, whether
3669 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
3670 // bits 3-0 contains the fields to be accessed in the special register, set by
3671 // the flags provided with the register.
3672 int Mask = 0;
3673 if (Reg == "apsr") {
3674 // The flags permitted for apsr are the same flags that are allowed in
3675 // M class registers. We get the flag value and then shift the flags into
3676 // the correct place to combine with the mask.
Artyom Skrobov6fbef2a2015-08-05 11:02:14 +00003677 Mask = getMClassFlagsMask(Flags, true);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003678 if (Mask == -1)
3679 return -1;
3680 return Mask << 2;
3681 }
3682
3683 if (Reg != "cpsr" && Reg != "spsr") {
3684 return -1;
3685 }
3686
3687 // This is the same as if the flags were "fc"
3688 if (Flags.empty() || Flags == "all")
3689 return Mask | 0x9;
3690
3691 // Inspect the supplied flags string and set the bits in the mask for
3692 // the relevant and valid flags allowed for cpsr and spsr.
3693 for (char Flag : Flags) {
3694 int FlagVal;
3695 switch (Flag) {
3696 case 'c':
3697 FlagVal = 0x1;
3698 break;
3699 case 'x':
3700 FlagVal = 0x2;
3701 break;
3702 case 's':
3703 FlagVal = 0x4;
3704 break;
3705 case 'f':
3706 FlagVal = 0x8;
3707 break;
3708 default:
3709 FlagVal = 0;
3710 }
3711
3712 // This avoids allowing strings where the same flag bit appears twice.
3713 if (!FlagVal || (Mask & FlagVal))
3714 return -1;
3715 Mask |= FlagVal;
3716 }
3717
3718 // If the register is spsr then we need to set the R bit.
3719 if (Reg == "spsr")
3720 Mask |= 0x10;
3721
3722 return Mask;
3723}
3724
3725// Lower the read_register intrinsic to ARM specific DAG nodes
3726// using the supplied metadata string to select the instruction node to use
3727// and the registers/masks to construct as operands for the node.
3728SDNode *ARMDAGToDAGISel::SelectReadRegister(SDNode *N){
3729 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3730 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3731 bool IsThumb2 = Subtarget->isThumb2();
3732 SDLoc DL(N);
3733
3734 std::vector<SDValue> Ops;
3735 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3736
3737 if (!Ops.empty()) {
3738 // If the special register string was constructed of fields (as defined
3739 // in the ACLE) then need to lower to MRC node (32 bit) or
3740 // MRRC node(64 bit), we can make the distinction based on the number of
3741 // operands we have.
3742 unsigned Opcode;
3743 SmallVector<EVT, 3> ResTypes;
3744 if (Ops.size() == 5){
3745 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
3746 ResTypes.append({ MVT::i32, MVT::Other });
3747 } else {
3748 assert(Ops.size() == 3 &&
3749 "Invalid number of fields in special register string.");
3750 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
3751 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
3752 }
3753
3754 Ops.push_back(getAL(CurDAG, DL));
3755 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3756 Ops.push_back(N->getOperand(0));
3757 return CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops);
3758 }
3759
3760 std::string SpecialReg = RegString->getString().lower();
3761
3762 int BankedReg = getBankedRegisterMask(SpecialReg);
3763 if (BankedReg != -1) {
3764 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
3765 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3766 N->getOperand(0) };
3767 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
3768 DL, MVT::i32, MVT::Other, Ops);
3769 }
3770
3771 // The VFP registers are read by creating SelectionDAG nodes with opcodes
3772 // corresponding to the register that is being read from. So we switch on the
3773 // string to find which opcode we need to use.
3774 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3775 .Case("fpscr", ARM::VMRS)
3776 .Case("fpexc", ARM::VMRS_FPEXC)
3777 .Case("fpsid", ARM::VMRS_FPSID)
3778 .Case("mvfr0", ARM::VMRS_MVFR0)
3779 .Case("mvfr1", ARM::VMRS_MVFR1)
3780 .Case("mvfr2", ARM::VMRS_MVFR2)
3781 .Case("fpinst", ARM::VMRS_FPINST)
3782 .Case("fpinst2", ARM::VMRS_FPINST2)
3783 .Default(0);
3784
3785 // If an opcode was found then we can lower the read to a VFP instruction.
3786 if (Opcode) {
3787 if (!Subtarget->hasVFP2())
3788 return nullptr;
3789 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
3790 return nullptr;
3791
3792 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3793 N->getOperand(0) };
3794 return CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops);
3795 }
3796
3797 // If the target is M Class then need to validate that the register string
3798 // is an acceptable value, so check that a mask can be constructed from the
3799 // string.
3800 if (Subtarget->isMClass()) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00003801 StringRef Flags = "", Reg = SpecialReg;
3802 if (Reg.endswith("_ns")) {
3803 Flags = "ns";
3804 Reg = Reg.drop_back(3);
3805 }
3806
3807 int SYSmValue = getMClassRegisterMask(Reg, Flags, true, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003808 if (SYSmValue == -1)
3809 return nullptr;
3810
3811 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
3812 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3813 N->getOperand(0) };
3814 return CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops);
3815 }
3816
3817 // Here we know the target is not M Class so we need to check if it is one
3818 // of the remaining possible values which are apsr, cpsr or spsr.
3819 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
3820 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3821 N->getOperand(0) };
3822 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS, DL,
3823 MVT::i32, MVT::Other, Ops);
3824 }
3825
3826 if (SpecialReg == "spsr") {
3827 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3828 N->getOperand(0) };
3829 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys,
3830 DL, MVT::i32, MVT::Other, Ops);
3831 }
3832
3833 return nullptr;
3834}
3835
3836// Lower the write_register intrinsic to ARM specific DAG nodes
3837// using the supplied metadata string to select the instruction node to use
3838// and the registers/masks to use in the nodes
3839SDNode *ARMDAGToDAGISel::SelectWriteRegister(SDNode *N){
3840 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3841 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3842 bool IsThumb2 = Subtarget->isThumb2();
3843 SDLoc DL(N);
3844
3845 std::vector<SDValue> Ops;
3846 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3847
3848 if (!Ops.empty()) {
3849 // If the special register string was constructed of fields (as defined
3850 // in the ACLE) then need to lower to MCR node (32 bit) or
3851 // MCRR node(64 bit), we can make the distinction based on the number of
3852 // operands we have.
3853 unsigned Opcode;
3854 if (Ops.size() == 5) {
3855 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
3856 Ops.insert(Ops.begin()+2, N->getOperand(2));
3857 } else {
3858 assert(Ops.size() == 3 &&
3859 "Invalid number of fields in special register string.");
3860 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
3861 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
3862 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
3863 }
3864
3865 Ops.push_back(getAL(CurDAG, DL));
3866 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3867 Ops.push_back(N->getOperand(0));
3868
3869 return CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops);
3870 }
3871
3872 std::string SpecialReg = RegString->getString().lower();
3873 int BankedReg = getBankedRegisterMask(SpecialReg);
3874 if (BankedReg != -1) {
3875 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
3876 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3877 N->getOperand(0) };
3878 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
3879 DL, MVT::Other, Ops);
3880 }
3881
3882 // The VFP registers are written to by creating SelectionDAG nodes with
3883 // opcodes corresponding to the register that is being written. So we switch
3884 // on the string to find which opcode we need to use.
3885 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3886 .Case("fpscr", ARM::VMSR)
3887 .Case("fpexc", ARM::VMSR_FPEXC)
3888 .Case("fpsid", ARM::VMSR_FPSID)
3889 .Case("fpinst", ARM::VMSR_FPINST)
3890 .Case("fpinst2", ARM::VMSR_FPINST2)
3891 .Default(0);
3892
3893 if (Opcode) {
3894 if (!Subtarget->hasVFP2())
3895 return nullptr;
3896 Ops = { N->getOperand(2), getAL(CurDAG, DL),
3897 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
3898 return CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops);
3899 }
3900
Bradley Smithf277c8a2016-01-25 11:25:36 +00003901 std::pair<StringRef, StringRef> Fields;
3902 Fields = StringRef(SpecialReg).rsplit('_');
3903 std::string Reg = Fields.first.str();
3904 StringRef Flags = Fields.second;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003905
3906 // If the target was M Class then need to validate the special register value
3907 // and retrieve the mask for use in the instruction node.
3908 if (Subtarget->isMClass()) {
3909 // basepri_max gets split so need to correct Reg and Flags.
3910 if (SpecialReg == "basepri_max") {
3911 Reg = SpecialReg;
3912 Flags = "";
3913 }
3914 int SYSmValue = getMClassRegisterMask(Reg, Flags, false, Subtarget);
3915 if (SYSmValue == -1)
3916 return nullptr;
3917
3918 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
3919 N->getOperand(2), getAL(CurDAG, DL),
3920 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
3921 return CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops);
3922 }
3923
3924 // We then check to see if a valid mask can be constructed for one of the
3925 // register string values permitted for the A and R class cores. These values
3926 // are apsr, spsr and cpsr; these are also valid on older cores.
3927 int Mask = getARClassRegisterMask(Reg, Flags);
3928 if (Mask != -1) {
3929 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
3930 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3931 N->getOperand(0) };
3932 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
3933 DL, MVT::Other, Ops);
3934 }
3935
3936 return nullptr;
3937}
3938
Weiming Zhaoc5987002013-02-14 18:10:21 +00003939SDNode *ARMDAGToDAGISel::SelectInlineAsm(SDNode *N){
3940 std::vector<SDValue> AsmNodeOperands;
3941 unsigned Flag, Kind;
3942 bool Changed = false;
3943 unsigned NumOps = N->getNumOperands();
3944
Weiming Zhaoc5987002013-02-14 18:10:21 +00003945 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
3946 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
3947 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
3948 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003949 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
3950 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
3951 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00003952
Andrew Trickef9de2a2013-05-25 02:42:55 +00003953 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00003954 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
3955 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003956
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003957 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003958 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003959 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00003960 SDValue op = N->getOperand(i);
3961 AsmNodeOperands.push_back(op);
3962
3963 if (i < InlineAsm::Op_FirstOperand)
3964 continue;
3965
3966 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
3967 Flag = C->getZExtValue();
3968 Kind = InlineAsm::getKind(Flag);
3969 }
3970 else
3971 continue;
3972
Joey Gouly392cdad2013-07-08 19:52:51 +00003973 // Immediate operands to inline asm in the SelectionDAG are modeled with
3974 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
3975 // the second is a constant with the value of the immediate. If we get here
3976 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00003977 if (Kind == InlineAsm::Kind_Imm) {
3978 SDValue op = N->getOperand(++i);
3979 AsmNodeOperands.push_back(op);
3980 continue;
3981 }
3982
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003983 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
3984 if (NumRegs)
3985 OpChanged.push_back(false);
3986
3987 unsigned DefIdx = 0;
3988 bool IsTiedToChangedOp = false;
3989 // If it's a use that is tied with a previous def, it has no
3990 // reg class constraint.
3991 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
3992 IsTiedToChangedOp = OpChanged[DefIdx];
3993
Weiming Zhaoc5987002013-02-14 18:10:21 +00003994 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
3995 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
3996 continue;
3997
Weiming Zhaoc5987002013-02-14 18:10:21 +00003998 unsigned RC;
3999 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004000 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
4001 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00004002 continue;
4003
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004004 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00004005 SDValue V0 = N->getOperand(i+1);
4006 SDValue V1 = N->getOperand(i+2);
4007 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
4008 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
4009 SDValue PairedReg;
4010 MachineRegisterInfo &MRI = MF->getRegInfo();
4011
4012 if (Kind == InlineAsm::Kind_RegDef ||
4013 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
4014 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
4015 // the original GPRs.
4016
4017 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4018 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4019 SDValue Chain = SDValue(N,0);
4020
4021 SDNode *GU = N->getGluedUser();
4022 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
4023 Chain.getValue(1));
4024
4025 // Extract values from a GPRPair reg and copy to the original GPR reg.
4026 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4027 RegCopy);
4028 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4029 RegCopy);
4030 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
4031 RegCopy.getValue(1));
4032 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
4033
4034 // Update the original glue user.
4035 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
4036 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00004037 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004038 }
4039 else {
4040 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
4041 // GPRPair and then pass the GPRPair to the inline asm.
4042 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
4043
4044 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
4045 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
4046 Chain.getValue(1));
4047 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
4048 T0.getValue(1));
4049 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
4050
4051 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
4052 // i32 VRs of inline asm with it.
4053 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4054 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4055 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
4056
4057 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
4058 Glue = Chain.getValue(1);
4059 }
4060
4061 Changed = true;
4062
4063 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004064 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004065 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00004066 if (IsTiedToChangedOp)
4067 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
4068 else
4069 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004070 // Replace the current flag.
4071 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00004072 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004073 // Add the new register node and skip the original two GPRs.
4074 AsmNodeOperands.push_back(PairedReg);
4075 // Skip the next two GPRs.
4076 i += 2;
4077 }
4078 }
4079
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004080 if (Glue.getNode())
4081 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004082 if (!Changed)
Craig Topper062a2ba2014-04-25 05:30:21 +00004083 return nullptr;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004084
Andrew Trickef9de2a2013-05-25 02:42:55 +00004085 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00004086 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004087 New->setNodeId(-1);
4088 return New.getNode();
4089}
4090
4091
Bob Wilsona2c462b2009-05-19 05:53:42 +00004092bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00004093SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00004094 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004095 switch(ConstraintID) {
4096 default:
4097 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00004098 case InlineAsm::Constraint_i:
4099 // FIXME: It seems strange that 'i' is needed here since it's supposed to
4100 // be an immediate and not a memory constraint.
4101 // Fallthrough.
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004102 case InlineAsm::Constraint_m:
James Molloy72222f52015-10-26 10:04:52 +00004103 case InlineAsm::Constraint_o:
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004104 case InlineAsm::Constraint_Q:
4105 case InlineAsm::Constraint_Um:
4106 case InlineAsm::Constraint_Un:
4107 case InlineAsm::Constraint_Uq:
4108 case InlineAsm::Constraint_Us:
4109 case InlineAsm::Constraint_Ut:
4110 case InlineAsm::Constraint_Uv:
4111 case InlineAsm::Constraint_Uy:
4112 // Require the address to be in a register. That is safe for all ARM
4113 // variants and it is hard to do anything much smarter without knowing
4114 // how the operand is used.
4115 OutOps.push_back(Op);
4116 return false;
4117 }
4118 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00004119}
4120
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004121/// createARMISelDag - This pass converts a legalized DAG into a
4122/// ARM-specific DAG, ready for instruction scheduling.
4123///
Bob Wilson2dd957f2009-09-28 14:30:20 +00004124FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
4125 CodeGenOpt::Level OptLevel) {
4126 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004127}