blob: a6087d663a3e183ba8c6e01c209ddc93c9eb9756 [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"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000032#include "llvm/Support/Debug.h"
Torok Edwinfb8d6d52009-07-08 20:53:28 +000033#include "llvm/Support/ErrorHandling.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000034#include "llvm/Target/TargetLowering.h"
35#include "llvm/Target/TargetOptions.h"
Torok Edwinfb8d6d52009-07-08 20:53:28 +000036
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000037using namespace llvm;
38
Chandler Carruth84e68b22014-04-22 02:41:26 +000039#define DEBUG_TYPE "arm-isel"
40
Evan Cheng59069ec2010-07-30 23:33:54 +000041static cl::opt<bool>
42DisableShifterOp("disable-shifter-op", cl::Hidden,
43 cl::desc("Disable isel of shifter-op"),
44 cl::init(false));
45
Evan Cheng62c7b5b2010-12-05 22:04:16 +000046static cl::opt<bool>
47CheckVMLxHazard("check-vmlx-hazard", cl::Hidden,
48 cl::desc("Check fp vmla / vmls hazard at isel time"),
Bob Wilson0858c3a2011-04-19 18:11:57 +000049 cl::init(true));
Evan Cheng62c7b5b2010-12-05 22:04:16 +000050
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000051//===--------------------------------------------------------------------===//
52/// ARMDAGToDAGISel - ARM specific code to select ARM machine
53/// instructions for SelectionDAG operations.
54///
55namespace {
Jim Grosbach08605202010-09-29 19:03:54 +000056
57enum AddrMode2Type {
58 AM2_BASE, // Simple AM2 (+-imm12)
59 AM2_SHOP // Shifter-op AM2
60};
61
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000062class ARMDAGToDAGISel : public SelectionDAGISel {
Evan Cheng10043e22007-01-19 07:51:42 +000063 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
64 /// make the right decision when generating code for different targets.
65 const ARMSubtarget *Subtarget;
66
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000067public:
Eric Christopher2f991c92014-07-03 22:24:49 +000068 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, CodeGenOpt::Level OptLevel)
69 : SelectionDAGISel(tm, OptLevel) {}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000070
Eric Christopher0e6e7cf2014-05-22 02:00:27 +000071 bool runOnMachineFunction(MachineFunction &MF) override {
72 // Reset the subtarget each time through.
Eric Christopher22b2ad22015-02-20 08:24:37 +000073 Subtarget = &MF.getSubtarget<ARMSubtarget>();
Eric Christopher0e6e7cf2014-05-22 02:00:27 +000074 SelectionDAGISel::runOnMachineFunction(MF);
75 return true;
76 }
77
Craig Topper6bc27bf2014-03-10 02:09:33 +000078 const char *getPassName() const override {
Evan Cheng10043e22007-01-19 07:51:42 +000079 return "ARM Instruction Selection";
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000080 }
81
Craig Topper6bc27bf2014-03-10 02:09:33 +000082 void PreprocessISelDAG() override;
Evan Chengeae6d2c2012-12-19 20:16:09 +000083
Bob Wilson4facd962009-10-08 18:51:31 +000084 /// getI32Imm - Return a target constant of type i32 with the specified
85 /// value.
Benjamin Kramerbdc49562016-06-12 15:39:02 +000086 inline SDValue getI32Imm(unsigned Imm, const SDLoc &dl) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +000087 return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000088 }
89
Justin Bogner45571362016-05-12 00:31:09 +000090 void Select(SDNode *N) override;
Evan Cheng62c7b5b2010-12-05 22:04:16 +000091
92 bool hasNoVMLxHazardUse(SDNode *N) const;
Evan Cheng59bbc542010-10-27 23:41:30 +000093 bool isShifterOpProfitable(const SDValue &Shift,
94 ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt);
Owen Andersonb595ed02011-07-21 18:54:16 +000095 bool SelectRegShifterOperand(SDValue N, SDValue &A,
96 SDValue &B, SDValue &C,
97 bool CheckProfitability = true);
98 bool SelectImmShifterOperand(SDValue N, SDValue &A,
Owen Anderson04912702011-07-21 23:38:37 +000099 SDValue &B, bool CheckProfitability = true);
100 bool SelectShiftRegShifterOperand(SDValue N, SDValue &A,
Owen Anderson6d557452011-03-18 19:46:58 +0000101 SDValue &B, SDValue &C) {
102 // Don't apply the profitability check
Owen Anderson04912702011-07-21 23:38:37 +0000103 return SelectRegShifterOperand(N, A, B, C, false);
104 }
105 bool SelectShiftImmShifterOperand(SDValue N, SDValue &A,
106 SDValue &B) {
107 // Don't apply the profitability check
108 return SelectImmShifterOperand(N, A, B, false);
Owen Anderson6d557452011-03-18 19:46:58 +0000109 }
110
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000111 bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
112 bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);
113
Jim Grosbach08605202010-09-29 19:03:54 +0000114 AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base,
115 SDValue &Offset, SDValue &Opc);
116 bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset,
117 SDValue &Opc) {
118 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE;
119 }
120
121 bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset,
122 SDValue &Opc) {
123 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP;
124 }
125
126 bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset,
127 SDValue &Opc) {
128 SelectAddrMode2Worker(N, Base, Offset, Opc);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000129// return SelectAddrMode2ShOp(N, Base, Offset, Opc);
Jim Grosbach08605202010-09-29 19:03:54 +0000130 // This always matches one way or another.
131 return true;
132 }
133
Tim Northover42180442013-08-22 09:57:11 +0000134 bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) {
135 const ConstantSDNode *CN = cast<ConstantSDNode>(N);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000136 Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32);
Tim Northover42180442013-08-22 09:57:11 +0000137 Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32);
138 return true;
139 }
140
Owen Anderson2aedba62011-07-26 20:54:26 +0000141 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
142 SDValue &Offset, SDValue &Opc);
143 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000144 SDValue &Offset, SDValue &Opc);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000145 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
146 SDValue &Offset, SDValue &Opc);
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000147 bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000148 bool SelectAddrMode3(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000149 SDValue &Offset, SDValue &Opc);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000150 bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000151 SDValue &Offset, SDValue &Opc);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000152 bool SelectAddrMode5(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000153 SDValue &Offset);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000154 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
Bob Wilsone3ecd5f2011-02-25 06:42:42 +0000155 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000156
Evan Chengdfce83c2011-01-17 08:03:18 +0000157 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
Evan Cheng10043e22007-01-19 07:51:42 +0000158
Bill Wendling092a7bd2010-12-14 03:36:38 +0000159 // Thumb Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000160 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
Bill Wendling092a7bd2010-12-14 03:36:38 +0000161 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
162 SDValue &OffImm);
163 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
164 SDValue &OffImm);
165 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
166 SDValue &OffImm);
167 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
168 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000169 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +0000170
Bill Wendling092a7bd2010-12-14 03:36:38 +0000171 // Thumb 2 Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000172 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
173 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000174 SDValue &OffImm);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000175 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +0000176 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000177 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000178 SDValue &OffReg, SDValue &ShImm);
Tim Northovera7ecd242013-07-16 09:46:55 +0000179 bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Chengb23b50d2009-06-29 07:51:04 +0000180
Evan Cheng0fc80842010-11-12 22:42:47 +0000181 inline bool is_so_imm(unsigned Imm) const {
182 return ARM_AM::getSOImmVal(Imm) != -1;
183 }
184
185 inline bool is_so_imm_not(unsigned Imm) const {
186 return ARM_AM::getSOImmVal(~Imm) != -1;
187 }
188
189 inline bool is_t2_so_imm(unsigned Imm) const {
190 return ARM_AM::getT2SOImmVal(Imm) != -1;
191 }
192
193 inline bool is_t2_so_imm_not(unsigned Imm) const {
194 return ARM_AM::getT2SOImmVal(~Imm) != -1;
195 }
196
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000197 // Include the pieces autogenerated from the target description.
198#include "ARMGenDAGISel.inc"
Bob Wilsona2c462b2009-05-19 05:53:42 +0000199
200private:
Justin Bogner45571362016-05-12 00:31:09 +0000201 /// Indexed (pre/post inc/dec) load matching code for ARM.
202 bool tryARMIndexedLoad(SDNode *N);
203 bool tryT2IndexedLoad(SDNode *N);
Evan Cheng84c6cda2009-07-02 07:28:31 +0000204
Bob Wilson340861d2010-03-23 05:25:43 +0000205 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
206 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson12b47992009-10-14 17:28:52 +0000207 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson340861d2010-03-23 05:25:43 +0000208 /// For NumVecs <= 2, QOpcodes1 is not used.
Justin Bogner45571362016-05-12 00:31:09 +0000209 void SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
210 const uint16_t *DOpcodes, const uint16_t *QOpcodes0,
211 const uint16_t *QOpcodes1);
Bob Wilson12b47992009-10-14 17:28:52 +0000212
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000213 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000214 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000215 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000216 /// For NumVecs <= 2, QOpcodes1 is not used.
Justin Bogner45571362016-05-12 00:31:09 +0000217 void SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
218 const uint16_t *DOpcodes, const uint16_t *QOpcodes0,
219 const uint16_t *QOpcodes1);
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000220
Bob Wilson93117bc2009-10-14 16:46:45 +0000221 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilson4145e3a2009-10-14 16:19:03 +0000222 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsond5c57a52010-09-13 23:01:35 +0000223 /// load/store of D registers and Q registers.
Justin Bogner45571362016-05-12 00:31:09 +0000224 void SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
225 unsigned NumVecs, const uint16_t *DOpcodes,
226 const uint16_t *QOpcodes);
Bob Wilson4145e3a2009-10-14 16:19:03 +0000227
Bob Wilson2d790df2010-11-28 06:51:26 +0000228 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
229 /// should be 2, 3 or 4. The opcode array specifies the instructions used
230 /// for loading D registers. (Q registers are not supported.)
Justin Bogner45571362016-05-12 00:31:09 +0000231 void SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
232 const uint16_t *Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +0000233
Bob Wilson5bc8a792010-07-07 00:08:54 +0000234 /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2,
235 /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be
236 /// generated to force the table registers to be consecutive.
Justin Bogner45571362016-05-12 00:31:09 +0000237 void SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc);
Bob Wilson3ed511b2010-07-06 23:36:25 +0000238
Justin Bogner45571362016-05-12 00:31:09 +0000239 /// Try to select SBFX/UBFX instructions for ARM.
240 bool tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000241
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000242 // Select special operations if node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +0000243 bool tryABSOp(SDNode *N);
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000244
Justin Bogner45571362016-05-12 00:31:09 +0000245 bool tryReadRegister(SDNode *N);
246 bool tryWriteRegister(SDNode *N);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +0000247
Justin Bogner45571362016-05-12 00:31:09 +0000248 bool tryInlineAsm(SDNode *N);
Weiming Zhaoc5987002013-02-14 18:10:21 +0000249
Justin Bogner45571362016-05-12 00:31:09 +0000250 void SelectConcatVector(SDNode *N);
Evan Chengd85631e2010-05-05 18:28:36 +0000251
Justin Bogner45571362016-05-12 00:31:09 +0000252 bool trySMLAWSMULW(SDNode *N);
Sam Parker2d5126c2016-04-08 16:02:53 +0000253
Justin Bogner45571362016-05-12 00:31:09 +0000254 void SelectCMP_SWAP(SDNode *N);
Tim Northoverb629c772016-04-18 21:48:55 +0000255
Evan Chengd9c55362009-07-02 01:23:32 +0000256 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
257 /// inline asm expressions.
Daniel Sanders60f1db02015-03-13 12:45:09 +0000258 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Craig Topper6bc27bf2014-03-10 02:09:33 +0000259 std::vector<SDValue> &OutOps) override;
Bob Wilsone6b778d2009-10-06 22:01:59 +0000260
Weiming Zhao95782222012-11-17 00:23:35 +0000261 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhao8f56f882012-11-16 21:55:34 +0000262 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao95782222012-11-17 00:23:35 +0000263 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
264 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
265 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Chengc2ae5f52010-05-10 17:34:18 +0000266
Bob Wilsond8a9a042010-06-04 00:04:02 +0000267 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +0000268 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
269 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
270 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000271
272 // Get the alignment operand for a NEON VLD or VST instruction.
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000273 SDValue GetVLDSTAlign(SDValue Align, const SDLoc &dl, unsigned NumVecs,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000274 bool is64BitVector);
John Brawn056e6782015-09-14 15:19:41 +0000275
276 /// Returns the number of instructions required to materialize the given
277 /// constant in a register, or 3 if a literal pool load is needed.
278 unsigned ConstantMaterializationCost(unsigned Val) const;
279
280 /// Checks if N is a multiplication by a constant where we can extract out a
281 /// power of two from the constant so that it can be used in a shift, but only
282 /// if it simplifies the materialization of the constant. Returns true if it
283 /// is, and assigns to PowerOfTwo the power of two that should be extracted
284 /// out and to NewMulConst the new constant to be multiplied by.
285 bool canExtractShiftFromMul(const SDValue &N, unsigned MaxShift,
286 unsigned &PowerOfTwo, SDValue &NewMulConst) const;
287
288 /// Replace N with M in CurDAG, in a way that also ensures that M gets
289 /// selected when N would have been selected.
290 void replaceDAGValue(const SDValue &N, SDValue M);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000291};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000292}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000293
Sandeep Patel423e42b2009-10-13 18:59:48 +0000294/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
295/// operand. If so Imm will receive the 32-bit value.
296static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
297 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
298 Imm = cast<ConstantSDNode>(N)->getZExtValue();
299 return true;
300 }
301 return false;
302}
303
304// isInt32Immediate - This method tests to see if a constant operand.
305// If so Imm will receive the 32 bit value.
306static bool isInt32Immediate(SDValue N, unsigned &Imm) {
307 return isInt32Immediate(N.getNode(), Imm);
308}
309
310// isOpcWithIntImmediate - This method tests to see if the node is a specific
311// opcode and that it has a immediate integer right operand.
312// If so Imm will receive the 32 bit value.
313static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
314 return N->getOpcode() == Opc &&
315 isInt32Immediate(N->getOperand(1).getNode(), Imm);
316}
317
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000318/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000319/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000320///
321/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000322static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000323 int RangeMin, int RangeMax,
324 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000325 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000326
327 // Check that this is a constant.
328 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
329 if (!C)
330 return false;
331
332 ScaledConstant = (int) C->getZExtValue();
333 if ((ScaledConstant % Scale) != 0)
334 return false;
335
336 ScaledConstant /= Scale;
337 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
338}
339
Evan Chengeae6d2c2012-12-19 20:16:09 +0000340void ARMDAGToDAGISel::PreprocessISelDAG() {
341 if (!Subtarget->hasV6T2Ops())
342 return;
343
344 bool isThumb2 = Subtarget->isThumb();
345 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
346 E = CurDAG->allnodes_end(); I != E; ) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000347 SDNode *N = &*I++; // Preincrement iterator to avoid invalidation issues.
Evan Chengeae6d2c2012-12-19 20:16:09 +0000348
349 if (N->getOpcode() != ISD::ADD)
350 continue;
351
352 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
353 // leading zeros, followed by consecutive set bits, followed by 1 or 2
354 // trailing zeros, e.g. 1020.
355 // Transform the expression to
356 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
357 // of trailing zeros of c2. The left shift would be folded as an shifter
358 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
359 // node (UBFX).
360
361 SDValue N0 = N->getOperand(0);
362 SDValue N1 = N->getOperand(1);
363 unsigned And_imm = 0;
364 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
365 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
366 std::swap(N0, N1);
367 }
368 if (!And_imm)
369 continue;
370
371 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000372 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000373 if (TZ != 1 && TZ != 2)
374 // Be conservative here. Shifter operands aren't always free. e.g. On
375 // Swift, left shifter operand of 1 / 2 for free but others are not.
376 // e.g.
377 // ubfx r3, r1, #16, #8
378 // ldr.w r3, [r0, r3, lsl #2]
379 // vs.
380 // mov.w r9, #1020
381 // and.w r2, r9, r1, lsr #14
382 // ldr r2, [r0, r2]
383 continue;
384 And_imm >>= TZ;
385 if (And_imm & (And_imm + 1))
386 continue;
387
388 // Look for (and (srl X, c1), c2).
389 SDValue Srl = N1.getOperand(0);
390 unsigned Srl_imm = 0;
391 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
392 (Srl_imm <= 2))
393 continue;
394
395 // Make sure first operand is not a shifter operand which would prevent
396 // folding of the left shift.
397 SDValue CPTmp0;
398 SDValue CPTmp1;
399 SDValue CPTmp2;
400 if (isThumb2) {
John Brawnd8b405a2015-09-07 11:45:18 +0000401 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
Evan Chengeae6d2c2012-12-19 20:16:09 +0000402 continue;
403 } else {
404 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
405 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
406 continue;
407 }
408
409 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000410 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000411 Srl.getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000412 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl),
413 MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000414 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000415 Srl,
416 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000417 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000418 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32));
Evan Chengeae6d2c2012-12-19 20:16:09 +0000419 CurDAG->UpdateNodeOperands(N, N0, N1);
Jim Grosbach1a597112014-04-03 23:43:18 +0000420 }
Evan Chengeae6d2c2012-12-19 20:16:09 +0000421}
422
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000423/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
424/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
425/// least on current ARM implementations) which should be avoidded.
426bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
427 if (OptLevel == CodeGenOpt::None)
428 return true;
429
430 if (!CheckVMLxHazard)
431 return true;
Bob Wilsone8a549c2012-09-29 21:43:49 +0000432
Tim Northover0feb91e2014-04-01 14:10:07 +0000433 if (!Subtarget->isCortexA7() && !Subtarget->isCortexA8() &&
434 !Subtarget->isCortexA9() && !Subtarget->isSwift())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000435 return true;
436
437 if (!N->hasOneUse())
438 return false;
439
440 SDNode *Use = *N->use_begin();
441 if (Use->getOpcode() == ISD::CopyToReg)
442 return true;
443 if (Use->isMachineOpcode()) {
Eric Christopher2f991c92014-07-03 22:24:49 +0000444 const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>(
Eric Christopherfc6de422014-08-05 02:39:49 +0000445 CurDAG->getSubtarget().getInstrInfo());
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000446
Evan Cheng6cc775f2011-06-28 19:10:37 +0000447 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
448 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000449 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000450 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000451 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
452 return true;
453 // vmlx feeding into another vmlx. We actually want to unfold
454 // the use later in the MLxExpansion pass. e.g.
455 // vmla
456 // vmla (stall 8 cycles)
457 //
458 // vmul (5 cycles)
459 // vadd (5 cycles)
460 // vmla
461 // This adds up to about 18 - 19 cycles.
462 //
463 // vmla
464 // vmul (stall 4 cycles)
465 // vadd adds up to about 14 cycles.
466 return TII->isFpMLxInstruction(Opcode);
467 }
468
469 return false;
470}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000471
Evan Cheng59bbc542010-10-27 23:41:30 +0000472bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
473 ARM_AM::ShiftOpc ShOpcVal,
474 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000475 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000476 return true;
477 if (Shift.hasOneUse())
478 return true;
479 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000480 return ShOpcVal == ARM_AM::lsl &&
481 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000482}
483
John Brawn056e6782015-09-14 15:19:41 +0000484unsigned ARMDAGToDAGISel::ConstantMaterializationCost(unsigned Val) const {
485 if (Subtarget->isThumb()) {
486 if (Val <= 255) return 1; // MOV
487 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
James Molloy65b6be12016-06-14 13:33:07 +0000488 if (Val <= 510) return 2; // MOV + ADDi8
John Brawn056e6782015-09-14 15:19:41 +0000489 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)) {
Justin Bogner8752be72016-05-05 01:43:49 +0000553 HandleSDNode Handle(N);
John Brawn056e6782015-09-14 15:19:41 +0000554 replaceDAGValue(N.getOperand(1), NewMulConst);
Justin Bogner8752be72016-05-05 01:43:49 +0000555 BaseReg = Handle.getValue();
John Brawn056e6782015-09-14 15:19:41 +0000556 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ARM_AM::lsl,
557 PowerOfTwo),
558 SDLoc(N), MVT::i32);
559 return true;
560 }
561 }
562
Evan Chenga20cde32011-07-20 23:34:39 +0000563 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000564
565 // Don't match base register only case. That is matched to a separate
566 // lower complexity pattern with explicit register operand.
567 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000568
Evan Chengb23b50d2009-06-29 07:51:04 +0000569 BaseReg = N.getOperand(0);
570 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000571 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
572 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000573 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000574 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000575 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000576 return true;
577}
578
Owen Andersonb595ed02011-07-21 18:54:16 +0000579bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
580 SDValue &BaseReg,
581 SDValue &ShReg,
582 SDValue &Opc,
583 bool CheckProfitability) {
584 if (DisableShifterOp)
585 return false;
586
587 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
588
589 // Don't match base register only case. That is matched to a separate
590 // lower complexity pattern with explicit register operand.
591 if (ShOpcVal == ARM_AM::no_shift) return false;
592
593 BaseReg = N.getOperand(0);
594 unsigned ShImmVal = 0;
595 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
596 if (RHS) return false;
597
598 ShReg = N.getOperand(1);
599 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
600 return false;
601 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000602 SDLoc(N), MVT::i32);
Owen Andersonb595ed02011-07-21 18:54:16 +0000603 return true;
604}
605
606
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000607bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
608 SDValue &Base,
609 SDValue &OffImm) {
610 // Match simple R + imm12 operands.
611
612 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000613 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
614 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000615 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000616 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000617 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000618 Base = CurDAG->getTargetFrameIndex(
619 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000620 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000621 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000622 }
Owen Anderson6d557452011-03-18 19:46:58 +0000623
Chris Lattner46c01a32011-02-13 22:25:43 +0000624 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000625 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000626 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000627 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000628 Base = N.getOperand(0);
629 } else
630 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000631 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000632 return true;
633 }
634
635 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Renato Golin63e27982014-09-09 09:57:59 +0000636 int RHSC = (int)RHS->getSExtValue();
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000637 if (N.getOpcode() == ISD::SUB)
638 RHSC = -RHSC;
639
Renato Golin63e27982014-09-09 09:57:59 +0000640 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000641 Base = N.getOperand(0);
642 if (Base.getOpcode() == ISD::FrameIndex) {
643 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000644 Base = CurDAG->getTargetFrameIndex(
645 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000646 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000647 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000648 return true;
649 }
650 }
651
652 // Base only.
653 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000654 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000655 return true;
656}
657
658
659
660bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
661 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000662 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000663 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000664 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
665 // X * [3,5,9] -> X + X * [2,4,8] etc.
666 int RHSC = (int)RHS->getZExtValue();
667 if (RHSC & 1) {
668 RHSC = RHSC & ~1;
669 ARM_AM::AddrOpc AddSub = ARM_AM::add;
670 if (RHSC < 0) {
671 AddSub = ARM_AM::sub;
672 RHSC = - RHSC;
673 }
674 if (isPowerOf2_32(RHSC)) {
675 unsigned ShAmt = Log2_32(RHSC);
676 Base = Offset = N.getOperand(0);
677 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
678 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000679 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000680 return true;
681 }
682 }
683 }
684 }
685
Chris Lattner46c01a32011-02-13 22:25:43 +0000686 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
687 // ISD::OR that is equivalent to an ISD::ADD.
688 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000689 return false;
690
691 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000692 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000693 int RHSC;
694 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
695 -0x1000+1, 0x1000, RHSC)) // 12 bits.
696 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000697 }
698
699 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000700 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000701 ARM_AM::ShiftOpc ShOpcVal =
702 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000703 unsigned ShAmt = 0;
704
705 Base = N.getOperand(0);
706 Offset = N.getOperand(1);
707
708 if (ShOpcVal != ARM_AM::no_shift) {
709 // Check to see if the RHS of the shift is a constant, if not, we can't fold
710 // it.
711 if (ConstantSDNode *Sh =
712 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
713 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000714 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
715 Offset = N.getOperand(1).getOperand(0);
716 else {
717 ShAmt = 0;
718 ShOpcVal = ARM_AM::no_shift;
719 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000720 } else {
721 ShOpcVal = ARM_AM::no_shift;
722 }
723 }
724
725 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000726 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000727 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
728 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000729 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000730 if (ShOpcVal != ARM_AM::no_shift) {
731 // Check to see if the RHS of the shift is a constant, if not, we can't
732 // fold it.
733 if (ConstantSDNode *Sh =
734 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
735 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000736 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000737 Offset = N.getOperand(0).getOperand(0);
738 Base = N.getOperand(1);
739 } else {
740 ShAmt = 0;
741 ShOpcVal = ARM_AM::no_shift;
742 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000743 } else {
744 ShOpcVal = ARM_AM::no_shift;
745 }
746 }
747 }
748
John Brawn056e6782015-09-14 15:19:41 +0000749 // If Offset is a multiply-by-constant and it's profitable to extract a shift
750 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +0000751 if (Offset.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +0000752 unsigned PowerOfTwo = 0;
753 SDValue NewMulConst;
754 if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) {
755 replaceDAGValue(Offset.getOperand(1), NewMulConst);
756 ShAmt = PowerOfTwo;
757 ShOpcVal = ARM_AM::lsl;
758 }
759 }
760
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000761 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000762 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000763 return true;
764}
765
766
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000767//-----
768
Jim Grosbach08605202010-09-29 19:03:54 +0000769AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
770 SDValue &Base,
771 SDValue &Offset,
772 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000773 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000774 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000775 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
776 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmaneffb8942008-09-12 16:56:44 +0000777 int RHSC = (int)RHS->getZExtValue();
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000778 if (RHSC & 1) {
779 RHSC = RHSC & ~1;
780 ARM_AM::AddrOpc AddSub = ARM_AM::add;
781 if (RHSC < 0) {
782 AddSub = ARM_AM::sub;
783 RHSC = - RHSC;
784 }
785 if (isPowerOf2_32(RHSC)) {
786 unsigned ShAmt = Log2_32(RHSC);
787 Base = Offset = N.getOperand(0);
788 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
789 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000790 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000791 return AM2_SHOP;
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000792 }
793 }
794 }
795 }
796
Chris Lattner46c01a32011-02-13 22:25:43 +0000797 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
798 // ISD::OR that is equivalent to an ADD.
799 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000800 Base = N;
801 if (N.getOpcode() == ISD::FrameIndex) {
802 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000803 Base = CurDAG->getTargetFrameIndex(
804 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +0000805 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000806 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000807 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000808 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000809 Base = N.getOperand(0);
810 }
Owen Anderson9f944592009-08-11 20:47:22 +0000811 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000812 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
813 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000814 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000815 return AM2_BASE;
Rafael Espindola708cb602006-11-08 17:07:32 +0000816 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000817
Evan Cheng10043e22007-01-19 07:51:42 +0000818 // Match simple R +/- imm12 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +0000819 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000820 int RHSC;
821 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
822 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
823 Base = N.getOperand(0);
824 if (Base.getOpcode() == ISD::FrameIndex) {
825 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000826 Base = CurDAG->getTargetFrameIndex(
827 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Rafael Espindola708cb602006-11-08 17:07:32 +0000828 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000829 Offset = CurDAG->getRegister(0, MVT::i32);
830
831 ARM_AM::AddrOpc AddSub = ARM_AM::add;
832 if (RHSC < 0) {
833 AddSub = ARM_AM::sub;
834 RHSC = - RHSC;
835 }
836 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
837 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000838 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000839 return AM2_BASE;
Evan Cheng10043e22007-01-19 07:51:42 +0000840 }
Jim Grosbachc7b10f32010-09-29 17:32:29 +0000841 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000842
Bob Wilsone8a549c2012-09-29 21:43:49 +0000843 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000844 // Compute R +/- (R << N) and reuse it.
845 Base = N;
846 Offset = CurDAG->getRegister(0, MVT::i32);
847 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
848 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000849 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000850 return AM2_BASE;
851 }
852
Johnny Chenb678a562009-10-27 17:25:15 +0000853 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000854 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chenga20cde32011-07-20 23:34:39 +0000855 ARM_AM::ShiftOpc ShOpcVal =
856 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000857 unsigned ShAmt = 0;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000858
Evan Cheng10043e22007-01-19 07:51:42 +0000859 Base = N.getOperand(0);
860 Offset = N.getOperand(1);
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000861
Evan Cheng10043e22007-01-19 07:51:42 +0000862 if (ShOpcVal != ARM_AM::no_shift) {
863 // Check to see if the RHS of the shift is a constant, if not, we can't fold
864 // it.
865 if (ConstantSDNode *Sh =
866 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000867 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000868 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
869 Offset = N.getOperand(1).getOperand(0);
870 else {
871 ShAmt = 0;
872 ShOpcVal = ARM_AM::no_shift;
873 }
Evan Cheng10043e22007-01-19 07:51:42 +0000874 } else {
875 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola708cb602006-11-08 17:07:32 +0000876 }
877 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000878
Evan Cheng10043e22007-01-19 07:51:42 +0000879 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000880 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000881 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
882 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000883 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000884 if (ShOpcVal != ARM_AM::no_shift) {
885 // Check to see if the RHS of the shift is a constant, if not, we can't
886 // fold it.
887 if (ConstantSDNode *Sh =
888 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000889 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000890 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000891 Offset = N.getOperand(0).getOperand(0);
892 Base = N.getOperand(1);
893 } else {
894 ShAmt = 0;
895 ShOpcVal = ARM_AM::no_shift;
896 }
Evan Cheng10043e22007-01-19 07:51:42 +0000897 } else {
898 ShOpcVal = ARM_AM::no_shift;
899 }
900 }
901 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000902
Evan Cheng10043e22007-01-19 07:51:42 +0000903 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000904 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000905 return AM2_SHOP;
Rafael Espindola708cb602006-11-08 17:07:32 +0000906}
907
Owen Anderson2aedba62011-07-26 20:54:26 +0000908bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000909 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000910 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000911 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
912 ? cast<LoadSDNode>(Op)->getAddressingMode()
913 : cast<StoreSDNode>(Op)->getAddressingMode();
914 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
915 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000916 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000917 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
918 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000919
920 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000921 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000922 unsigned ShAmt = 0;
923 if (ShOpcVal != ARM_AM::no_shift) {
924 // Check to see if the RHS of the shift is a constant, if not, we can't fold
925 // it.
926 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000927 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000928 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
929 Offset = N.getOperand(0);
930 else {
931 ShAmt = 0;
932 ShOpcVal = ARM_AM::no_shift;
933 }
Evan Cheng10043e22007-01-19 07:51:42 +0000934 } else {
935 ShOpcVal = ARM_AM::no_shift;
936 }
937 }
938
939 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000940 SDLoc(N), MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000941 return true;
942}
943
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000944bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
945 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000946 unsigned Opcode = Op->getOpcode();
947 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
948 ? cast<LoadSDNode>(Op)->getAddressingMode()
949 : cast<StoreSDNode>(Op)->getAddressingMode();
950 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
951 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000952 int Val;
953 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000954 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000955 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000956 Opc = CurDAG->getTargetConstant(Val, SDLoc(Op), MVT::i32);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000957 return true;
958 }
959
960 return false;
961}
962
963
Owen Anderson2aedba62011-07-26 20:54:26 +0000964bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
965 SDValue &Offset, SDValue &Opc) {
966 unsigned Opcode = Op->getOpcode();
967 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
968 ? cast<LoadSDNode>(Op)->getAddressingMode()
969 : cast<StoreSDNode>(Op)->getAddressingMode();
970 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
971 ? ARM_AM::add : ARM_AM::sub;
972 int Val;
973 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
974 Offset = CurDAG->getRegister(0, MVT::i32);
975 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
976 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000977 SDLoc(Op), MVT::i32);
Owen Anderson2aedba62011-07-26 20:54:26 +0000978 return true;
979 }
980
981 return false;
982}
983
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000984bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
985 Base = N;
986 return true;
987}
Evan Cheng10043e22007-01-19 07:51:42 +0000988
Chris Lattner0e023ea2010-09-21 20:31:19 +0000989bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000990 SDValue &Base, SDValue &Offset,
991 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000992 if (N.getOpcode() == ISD::SUB) {
993 // X - C is canonicalize to X + -C, no need to handle it here.
994 Base = N.getOperand(0);
995 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000996 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0), SDLoc(N),
997 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000998 return true;
999 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001000
Chris Lattner46c01a32011-02-13 22:25:43 +00001001 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +00001002 Base = N;
1003 if (N.getOpcode() == ISD::FrameIndex) {
1004 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001005 Base = CurDAG->getTargetFrameIndex(
1006 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001007 }
Owen Anderson9f944592009-08-11 20:47:22 +00001008 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001009 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1010 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001011 return true;
1012 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001013
Evan Cheng10043e22007-01-19 07:51:42 +00001014 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001015 int RHSC;
1016 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
1017 -256 + 1, 256, RHSC)) { // 8 bits.
1018 Base = N.getOperand(0);
1019 if (Base.getOpcode() == ISD::FrameIndex) {
1020 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001021 Base = CurDAG->getTargetFrameIndex(
1022 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001023 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001024 Offset = CurDAG->getRegister(0, MVT::i32);
1025
1026 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1027 if (RHSC < 0) {
1028 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001029 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001030 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001031 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC), SDLoc(N),
1032 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001033 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001034 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001035
Evan Cheng10043e22007-01-19 07:51:42 +00001036 Base = N.getOperand(0);
1037 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001038 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1039 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001040 return true;
1041}
1042
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001043bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001044 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001045 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +00001046 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1047 ? cast<LoadSDNode>(Op)->getAddressingMode()
1048 : cast<StoreSDNode>(Op)->getAddressingMode();
1049 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
1050 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001051 int Val;
1052 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
1053 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001054 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), SDLoc(Op),
1055 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001056 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001057 }
1058
1059 Offset = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001060 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), SDLoc(Op),
1061 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001062 return true;
1063}
1064
Jim Grosbachd37f0712010-10-21 19:38:40 +00001065bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001066 SDValue &Base, SDValue &Offset) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001067 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +00001068 Base = N;
1069 if (N.getOpcode() == ISD::FrameIndex) {
1070 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001071 Base = CurDAG->getTargetFrameIndex(
1072 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +00001073 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001074 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001075 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001076 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +00001077 Base = N.getOperand(0);
1078 }
1079 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001080 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001081 return true;
1082 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001083
Evan Cheng10043e22007-01-19 07:51:42 +00001084 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001085 int RHSC;
1086 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
1087 -256 + 1, 256, RHSC)) {
1088 Base = N.getOperand(0);
1089 if (Base.getOpcode() == ISD::FrameIndex) {
1090 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001091 Base = CurDAG->getTargetFrameIndex(
1092 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001093 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001094
1095 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1096 if (RHSC < 0) {
1097 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001098 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001099 }
1100 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001101 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001102 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001103 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001104
Evan Cheng10043e22007-01-19 07:51:42 +00001105 Base = N;
1106 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001107 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001108 return true;
1109}
1110
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001111bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
1112 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +00001113 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001114
1115 unsigned Alignment = 0;
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001116
1117 MemSDNode *MemN = cast<MemSDNode>(Parent);
1118
1119 if (isa<LSBaseSDNode>(MemN) ||
1120 ((MemN->getOpcode() == ARMISD::VST1_UPD ||
1121 MemN->getOpcode() == ARMISD::VLD1_UPD) &&
1122 MemN->getConstantOperandVal(MemN->getNumOperands() - 1) == 1)) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001123 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
1124 // The maximum alignment is equal to the memory size being referenced.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001125 unsigned MMOAlign = MemN->getAlignment();
1126 unsigned MemSize = MemN->getMemoryVT().getSizeInBits() / 8;
1127 if (MMOAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001128 Alignment = MemSize;
1129 } else {
1130 // All other uses of addrmode6 are for intrinsics. For now just record
1131 // the raw alignment value; it will be refined later based on the legal
1132 // alignment operands for the intrinsic.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001133 Alignment = MemN->getAlignment();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001134 }
1135
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001136 Align = CurDAG->getTargetConstant(Alignment, SDLoc(N), MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001137 return true;
1138}
1139
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001140bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1141 SDValue &Offset) {
1142 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1143 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1144 if (AM != ISD::POST_INC)
1145 return false;
1146 Offset = N;
1147 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1148 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1149 Offset = CurDAG->getRegister(0, MVT::i32);
1150 }
1151 return true;
1152}
1153
Chris Lattner0e023ea2010-09-21 20:31:19 +00001154bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001155 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001156 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1157 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001158 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001159 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001160 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001161 return true;
1162 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001163
Evan Cheng10043e22007-01-19 07:51:42 +00001164 return false;
1165}
1166
Bill Wendling092a7bd2010-12-14 03:36:38 +00001167
1168//===----------------------------------------------------------------------===//
1169// Thumb Addressing Modes
1170//===----------------------------------------------------------------------===//
1171
Chris Lattner0e023ea2010-09-21 20:31:19 +00001172bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001173 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001174 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001175 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001176 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001177 return false;
1178
1179 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001180 return true;
1181 }
1182
Evan Cheng10043e22007-01-19 07:51:42 +00001183 Base = N.getOperand(0);
1184 Offset = N.getOperand(1);
1185 return true;
1186}
1187
Evan Cheng139edae2007-01-24 02:21:22 +00001188bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001189ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1190 SDValue &Base, SDValue &OffImm) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001191 if (!CurDAG->isBaseWithConstantOffset(N)) {
John Brawn68acdcb2015-08-13 10:48:22 +00001192 if (N.getOpcode() == ISD::ADD) {
1193 return false; // We want to select register offset instead
1194 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001195 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001196 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001197 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001198 Base = N.getOperand(0);
1199 } else {
1200 Base = N;
1201 }
1202
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001203 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001204 return true;
1205 }
1206
Evan Cheng10043e22007-01-19 07:51:42 +00001207 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001208 int RHSC;
1209 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1210 Base = N.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001211 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001212 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001213 }
1214
John Brawn68acdcb2015-08-13 10:48:22 +00001215 // Offset is too large, so use register offset instead.
1216 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001217}
1218
Bill Wendling092a7bd2010-12-14 03:36:38 +00001219bool
1220ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1221 SDValue &OffImm) {
1222 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001223}
1224
Bill Wendling092a7bd2010-12-14 03:36:38 +00001225bool
1226ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1227 SDValue &OffImm) {
1228 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001229}
1230
Bill Wendling092a7bd2010-12-14 03:36:38 +00001231bool
1232ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1233 SDValue &OffImm) {
1234 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001235}
1236
Chris Lattner0e023ea2010-09-21 20:31:19 +00001237bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1238 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001239 if (N.getOpcode() == ISD::FrameIndex) {
1240 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001241 // Only multiples of 4 are allowed for the offset, so the frame object
1242 // alignment must be at least 4.
1243 MachineFrameInfo *MFI = MF->getFrameInfo();
1244 if (MFI->getObjectAlignment(FI) < 4)
1245 MFI->setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001246 Base = CurDAG->getTargetFrameIndex(
1247 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001248 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001249 return true;
1250 }
Evan Cheng139edae2007-01-24 02:21:22 +00001251
Chris Lattner46c01a32011-02-13 22:25:43 +00001252 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001253 return false;
1254
1255 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001256 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1257 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001258 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001259 int RHSC;
1260 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1261 Base = N.getOperand(0);
1262 if (Base.getOpcode() == ISD::FrameIndex) {
1263 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001264 // For LHS+RHS to result in an offset that's a multiple of 4 the object
1265 // indexed by the LHS must be 4-byte aligned.
1266 MachineFrameInfo *MFI = MF->getFrameInfo();
1267 if (MFI->getObjectAlignment(FI) < 4)
1268 MFI->setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001269 Base = CurDAG->getTargetFrameIndex(
1270 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng139edae2007-01-24 02:21:22 +00001271 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001272 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001273 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001274 }
1275 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001276
Evan Cheng10043e22007-01-19 07:51:42 +00001277 return false;
1278}
1279
Bill Wendling092a7bd2010-12-14 03:36:38 +00001280
1281//===----------------------------------------------------------------------===//
1282// Thumb 2 Addressing Modes
1283//===----------------------------------------------------------------------===//
1284
1285
Chris Lattner0e023ea2010-09-21 20:31:19 +00001286bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001287 SDValue &Base, SDValue &OffImm) {
1288 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001289
Evan Cheng36064672009-08-11 08:52:18 +00001290 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001291 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1292 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001293 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001294 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001295 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001296 Base = CurDAG->getTargetFrameIndex(
1297 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001298 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001299 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001300 }
Owen Anderson6d557452011-03-18 19:46:58 +00001301
Chris Lattner46c01a32011-02-13 22:25:43 +00001302 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001303 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001304 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001305 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng36064672009-08-11 08:52:18 +00001306 Base = N.getOperand(0);
1307 if (Base.getOpcode() == ISD::TargetConstantPool)
1308 return false; // We want to select t2LDRpci instead.
1309 } else
1310 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001311 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001312 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001313 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001314
1315 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001316 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001317 // Let t2LDRi8 handle (R - imm8).
1318 return false;
1319
Evan Chengb23b50d2009-06-29 07:51:04 +00001320 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001321 if (N.getOpcode() == ISD::SUB)
1322 RHSC = -RHSC;
1323
1324 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001325 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001326 if (Base.getOpcode() == ISD::FrameIndex) {
1327 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001328 Base = CurDAG->getTargetFrameIndex(
1329 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin79c079b2009-07-30 18:56:48 +00001330 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001331 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001332 return true;
1333 }
1334 }
1335
Evan Cheng36064672009-08-11 08:52:18 +00001336 // Base only.
1337 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001338 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001339 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001340}
1341
Chris Lattner0e023ea2010-09-21 20:31:19 +00001342bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001343 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001344 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001345 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1346 !CurDAG->isBaseWithConstantOffset(N))
1347 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001348
Chris Lattner46c01a32011-02-13 22:25:43 +00001349 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1350 int RHSC = (int)RHS->getSExtValue();
1351 if (N.getOpcode() == ISD::SUB)
1352 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001353
Chris Lattner46c01a32011-02-13 22:25:43 +00001354 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1355 Base = N.getOperand(0);
1356 if (Base.getOpcode() == ISD::FrameIndex) {
1357 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001358 Base = CurDAG->getTargetFrameIndex(
1359 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Chengb23b50d2009-06-29 07:51:04 +00001360 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001361 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Chris Lattner46c01a32011-02-13 22:25:43 +00001362 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001363 }
1364 }
1365
1366 return false;
1367}
1368
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001369bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001370 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001371 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001372 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1373 ? cast<LoadSDNode>(Op)->getAddressingMode()
1374 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001375 int RHSC;
1376 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1377 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001378 ? CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32)
1379 : CurDAG->getTargetConstant(-RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001380 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001381 }
1382
1383 return false;
1384}
1385
Chris Lattner0e023ea2010-09-21 20:31:19 +00001386bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001387 SDValue &Base,
1388 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001389 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001390 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001391 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001392
Evan Cheng36064672009-08-11 08:52:18 +00001393 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1394 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1395 int RHSC = (int)RHS->getZExtValue();
1396 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1397 return false;
1398 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001399 return false;
1400 }
1401
Evan Chengb23b50d2009-06-29 07:51:04 +00001402 // Look for (R + R) or (R + (R << [1,2,3])).
1403 unsigned ShAmt = 0;
1404 Base = N.getOperand(0);
1405 OffReg = N.getOperand(1);
1406
1407 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001408 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001409 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001410 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001411 if (ShOpcVal == ARM_AM::lsl)
1412 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001413 }
1414
Evan Chengb23b50d2009-06-29 07:51:04 +00001415 if (ShOpcVal == ARM_AM::lsl) {
1416 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1417 // it.
1418 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1419 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001420 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1421 OffReg = OffReg.getOperand(0);
1422 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001423 ShAmt = 0;
Evan Cheng59bbc542010-10-27 23:41:30 +00001424 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001425 }
David Goodwinf3912052009-07-15 15:50:19 +00001426 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001427
John Brawn056e6782015-09-14 15:19:41 +00001428 // If OffReg is a multiply-by-constant and it's profitable to extract a shift
1429 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +00001430 if (OffReg.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +00001431 unsigned PowerOfTwo = 0;
1432 SDValue NewMulConst;
1433 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
1434 replaceDAGValue(OffReg.getOperand(1), NewMulConst);
1435 ShAmt = PowerOfTwo;
1436 }
1437 }
1438
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001439 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001440
1441 return true;
1442}
1443
Tim Northovera7ecd242013-07-16 09:46:55 +00001444bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1445 SDValue &OffImm) {
Alp Tokercb402912014-01-24 17:20:08 +00001446 // This *must* succeed since it's used for the irreplaceable ldrex and strex
Tim Northovera7ecd242013-07-16 09:46:55 +00001447 // instructions.
1448 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001449 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001450
1451 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1452 return true;
1453
1454 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1455 if (!RHS)
1456 return true;
1457
1458 uint32_t RHSC = (int)RHS->getZExtValue();
1459 if (RHSC > 1020 || RHSC % 4 != 0)
1460 return true;
1461
1462 Base = N.getOperand(0);
1463 if (Base.getOpcode() == ISD::FrameIndex) {
1464 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001465 Base = CurDAG->getTargetFrameIndex(
1466 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Tim Northovera7ecd242013-07-16 09:46:55 +00001467 }
1468
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001469 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001470 return true;
1471}
1472
Evan Chengb23b50d2009-06-29 07:51:04 +00001473//===--------------------------------------------------------------------===//
1474
Evan Cheng7e90b112007-07-05 07:15:27 +00001475/// getAL - Returns a ARMCC::AL immediate node.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001476static inline SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001477 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001478}
1479
Justin Bogner45571362016-05-12 00:31:09 +00001480bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001481 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001482 ISD::MemIndexedMode AM = LD->getAddressingMode();
1483 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001484 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001485
Owen Anderson53aa7a92009-08-10 22:56:29 +00001486 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001487 SDValue Offset, AMOpc;
1488 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1489 unsigned Opcode = 0;
1490 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001491 if (LoadedVT == MVT::i32 && isPre &&
1492 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1493 Opcode = ARM::LDR_PRE_IMM;
1494 Match = true;
1495 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001496 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001497 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001498 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001499 } else if (LoadedVT == MVT::i32 &&
1500 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001501 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001502 Match = true;
1503
Owen Anderson9f944592009-08-11 20:47:22 +00001504 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001505 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001506 Match = true;
1507 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1508 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1509 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001510 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001511 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001512 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001513 Match = true;
1514 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1515 }
1516 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001517 if (isPre &&
1518 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001519 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001520 Opcode = ARM::LDRB_PRE_IMM;
1521 } else if (!isPre &&
1522 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1523 Match = true;
1524 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001525 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1526 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001527 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001528 }
1529 }
1530 }
1531
1532 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001533 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1534 SDValue Chain = LD->getChain();
1535 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001536 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001537 CurDAG->getRegister(0, MVT::i32), Chain };
Justin Bogner45571362016-05-12 00:31:09 +00001538 ReplaceNode(N, CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
1539 MVT::i32, MVT::Other, Ops));
1540 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001541 } else {
1542 SDValue Chain = LD->getChain();
1543 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001544 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001545 CurDAG->getRegister(0, MVT::i32), Chain };
Justin Bogner45571362016-05-12 00:31:09 +00001546 ReplaceNode(N, CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
1547 MVT::i32, MVT::Other, Ops));
1548 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001549 }
Evan Chengd9c55362009-07-02 01:23:32 +00001550 }
1551
Justin Bogner45571362016-05-12 00:31:09 +00001552 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001553}
1554
Justin Bogner45571362016-05-12 00:31:09 +00001555bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001556 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001557 ISD::MemIndexedMode AM = LD->getAddressingMode();
1558 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001559 return false;
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:
Justin Bogner45571362016-05-12 00:31:09 +00001586 return false;
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 };
Justin Bogner45571362016-05-12 00:31:09 +00001596 ReplaceNode(N, CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1597 MVT::Other, Ops));
1598 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001599 }
1600
Justin Bogner45571362016-05-12 00:31:09 +00001601 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001602}
1603
Weiming Zhao8f56f882012-11-16 21:55:34 +00001604/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1605SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001606 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001607 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001608 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1609 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1610 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001611 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001612 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001613}
1614
Weiming Zhao95782222012-11-17 00:23:35 +00001615/// \brief Form a D register from a pair of S registers.
1616SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001617 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001618 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001619 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1620 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1621 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001622 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001623 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001624}
1625
Weiming Zhao95782222012-11-17 00:23:35 +00001626/// \brief Form a quad register from a pair of D registers.
1627SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001628 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001629 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1630 MVT::i32);
1631 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1632 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001633 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001634 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001635}
1636
Weiming Zhao95782222012-11-17 00:23:35 +00001637/// \brief Form 4 consecutive D registers from a pair of Q registers.
1638SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001639 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001640 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1641 MVT::i32);
1642 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1643 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001644 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001645 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001646}
1647
Weiming Zhao95782222012-11-17 00:23:35 +00001648/// \brief Form 4 consecutive S registers.
1649SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001650 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001651 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001652 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001653 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1654 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1655 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1656 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1657 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001658 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1659 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001660 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001661}
1662
Weiming Zhao95782222012-11-17 00:23:35 +00001663/// \brief Form 4 consecutive D registers.
1664SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001665 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001666 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001667 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1668 MVT::i32);
1669 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1670 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1671 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1672 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001673 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1674 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001675 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001676}
1677
Weiming Zhao95782222012-11-17 00:23:35 +00001678/// \brief Form 4 consecutive Q registers.
1679SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001680 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001681 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001682 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1683 MVT::i32);
1684 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1685 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1686 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1687 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001688 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1689 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001690 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001691}
1692
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001693/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1694/// of a NEON VLD or VST instruction. The supported values depend on the
1695/// number of registers being loaded.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001696SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, const SDLoc &dl,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001697 unsigned NumVecs, bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001698 unsigned NumRegs = NumVecs;
1699 if (!is64BitVector && NumVecs < 3)
1700 NumRegs *= 2;
1701
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001702 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001703 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001704 Alignment = 32;
1705 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1706 Alignment = 16;
1707 else if (Alignment >= 8)
1708 Alignment = 8;
1709 else
1710 Alignment = 0;
1711
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001712 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001713}
1714
Jiangning Liu4df23632014-01-16 09:16:13 +00001715static bool isVLDfixed(unsigned Opc)
1716{
1717 switch (Opc) {
1718 default: return false;
1719 case ARM::VLD1d8wb_fixed : return true;
1720 case ARM::VLD1d16wb_fixed : return true;
1721 case ARM::VLD1d64Qwb_fixed : return true;
1722 case ARM::VLD1d32wb_fixed : return true;
1723 case ARM::VLD1d64wb_fixed : return true;
1724 case ARM::VLD1d64TPseudoWB_fixed : return true;
1725 case ARM::VLD1d64QPseudoWB_fixed : return true;
1726 case ARM::VLD1q8wb_fixed : return true;
1727 case ARM::VLD1q16wb_fixed : return true;
1728 case ARM::VLD1q32wb_fixed : return true;
1729 case ARM::VLD1q64wb_fixed : return true;
1730 case ARM::VLD2d8wb_fixed : return true;
1731 case ARM::VLD2d16wb_fixed : return true;
1732 case ARM::VLD2d32wb_fixed : return true;
1733 case ARM::VLD2q8PseudoWB_fixed : return true;
1734 case ARM::VLD2q16PseudoWB_fixed : return true;
1735 case ARM::VLD2q32PseudoWB_fixed : return true;
1736 case ARM::VLD2DUPd8wb_fixed : return true;
1737 case ARM::VLD2DUPd16wb_fixed : return true;
1738 case ARM::VLD2DUPd32wb_fixed : return true;
1739 }
1740}
1741
1742static bool isVSTfixed(unsigned Opc)
1743{
1744 switch (Opc) {
1745 default: return false;
1746 case ARM::VST1d8wb_fixed : return true;
1747 case ARM::VST1d16wb_fixed : return true;
1748 case ARM::VST1d32wb_fixed : return true;
1749 case ARM::VST1d64wb_fixed : return true;
Jim Grosbach1a597112014-04-03 23:43:18 +00001750 case ARM::VST1q8wb_fixed : return true;
1751 case ARM::VST1q16wb_fixed : return true;
1752 case ARM::VST1q32wb_fixed : return true;
1753 case ARM::VST1q64wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001754 case ARM::VST1d64TPseudoWB_fixed : return true;
1755 case ARM::VST1d64QPseudoWB_fixed : return true;
1756 case ARM::VST2d8wb_fixed : return true;
1757 case ARM::VST2d16wb_fixed : return true;
1758 case ARM::VST2d32wb_fixed : return true;
1759 case ARM::VST2q8PseudoWB_fixed : return true;
1760 case ARM::VST2q16PseudoWB_fixed : return true;
1761 case ARM::VST2q32PseudoWB_fixed : return true;
1762 }
1763}
1764
Jim Grosbach2098cb12011-10-24 21:45:13 +00001765// Get the register stride update opcode of a VLD/VST instruction that
1766// is otherwise equivalent to the given fixed stride updating instruction.
1767static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
Jiangning Liu4df23632014-01-16 09:16:13 +00001768 assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1769 && "Incorrect fixed stride updating instruction.");
Jim Grosbach2098cb12011-10-24 21:45:13 +00001770 switch (Opc) {
1771 default: break;
1772 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1773 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1774 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1775 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1776 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1777 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1778 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1779 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jiangning Liu4df23632014-01-16 09:16:13 +00001780 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1781 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1782 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1783 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001784
1785 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1786 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1787 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1788 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1789 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1790 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1791 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1792 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001793 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001794 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001795
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001796 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1797 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1798 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001799 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1800 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1801 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1802
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001803 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1804 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1805 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001806 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1807 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1808 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001809
Jim Grosbach13a292c2012-03-06 22:01:44 +00001810 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1811 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1812 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001813 }
1814 return Opc; // If not one we handle, return it unchanged.
1815}
1816
Justin Bogner45571362016-05-12 00:31:09 +00001817void ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
1818 const uint16_t *DOpcodes,
1819 const uint16_t *QOpcodes0,
1820 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001821 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001822 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001823
Bob Wilsonae08a732010-03-20 22:13:40 +00001824 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001825 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1826 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001827 return;
Bob Wilson12b47992009-10-14 17:28:52 +00001828
1829 SDValue Chain = N->getOperand(0);
1830 EVT VT = N->getValueType(0);
1831 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001832 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001833
Bob Wilson12b47992009-10-14 17:28:52 +00001834 unsigned OpcodeIndex;
1835 switch (VT.getSimpleVT().SimpleTy) {
1836 default: llvm_unreachable("unhandled vld type");
1837 // Double-register operations:
1838 case MVT::v8i8: OpcodeIndex = 0; break;
1839 case MVT::v4i16: OpcodeIndex = 1; break;
1840 case MVT::v2f32:
1841 case MVT::v2i32: OpcodeIndex = 2; break;
1842 case MVT::v1i64: OpcodeIndex = 3; break;
1843 // Quad-register operations:
1844 case MVT::v16i8: OpcodeIndex = 0; break;
1845 case MVT::v8i16: OpcodeIndex = 1; break;
1846 case MVT::v4f32:
1847 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001848 case MVT::v2f64:
Bob Wilson340861d2010-03-23 05:25:43 +00001849 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001850 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson340861d2010-03-23 05:25:43 +00001851 break;
Bob Wilson12b47992009-10-14 17:28:52 +00001852 }
1853
Bob Wilson35fafca2010-09-03 18:16:02 +00001854 EVT ResTy;
1855 if (NumVecs == 1)
1856 ResTy = VT;
1857 else {
1858 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1859 if (!is64BitVector)
1860 ResTyElts *= 2;
1861 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1862 }
Bob Wilson06fce872011-02-07 17:43:21 +00001863 std::vector<EVT> ResTys;
1864 ResTys.push_back(ResTy);
1865 if (isUpdating)
1866 ResTys.push_back(MVT::i32);
1867 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001868
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001869 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001870 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001871 SDNode *VLd;
1872 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001873
Bob Wilson06fce872011-02-07 17:43:21 +00001874 // Double registers and VLD1/VLD2 quad registers are directly supported.
1875 if (is64BitVector || NumVecs <= 2) {
1876 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1877 QOpcodes0[OpcodeIndex]);
1878 Ops.push_back(MemAddr);
1879 Ops.push_back(Align);
1880 if (isUpdating) {
1881 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachd146a022011-12-09 21:28:25 +00001882 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach2098cb12011-10-24 21:45:13 +00001883 // case entirely when the rest are updated to that form, too.
Jiangning Liu4df23632014-01-16 09:16:13 +00001884 if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001885 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001886 // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001887 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00001888 if ((NumVecs > 2 && !isVLDfixed(Opc)) ||
Jim Grosbach05df4602011-10-31 21:50:31 +00001889 !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001890 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Evan Cheng630063a2010-05-10 21:26:24 +00001891 }
Bob Wilson06fce872011-02-07 17:43:21 +00001892 Ops.push_back(Pred);
1893 Ops.push_back(Reg0);
1894 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001895 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001896
Bob Wilson12b47992009-10-14 17:28:52 +00001897 } else {
1898 // Otherwise, quad registers are loaded with two separate instructions,
1899 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001900 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001901
Bob Wilson06fce872011-02-07 17:43:21 +00001902 // Load the even subregs. This is always an updating load, so that it
1903 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001904 SDValue ImplDef =
1905 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1906 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001907 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001908 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001909 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001910
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001911 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001912 Ops.push_back(SDValue(VLdA, 1));
1913 Ops.push_back(Align);
1914 if (isUpdating) {
1915 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1916 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1917 "only constant post-increment update allowed for VLD3/4");
1918 (void)Inc;
1919 Ops.push_back(Reg0);
1920 }
1921 Ops.push_back(SDValue(VLdA, 0));
1922 Ops.push_back(Pred);
1923 Ops.push_back(Reg0);
1924 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001925 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001926 }
Bob Wilson12b47992009-10-14 17:28:52 +00001927
Evan Cheng40791332011-04-19 00:04:03 +00001928 // Transfer memoperands.
1929 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1930 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1931 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1932
Justin Bogner45571362016-05-12 00:31:09 +00001933 if (NumVecs == 1) {
1934 ReplaceNode(N, VLd);
1935 return;
1936 }
Bob Wilson06fce872011-02-07 17:43:21 +00001937
1938 // Extract out the subregisters.
1939 SDValue SuperReg = SDValue(VLd, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00001940 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
1941 ARM::qsub_3 == ARM::qsub_0 + 3,
1942 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00001943 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1944 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1945 ReplaceUses(SDValue(N, Vec),
1946 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1947 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1948 if (isUpdating)
1949 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00001950 CurDAG->RemoveDeadNode(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001951}
1952
Justin Bogner45571362016-05-12 00:31:09 +00001953void ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
1954 const uint16_t *DOpcodes,
1955 const uint16_t *QOpcodes0,
1956 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001957 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001958 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001959
Bob Wilsonae08a732010-03-20 22:13:40 +00001960 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001961 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1962 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1963 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001964 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001965
Evan Cheng40791332011-04-19 00:04:03 +00001966 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1967 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1968
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001969 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00001970 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001971 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001972 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001973
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001974 unsigned OpcodeIndex;
1975 switch (VT.getSimpleVT().SimpleTy) {
1976 default: llvm_unreachable("unhandled vst type");
1977 // Double-register operations:
1978 case MVT::v8i8: OpcodeIndex = 0; break;
1979 case MVT::v4i16: OpcodeIndex = 1; break;
1980 case MVT::v2f32:
1981 case MVT::v2i32: OpcodeIndex = 2; break;
1982 case MVT::v1i64: OpcodeIndex = 3; break;
1983 // Quad-register operations:
1984 case MVT::v16i8: OpcodeIndex = 0; break;
1985 case MVT::v8i16: OpcodeIndex = 1; break;
1986 case MVT::v4f32:
1987 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001988 case MVT::v2f64:
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001989 case MVT::v2i64: OpcodeIndex = 3;
1990 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
1991 break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001992 }
1993
Bob Wilson06fce872011-02-07 17:43:21 +00001994 std::vector<EVT> ResTys;
1995 if (isUpdating)
1996 ResTys.push_back(MVT::i32);
1997 ResTys.push_back(MVT::Other);
1998
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001999 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002000 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00002001 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00002002
Bob Wilson06fce872011-02-07 17:43:21 +00002003 // Double registers and VST1/VST2 quad registers are directly supported.
2004 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00002005 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00002006 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00002007 SrcReg = N->getOperand(Vec0Idx);
2008 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00002009 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00002010 SDValue V0 = N->getOperand(Vec0Idx + 0);
2011 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00002012 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002013 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002014 else {
Bob Wilson06fce872011-02-07 17:43:21 +00002015 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00002016 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00002017 // an undef.
2018 SDValue V3 = (NumVecs == 3)
2019 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002020 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002021 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002022 }
Bob Wilson950882b2010-08-28 05:12:57 +00002023 } else {
2024 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00002025 SDValue Q0 = N->getOperand(Vec0Idx);
2026 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00002027 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002028 }
Bob Wilson06fce872011-02-07 17:43:21 +00002029
2030 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2031 QOpcodes0[OpcodeIndex]);
2032 Ops.push_back(MemAddr);
2033 Ops.push_back(Align);
2034 if (isUpdating) {
2035 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbach88ac7612011-12-14 21:32:11 +00002036 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach05df4602011-10-31 21:50:31 +00002037 // case entirely when the rest are updated to that form, too.
Jim Grosbach88ac7612011-12-14 21:32:11 +00002038 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach05df4602011-10-31 21:50:31 +00002039 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00002040 // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00002041 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00002042 if (!isa<ConstantSDNode>(Inc.getNode()))
2043 Ops.push_back(Inc);
2044 else if (NumVecs > 2 && !isVSTfixed(Opc))
2045 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002046 }
2047 Ops.push_back(SrcReg);
2048 Ops.push_back(Pred);
2049 Ops.push_back(Reg0);
2050 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00002051 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002052
2053 // Transfer memoperands.
2054 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
2055
Justin Bogner45571362016-05-12 00:31:09 +00002056 ReplaceNode(N, VSt);
2057 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002058 }
2059
2060 // Otherwise, quad registers are stored with two separate instructions,
2061 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00002062
Bob Wilson01ac8f92010-06-16 21:34:01 +00002063 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00002064 SDValue V0 = N->getOperand(Vec0Idx + 0);
2065 SDValue V1 = N->getOperand(Vec0Idx + 1);
2066 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00002067 SDValue V3 = (NumVecs == 3)
2068 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002069 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002070 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002071
Bob Wilson06fce872011-02-07 17:43:21 +00002072 // Store the even D registers. This is always an updating store, so that it
2073 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00002074 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2075 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2076 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00002077 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00002078 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002079 Chain = SDValue(VStA, 1);
2080
2081 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00002082 Ops.push_back(SDValue(VStA, 0));
2083 Ops.push_back(Align);
2084 if (isUpdating) {
2085 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2086 assert(isa<ConstantSDNode>(Inc.getNode()) &&
2087 "only constant post-increment update allowed for VST3/4");
2088 (void)Inc;
2089 Ops.push_back(Reg0);
2090 }
2091 Ops.push_back(RegSeq);
2092 Ops.push_back(Pred);
2093 Ops.push_back(Reg0);
2094 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00002095 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00002096 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002097 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002098 ReplaceNode(N, VStB);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002099}
2100
Justin Bogner45571362016-05-12 00:31:09 +00002101void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
2102 unsigned NumVecs,
2103 const uint16_t *DOpcodes,
2104 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002105 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002106 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002107
Bob Wilsonae08a732010-03-20 22:13:40 +00002108 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00002109 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2110 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2111 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002112 return;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002113
Evan Cheng40791332011-04-19 00:04:03 +00002114 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2115 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2116
Bob Wilson4145e3a2009-10-14 16:19:03 +00002117 SDValue Chain = N->getOperand(0);
2118 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002119 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2120 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002121 bool is64BitVector = VT.is64BitVector();
2122
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002123 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002124 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002125 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002126 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2127 if (Alignment > NumBytes)
2128 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002129 if (Alignment < 8 && Alignment < NumBytes)
2130 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002131 // Alignment must be a power of two; make sure of that.
2132 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002133 if (Alignment == 1)
2134 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002135 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002136 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002137
Bob Wilson4145e3a2009-10-14 16:19:03 +00002138 unsigned OpcodeIndex;
2139 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002140 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002141 // Double-register operations:
2142 case MVT::v8i8: OpcodeIndex = 0; break;
2143 case MVT::v4i16: OpcodeIndex = 1; break;
2144 case MVT::v2f32:
2145 case MVT::v2i32: OpcodeIndex = 2; break;
2146 // Quad-register operations:
2147 case MVT::v8i16: OpcodeIndex = 0; break;
2148 case MVT::v4f32:
2149 case MVT::v4i32: OpcodeIndex = 1; break;
2150 }
2151
Bob Wilson06fce872011-02-07 17:43:21 +00002152 std::vector<EVT> ResTys;
2153 if (IsLoad) {
2154 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2155 if (!is64BitVector)
2156 ResTyElts *= 2;
2157 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2158 MVT::i64, ResTyElts));
2159 }
2160 if (isUpdating)
2161 ResTys.push_back(MVT::i32);
2162 ResTys.push_back(MVT::Other);
2163
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002164 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002165 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002166
Bob Wilson06fce872011-02-07 17:43:21 +00002167 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002168 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002169 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002170 if (isUpdating) {
2171 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2172 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
2173 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002174
Bob Wilsond5c57a52010-09-13 23:01:35 +00002175 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002176 SDValue V0 = N->getOperand(Vec0Idx + 0);
2177 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002178 if (NumVecs == 2) {
2179 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002180 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002181 else
Weiming Zhao95782222012-11-17 00:23:35 +00002182 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002183 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002184 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002185 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002186 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2187 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002188 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002189 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002190 else
Weiming Zhao95782222012-11-17 00:23:35 +00002191 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002192 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002193 Ops.push_back(SuperReg);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002194 Ops.push_back(getI32Imm(Lane, dl));
Evan Chenga33fc862009-11-21 06:21:52 +00002195 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002196 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002197 Ops.push_back(Chain);
2198
Bob Wilson06fce872011-02-07 17:43:21 +00002199 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2200 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002201 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002202 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002203 if (!IsLoad) {
2204 ReplaceNode(N, VLdLn);
2205 return;
2206 }
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002207
Bob Wilsond5c57a52010-09-13 23:01:35 +00002208 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002209 SuperReg = SDValue(VLdLn, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00002210 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2211 ARM::qsub_3 == ARM::qsub_0 + 3,
2212 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00002213 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002214 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2215 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002216 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2217 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2218 if (isUpdating)
2219 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002220 CurDAG->RemoveDeadNode(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002221}
2222
Justin Bogner45571362016-05-12 00:31:09 +00002223void ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
2224 const uint16_t *Opcodes) {
Bob Wilson2d790df2010-11-28 06:51:26 +00002225 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002226 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002227
2228 SDValue MemAddr, Align;
2229 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002230 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00002231
Evan Cheng40791332011-04-19 00:04:03 +00002232 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2233 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2234
Bob Wilson2d790df2010-11-28 06:51:26 +00002235 SDValue Chain = N->getOperand(0);
2236 EVT VT = N->getValueType(0);
2237
2238 unsigned Alignment = 0;
2239 if (NumVecs != 3) {
2240 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2241 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2242 if (Alignment > NumBytes)
2243 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002244 if (Alignment < 8 && Alignment < NumBytes)
2245 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002246 // Alignment must be a power of two; make sure of that.
2247 Alignment = (Alignment & -Alignment);
2248 if (Alignment == 1)
2249 Alignment = 0;
2250 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002251 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson2d790df2010-11-28 06:51:26 +00002252
2253 unsigned OpcodeIndex;
2254 switch (VT.getSimpleVT().SimpleTy) {
2255 default: llvm_unreachable("unhandled vld-dup type");
2256 case MVT::v8i8: OpcodeIndex = 0; break;
2257 case MVT::v4i16: OpcodeIndex = 1; break;
2258 case MVT::v2f32:
2259 case MVT::v2i32: OpcodeIndex = 2; break;
2260 }
2261
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002262 SDValue Pred = getAL(CurDAG, dl);
Bob Wilson2d790df2010-11-28 06:51:26 +00002263 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2264 SDValue SuperReg;
2265 unsigned Opc = Opcodes[OpcodeIndex];
Bob Wilson06fce872011-02-07 17:43:21 +00002266 SmallVector<SDValue, 6> Ops;
2267 Ops.push_back(MemAddr);
2268 Ops.push_back(Align);
2269 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002270 // fixed-stride update instructions don't have an explicit writeback
2271 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002272 SDValue Inc = N->getOperand(2);
Jim Grosbachc80a2642011-12-21 19:40:55 +00002273 if (!isa<ConstantSDNode>(Inc.getNode()))
2274 Ops.push_back(Inc);
2275 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2276 else if (NumVecs > 2)
2277 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002278 }
2279 Ops.push_back(Pred);
2280 Ops.push_back(Reg0);
2281 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002282
2283 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002284 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002285 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002286 if (isUpdating)
2287 ResTys.push_back(MVT::i32);
2288 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002289 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002290 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002291 SuperReg = SDValue(VLdDup, 0);
Bob Wilson2d790df2010-11-28 06:51:26 +00002292
2293 // Extract the subregisters.
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00002294 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7, "Unexpected subreg numbering");
Bob Wilson2d790df2010-11-28 06:51:26 +00002295 unsigned SubIdx = ARM::dsub_0;
2296 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2297 ReplaceUses(SDValue(N, Vec),
2298 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Bob Wilson06fce872011-02-07 17:43:21 +00002299 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2300 if (isUpdating)
2301 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002302 CurDAG->RemoveDeadNode(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002303}
2304
Justin Bogner45571362016-05-12 00:31:09 +00002305void ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2306 unsigned Opc) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00002307 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002308 SDLoc dl(N);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002309 EVT VT = N->getValueType(0);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002310 unsigned FirstTblReg = IsExt ? 2 : 1;
Bob Wilson3ed511b2010-07-06 23:36:25 +00002311
2312 // Form a REG_SEQUENCE to force register allocation.
2313 SDValue RegSeq;
Bob Wilson5bc8a792010-07-07 00:08:54 +00002314 SDValue V0 = N->getOperand(FirstTblReg + 0);
2315 SDValue V1 = N->getOperand(FirstTblReg + 1);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002316 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002317 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002318 else {
Bob Wilson5bc8a792010-07-07 00:08:54 +00002319 SDValue V2 = N->getOperand(FirstTblReg + 2);
Jim Grosbachd37f0712010-10-21 19:38:40 +00002320 // If it's a vtbl3, form a quad D-register and leave the last part as
Bob Wilson3ed511b2010-07-06 23:36:25 +00002321 // an undef.
2322 SDValue V3 = (NumVecs == 3)
2323 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson5bc8a792010-07-07 00:08:54 +00002324 : N->getOperand(FirstTblReg + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002325 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002326 }
2327
Bob Wilson5bc8a792010-07-07 00:08:54 +00002328 SmallVector<SDValue, 6> Ops;
2329 if (IsExt)
2330 Ops.push_back(N->getOperand(1));
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00002331 Ops.push_back(RegSeq);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002332 Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002333 Ops.push_back(getAL(CurDAG, dl)); // predicate
Bob Wilson3ed511b2010-07-06 23:36:25 +00002334 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
Justin Bogner45571362016-05-12 00:31:09 +00002335 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
Bob Wilson3ed511b2010-07-06 23:36:25 +00002336}
2337
Justin Bogner45571362016-05-12 00:31:09 +00002338bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002339 if (!Subtarget->hasV6T2Ops())
Justin Bogner45571362016-05-12 00:31:09 +00002340 return false;
Bob Wilson93117bc2009-10-14 16:46:45 +00002341
Evan Chengeae6d2c2012-12-19 20:16:09 +00002342 unsigned Opc = isSigned
2343 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002344 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002345 SDLoc dl(N);
Jim Grosbach825cb292010-04-22 23:24:18 +00002346
Jim Grosbach825cb292010-04-22 23:24:18 +00002347 // For unsigned extracts, check for a shift right and mask
2348 unsigned And_imm = 0;
2349 if (N->getOpcode() == ISD::AND) {
2350 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2351
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002352 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002353 if (And_imm & (And_imm + 1))
Justin Bogner45571362016-05-12 00:31:09 +00002354 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002355
2356 unsigned Srl_imm = 0;
2357 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2358 Srl_imm)) {
2359 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2360
Jim Grosbach03f56d92011-07-27 21:09:25 +00002361 // Note: The width operand is encoded as width-1.
Benjamin Kramer5f6a9072015-02-12 15:35:40 +00002362 unsigned Width = countTrailingOnes(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002363 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002364
Jim Grosbach825cb292010-04-22 23:24:18 +00002365 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002366
2367 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2368 // It's cheaper to use a right shift to extract the top bits.
2369 if (Subtarget->isThumb()) {
2370 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2371 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002372 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2373 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002374 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2375 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002376 }
2377
2378 // ARM models shift instructions as MOVsi with shifter operand.
2379 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2380 SDValue ShOpc =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002381 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), dl,
Evan Chengeae6d2c2012-12-19 20:16:09 +00002382 MVT::i32);
2383 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002384 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002385 CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops);
2386 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002387 }
2388
Jim Grosbach825cb292010-04-22 23:24:18 +00002389 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002390 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2391 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2392 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002393 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2394 return true;
Jim Grosbach825cb292010-04-22 23:24:18 +00002395 }
2396 }
Justin Bogner45571362016-05-12 00:31:09 +00002397 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002398 }
2399
2400 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002401 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002402 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002403 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2404 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002405 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002406 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002407 // Note: The width operand is encoded as width-1.
2408 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002409 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002410 if (LSB < 0)
Justin Bogner45571362016-05-12 00:31:09 +00002411 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002412 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002413 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002414 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2415 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2416 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002417 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2418 return true;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002419 }
2420 }
Tim Northover14ff2df2014-07-23 13:59:12 +00002421
Oliver Stannard92ca83c2016-06-01 12:01:01 +00002422 // Or we are looking for a shift of an and, with a mask operand
2423 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, And_imm) &&
2424 isShiftedMask_32(And_imm)) {
2425 unsigned Srl_imm = 0;
2426 unsigned LSB = countTrailingZeros(And_imm);
2427 // Shift must be the same as the ands lsb
2428 if (isInt32Immediate(N->getOperand(1), Srl_imm) && Srl_imm == LSB) {
2429 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2430 unsigned MSB = 31 - countLeadingZeros(And_imm);
2431 // Note: The width operand is encoded as width-1.
2432 unsigned Width = MSB - LSB;
2433 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2434 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2435 CurDAG->getTargetConstant(Srl_imm, dl, MVT::i32),
2436 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2437 getAL(CurDAG, dl), Reg0 };
2438 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2439 return true;
2440 }
2441 }
2442
Tim Northover14ff2df2014-07-23 13:59:12 +00002443 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
2444 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2445 unsigned LSB = 0;
2446 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) &&
2447 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB))
Justin Bogner45571362016-05-12 00:31:09 +00002448 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002449
2450 if (LSB + Width > 32)
Justin Bogner45571362016-05-12 00:31:09 +00002451 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002452
2453 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2454 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002455 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2456 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
2457 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002458 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2459 return true;
Tim Northover14ff2df2014-07-23 13:59:12 +00002460 }
2461
Justin Bogner45571362016-05-12 00:31:09 +00002462 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002463}
2464
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002465/// Target-specific DAG combining for ISD::XOR.
2466/// Target-independent combining lowers SELECT_CC nodes of the form
2467/// select_cc setg[ge] X, 0, X, -X
2468/// select_cc setgt X, -1, X, -X
2469/// select_cc setl[te] X, 0, -X, X
2470/// select_cc setlt X, 1, -X, X
2471/// which represent Integer ABS into:
2472/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2473/// ARM instruction selection detects the latter and matches it to
2474/// ARM::ABS or ARM::t2ABS machine node.
Justin Bogner45571362016-05-12 00:31:09 +00002475bool ARMDAGToDAGISel::tryABSOp(SDNode *N){
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002476 SDValue XORSrc0 = N->getOperand(0);
2477 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002478 EVT VT = N->getValueType(0);
2479
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002480 if (Subtarget->isThumb1Only())
Justin Bogner45571362016-05-12 00:31:09 +00002481 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002482
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002483 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Justin Bogner45571362016-05-12 00:31:09 +00002484 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002485
2486 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2487 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2488 SDValue SRASrc0 = XORSrc1.getOperand(0);
2489 SDValue SRASrc1 = XORSrc1.getOperand(1);
2490 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2491 EVT XType = SRASrc0.getValueType();
2492 unsigned Size = XType.getSizeInBits() - 1;
2493
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002494 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
Craig Topper062a2ba2014-04-25 05:30:21 +00002495 XType.isInteger() && SRAConstant != nullptr &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002496 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002497 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Justin Bogner45571362016-05-12 00:31:09 +00002498 CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2499 return true;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002500 }
2501
Justin Bogner45571362016-05-12 00:31:09 +00002502 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002503}
2504
Sam Parker2d5126c2016-04-08 16:02:53 +00002505static bool SearchSignedMulShort(SDValue SignExt, unsigned *Opc, SDValue &Src1,
2506 bool Accumulate) {
2507 // For SM*WB, we need to some form of sext.
2508 // For SM*WT, we need to search for (sra X, 16)
2509 // Src1 then gets set to X.
2510 if ((SignExt.getOpcode() == ISD::SIGN_EXTEND ||
2511 SignExt.getOpcode() == ISD::SIGN_EXTEND_INREG ||
2512 SignExt.getOpcode() == ISD::AssertSext) &&
2513 SignExt.getValueType() == MVT::i32) {
2514
2515 *Opc = Accumulate ? ARM::SMLAWB : ARM::SMULWB;
2516 Src1 = SignExt.getOperand(0);
2517 return true;
2518 }
2519
2520 if (SignExt.getOpcode() != ISD::SRA)
2521 return false;
2522
2523 ConstantSDNode *SRASrc1 = dyn_cast<ConstantSDNode>(SignExt.getOperand(1));
2524 if (!SRASrc1 || SRASrc1->getZExtValue() != 16)
2525 return false;
2526
2527 SDValue Op0 = SignExt.getOperand(0);
2528
2529 // The sign extend operand for SM*WB could be generated by a shl and ashr.
2530 if (Op0.getOpcode() == ISD::SHL) {
2531 SDValue SHL = Op0;
2532 ConstantSDNode *SHLSrc1 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
2533 if (!SHLSrc1 || SHLSrc1->getZExtValue() != 16)
2534 return false;
2535
2536 *Opc = Accumulate ? ARM::SMLAWB : ARM::SMULWB;
2537 Src1 = Op0.getOperand(0);
2538 return true;
2539 }
2540 *Opc = Accumulate ? ARM::SMLAWT : ARM::SMULWT;
2541 Src1 = SignExt.getOperand(0);
2542 return true;
2543}
2544
2545static bool SearchSignedMulLong(SDValue OR, unsigned *Opc, SDValue &Src0,
2546 SDValue &Src1, bool Accumulate) {
2547 // First we look for:
2548 // (add (or (srl ?, 16), (shl ?, 16)))
2549 if (OR.getOpcode() != ISD::OR)
2550 return false;
2551
2552 SDValue SRL = OR.getOperand(0);
2553 SDValue SHL = OR.getOperand(1);
2554
2555 if (SRL.getOpcode() != ISD::SRL || SHL.getOpcode() != ISD::SHL) {
2556 SRL = OR.getOperand(1);
2557 SHL = OR.getOperand(0);
2558 if (SRL.getOpcode() != ISD::SRL || SHL.getOpcode() != ISD::SHL)
2559 return false;
2560 }
2561
2562 ConstantSDNode *SRLSrc1 = dyn_cast<ConstantSDNode>(SRL.getOperand(1));
2563 ConstantSDNode *SHLSrc1 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
2564 if (!SRLSrc1 || !SHLSrc1 || SRLSrc1->getZExtValue() != 16 ||
2565 SHLSrc1->getZExtValue() != 16)
2566 return false;
2567
2568 // The first operands to the shifts need to be the two results from the
2569 // same smul_lohi node.
2570 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
2571 SRL.getOperand(0).getOpcode() != ISD::SMUL_LOHI)
2572 return false;
2573
2574 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
2575 if (SRL.getOperand(0) != SDValue(SMULLOHI, 0) ||
2576 SHL.getOperand(0) != SDValue(SMULLOHI, 1))
2577 return false;
2578
2579 // Now we have:
2580 // (add (or (srl (smul_lohi ?, ?), 16), (shl (smul_lohi ?, ?), 16)))
2581 // For SMLAW[B|T] smul_lohi will take a 32-bit and a 16-bit arguments.
2582 // For SMLAWB the 16-bit value will signed extended somehow.
2583 // For SMLAWT only the SRA is required.
2584
2585 // Check both sides of SMUL_LOHI
2586 if (SearchSignedMulShort(SMULLOHI->getOperand(0), Opc, Src1, Accumulate)) {
2587 Src0 = SMULLOHI->getOperand(1);
2588 } else if (SearchSignedMulShort(SMULLOHI->getOperand(1), Opc, Src1,
2589 Accumulate)) {
2590 Src0 = SMULLOHI->getOperand(0);
2591 } else {
2592 return false;
2593 }
2594 return true;
2595}
2596
Justin Bogner45571362016-05-12 00:31:09 +00002597bool ARMDAGToDAGISel::trySMLAWSMULW(SDNode *N) {
Sam Parker2d5126c2016-04-08 16:02:53 +00002598 SDLoc dl(N);
2599 SDValue Src0 = N->getOperand(0);
2600 SDValue Src1 = N->getOperand(1);
2601 SDValue A, B;
2602 unsigned Opc = 0;
2603
2604 if (N->getOpcode() == ISD::ADD) {
2605 if (Src0.getOpcode() != ISD::OR && Src1.getOpcode() != ISD::OR)
Justin Bogner45571362016-05-12 00:31:09 +00002606 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002607
2608 SDValue Acc;
2609 if (SearchSignedMulLong(Src0, &Opc, A, B, true)) {
2610 Acc = Src1;
2611 } else if (SearchSignedMulLong(Src1, &Opc, A, B, true)) {
2612 Acc = Src0;
2613 } else {
Justin Bogner45571362016-05-12 00:31:09 +00002614 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002615 }
2616 if (Opc == 0)
Justin Bogner45571362016-05-12 00:31:09 +00002617 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002618
2619 SDValue Ops[] = { A, B, Acc, getAL(CurDAG, dl),
2620 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002621 CurDAG->SelectNodeTo(N, Opc, MVT::i32, MVT::Other, Ops);
2622 return true;
Sam Parker2d5126c2016-04-08 16:02:53 +00002623 } else if (N->getOpcode() == ISD::OR &&
2624 SearchSignedMulLong(SDValue(N, 0), &Opc, A, B, false)) {
2625 if (Opc == 0)
Justin Bogner45571362016-05-12 00:31:09 +00002626 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002627
2628 SDValue Ops[] = { A, B, getAL(CurDAG, dl),
2629 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002630 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2631 return true;
Sam Parker2d5126c2016-04-08 16:02:53 +00002632 }
Justin Bogner45571362016-05-12 00:31:09 +00002633 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002634}
2635
Tim Northoverb629c772016-04-18 21:48:55 +00002636/// We've got special pseudo-instructions for these
Justin Bogner45571362016-05-12 00:31:09 +00002637void ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *N) {
Tim Northoverb629c772016-04-18 21:48:55 +00002638 unsigned Opcode;
2639 EVT MemTy = cast<MemSDNode>(N)->getMemoryVT();
2640 if (MemTy == MVT::i8)
2641 Opcode = ARM::CMP_SWAP_8;
2642 else if (MemTy == MVT::i16)
2643 Opcode = ARM::CMP_SWAP_16;
2644 else if (MemTy == MVT::i32)
2645 Opcode = ARM::CMP_SWAP_32;
2646 else
2647 llvm_unreachable("Unknown AtomicCmpSwap type");
2648
2649 SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3),
2650 N->getOperand(0)};
2651 SDNode *CmpSwap = CurDAG->getMachineNode(
2652 Opcode, SDLoc(N),
2653 CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other), Ops);
2654
2655 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2656 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
2657 cast<MachineSDNode>(CmpSwap)->setMemRefs(MemOp, MemOp + 1);
2658
2659 ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0));
2660 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002661 CurDAG->RemoveDeadNode(N);
Tim Northoverb629c772016-04-18 21:48:55 +00002662}
2663
Justin Bogner45571362016-05-12 00:31:09 +00002664void ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
Evan Chengd85631e2010-05-05 18:28:36 +00002665 // The only time a CONCAT_VECTORS operation can have legal types is when
2666 // two 64-bit vectors are concatenated to a 128-bit vector.
2667 EVT VT = N->getValueType(0);
2668 if (!VT.is128BitVector() || N->getNumOperands() != 2)
2669 llvm_unreachable("unexpected CONCAT_VECTORS");
Justin Bogner45571362016-05-12 00:31:09 +00002670 ReplaceNode(N, createDRegPairNode(VT, N->getOperand(0), N->getOperand(1)));
Evan Chengd85631e2010-05-05 18:28:36 +00002671}
2672
Justin Bogner45571362016-05-12 00:31:09 +00002673void ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002674 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002675
Tim Northover31d093c2013-09-22 08:21:56 +00002676 if (N->isMachineOpcode()) {
2677 N->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00002678 return; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00002679 }
Rafael Espindola4e760152006-06-12 12:28:08 +00002680
2681 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002682 default: break;
Sam Parker2d5126c2016-04-08 16:02:53 +00002683 case ISD::ADD:
Justin Bogner45571362016-05-12 00:31:09 +00002684 case ISD::OR:
2685 if (trySMLAWSMULW(N))
2686 return;
Sam Parker2d5126c2016-04-08 16:02:53 +00002687 break;
Justin Bogner45571362016-05-12 00:31:09 +00002688 case ISD::WRITE_REGISTER:
2689 if (tryWriteRegister(N))
2690 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002691 break;
Justin Bogner45571362016-05-12 00:31:09 +00002692 case ISD::READ_REGISTER:
2693 if (tryReadRegister(N))
2694 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002695 break;
Justin Bogner45571362016-05-12 00:31:09 +00002696 case ISD::INLINEASM:
2697 if (tryInlineAsm(N))
2698 return;
Weiming Zhaoc5987002013-02-14 18:10:21 +00002699 break;
Justin Bogner45571362016-05-12 00:31:09 +00002700 case ISD::XOR:
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002701 // Select special operations if XOR node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +00002702 if (tryABSOp(N))
2703 return;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002704 // Other cases are autogenerated.
2705 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002706 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002707 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
John Brawn056e6782015-09-14 15:19:41 +00002708 // If we can't materialize the constant we need to use a literal pool
2709 if (ConstantMaterializationCost(Val) > 2) {
Eric Christopherb17140d2014-10-08 07:32:17 +00002710 SDValue CPIdx = CurDAG->getTargetConstantPool(
2711 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
Mehdi Amini44ede332015-07-09 02:09:04 +00002712 TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng1526ba52007-01-24 08:53:17 +00002713
2714 SDNode *ResNode;
Tim Northover55c625f2014-01-23 13:43:47 +00002715 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002716 SDValue Pred = getAL(CurDAG, dl);
Owen Anderson9f944592009-08-11 20:47:22 +00002717 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002718 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002719 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002720 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002721 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002722 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002723 CPIdx,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002724 CurDAG->getTargetConstant(0, dl, MVT::i32),
2725 getAL(CurDAG, dl),
Owen Anderson9f944592009-08-11 20:47:22 +00002726 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002727 CurDAG->getEntryNode()
2728 };
Justin Bogner45571362016-05-12 00:31:09 +00002729 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
2730 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002731 }
Justin Bognered4f3782016-05-12 00:20:19 +00002732 ReplaceNode(N, ResNode);
Justin Bogner45571362016-05-12 00:31:09 +00002733 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002734 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002735
Evan Cheng10043e22007-01-19 07:51:42 +00002736 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002737 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002738 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002739 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002740 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002741 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00002742 SDValue TFI = CurDAG->getTargetFrameIndex(
2743 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin22c2fba2009-07-08 23:10:31 +00002744 if (Subtarget->isThumb1Only()) {
Renato Golinb9887ef2015-02-25 14:41:06 +00002745 // Set the alignment of the frame object to 4, to avoid having to generate
2746 // more than one ADD
2747 MachineFrameInfo *MFI = MF->getFrameInfo();
2748 if (MFI->getObjectAlignment(FI) < 4)
2749 MFI->setObjectAlignment(FI, 4);
Justin Bogner45571362016-05-12 00:31:09 +00002750 CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
2751 CurDAG->getTargetConstant(0, dl, MVT::i32));
2752 return;
Jim Grosbachfde21102009-04-07 20:34:09 +00002753 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002754 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2755 ARM::t2ADDri : ARM::ADDri);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002756 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
2757 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002758 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002759 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2760 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00002761 }
Evan Cheng10043e22007-01-19 07:51:42 +00002762 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002763 case ISD::SRL:
Justin Bogner45571362016-05-12 00:31:09 +00002764 if (tryV6T2BitfieldExtractOp(N, false))
2765 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002766 break;
Tim Northover14ff2df2014-07-23 13:59:12 +00002767 case ISD::SIGN_EXTEND_INREG:
Sandeep Patel423e42b2009-10-13 18:59:48 +00002768 case ISD::SRA:
Justin Bogner45571362016-05-12 00:31:09 +00002769 if (tryV6T2BitfieldExtractOp(N, true))
2770 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002771 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002772 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002773 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002774 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002775 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002776 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002777 if (!RHSV) break;
2778 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002779 unsigned ShImm = Log2_32(RHSV-1);
2780 if (ShImm >= 32)
2781 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002782 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002783 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002784 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002785 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002786 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002787 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002788 CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
2789 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002790 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002791 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2792 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002793 CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
2794 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002795 }
Evan Cheng10043e22007-01-19 07:51:42 +00002796 }
2797 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002798 unsigned ShImm = Log2_32(RHSV+1);
2799 if (ShImm >= 32)
2800 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002801 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002802 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002803 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002804 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002805 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002806 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002807 CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
2808 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002809 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002810 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2811 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002812 CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
2813 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002814 }
Evan Cheng10043e22007-01-19 07:51:42 +00002815 }
2816 }
2817 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002818 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002819 // Check for unsigned bitfield extract
Justin Bogner45571362016-05-12 00:31:09 +00002820 if (tryV6T2BitfieldExtractOp(N, false))
2821 return;
Jim Grosbach825cb292010-04-22 23:24:18 +00002822
James Molloyfeb9f422016-06-09 07:39:08 +00002823 // If an immediate is used in an AND node, it is possible that the immediate
2824 // can be more optimally materialized when negated. If this is the case we
2825 // can negate the immediate and use a BIC instead.
2826 auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1));
2827 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
2828 uint32_t Imm = (uint32_t) N1C->getZExtValue();
2829
2830 // In Thumb2 mode, an AND can take a 12-bit immediate. If this
2831 // immediate can be negated and fit in the immediate operand of
2832 // a t2BIC, don't do any manual transform here as this can be
2833 // handled by the generic ISel machinery.
2834 bool PreferImmediateEncoding =
2835 Subtarget->hasThumb2() && !is_t2_so_imm(Imm) && is_t2_so_imm_not(Imm);
2836 if (!PreferImmediateEncoding &&
2837 ConstantMaterializationCost(Imm) >
2838 ConstantMaterializationCost(~Imm)) {
2839 // The current immediate costs more to materialize than a negated
2840 // immediate, so negate the immediate and use a BIC.
2841 SDValue NewImm =
2842 CurDAG->getConstant(~N1C->getZExtValue(), dl, MVT::i32);
2843 CurDAG->RepositionNode(N->getIterator(), NewImm.getNode());
2844
2845 if (!Subtarget->hasThumb2()) {
2846 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
2847 N->getOperand(0), NewImm, getAL(CurDAG, dl),
2848 CurDAG->getRegister(0, MVT::i32)};
2849 ReplaceNode(N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32, Ops));
2850 return;
2851 } else {
2852 SDValue Ops[] = {N->getOperand(0), NewImm, getAL(CurDAG, dl),
2853 CurDAG->getRegister(0, MVT::i32),
2854 CurDAG->getRegister(0, MVT::i32)};
2855 ReplaceNode(N,
2856 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32, Ops));
2857 return;
2858 }
2859 }
2860 }
2861
Evan Cheng786b15f2009-10-21 08:15:52 +00002862 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2863 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2864 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2865 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2866 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002867 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002868 if (VT != MVT::i32)
2869 break;
2870 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2871 ? ARM::t2MOVTi16
2872 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2873 if (!Opc)
2874 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002875 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
James Molloyfeb9f422016-06-09 07:39:08 +00002876 N1C = dyn_cast<ConstantSDNode>(N1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002877 if (!N1C)
2878 break;
2879 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2880 SDValue N2 = N0.getOperand(1);
2881 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2882 if (!N2C)
2883 break;
2884 unsigned N1CVal = N1C->getZExtValue();
2885 unsigned N2CVal = N2C->getZExtValue();
2886 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2887 (N1CVal & 0xffffU) == 0xffffU &&
2888 (N2CVal & 0xffffU) == 0x0U) {
2889 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002890 dl, MVT::i32);
Evan Cheng786b15f2009-10-21 08:15:52 +00002891 SDValue Ops[] = { N0.getOperand(0), Imm16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002892 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002893 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
2894 return;
Evan Cheng786b15f2009-10-21 08:15:52 +00002895 }
2896 }
2897 break;
2898 }
Jim Grosbachd7cf55c2009-11-09 00:11:35 +00002899 case ARMISD::VMOVRRD:
Justin Bogner45571362016-05-12 00:31:09 +00002900 ReplaceNode(N, CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
2901 N->getOperand(0), getAL(CurDAG, dl),
2902 CurDAG->getRegister(0, MVT::i32)));
2903 return;
Dan Gohmana1603612007-10-08 18:33:35 +00002904 case ISD::UMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002905 if (Subtarget->isThumb1Only())
2906 break;
2907 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002908 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002909 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002910 ReplaceNode(
2911 N, CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops));
2912 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002913 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002914 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002915 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002916 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002917 ReplaceNode(N, CurDAG->getMachineNode(
2918 Subtarget->hasV6Ops() ? ARM::UMULL : ARM::UMULLv5, dl,
2919 MVT::i32, MVT::i32, Ops));
2920 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002921 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002922 }
Dan Gohmana1603612007-10-08 18:33:35 +00002923 case ISD::SMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002924 if (Subtarget->isThumb1Only())
2925 break;
2926 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002927 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002928 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002929 ReplaceNode(
2930 N, CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops));
2931 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002932 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002933 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002934 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002935 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002936 ReplaceNode(N, CurDAG->getMachineNode(
2937 Subtarget->hasV6Ops() ? ARM::SMULL : ARM::SMULLv5, dl,
2938 MVT::i32, MVT::i32, Ops));
2939 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002940 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002941 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002942 case ARMISD::UMLAL:{
2943 if (Subtarget->isThumb()) {
2944 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002945 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002946 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002947 ReplaceNode(
2948 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops));
2949 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002950 }else{
2951 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002952 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002953 CurDAG->getRegister(0, MVT::i32),
2954 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002955 ReplaceNode(N, CurDAG->getMachineNode(
2956 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl,
2957 MVT::i32, MVT::i32, Ops));
2958 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002959 }
2960 }
2961 case ARMISD::SMLAL:{
2962 if (Subtarget->isThumb()) {
2963 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002964 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002965 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002966 ReplaceNode(
2967 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops));
2968 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002969 }else{
2970 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002971 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002972 CurDAG->getRegister(0, MVT::i32),
2973 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002974 ReplaceNode(N, CurDAG->getMachineNode(
2975 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl,
2976 MVT::i32, MVT::i32, Ops));
2977 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002978 }
2979 }
Evan Cheng10043e22007-01-19 07:51:42 +00002980 case ISD::LOAD: {
Justin Bogner45571362016-05-12 00:31:09 +00002981 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
2982 if (tryT2IndexedLoad(N))
2983 return;
2984 } else if (tryARMIndexedLoad(N))
2985 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002986 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002987 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00002988 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002989 case ARMISD::BRCOND: {
2990 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2991 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2992 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00002993
Evan Cheng7e90b112007-07-05 07:15:27 +00002994 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2995 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2996 // Pattern complexity = 6 cost = 1 size = 0
2997
David Goodwin27303cd2009-06-30 18:04:13 +00002998 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2999 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
3000 // Pattern complexity = 6 cost = 1 size = 0
3001
Jim Grosbachf24f9d92009-08-11 15:33:49 +00003002 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00003003 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003004 SDValue Chain = N->getOperand(0);
3005 SDValue N1 = N->getOperand(1);
3006 SDValue N2 = N->getOperand(2);
3007 SDValue N3 = N->getOperand(3);
3008 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00003009 assert(N1.getOpcode() == ISD::BasicBlock);
3010 assert(N2.getOpcode() == ISD::Constant);
3011 assert(N3.getOpcode() == ISD::Register);
3012
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003013 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003014 cast<ConstantSDNode>(N2)->getZExtValue()), dl,
Owen Anderson9f944592009-08-11 20:47:22 +00003015 MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003016 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00003017 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00003018 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003019 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003020 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003021 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003022 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00003023 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003024 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00003025 SDValue(Chain.getNode(), Chain.getResNo()));
Justin Bognered4f3782016-05-12 00:20:19 +00003026 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003027 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00003028 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003029 case ARMISD::VZIP: {
3030 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003031 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003032 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003033 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003034 case MVT::v8i8: Opc = ARM::VZIPd8; break;
3035 case MVT::v4i16: Opc = ARM::VZIPd16; break;
3036 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00003037 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3038 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003039 case MVT::v16i8: Opc = ARM::VZIPq8; break;
3040 case MVT::v8i16: Opc = ARM::VZIPq16; break;
3041 case MVT::v4f32:
3042 case MVT::v4i32: Opc = ARM::VZIPq32; break;
3043 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003044 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003045 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3046 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003047 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3048 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003049 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003050 case ARMISD::VUZP: {
3051 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003052 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003053 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003054 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003055 case MVT::v8i8: Opc = ARM::VUZPd8; break;
3056 case MVT::v4i16: Opc = ARM::VUZPd16; break;
3057 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00003058 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3059 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003060 case MVT::v16i8: Opc = ARM::VUZPq8; break;
3061 case MVT::v8i16: Opc = ARM::VUZPq16; break;
3062 case MVT::v4f32:
3063 case MVT::v4i32: Opc = ARM::VUZPq32; break;
3064 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003065 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003066 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3067 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003068 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3069 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003070 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003071 case ARMISD::VTRN: {
3072 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003073 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003074 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003075 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003076 case MVT::v8i8: Opc = ARM::VTRNd8; break;
3077 case MVT::v4i16: Opc = ARM::VTRNd16; break;
3078 case MVT::v2f32:
3079 case MVT::v2i32: Opc = ARM::VTRNd32; break;
3080 case MVT::v16i8: Opc = ARM::VTRNq8; break;
3081 case MVT::v8i16: Opc = ARM::VTRNq16; break;
3082 case MVT::v4f32:
3083 case MVT::v4i32: Opc = ARM::VTRNq32; break;
3084 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003085 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003086 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3087 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003088 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3089 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003090 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003091 case ARMISD::BUILD_VECTOR: {
3092 EVT VecVT = N->getValueType(0);
3093 EVT EltVT = VecVT.getVectorElementType();
3094 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00003095 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00003096 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003097 ReplaceNode(
3098 N, createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3099 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003100 }
Duncan Sands14627772010-11-03 12:17:33 +00003101 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003102 if (NumElts == 2) {
3103 ReplaceNode(
3104 N, createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3105 return;
3106 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003107 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003108 ReplaceNode(N,
3109 createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
3110 N->getOperand(2), N->getOperand(3)));
3111 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003112 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003113
Bob Wilson2d790df2010-11-28 06:51:26 +00003114 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003115 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
3116 ARM::VLD2DUPd32 };
Justin Bogner45571362016-05-12 00:31:09 +00003117 SelectVLDDup(N, false, 2, Opcodes);
3118 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00003119 }
3120
Bob Wilson77ab1652010-11-29 19:35:29 +00003121 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003122 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
3123 ARM::VLD3DUPd16Pseudo,
3124 ARM::VLD3DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003125 SelectVLDDup(N, false, 3, Opcodes);
3126 return;
Bob Wilson77ab1652010-11-29 19:35:29 +00003127 }
3128
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003129 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003130 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
3131 ARM::VLD4DUPd16Pseudo,
3132 ARM::VLD4DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003133 SelectVLDDup(N, false, 4, Opcodes);
3134 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003135 }
3136
3137 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003138 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
3139 ARM::VLD2DUPd16wb_fixed,
3140 ARM::VLD2DUPd32wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003141 SelectVLDDup(N, true, 2, Opcodes);
3142 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003143 }
3144
3145 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003146 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
3147 ARM::VLD3DUPd16Pseudo_UPD,
3148 ARM::VLD3DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003149 SelectVLDDup(N, true, 3, Opcodes);
3150 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003151 }
3152
3153 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003154 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
3155 ARM::VLD4DUPd16Pseudo_UPD,
3156 ARM::VLD4DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003157 SelectVLDDup(N, true, 4, Opcodes);
3158 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003159 }
3160
3161 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003162 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
3163 ARM::VLD1d16wb_fixed,
3164 ARM::VLD1d32wb_fixed,
3165 ARM::VLD1d64wb_fixed };
3166 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
3167 ARM::VLD1q16wb_fixed,
3168 ARM::VLD1q32wb_fixed,
3169 ARM::VLD1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003170 SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
3171 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003172 }
3173
3174 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003175 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
3176 ARM::VLD2d16wb_fixed,
3177 ARM::VLD2d32wb_fixed,
3178 ARM::VLD1q64wb_fixed};
3179 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
3180 ARM::VLD2q16PseudoWB_fixed,
3181 ARM::VLD2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003182 SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
3183 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003184 }
3185
3186 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003187 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
3188 ARM::VLD3d16Pseudo_UPD,
3189 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003190 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003191 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3192 ARM::VLD3q16Pseudo_UPD,
3193 ARM::VLD3q32Pseudo_UPD };
3194 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3195 ARM::VLD3q16oddPseudo_UPD,
3196 ARM::VLD3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003197 SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3198 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003199 }
3200
3201 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003202 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3203 ARM::VLD4d16Pseudo_UPD,
3204 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003205 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003206 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3207 ARM::VLD4q16Pseudo_UPD,
3208 ARM::VLD4q32Pseudo_UPD };
3209 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3210 ARM::VLD4q16oddPseudo_UPD,
3211 ARM::VLD4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003212 SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3213 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003214 }
3215
3216 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003217 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3218 ARM::VLD2LNd16Pseudo_UPD,
3219 ARM::VLD2LNd32Pseudo_UPD };
3220 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3221 ARM::VLD2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003222 SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3223 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003224 }
3225
3226 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003227 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3228 ARM::VLD3LNd16Pseudo_UPD,
3229 ARM::VLD3LNd32Pseudo_UPD };
3230 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3231 ARM::VLD3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003232 SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3233 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003234 }
3235
3236 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003237 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3238 ARM::VLD4LNd16Pseudo_UPD,
3239 ARM::VLD4LNd32Pseudo_UPD };
3240 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3241 ARM::VLD4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003242 SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3243 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003244 }
3245
3246 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003247 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3248 ARM::VST1d16wb_fixed,
3249 ARM::VST1d32wb_fixed,
3250 ARM::VST1d64wb_fixed };
3251 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3252 ARM::VST1q16wb_fixed,
3253 ARM::VST1q32wb_fixed,
3254 ARM::VST1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003255 SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
3256 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003257 }
3258
3259 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003260 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3261 ARM::VST2d16wb_fixed,
3262 ARM::VST2d32wb_fixed,
3263 ARM::VST1q64wb_fixed};
3264 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3265 ARM::VST2q16PseudoWB_fixed,
3266 ARM::VST2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003267 SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
3268 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003269 }
3270
3271 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003272 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3273 ARM::VST3d16Pseudo_UPD,
3274 ARM::VST3d32Pseudo_UPD,
3275 ARM::VST1d64TPseudoWB_fixed};
3276 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3277 ARM::VST3q16Pseudo_UPD,
3278 ARM::VST3q32Pseudo_UPD };
3279 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3280 ARM::VST3q16oddPseudo_UPD,
3281 ARM::VST3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003282 SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3283 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003284 }
3285
3286 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003287 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3288 ARM::VST4d16Pseudo_UPD,
3289 ARM::VST4d32Pseudo_UPD,
3290 ARM::VST1d64QPseudoWB_fixed};
3291 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3292 ARM::VST4q16Pseudo_UPD,
3293 ARM::VST4q32Pseudo_UPD };
3294 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3295 ARM::VST4q16oddPseudo_UPD,
3296 ARM::VST4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003297 SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3298 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003299 }
3300
3301 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003302 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3303 ARM::VST2LNd16Pseudo_UPD,
3304 ARM::VST2LNd32Pseudo_UPD };
3305 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3306 ARM::VST2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003307 SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3308 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003309 }
3310
3311 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003312 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3313 ARM::VST3LNd16Pseudo_UPD,
3314 ARM::VST3LNd32Pseudo_UPD };
3315 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3316 ARM::VST3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003317 SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3318 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003319 }
3320
3321 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003322 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3323 ARM::VST4LNd16Pseudo_UPD,
3324 ARM::VST4LNd32Pseudo_UPD };
3325 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3326 ARM::VST4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003327 SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
3328 return;
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003329 }
3330
Bob Wilsone0636a72009-08-26 17:39:53 +00003331 case ISD::INTRINSIC_VOID:
3332 case ISD::INTRINSIC_W_CHAIN: {
3333 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003334 switch (IntNo) {
3335 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003336 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003337
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003338 case Intrinsic::arm_mrrc:
3339 case Intrinsic::arm_mrrc2: {
3340 SDLoc dl(N);
3341 SDValue Chain = N->getOperand(0);
3342 unsigned Opc;
3343
3344 if (Subtarget->isThumb())
3345 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
3346 else
3347 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
3348
3349 SmallVector<SDValue, 5> Ops;
3350 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(), dl)); /* coproc */
3351 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(), dl)); /* opc */
3352 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(4))->getZExtValue(), dl)); /* CRm */
3353
3354 // The mrrc2 instruction in ARM doesn't allow predicates, the top 4 bits of the encoded
3355 // instruction will always be '1111' but it is possible in assembly language to specify
3356 // AL as a predicate to mrrc2 but it doesn't make any difference to the encoded instruction.
3357 if (Opc != ARM::MRRC2) {
3358 Ops.push_back(getAL(CurDAG, dl));
3359 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3360 }
3361
3362 Ops.push_back(Chain);
3363
3364 // Writes to two registers.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003365 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003366
3367 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, RetType, Ops));
3368 return;
3369 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003370 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003371 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003372 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003373 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003374 SDValue MemAddr = N->getOperand(2);
Bradley Smith433c22e2016-01-15 10:26:51 +00003375 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
Tim Northover1ff5f292014-03-26 14:39:31 +00003376
3377 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3378 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3379 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003380
3381 // arm_ldrexd returns a i64 value in {i32, i32}
3382 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003383 if (isThumb) {
3384 ResTys.push_back(MVT::i32);
3385 ResTys.push_back(MVT::i32);
3386 } else
3387 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003388 ResTys.push_back(MVT::Other);
3389
Weiming Zhao8f56f882012-11-16 21:55:34 +00003390 // Place arguments in the right order.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003391 SDValue Ops[] = {MemAddr, getAL(CurDAG, dl),
3392 CurDAG->getRegister(0, MVT::i32), Chain};
Michael Liaob53d8962013-04-19 22:22:57 +00003393 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003394 // Transfer memoperands.
3395 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3396 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3397 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3398
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003399 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003400 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003401 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003402 SDValue Result;
3403 if (isThumb)
3404 Result = SDValue(Ld, 0);
3405 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003406 SDValue SubRegIdx =
3407 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003408 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003409 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003410 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003411 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003412 ReplaceUses(SDValue(N, 0), Result);
3413 }
3414 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003415 SDValue Result;
3416 if (isThumb)
3417 Result = SDValue(Ld, 1);
3418 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003419 SDValue SubRegIdx =
3420 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003421 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003422 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003423 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003424 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003425 ReplaceUses(SDValue(N, 1), Result);
3426 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003427 ReplaceUses(SDValue(N, 2), OutChain);
Justin Bognered4f3782016-05-12 00:20:19 +00003428 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003429 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003430 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003431 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003432 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003433 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003434 SDValue Chain = N->getOperand(0);
3435 SDValue Val0 = N->getOperand(2);
3436 SDValue Val1 = N->getOperand(3);
3437 SDValue MemAddr = N->getOperand(4);
3438
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003439 // Store exclusive double return a i32 value which is the return status
3440 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003441 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003442
Weiming Zhao8f56f882012-11-16 21:55:34 +00003443 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3444 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003445 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003446 if (isThumb) {
3447 Ops.push_back(Val0);
3448 Ops.push_back(Val1);
3449 } else
3450 // arm_strexd uses GPRPair.
3451 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003452 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003453 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003454 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3455 Ops.push_back(Chain);
3456
Tim Northover1ff5f292014-03-26 14:39:31 +00003457 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3458 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3459 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003460
Michael Liaob53d8962013-04-19 22:22:57 +00003461 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003462 // Transfer memoperands.
3463 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3464 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3465 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3466
Justin Bogner45571362016-05-12 00:31:09 +00003467 ReplaceNode(N, St);
3468 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003469 }
3470
Bob Wilson340861d2010-03-23 05:25:43 +00003471 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003472 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3473 ARM::VLD1d32, ARM::VLD1d64 };
3474 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3475 ARM::VLD1q32, ARM::VLD1q64};
Justin Bogner45571362016-05-12 00:31:09 +00003476 SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
3477 return;
Bob Wilson340861d2010-03-23 05:25:43 +00003478 }
3479
Bob Wilsone0636a72009-08-26 17:39:53 +00003480 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003481 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3482 ARM::VLD2d32, ARM::VLD1q64 };
3483 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3484 ARM::VLD2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003485 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3486 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003487 }
3488
3489 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003490 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3491 ARM::VLD3d16Pseudo,
3492 ARM::VLD3d32Pseudo,
3493 ARM::VLD1d64TPseudo };
3494 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3495 ARM::VLD3q16Pseudo_UPD,
3496 ARM::VLD3q32Pseudo_UPD };
3497 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3498 ARM::VLD3q16oddPseudo,
3499 ARM::VLD3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003500 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3501 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003502 }
3503
3504 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003505 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3506 ARM::VLD4d16Pseudo,
3507 ARM::VLD4d32Pseudo,
3508 ARM::VLD1d64QPseudo };
3509 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3510 ARM::VLD4q16Pseudo_UPD,
3511 ARM::VLD4q32Pseudo_UPD };
3512 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3513 ARM::VLD4q16oddPseudo,
3514 ARM::VLD4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003515 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3516 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003517 }
3518
Bob Wilsonda9817c2009-09-01 04:26:28 +00003519 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003520 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3521 ARM::VLD2LNd16Pseudo,
3522 ARM::VLD2LNd32Pseudo };
3523 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3524 ARM::VLD2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003525 SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
3526 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003527 }
3528
3529 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003530 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3531 ARM::VLD3LNd16Pseudo,
3532 ARM::VLD3LNd32Pseudo };
3533 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3534 ARM::VLD3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003535 SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
3536 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003537 }
3538
3539 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003540 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3541 ARM::VLD4LNd16Pseudo,
3542 ARM::VLD4LNd32Pseudo };
3543 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3544 ARM::VLD4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003545 SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
3546 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003547 }
3548
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003549 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003550 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3551 ARM::VST1d32, ARM::VST1d64 };
3552 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3553 ARM::VST1q32, ARM::VST1q64 };
Justin Bogner45571362016-05-12 00:31:09 +00003554 SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
3555 return;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003556 }
3557
Bob Wilsone0636a72009-08-26 17:39:53 +00003558 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003559 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3560 ARM::VST2d32, ARM::VST1q64 };
Benjamin Kramerf690da42016-06-17 14:14:29 +00003561 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3562 ARM::VST2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003563 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3564 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003565 }
3566
3567 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003568 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3569 ARM::VST3d16Pseudo,
3570 ARM::VST3d32Pseudo,
3571 ARM::VST1d64TPseudo };
3572 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3573 ARM::VST3q16Pseudo_UPD,
3574 ARM::VST3q32Pseudo_UPD };
3575 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3576 ARM::VST3q16oddPseudo,
3577 ARM::VST3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003578 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3579 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003580 }
3581
3582 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003583 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3584 ARM::VST4d16Pseudo,
3585 ARM::VST4d32Pseudo,
3586 ARM::VST1d64QPseudo };
3587 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3588 ARM::VST4q16Pseudo_UPD,
3589 ARM::VST4q32Pseudo_UPD };
3590 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3591 ARM::VST4q16oddPseudo,
3592 ARM::VST4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003593 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3594 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003595 }
Bob Wilsond7797752009-09-01 18:51:56 +00003596
3597 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003598 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3599 ARM::VST2LNd16Pseudo,
3600 ARM::VST2LNd32Pseudo };
3601 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3602 ARM::VST2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003603 SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
3604 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003605 }
3606
3607 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003608 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3609 ARM::VST3LNd16Pseudo,
3610 ARM::VST3LNd32Pseudo };
3611 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3612 ARM::VST3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003613 SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
3614 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003615 }
3616
3617 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003618 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3619 ARM::VST4LNd16Pseudo,
3620 ARM::VST4LNd32Pseudo };
3621 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3622 ARM::VST4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003623 SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
3624 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003625 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003626 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003627 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003628 }
Evan Chengd85631e2010-05-05 18:28:36 +00003629
Bob Wilson3ed511b2010-07-06 23:36:25 +00003630 case ISD::INTRINSIC_WO_CHAIN: {
3631 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3632 switch (IntNo) {
3633 default:
3634 break;
3635
3636 case Intrinsic::arm_neon_vtbl2:
Justin Bogner45571362016-05-12 00:31:09 +00003637 SelectVTBL(N, false, 2, ARM::VTBL2);
3638 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003639 case Intrinsic::arm_neon_vtbl3:
Justin Bogner45571362016-05-12 00:31:09 +00003640 SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
3641 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003642 case Intrinsic::arm_neon_vtbl4:
Justin Bogner45571362016-05-12 00:31:09 +00003643 SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
3644 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003645
3646 case Intrinsic::arm_neon_vtbx2:
Justin Bogner45571362016-05-12 00:31:09 +00003647 SelectVTBL(N, true, 2, ARM::VTBX2);
3648 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003649 case Intrinsic::arm_neon_vtbx3:
Justin Bogner45571362016-05-12 00:31:09 +00003650 SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
3651 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003652 case Intrinsic::arm_neon_vtbx4:
Justin Bogner45571362016-05-12 00:31:09 +00003653 SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
3654 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003655 }
3656 break;
3657 }
3658
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003659 case ARMISD::VTBL1: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003660 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003661 EVT VT = N->getValueType(0);
Benjamin Kramerf690da42016-06-17 14:14:29 +00003662 SDValue Ops[] = {N->getOperand(0), N->getOperand(1),
3663 getAL(CurDAG, dl), // Predicate
3664 CurDAG->getRegister(0, MVT::i32)}; // Predicate Register
Justin Bogner45571362016-05-12 00:31:09 +00003665 ReplaceNode(N, CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops));
3666 return;
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003667 }
3668 case ARMISD::VTBL2: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003669 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003670 EVT VT = N->getValueType(0);
3671
3672 // Form a REG_SEQUENCE to force register allocation.
3673 SDValue V0 = N->getOperand(0);
3674 SDValue V1 = N->getOperand(1);
Weiming Zhao95782222012-11-17 00:23:35 +00003675 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003676
Benjamin Kramerf690da42016-06-17 14:14:29 +00003677 SDValue Ops[] = {RegSeq, N->getOperand(2), getAL(CurDAG, dl), // Predicate
3678 CurDAG->getRegister(0, MVT::i32)}; // Predicate Register
Justin Bogner45571362016-05-12 00:31:09 +00003679 ReplaceNode(N, CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops));
3680 return;
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003681 }
3682
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003683 case ISD::CONCAT_VECTORS:
Justin Bogner45571362016-05-12 00:31:09 +00003684 SelectConcatVector(N);
3685 return;
Tim Northoverb629c772016-04-18 21:48:55 +00003686
3687 case ISD::ATOMIC_CMP_SWAP:
Justin Bogner45571362016-05-12 00:31:09 +00003688 SelectCMP_SWAP(N);
3689 return;
Evan Chengd85631e2010-05-05 18:28:36 +00003690 }
Evan Chengd5021732008-12-10 21:54:21 +00003691
Justin Bogner45571362016-05-12 00:31:09 +00003692 SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003693}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003694
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003695// Inspect a register string of the form
3696// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3697// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3698// and obtain the integer operands from them, adding these operands to the
3699// provided vector.
3700static void getIntOperandsFromRegisterString(StringRef RegString,
Benjamin Kramerbdc49562016-06-12 15:39:02 +00003701 SelectionDAG *CurDAG,
3702 const SDLoc &DL,
3703 std::vector<SDValue> &Ops) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003704 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003705 RegString.split(Fields, ':');
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003706
3707 if (Fields.size() > 1) {
3708 bool AllIntFields = true;
3709
3710 for (StringRef Field : Fields) {
3711 // Need to trim out leading 'cp' characters and get the integer field.
3712 unsigned IntField;
3713 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3714 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3715 }
3716
3717 assert(AllIntFields &&
3718 "Unexpected non-integer value in special register string.");
3719 }
3720}
3721
3722// Maps a Banked Register string to its mask value. The mask value returned is
3723// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3724// mask operand, which expresses which register is to be used, e.g. r8, and in
3725// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3726// was invalid.
3727static inline int getBankedRegisterMask(StringRef RegString) {
3728 return StringSwitch<int>(RegString.lower())
3729 .Case("r8_usr", 0x00)
3730 .Case("r9_usr", 0x01)
3731 .Case("r10_usr", 0x02)
3732 .Case("r11_usr", 0x03)
3733 .Case("r12_usr", 0x04)
3734 .Case("sp_usr", 0x05)
3735 .Case("lr_usr", 0x06)
3736 .Case("r8_fiq", 0x08)
3737 .Case("r9_fiq", 0x09)
3738 .Case("r10_fiq", 0x0a)
3739 .Case("r11_fiq", 0x0b)
3740 .Case("r12_fiq", 0x0c)
3741 .Case("sp_fiq", 0x0d)
3742 .Case("lr_fiq", 0x0e)
3743 .Case("lr_irq", 0x10)
3744 .Case("sp_irq", 0x11)
3745 .Case("lr_svc", 0x12)
3746 .Case("sp_svc", 0x13)
3747 .Case("lr_abt", 0x14)
3748 .Case("sp_abt", 0x15)
3749 .Case("lr_und", 0x16)
3750 .Case("sp_und", 0x17)
3751 .Case("lr_mon", 0x1c)
3752 .Case("sp_mon", 0x1d)
3753 .Case("elr_hyp", 0x1e)
3754 .Case("sp_hyp", 0x1f)
3755 .Case("spsr_fiq", 0x2e)
3756 .Case("spsr_irq", 0x30)
3757 .Case("spsr_svc", 0x32)
3758 .Case("spsr_abt", 0x34)
3759 .Case("spsr_und", 0x36)
3760 .Case("spsr_mon", 0x3c)
3761 .Case("spsr_hyp", 0x3e)
3762 .Default(-1);
3763}
3764
3765// Maps a MClass special register string to its value for use in the
3766// t2MRS_M / t2MSR_M instruction nodes as the SYSm value operand.
3767// Returns -1 to signify that the string was invalid.
3768static inline int getMClassRegisterSYSmValueMask(StringRef RegString) {
3769 return StringSwitch<int>(RegString.lower())
3770 .Case("apsr", 0x0)
3771 .Case("iapsr", 0x1)
3772 .Case("eapsr", 0x2)
3773 .Case("xpsr", 0x3)
3774 .Case("ipsr", 0x5)
3775 .Case("epsr", 0x6)
3776 .Case("iepsr", 0x7)
3777 .Case("msp", 0x8)
3778 .Case("psp", 0x9)
3779 .Case("primask", 0x10)
3780 .Case("basepri", 0x11)
3781 .Case("basepri_max", 0x12)
3782 .Case("faultmask", 0x13)
3783 .Case("control", 0x14)
Bradley Smithf277c8a2016-01-25 11:25:36 +00003784 .Case("msplim", 0x0a)
3785 .Case("psplim", 0x0b)
3786 .Case("sp", 0x18)
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003787 .Default(-1);
3788}
3789
3790// The flags here are common to those allowed for apsr in the A class cores and
3791// those allowed for the special registers in the M class cores. Returns a
3792// value representing which flags were present, -1 if invalid.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003793static inline int getMClassFlagsMask(StringRef Flags, bool hasDSP) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003794 if (Flags.empty())
Artyom Skrobovcf296442015-09-24 17:31:16 +00003795 return 0x2 | (int)hasDSP;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003796
3797 return StringSwitch<int>(Flags)
3798 .Case("g", 0x1)
3799 .Case("nzcvq", 0x2)
3800 .Case("nzcvqg", 0x3)
3801 .Default(-1);
3802}
3803
3804static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead,
3805 const ARMSubtarget *Subtarget) {
3806 // Ensure that the register (without flags) was a valid M Class special
3807 // register.
3808 int SYSmvalue = getMClassRegisterSYSmValueMask(Reg);
3809 if (SYSmvalue == -1)
3810 return -1;
3811
3812 // basepri, basepri_max and faultmask are only valid for V7m.
3813 if (!Subtarget->hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
3814 return -1;
3815
Bradley Smithf277c8a2016-01-25 11:25:36 +00003816 if (Subtarget->has8MSecExt() && Flags.lower() == "ns") {
3817 Flags = "";
3818 SYSmvalue |= 0x80;
3819 }
3820
3821 if (!Subtarget->has8MSecExt() &&
3822 (SYSmvalue == 0xa || SYSmvalue == 0xb || SYSmvalue > 0x14))
3823 return -1;
3824
3825 if (!Subtarget->hasV8MMainlineOps() &&
3826 (SYSmvalue == 0x8a || SYSmvalue == 0x8b || SYSmvalue == 0x91 ||
3827 SYSmvalue == 0x93))
3828 return -1;
3829
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003830 // If it was a read then we won't be expecting flags and so at this point
3831 // we can return the mask.
3832 if (IsRead) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00003833 if (Flags.empty())
3834 return SYSmvalue;
3835 else
3836 return -1;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003837 }
3838
3839 // We know we are now handling a write so need to get the mask for the flags.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003840 int Mask = getMClassFlagsMask(Flags, Subtarget->hasDSP());
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003841
3842 // Only apsr, iapsr, eapsr, xpsr can have flags. The other register values
3843 // shouldn't have flags present.
3844 if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.empty()))
3845 return -1;
3846
3847 // The _g and _nzcvqg versions are only valid if the DSP extension is
3848 // available.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003849 if (!Subtarget->hasDSP() && (Mask & 0x1))
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003850 return -1;
3851
3852 // The register was valid so need to put the mask in the correct place
3853 // (the flags need to be in bits 11-10) and combine with the SYSmvalue to
3854 // construct the operand for the instruction node.
3855 if (SYSmvalue < 0x4)
3856 return SYSmvalue | Mask << 10;
3857
3858 return SYSmvalue;
3859}
3860
3861static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
3862 // The mask operand contains the special register (R Bit) in bit 4, whether
3863 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
3864 // bits 3-0 contains the fields to be accessed in the special register, set by
3865 // the flags provided with the register.
3866 int Mask = 0;
3867 if (Reg == "apsr") {
3868 // The flags permitted for apsr are the same flags that are allowed in
3869 // M class registers. We get the flag value and then shift the flags into
3870 // the correct place to combine with the mask.
Artyom Skrobov6fbef2a2015-08-05 11:02:14 +00003871 Mask = getMClassFlagsMask(Flags, true);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003872 if (Mask == -1)
3873 return -1;
3874 return Mask << 2;
3875 }
3876
3877 if (Reg != "cpsr" && Reg != "spsr") {
3878 return -1;
3879 }
3880
3881 // This is the same as if the flags were "fc"
3882 if (Flags.empty() || Flags == "all")
3883 return Mask | 0x9;
3884
3885 // Inspect the supplied flags string and set the bits in the mask for
3886 // the relevant and valid flags allowed for cpsr and spsr.
3887 for (char Flag : Flags) {
3888 int FlagVal;
3889 switch (Flag) {
3890 case 'c':
3891 FlagVal = 0x1;
3892 break;
3893 case 'x':
3894 FlagVal = 0x2;
3895 break;
3896 case 's':
3897 FlagVal = 0x4;
3898 break;
3899 case 'f':
3900 FlagVal = 0x8;
3901 break;
3902 default:
3903 FlagVal = 0;
3904 }
3905
3906 // This avoids allowing strings where the same flag bit appears twice.
3907 if (!FlagVal || (Mask & FlagVal))
3908 return -1;
3909 Mask |= FlagVal;
3910 }
3911
3912 // If the register is spsr then we need to set the R bit.
3913 if (Reg == "spsr")
3914 Mask |= 0x10;
3915
3916 return Mask;
3917}
3918
3919// Lower the read_register intrinsic to ARM specific DAG nodes
3920// using the supplied metadata string to select the instruction node to use
3921// and the registers/masks to construct as operands for the node.
Justin Bogner45571362016-05-12 00:31:09 +00003922bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003923 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3924 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3925 bool IsThumb2 = Subtarget->isThumb2();
3926 SDLoc DL(N);
3927
3928 std::vector<SDValue> Ops;
3929 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3930
3931 if (!Ops.empty()) {
3932 // If the special register string was constructed of fields (as defined
3933 // in the ACLE) then need to lower to MRC node (32 bit) or
3934 // MRRC node(64 bit), we can make the distinction based on the number of
3935 // operands we have.
3936 unsigned Opcode;
3937 SmallVector<EVT, 3> ResTypes;
3938 if (Ops.size() == 5){
3939 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
3940 ResTypes.append({ MVT::i32, MVT::Other });
3941 } else {
3942 assert(Ops.size() == 3 &&
3943 "Invalid number of fields in special register string.");
3944 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
3945 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
3946 }
3947
3948 Ops.push_back(getAL(CurDAG, DL));
3949 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3950 Ops.push_back(N->getOperand(0));
Justin Bogner45571362016-05-12 00:31:09 +00003951 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops));
3952 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003953 }
3954
3955 std::string SpecialReg = RegString->getString().lower();
3956
3957 int BankedReg = getBankedRegisterMask(SpecialReg);
3958 if (BankedReg != -1) {
3959 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
3960 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3961 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003962 ReplaceNode(
3963 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
3964 DL, MVT::i32, MVT::Other, Ops));
3965 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003966 }
3967
3968 // The VFP registers are read by creating SelectionDAG nodes with opcodes
3969 // corresponding to the register that is being read from. So we switch on the
3970 // string to find which opcode we need to use.
3971 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3972 .Case("fpscr", ARM::VMRS)
3973 .Case("fpexc", ARM::VMRS_FPEXC)
3974 .Case("fpsid", ARM::VMRS_FPSID)
3975 .Case("mvfr0", ARM::VMRS_MVFR0)
3976 .Case("mvfr1", ARM::VMRS_MVFR1)
3977 .Case("mvfr2", ARM::VMRS_MVFR2)
3978 .Case("fpinst", ARM::VMRS_FPINST)
3979 .Case("fpinst2", ARM::VMRS_FPINST2)
3980 .Default(0);
3981
3982 // If an opcode was found then we can lower the read to a VFP instruction.
3983 if (Opcode) {
3984 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00003985 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003986 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
Justin Bogner45571362016-05-12 00:31:09 +00003987 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003988
3989 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3990 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003991 ReplaceNode(N,
3992 CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops));
3993 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003994 }
3995
3996 // If the target is M Class then need to validate that the register string
3997 // is an acceptable value, so check that a mask can be constructed from the
3998 // string.
3999 if (Subtarget->isMClass()) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00004000 StringRef Flags = "", Reg = SpecialReg;
4001 if (Reg.endswith("_ns")) {
4002 Flags = "ns";
4003 Reg = Reg.drop_back(3);
4004 }
4005
4006 int SYSmValue = getMClassRegisterMask(Reg, Flags, true, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004007 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004008 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004009
4010 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4011 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4012 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004013 ReplaceNode(
4014 N, CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops));
4015 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004016 }
4017
4018 // Here we know the target is not M Class so we need to check if it is one
4019 // of the remaining possible values which are apsr, cpsr or spsr.
4020 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
4021 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4022 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004023 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
4024 DL, MVT::i32, MVT::Other, Ops));
4025 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004026 }
4027
4028 if (SpecialReg == "spsr") {
4029 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4030 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004031 ReplaceNode(
4032 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys, DL,
4033 MVT::i32, MVT::Other, Ops));
4034 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004035 }
4036
Justin Bogner45571362016-05-12 00:31:09 +00004037 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004038}
4039
4040// Lower the write_register intrinsic to ARM specific DAG nodes
4041// using the supplied metadata string to select the instruction node to use
4042// and the registers/masks to use in the nodes
Justin Bogner45571362016-05-12 00:31:09 +00004043bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004044 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
4045 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
4046 bool IsThumb2 = Subtarget->isThumb2();
4047 SDLoc DL(N);
4048
4049 std::vector<SDValue> Ops;
4050 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
4051
4052 if (!Ops.empty()) {
4053 // If the special register string was constructed of fields (as defined
4054 // in the ACLE) then need to lower to MCR node (32 bit) or
4055 // MCRR node(64 bit), we can make the distinction based on the number of
4056 // operands we have.
4057 unsigned Opcode;
4058 if (Ops.size() == 5) {
4059 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
4060 Ops.insert(Ops.begin()+2, N->getOperand(2));
4061 } else {
4062 assert(Ops.size() == 3 &&
4063 "Invalid number of fields in special register string.");
4064 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
4065 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
4066 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
4067 }
4068
4069 Ops.push_back(getAL(CurDAG, DL));
4070 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4071 Ops.push_back(N->getOperand(0));
4072
Justin Bogner45571362016-05-12 00:31:09 +00004073 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4074 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004075 }
4076
4077 std::string SpecialReg = RegString->getString().lower();
4078 int BankedReg = getBankedRegisterMask(SpecialReg);
4079 if (BankedReg != -1) {
4080 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
4081 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4082 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004083 ReplaceNode(
4084 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
4085 DL, MVT::Other, Ops));
4086 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004087 }
4088
4089 // The VFP registers are written to by creating SelectionDAG nodes with
4090 // opcodes corresponding to the register that is being written. So we switch
4091 // on the string to find which opcode we need to use.
4092 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
4093 .Case("fpscr", ARM::VMSR)
4094 .Case("fpexc", ARM::VMSR_FPEXC)
4095 .Case("fpsid", ARM::VMSR_FPSID)
4096 .Case("fpinst", ARM::VMSR_FPINST)
4097 .Case("fpinst2", ARM::VMSR_FPINST2)
4098 .Default(0);
4099
4100 if (Opcode) {
4101 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004102 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004103 Ops = { N->getOperand(2), getAL(CurDAG, DL),
4104 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004105 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4106 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004107 }
4108
Bradley Smithf277c8a2016-01-25 11:25:36 +00004109 std::pair<StringRef, StringRef> Fields;
4110 Fields = StringRef(SpecialReg).rsplit('_');
4111 std::string Reg = Fields.first.str();
4112 StringRef Flags = Fields.second;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004113
4114 // If the target was M Class then need to validate the special register value
4115 // and retrieve the mask for use in the instruction node.
4116 if (Subtarget->isMClass()) {
4117 // basepri_max gets split so need to correct Reg and Flags.
4118 if (SpecialReg == "basepri_max") {
4119 Reg = SpecialReg;
4120 Flags = "";
4121 }
4122 int SYSmValue = getMClassRegisterMask(Reg, Flags, false, Subtarget);
4123 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004124 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004125
4126 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4127 N->getOperand(2), getAL(CurDAG, DL),
4128 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004129 ReplaceNode(N, CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops));
4130 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004131 }
4132
4133 // We then check to see if a valid mask can be constructed for one of the
4134 // register string values permitted for the A and R class cores. These values
4135 // are apsr, spsr and cpsr; these are also valid on older cores.
4136 int Mask = getARClassRegisterMask(Reg, Flags);
4137 if (Mask != -1) {
4138 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
4139 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4140 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004141 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
4142 DL, MVT::Other, Ops));
4143 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004144 }
4145
Justin Bogner45571362016-05-12 00:31:09 +00004146 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004147}
4148
Justin Bogner45571362016-05-12 00:31:09 +00004149bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){
Weiming Zhaoc5987002013-02-14 18:10:21 +00004150 std::vector<SDValue> AsmNodeOperands;
4151 unsigned Flag, Kind;
4152 bool Changed = false;
4153 unsigned NumOps = N->getNumOperands();
4154
Weiming Zhaoc5987002013-02-14 18:10:21 +00004155 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
4156 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
4157 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
4158 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004159 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
4160 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
4161 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00004162
Andrew Trickef9de2a2013-05-25 02:42:55 +00004163 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00004164 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
4165 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004166
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004167 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004168 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004169 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00004170 SDValue op = N->getOperand(i);
4171 AsmNodeOperands.push_back(op);
4172
4173 if (i < InlineAsm::Op_FirstOperand)
4174 continue;
4175
4176 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
4177 Flag = C->getZExtValue();
4178 Kind = InlineAsm::getKind(Flag);
4179 }
4180 else
4181 continue;
4182
Joey Gouly392cdad2013-07-08 19:52:51 +00004183 // Immediate operands to inline asm in the SelectionDAG are modeled with
4184 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
4185 // the second is a constant with the value of the immediate. If we get here
4186 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00004187 if (Kind == InlineAsm::Kind_Imm) {
4188 SDValue op = N->getOperand(++i);
4189 AsmNodeOperands.push_back(op);
4190 continue;
4191 }
4192
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004193 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
4194 if (NumRegs)
4195 OpChanged.push_back(false);
4196
4197 unsigned DefIdx = 0;
4198 bool IsTiedToChangedOp = false;
4199 // If it's a use that is tied with a previous def, it has no
4200 // reg class constraint.
4201 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
4202 IsTiedToChangedOp = OpChanged[DefIdx];
4203
Weiming Zhaoc5987002013-02-14 18:10:21 +00004204 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
4205 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
4206 continue;
4207
Weiming Zhaoc5987002013-02-14 18:10:21 +00004208 unsigned RC;
4209 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004210 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
4211 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00004212 continue;
4213
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004214 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00004215 SDValue V0 = N->getOperand(i+1);
4216 SDValue V1 = N->getOperand(i+2);
4217 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
4218 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
4219 SDValue PairedReg;
4220 MachineRegisterInfo &MRI = MF->getRegInfo();
4221
4222 if (Kind == InlineAsm::Kind_RegDef ||
4223 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
4224 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
4225 // the original GPRs.
4226
4227 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4228 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4229 SDValue Chain = SDValue(N,0);
4230
4231 SDNode *GU = N->getGluedUser();
4232 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
4233 Chain.getValue(1));
4234
4235 // Extract values from a GPRPair reg and copy to the original GPR reg.
4236 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4237 RegCopy);
4238 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4239 RegCopy);
4240 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
4241 RegCopy.getValue(1));
4242 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
4243
4244 // Update the original glue user.
4245 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
4246 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00004247 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004248 }
4249 else {
4250 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
4251 // GPRPair and then pass the GPRPair to the inline asm.
4252 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
4253
4254 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
4255 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
4256 Chain.getValue(1));
4257 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
4258 T0.getValue(1));
4259 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
4260
4261 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
4262 // i32 VRs of inline asm with it.
4263 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4264 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4265 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
4266
4267 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
4268 Glue = Chain.getValue(1);
4269 }
4270
4271 Changed = true;
4272
4273 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004274 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004275 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00004276 if (IsTiedToChangedOp)
4277 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
4278 else
4279 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004280 // Replace the current flag.
4281 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00004282 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004283 // Add the new register node and skip the original two GPRs.
4284 AsmNodeOperands.push_back(PairedReg);
4285 // Skip the next two GPRs.
4286 i += 2;
4287 }
4288 }
4289
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004290 if (Glue.getNode())
4291 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004292 if (!Changed)
Justin Bogner45571362016-05-12 00:31:09 +00004293 return false;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004294
Andrew Trickef9de2a2013-05-25 02:42:55 +00004295 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00004296 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004297 New->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00004298 ReplaceNode(N, New.getNode());
4299 return true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004300}
4301
4302
Bob Wilsona2c462b2009-05-19 05:53:42 +00004303bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00004304SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00004305 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004306 switch(ConstraintID) {
4307 default:
4308 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00004309 case InlineAsm::Constraint_i:
4310 // FIXME: It seems strange that 'i' is needed here since it's supposed to
4311 // be an immediate and not a memory constraint.
4312 // Fallthrough.
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004313 case InlineAsm::Constraint_m:
James Molloy72222f52015-10-26 10:04:52 +00004314 case InlineAsm::Constraint_o:
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004315 case InlineAsm::Constraint_Q:
4316 case InlineAsm::Constraint_Um:
4317 case InlineAsm::Constraint_Un:
4318 case InlineAsm::Constraint_Uq:
4319 case InlineAsm::Constraint_Us:
4320 case InlineAsm::Constraint_Ut:
4321 case InlineAsm::Constraint_Uv:
4322 case InlineAsm::Constraint_Uy:
4323 // Require the address to be in a register. That is safe for all ARM
4324 // variants and it is hard to do anything much smarter without knowing
4325 // how the operand is used.
4326 OutOps.push_back(Op);
4327 return false;
4328 }
4329 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00004330}
4331
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004332/// createARMISelDag - This pass converts a legalized DAG into a
4333/// ARM-specific DAG, ready for instruction scheduling.
4334///
Bob Wilson2dd957f2009-09-28 14:30:20 +00004335FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
4336 CodeGenOpt::Level OptLevel) {
4337 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004338}