blob: a17c8ff0e10d549ba9dcb07547b2b661a90168a1 [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.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +000086 inline SDValue getI32Imm(unsigned Imm, SDLoc dl) {
87 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.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000273 SDValue GetVLDSTAlign(SDValue Align, SDLoc dl, unsigned NumVecs,
274 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 Molloyb1013832016-06-07 13:10:14 +0000488 if (Val <= 511) 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.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001476static inline SDValue getAL(SelectionDAG *CurDAG, SDLoc dl) {
1477 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.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001696SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, SDLoc dl,
1697 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
Tim Northover1ff5f292014-03-26 14:39:31 +00003338 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003339 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003340 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003341 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003342 SDValue MemAddr = N->getOperand(2);
Bradley Smith433c22e2016-01-15 10:26:51 +00003343 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
Tim Northover1ff5f292014-03-26 14:39:31 +00003344
3345 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3346 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3347 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003348
3349 // arm_ldrexd returns a i64 value in {i32, i32}
3350 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003351 if (isThumb) {
3352 ResTys.push_back(MVT::i32);
3353 ResTys.push_back(MVT::i32);
3354 } else
3355 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003356 ResTys.push_back(MVT::Other);
3357
Weiming Zhao8f56f882012-11-16 21:55:34 +00003358 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003359 SmallVector<SDValue, 7> Ops;
3360 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003361 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003362 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3363 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00003364 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003365 // Transfer memoperands.
3366 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3367 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3368 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3369
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003370 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003371 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003372 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003373 SDValue Result;
3374 if (isThumb)
3375 Result = SDValue(Ld, 0);
3376 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003377 SDValue SubRegIdx =
3378 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003379 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003380 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003381 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003382 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003383 ReplaceUses(SDValue(N, 0), Result);
3384 }
3385 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003386 SDValue Result;
3387 if (isThumb)
3388 Result = SDValue(Ld, 1);
3389 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003390 SDValue SubRegIdx =
3391 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003392 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003393 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003394 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003395 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003396 ReplaceUses(SDValue(N, 1), Result);
3397 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003398 ReplaceUses(SDValue(N, 2), OutChain);
Justin Bognered4f3782016-05-12 00:20:19 +00003399 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003400 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003401 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003402 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003403 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003404 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003405 SDValue Chain = N->getOperand(0);
3406 SDValue Val0 = N->getOperand(2);
3407 SDValue Val1 = N->getOperand(3);
3408 SDValue MemAddr = N->getOperand(4);
3409
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003410 // Store exclusive double return a i32 value which is the return status
3411 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003412 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003413
Weiming Zhao8f56f882012-11-16 21:55:34 +00003414 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3415 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003416 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003417 if (isThumb) {
3418 Ops.push_back(Val0);
3419 Ops.push_back(Val1);
3420 } else
3421 // arm_strexd uses GPRPair.
3422 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003423 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003424 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003425 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3426 Ops.push_back(Chain);
3427
Tim Northover1ff5f292014-03-26 14:39:31 +00003428 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3429 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3430 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003431
Michael Liaob53d8962013-04-19 22:22:57 +00003432 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003433 // Transfer memoperands.
3434 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3435 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3436 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3437
Justin Bogner45571362016-05-12 00:31:09 +00003438 ReplaceNode(N, St);
3439 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003440 }
3441
Bob Wilson340861d2010-03-23 05:25:43 +00003442 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003443 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3444 ARM::VLD1d32, ARM::VLD1d64 };
3445 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3446 ARM::VLD1q32, ARM::VLD1q64};
Justin Bogner45571362016-05-12 00:31:09 +00003447 SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
3448 return;
Bob Wilson340861d2010-03-23 05:25:43 +00003449 }
3450
Bob Wilsone0636a72009-08-26 17:39:53 +00003451 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003452 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3453 ARM::VLD2d32, ARM::VLD1q64 };
3454 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3455 ARM::VLD2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003456 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3457 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003458 }
3459
3460 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003461 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3462 ARM::VLD3d16Pseudo,
3463 ARM::VLD3d32Pseudo,
3464 ARM::VLD1d64TPseudo };
3465 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3466 ARM::VLD3q16Pseudo_UPD,
3467 ARM::VLD3q32Pseudo_UPD };
3468 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3469 ARM::VLD3q16oddPseudo,
3470 ARM::VLD3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003471 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3472 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003473 }
3474
3475 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003476 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3477 ARM::VLD4d16Pseudo,
3478 ARM::VLD4d32Pseudo,
3479 ARM::VLD1d64QPseudo };
3480 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3481 ARM::VLD4q16Pseudo_UPD,
3482 ARM::VLD4q32Pseudo_UPD };
3483 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3484 ARM::VLD4q16oddPseudo,
3485 ARM::VLD4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003486 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3487 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003488 }
3489
Bob Wilsonda9817c2009-09-01 04:26:28 +00003490 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003491 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3492 ARM::VLD2LNd16Pseudo,
3493 ARM::VLD2LNd32Pseudo };
3494 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3495 ARM::VLD2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003496 SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
3497 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003498 }
3499
3500 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003501 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3502 ARM::VLD3LNd16Pseudo,
3503 ARM::VLD3LNd32Pseudo };
3504 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3505 ARM::VLD3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003506 SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
3507 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003508 }
3509
3510 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003511 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3512 ARM::VLD4LNd16Pseudo,
3513 ARM::VLD4LNd32Pseudo };
3514 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3515 ARM::VLD4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003516 SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
3517 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003518 }
3519
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003520 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003521 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3522 ARM::VST1d32, ARM::VST1d64 };
3523 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3524 ARM::VST1q32, ARM::VST1q64 };
Justin Bogner45571362016-05-12 00:31:09 +00003525 SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
3526 return;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003527 }
3528
Bob Wilsone0636a72009-08-26 17:39:53 +00003529 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003530 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3531 ARM::VST2d32, ARM::VST1q64 };
3532 static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3533 ARM::VST2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003534 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3535 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003536 }
3537
3538 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003539 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3540 ARM::VST3d16Pseudo,
3541 ARM::VST3d32Pseudo,
3542 ARM::VST1d64TPseudo };
3543 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3544 ARM::VST3q16Pseudo_UPD,
3545 ARM::VST3q32Pseudo_UPD };
3546 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3547 ARM::VST3q16oddPseudo,
3548 ARM::VST3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003549 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3550 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003551 }
3552
3553 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003554 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3555 ARM::VST4d16Pseudo,
3556 ARM::VST4d32Pseudo,
3557 ARM::VST1d64QPseudo };
3558 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3559 ARM::VST4q16Pseudo_UPD,
3560 ARM::VST4q32Pseudo_UPD };
3561 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3562 ARM::VST4q16oddPseudo,
3563 ARM::VST4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003564 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3565 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003566 }
Bob Wilsond7797752009-09-01 18:51:56 +00003567
3568 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003569 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3570 ARM::VST2LNd16Pseudo,
3571 ARM::VST2LNd32Pseudo };
3572 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3573 ARM::VST2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003574 SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
3575 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003576 }
3577
3578 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003579 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3580 ARM::VST3LNd16Pseudo,
3581 ARM::VST3LNd32Pseudo };
3582 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3583 ARM::VST3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003584 SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
3585 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003586 }
3587
3588 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003589 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3590 ARM::VST4LNd16Pseudo,
3591 ARM::VST4LNd32Pseudo };
3592 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3593 ARM::VST4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003594 SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
3595 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003596 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003597 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003598 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003599 }
Evan Chengd85631e2010-05-05 18:28:36 +00003600
Bob Wilson3ed511b2010-07-06 23:36:25 +00003601 case ISD::INTRINSIC_WO_CHAIN: {
3602 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3603 switch (IntNo) {
3604 default:
3605 break;
3606
3607 case Intrinsic::arm_neon_vtbl2:
Justin Bogner45571362016-05-12 00:31:09 +00003608 SelectVTBL(N, false, 2, ARM::VTBL2);
3609 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003610 case Intrinsic::arm_neon_vtbl3:
Justin Bogner45571362016-05-12 00:31:09 +00003611 SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
3612 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003613 case Intrinsic::arm_neon_vtbl4:
Justin Bogner45571362016-05-12 00:31:09 +00003614 SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
3615 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003616
3617 case Intrinsic::arm_neon_vtbx2:
Justin Bogner45571362016-05-12 00:31:09 +00003618 SelectVTBL(N, true, 2, ARM::VTBX2);
3619 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003620 case Intrinsic::arm_neon_vtbx3:
Justin Bogner45571362016-05-12 00:31:09 +00003621 SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
3622 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003623 case Intrinsic::arm_neon_vtbx4:
Justin Bogner45571362016-05-12 00:31:09 +00003624 SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
3625 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003626 }
3627 break;
3628 }
3629
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003630 case ARMISD::VTBL1: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003631 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003632 EVT VT = N->getValueType(0);
3633 SmallVector<SDValue, 6> Ops;
3634
3635 Ops.push_back(N->getOperand(0));
3636 Ops.push_back(N->getOperand(1));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003637 Ops.push_back(getAL(CurDAG, dl)); // Predicate
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003638 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Justin Bogner45571362016-05-12 00:31:09 +00003639 ReplaceNode(N, CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops));
3640 return;
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003641 }
3642 case ARMISD::VTBL2: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003643 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003644 EVT VT = N->getValueType(0);
3645
3646 // Form a REG_SEQUENCE to force register allocation.
3647 SDValue V0 = N->getOperand(0);
3648 SDValue V1 = N->getOperand(1);
Weiming Zhao95782222012-11-17 00:23:35 +00003649 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003650
3651 SmallVector<SDValue, 6> Ops;
3652 Ops.push_back(RegSeq);
3653 Ops.push_back(N->getOperand(2));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003654 Ops.push_back(getAL(CurDAG, dl)); // Predicate
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003655 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Justin Bogner45571362016-05-12 00:31:09 +00003656 ReplaceNode(N, CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops));
3657 return;
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003658 }
3659
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003660 case ISD::CONCAT_VECTORS:
Justin Bogner45571362016-05-12 00:31:09 +00003661 SelectConcatVector(N);
3662 return;
Tim Northoverb629c772016-04-18 21:48:55 +00003663
3664 case ISD::ATOMIC_CMP_SWAP:
Justin Bogner45571362016-05-12 00:31:09 +00003665 SelectCMP_SWAP(N);
3666 return;
Evan Chengd85631e2010-05-05 18:28:36 +00003667 }
Evan Chengd5021732008-12-10 21:54:21 +00003668
Justin Bogner45571362016-05-12 00:31:09 +00003669 SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003670}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003671
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003672// Inspect a register string of the form
3673// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3674// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3675// and obtain the integer operands from them, adding these operands to the
3676// provided vector.
3677static void getIntOperandsFromRegisterString(StringRef RegString,
3678 SelectionDAG *CurDAG, SDLoc DL,
3679 std::vector<SDValue>& Ops) {
3680 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003681 RegString.split(Fields, ':');
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003682
3683 if (Fields.size() > 1) {
3684 bool AllIntFields = true;
3685
3686 for (StringRef Field : Fields) {
3687 // Need to trim out leading 'cp' characters and get the integer field.
3688 unsigned IntField;
3689 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3690 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3691 }
3692
3693 assert(AllIntFields &&
3694 "Unexpected non-integer value in special register string.");
3695 }
3696}
3697
3698// Maps a Banked Register string to its mask value. The mask value returned is
3699// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3700// mask operand, which expresses which register is to be used, e.g. r8, and in
3701// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3702// was invalid.
3703static inline int getBankedRegisterMask(StringRef RegString) {
3704 return StringSwitch<int>(RegString.lower())
3705 .Case("r8_usr", 0x00)
3706 .Case("r9_usr", 0x01)
3707 .Case("r10_usr", 0x02)
3708 .Case("r11_usr", 0x03)
3709 .Case("r12_usr", 0x04)
3710 .Case("sp_usr", 0x05)
3711 .Case("lr_usr", 0x06)
3712 .Case("r8_fiq", 0x08)
3713 .Case("r9_fiq", 0x09)
3714 .Case("r10_fiq", 0x0a)
3715 .Case("r11_fiq", 0x0b)
3716 .Case("r12_fiq", 0x0c)
3717 .Case("sp_fiq", 0x0d)
3718 .Case("lr_fiq", 0x0e)
3719 .Case("lr_irq", 0x10)
3720 .Case("sp_irq", 0x11)
3721 .Case("lr_svc", 0x12)
3722 .Case("sp_svc", 0x13)
3723 .Case("lr_abt", 0x14)
3724 .Case("sp_abt", 0x15)
3725 .Case("lr_und", 0x16)
3726 .Case("sp_und", 0x17)
3727 .Case("lr_mon", 0x1c)
3728 .Case("sp_mon", 0x1d)
3729 .Case("elr_hyp", 0x1e)
3730 .Case("sp_hyp", 0x1f)
3731 .Case("spsr_fiq", 0x2e)
3732 .Case("spsr_irq", 0x30)
3733 .Case("spsr_svc", 0x32)
3734 .Case("spsr_abt", 0x34)
3735 .Case("spsr_und", 0x36)
3736 .Case("spsr_mon", 0x3c)
3737 .Case("spsr_hyp", 0x3e)
3738 .Default(-1);
3739}
3740
3741// Maps a MClass special register string to its value for use in the
3742// t2MRS_M / t2MSR_M instruction nodes as the SYSm value operand.
3743// Returns -1 to signify that the string was invalid.
3744static inline int getMClassRegisterSYSmValueMask(StringRef RegString) {
3745 return StringSwitch<int>(RegString.lower())
3746 .Case("apsr", 0x0)
3747 .Case("iapsr", 0x1)
3748 .Case("eapsr", 0x2)
3749 .Case("xpsr", 0x3)
3750 .Case("ipsr", 0x5)
3751 .Case("epsr", 0x6)
3752 .Case("iepsr", 0x7)
3753 .Case("msp", 0x8)
3754 .Case("psp", 0x9)
3755 .Case("primask", 0x10)
3756 .Case("basepri", 0x11)
3757 .Case("basepri_max", 0x12)
3758 .Case("faultmask", 0x13)
3759 .Case("control", 0x14)
Bradley Smithf277c8a2016-01-25 11:25:36 +00003760 .Case("msplim", 0x0a)
3761 .Case("psplim", 0x0b)
3762 .Case("sp", 0x18)
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003763 .Default(-1);
3764}
3765
3766// The flags here are common to those allowed for apsr in the A class cores and
3767// those allowed for the special registers in the M class cores. Returns a
3768// value representing which flags were present, -1 if invalid.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003769static inline int getMClassFlagsMask(StringRef Flags, bool hasDSP) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003770 if (Flags.empty())
Artyom Skrobovcf296442015-09-24 17:31:16 +00003771 return 0x2 | (int)hasDSP;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003772
3773 return StringSwitch<int>(Flags)
3774 .Case("g", 0x1)
3775 .Case("nzcvq", 0x2)
3776 .Case("nzcvqg", 0x3)
3777 .Default(-1);
3778}
3779
3780static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead,
3781 const ARMSubtarget *Subtarget) {
3782 // Ensure that the register (without flags) was a valid M Class special
3783 // register.
3784 int SYSmvalue = getMClassRegisterSYSmValueMask(Reg);
3785 if (SYSmvalue == -1)
3786 return -1;
3787
3788 // basepri, basepri_max and faultmask are only valid for V7m.
3789 if (!Subtarget->hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
3790 return -1;
3791
Bradley Smithf277c8a2016-01-25 11:25:36 +00003792 if (Subtarget->has8MSecExt() && Flags.lower() == "ns") {
3793 Flags = "";
3794 SYSmvalue |= 0x80;
3795 }
3796
3797 if (!Subtarget->has8MSecExt() &&
3798 (SYSmvalue == 0xa || SYSmvalue == 0xb || SYSmvalue > 0x14))
3799 return -1;
3800
3801 if (!Subtarget->hasV8MMainlineOps() &&
3802 (SYSmvalue == 0x8a || SYSmvalue == 0x8b || SYSmvalue == 0x91 ||
3803 SYSmvalue == 0x93))
3804 return -1;
3805
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003806 // If it was a read then we won't be expecting flags and so at this point
3807 // we can return the mask.
3808 if (IsRead) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00003809 if (Flags.empty())
3810 return SYSmvalue;
3811 else
3812 return -1;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003813 }
3814
3815 // We know we are now handling a write so need to get the mask for the flags.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003816 int Mask = getMClassFlagsMask(Flags, Subtarget->hasDSP());
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003817
3818 // Only apsr, iapsr, eapsr, xpsr can have flags. The other register values
3819 // shouldn't have flags present.
3820 if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.empty()))
3821 return -1;
3822
3823 // The _g and _nzcvqg versions are only valid if the DSP extension is
3824 // available.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003825 if (!Subtarget->hasDSP() && (Mask & 0x1))
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003826 return -1;
3827
3828 // The register was valid so need to put the mask in the correct place
3829 // (the flags need to be in bits 11-10) and combine with the SYSmvalue to
3830 // construct the operand for the instruction node.
3831 if (SYSmvalue < 0x4)
3832 return SYSmvalue | Mask << 10;
3833
3834 return SYSmvalue;
3835}
3836
3837static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
3838 // The mask operand contains the special register (R Bit) in bit 4, whether
3839 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
3840 // bits 3-0 contains the fields to be accessed in the special register, set by
3841 // the flags provided with the register.
3842 int Mask = 0;
3843 if (Reg == "apsr") {
3844 // The flags permitted for apsr are the same flags that are allowed in
3845 // M class registers. We get the flag value and then shift the flags into
3846 // the correct place to combine with the mask.
Artyom Skrobov6fbef2a2015-08-05 11:02:14 +00003847 Mask = getMClassFlagsMask(Flags, true);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003848 if (Mask == -1)
3849 return -1;
3850 return Mask << 2;
3851 }
3852
3853 if (Reg != "cpsr" && Reg != "spsr") {
3854 return -1;
3855 }
3856
3857 // This is the same as if the flags were "fc"
3858 if (Flags.empty() || Flags == "all")
3859 return Mask | 0x9;
3860
3861 // Inspect the supplied flags string and set the bits in the mask for
3862 // the relevant and valid flags allowed for cpsr and spsr.
3863 for (char Flag : Flags) {
3864 int FlagVal;
3865 switch (Flag) {
3866 case 'c':
3867 FlagVal = 0x1;
3868 break;
3869 case 'x':
3870 FlagVal = 0x2;
3871 break;
3872 case 's':
3873 FlagVal = 0x4;
3874 break;
3875 case 'f':
3876 FlagVal = 0x8;
3877 break;
3878 default:
3879 FlagVal = 0;
3880 }
3881
3882 // This avoids allowing strings where the same flag bit appears twice.
3883 if (!FlagVal || (Mask & FlagVal))
3884 return -1;
3885 Mask |= FlagVal;
3886 }
3887
3888 // If the register is spsr then we need to set the R bit.
3889 if (Reg == "spsr")
3890 Mask |= 0x10;
3891
3892 return Mask;
3893}
3894
3895// Lower the read_register intrinsic to ARM specific DAG nodes
3896// using the supplied metadata string to select the instruction node to use
3897// and the registers/masks to construct as operands for the node.
Justin Bogner45571362016-05-12 00:31:09 +00003898bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003899 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3900 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3901 bool IsThumb2 = Subtarget->isThumb2();
3902 SDLoc DL(N);
3903
3904 std::vector<SDValue> Ops;
3905 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3906
3907 if (!Ops.empty()) {
3908 // If the special register string was constructed of fields (as defined
3909 // in the ACLE) then need to lower to MRC node (32 bit) or
3910 // MRRC node(64 bit), we can make the distinction based on the number of
3911 // operands we have.
3912 unsigned Opcode;
3913 SmallVector<EVT, 3> ResTypes;
3914 if (Ops.size() == 5){
3915 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
3916 ResTypes.append({ MVT::i32, MVT::Other });
3917 } else {
3918 assert(Ops.size() == 3 &&
3919 "Invalid number of fields in special register string.");
3920 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
3921 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
3922 }
3923
3924 Ops.push_back(getAL(CurDAG, DL));
3925 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3926 Ops.push_back(N->getOperand(0));
Justin Bogner45571362016-05-12 00:31:09 +00003927 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops));
3928 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003929 }
3930
3931 std::string SpecialReg = RegString->getString().lower();
3932
3933 int BankedReg = getBankedRegisterMask(SpecialReg);
3934 if (BankedReg != -1) {
3935 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
3936 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3937 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003938 ReplaceNode(
3939 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
3940 DL, MVT::i32, MVT::Other, Ops));
3941 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003942 }
3943
3944 // The VFP registers are read by creating SelectionDAG nodes with opcodes
3945 // corresponding to the register that is being read from. So we switch on the
3946 // string to find which opcode we need to use.
3947 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3948 .Case("fpscr", ARM::VMRS)
3949 .Case("fpexc", ARM::VMRS_FPEXC)
3950 .Case("fpsid", ARM::VMRS_FPSID)
3951 .Case("mvfr0", ARM::VMRS_MVFR0)
3952 .Case("mvfr1", ARM::VMRS_MVFR1)
3953 .Case("mvfr2", ARM::VMRS_MVFR2)
3954 .Case("fpinst", ARM::VMRS_FPINST)
3955 .Case("fpinst2", ARM::VMRS_FPINST2)
3956 .Default(0);
3957
3958 // If an opcode was found then we can lower the read to a VFP instruction.
3959 if (Opcode) {
3960 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00003961 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003962 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
Justin Bogner45571362016-05-12 00:31:09 +00003963 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003964
3965 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3966 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003967 ReplaceNode(N,
3968 CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops));
3969 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003970 }
3971
3972 // If the target is M Class then need to validate that the register string
3973 // is an acceptable value, so check that a mask can be constructed from the
3974 // string.
3975 if (Subtarget->isMClass()) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00003976 StringRef Flags = "", Reg = SpecialReg;
3977 if (Reg.endswith("_ns")) {
3978 Flags = "ns";
3979 Reg = Reg.drop_back(3);
3980 }
3981
3982 int SYSmValue = getMClassRegisterMask(Reg, Flags, true, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003983 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00003984 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003985
3986 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
3987 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3988 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003989 ReplaceNode(
3990 N, CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops));
3991 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003992 }
3993
3994 // Here we know the target is not M Class so we need to check if it is one
3995 // of the remaining possible values which are apsr, cpsr or spsr.
3996 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
3997 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3998 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003999 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
4000 DL, MVT::i32, MVT::Other, Ops));
4001 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004002 }
4003
4004 if (SpecialReg == "spsr") {
4005 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4006 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004007 ReplaceNode(
4008 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys, DL,
4009 MVT::i32, MVT::Other, Ops));
4010 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004011 }
4012
Justin Bogner45571362016-05-12 00:31:09 +00004013 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004014}
4015
4016// Lower the write_register intrinsic to ARM specific DAG nodes
4017// using the supplied metadata string to select the instruction node to use
4018// and the registers/masks to use in the nodes
Justin Bogner45571362016-05-12 00:31:09 +00004019bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004020 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
4021 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
4022 bool IsThumb2 = Subtarget->isThumb2();
4023 SDLoc DL(N);
4024
4025 std::vector<SDValue> Ops;
4026 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
4027
4028 if (!Ops.empty()) {
4029 // If the special register string was constructed of fields (as defined
4030 // in the ACLE) then need to lower to MCR node (32 bit) or
4031 // MCRR node(64 bit), we can make the distinction based on the number of
4032 // operands we have.
4033 unsigned Opcode;
4034 if (Ops.size() == 5) {
4035 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
4036 Ops.insert(Ops.begin()+2, N->getOperand(2));
4037 } else {
4038 assert(Ops.size() == 3 &&
4039 "Invalid number of fields in special register string.");
4040 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
4041 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
4042 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
4043 }
4044
4045 Ops.push_back(getAL(CurDAG, DL));
4046 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4047 Ops.push_back(N->getOperand(0));
4048
Justin Bogner45571362016-05-12 00:31:09 +00004049 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4050 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004051 }
4052
4053 std::string SpecialReg = RegString->getString().lower();
4054 int BankedReg = getBankedRegisterMask(SpecialReg);
4055 if (BankedReg != -1) {
4056 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
4057 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4058 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004059 ReplaceNode(
4060 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
4061 DL, MVT::Other, Ops));
4062 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004063 }
4064
4065 // The VFP registers are written to by creating SelectionDAG nodes with
4066 // opcodes corresponding to the register that is being written. So we switch
4067 // on the string to find which opcode we need to use.
4068 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
4069 .Case("fpscr", ARM::VMSR)
4070 .Case("fpexc", ARM::VMSR_FPEXC)
4071 .Case("fpsid", ARM::VMSR_FPSID)
4072 .Case("fpinst", ARM::VMSR_FPINST)
4073 .Case("fpinst2", ARM::VMSR_FPINST2)
4074 .Default(0);
4075
4076 if (Opcode) {
4077 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004078 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004079 Ops = { N->getOperand(2), getAL(CurDAG, DL),
4080 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004081 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4082 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004083 }
4084
Bradley Smithf277c8a2016-01-25 11:25:36 +00004085 std::pair<StringRef, StringRef> Fields;
4086 Fields = StringRef(SpecialReg).rsplit('_');
4087 std::string Reg = Fields.first.str();
4088 StringRef Flags = Fields.second;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004089
4090 // If the target was M Class then need to validate the special register value
4091 // and retrieve the mask for use in the instruction node.
4092 if (Subtarget->isMClass()) {
4093 // basepri_max gets split so need to correct Reg and Flags.
4094 if (SpecialReg == "basepri_max") {
4095 Reg = SpecialReg;
4096 Flags = "";
4097 }
4098 int SYSmValue = getMClassRegisterMask(Reg, Flags, false, Subtarget);
4099 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004100 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004101
4102 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4103 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(ARM::t2MSR_M, DL, MVT::Other, Ops));
4106 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004107 }
4108
4109 // We then check to see if a valid mask can be constructed for one of the
4110 // register string values permitted for the A and R class cores. These values
4111 // are apsr, spsr and cpsr; these are also valid on older cores.
4112 int Mask = getARClassRegisterMask(Reg, Flags);
4113 if (Mask != -1) {
4114 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
4115 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4116 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004117 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
4118 DL, MVT::Other, Ops));
4119 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004120 }
4121
Justin Bogner45571362016-05-12 00:31:09 +00004122 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004123}
4124
Justin Bogner45571362016-05-12 00:31:09 +00004125bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){
Weiming Zhaoc5987002013-02-14 18:10:21 +00004126 std::vector<SDValue> AsmNodeOperands;
4127 unsigned Flag, Kind;
4128 bool Changed = false;
4129 unsigned NumOps = N->getNumOperands();
4130
Weiming Zhaoc5987002013-02-14 18:10:21 +00004131 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
4132 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
4133 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
4134 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004135 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
4136 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
4137 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00004138
Andrew Trickef9de2a2013-05-25 02:42:55 +00004139 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00004140 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
4141 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004142
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004143 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004144 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004145 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00004146 SDValue op = N->getOperand(i);
4147 AsmNodeOperands.push_back(op);
4148
4149 if (i < InlineAsm::Op_FirstOperand)
4150 continue;
4151
4152 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
4153 Flag = C->getZExtValue();
4154 Kind = InlineAsm::getKind(Flag);
4155 }
4156 else
4157 continue;
4158
Joey Gouly392cdad2013-07-08 19:52:51 +00004159 // Immediate operands to inline asm in the SelectionDAG are modeled with
4160 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
4161 // the second is a constant with the value of the immediate. If we get here
4162 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00004163 if (Kind == InlineAsm::Kind_Imm) {
4164 SDValue op = N->getOperand(++i);
4165 AsmNodeOperands.push_back(op);
4166 continue;
4167 }
4168
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004169 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
4170 if (NumRegs)
4171 OpChanged.push_back(false);
4172
4173 unsigned DefIdx = 0;
4174 bool IsTiedToChangedOp = false;
4175 // If it's a use that is tied with a previous def, it has no
4176 // reg class constraint.
4177 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
4178 IsTiedToChangedOp = OpChanged[DefIdx];
4179
Weiming Zhaoc5987002013-02-14 18:10:21 +00004180 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
4181 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
4182 continue;
4183
Weiming Zhaoc5987002013-02-14 18:10:21 +00004184 unsigned RC;
4185 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004186 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
4187 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00004188 continue;
4189
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004190 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00004191 SDValue V0 = N->getOperand(i+1);
4192 SDValue V1 = N->getOperand(i+2);
4193 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
4194 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
4195 SDValue PairedReg;
4196 MachineRegisterInfo &MRI = MF->getRegInfo();
4197
4198 if (Kind == InlineAsm::Kind_RegDef ||
4199 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
4200 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
4201 // the original GPRs.
4202
4203 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4204 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4205 SDValue Chain = SDValue(N,0);
4206
4207 SDNode *GU = N->getGluedUser();
4208 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
4209 Chain.getValue(1));
4210
4211 // Extract values from a GPRPair reg and copy to the original GPR reg.
4212 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4213 RegCopy);
4214 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4215 RegCopy);
4216 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
4217 RegCopy.getValue(1));
4218 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
4219
4220 // Update the original glue user.
4221 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
4222 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00004223 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004224 }
4225 else {
4226 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
4227 // GPRPair and then pass the GPRPair to the inline asm.
4228 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
4229
4230 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
4231 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
4232 Chain.getValue(1));
4233 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
4234 T0.getValue(1));
4235 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
4236
4237 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
4238 // i32 VRs of inline asm with it.
4239 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4240 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4241 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
4242
4243 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
4244 Glue = Chain.getValue(1);
4245 }
4246
4247 Changed = true;
4248
4249 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004250 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004251 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00004252 if (IsTiedToChangedOp)
4253 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
4254 else
4255 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004256 // Replace the current flag.
4257 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00004258 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004259 // Add the new register node and skip the original two GPRs.
4260 AsmNodeOperands.push_back(PairedReg);
4261 // Skip the next two GPRs.
4262 i += 2;
4263 }
4264 }
4265
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004266 if (Glue.getNode())
4267 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004268 if (!Changed)
Justin Bogner45571362016-05-12 00:31:09 +00004269 return false;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004270
Andrew Trickef9de2a2013-05-25 02:42:55 +00004271 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00004272 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004273 New->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00004274 ReplaceNode(N, New.getNode());
4275 return true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004276}
4277
4278
Bob Wilsona2c462b2009-05-19 05:53:42 +00004279bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00004280SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00004281 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004282 switch(ConstraintID) {
4283 default:
4284 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00004285 case InlineAsm::Constraint_i:
4286 // FIXME: It seems strange that 'i' is needed here since it's supposed to
4287 // be an immediate and not a memory constraint.
4288 // Fallthrough.
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004289 case InlineAsm::Constraint_m:
James Molloy72222f52015-10-26 10:04:52 +00004290 case InlineAsm::Constraint_o:
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004291 case InlineAsm::Constraint_Q:
4292 case InlineAsm::Constraint_Um:
4293 case InlineAsm::Constraint_Un:
4294 case InlineAsm::Constraint_Uq:
4295 case InlineAsm::Constraint_Us:
4296 case InlineAsm::Constraint_Ut:
4297 case InlineAsm::Constraint_Uv:
4298 case InlineAsm::Constraint_Uy:
4299 // Require the address to be in a register. That is safe for all ARM
4300 // variants and it is hard to do anything much smarter without knowing
4301 // how the operand is used.
4302 OutOps.push_back(Op);
4303 return false;
4304 }
4305 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00004306}
4307
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004308/// createARMISelDag - This pass converts a legalized DAG into a
4309/// ARM-specific DAG, ready for instruction scheduling.
4310///
Bob Wilson2dd957f2009-09-28 14:30:20 +00004311FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
4312 CodeGenOpt::Level OptLevel) {
4313 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004314}