blob: 0ee59445841dda1deb567fd7256dfb03e7b6a9e8 [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
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000046//===--------------------------------------------------------------------===//
47/// ARMDAGToDAGISel - ARM specific code to select ARM machine
48/// instructions for SelectionDAG operations.
49///
50namespace {
Jim Grosbach08605202010-09-29 19:03:54 +000051
52enum AddrMode2Type {
53 AM2_BASE, // Simple AM2 (+-imm12)
54 AM2_SHOP // Shifter-op AM2
55};
56
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000057class ARMDAGToDAGISel : public SelectionDAGISel {
Evan Cheng10043e22007-01-19 07:51:42 +000058 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
59 /// make the right decision when generating code for different targets.
60 const ARMSubtarget *Subtarget;
61
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000062public:
Eric Christopher2f991c92014-07-03 22:24:49 +000063 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, CodeGenOpt::Level OptLevel)
64 : SelectionDAGISel(tm, OptLevel) {}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000065
Eric Christopher0e6e7cf2014-05-22 02:00:27 +000066 bool runOnMachineFunction(MachineFunction &MF) override {
67 // Reset the subtarget each time through.
Eric Christopher22b2ad22015-02-20 08:24:37 +000068 Subtarget = &MF.getSubtarget<ARMSubtarget>();
Eric Christopher0e6e7cf2014-05-22 02:00:27 +000069 SelectionDAGISel::runOnMachineFunction(MF);
70 return true;
71 }
72
Craig Topper6bc27bf2014-03-10 02:09:33 +000073 const char *getPassName() const override {
Evan Cheng10043e22007-01-19 07:51:42 +000074 return "ARM Instruction Selection";
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000075 }
76
Craig Topper6bc27bf2014-03-10 02:09:33 +000077 void PreprocessISelDAG() override;
Evan Chengeae6d2c2012-12-19 20:16:09 +000078
Bob Wilson4facd962009-10-08 18:51:31 +000079 /// getI32Imm - Return a target constant of type i32 with the specified
80 /// value.
Benjamin Kramerbdc49562016-06-12 15:39:02 +000081 inline SDValue getI32Imm(unsigned Imm, const SDLoc &dl) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +000082 return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000083 }
84
Justin Bogner45571362016-05-12 00:31:09 +000085 void Select(SDNode *N) override;
Evan Cheng62c7b5b2010-12-05 22:04:16 +000086
87 bool hasNoVMLxHazardUse(SDNode *N) const;
Evan Cheng59bbc542010-10-27 23:41:30 +000088 bool isShifterOpProfitable(const SDValue &Shift,
89 ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt);
Owen Andersonb595ed02011-07-21 18:54:16 +000090 bool SelectRegShifterOperand(SDValue N, SDValue &A,
91 SDValue &B, SDValue &C,
92 bool CheckProfitability = true);
93 bool SelectImmShifterOperand(SDValue N, SDValue &A,
Owen Anderson04912702011-07-21 23:38:37 +000094 SDValue &B, bool CheckProfitability = true);
95 bool SelectShiftRegShifterOperand(SDValue N, SDValue &A,
Owen Anderson6d557452011-03-18 19:46:58 +000096 SDValue &B, SDValue &C) {
97 // Don't apply the profitability check
Owen Anderson04912702011-07-21 23:38:37 +000098 return SelectRegShifterOperand(N, A, B, C, false);
99 }
100 bool SelectShiftImmShifterOperand(SDValue N, SDValue &A,
101 SDValue &B) {
102 // Don't apply the profitability check
103 return SelectImmShifterOperand(N, A, B, false);
Owen Anderson6d557452011-03-18 19:46:58 +0000104 }
105
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000106 bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
107 bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);
108
Jim Grosbach08605202010-09-29 19:03:54 +0000109 AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base,
110 SDValue &Offset, SDValue &Opc);
111 bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset,
112 SDValue &Opc) {
113 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE;
114 }
115
116 bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset,
117 SDValue &Opc) {
118 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP;
119 }
120
121 bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset,
122 SDValue &Opc) {
123 SelectAddrMode2Worker(N, Base, Offset, Opc);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000124// return SelectAddrMode2ShOp(N, Base, Offset, Opc);
Jim Grosbach08605202010-09-29 19:03:54 +0000125 // This always matches one way or another.
126 return true;
127 }
128
Tim Northover42180442013-08-22 09:57:11 +0000129 bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) {
130 const ConstantSDNode *CN = cast<ConstantSDNode>(N);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000131 Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32);
Tim Northover42180442013-08-22 09:57:11 +0000132 Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32);
133 return true;
134 }
135
Owen Anderson2aedba62011-07-26 20:54:26 +0000136 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
137 SDValue &Offset, SDValue &Opc);
138 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000139 SDValue &Offset, SDValue &Opc);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000140 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
141 SDValue &Offset, SDValue &Opc);
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000142 bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000143 bool SelectAddrMode3(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000144 SDValue &Offset, SDValue &Opc);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000145 bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000146 SDValue &Offset, SDValue &Opc);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000147 bool SelectAddrMode5(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000148 SDValue &Offset);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000149 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
Bob Wilsone3ecd5f2011-02-25 06:42:42 +0000150 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000151
Evan Chengdfce83c2011-01-17 08:03:18 +0000152 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
Evan Cheng10043e22007-01-19 07:51:42 +0000153
Bill Wendling092a7bd2010-12-14 03:36:38 +0000154 // Thumb Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000155 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
Bill Wendling092a7bd2010-12-14 03:36:38 +0000156 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
157 SDValue &OffImm);
158 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
159 SDValue &OffImm);
160 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
161 SDValue &OffImm);
162 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
163 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000164 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +0000165
Bill Wendling092a7bd2010-12-14 03:36:38 +0000166 // Thumb 2 Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000167 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
168 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000169 SDValue &OffImm);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000170 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +0000171 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000172 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000173 SDValue &OffReg, SDValue &ShImm);
Tim Northovera7ecd242013-07-16 09:46:55 +0000174 bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Chengb23b50d2009-06-29 07:51:04 +0000175
Evan Cheng0fc80842010-11-12 22:42:47 +0000176 inline bool is_so_imm(unsigned Imm) const {
177 return ARM_AM::getSOImmVal(Imm) != -1;
178 }
179
180 inline bool is_so_imm_not(unsigned Imm) const {
181 return ARM_AM::getSOImmVal(~Imm) != -1;
182 }
183
184 inline bool is_t2_so_imm(unsigned Imm) const {
185 return ARM_AM::getT2SOImmVal(Imm) != -1;
186 }
187
188 inline bool is_t2_so_imm_not(unsigned Imm) const {
189 return ARM_AM::getT2SOImmVal(~Imm) != -1;
190 }
191
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000192 // Include the pieces autogenerated from the target description.
193#include "ARMGenDAGISel.inc"
Bob Wilsona2c462b2009-05-19 05:53:42 +0000194
195private:
Justin Bogner45571362016-05-12 00:31:09 +0000196 /// Indexed (pre/post inc/dec) load matching code for ARM.
197 bool tryARMIndexedLoad(SDNode *N);
James Molloyb3326df2016-07-15 08:03:56 +0000198 bool tryT1IndexedLoad(SDNode *N);
Justin Bogner45571362016-05-12 00:31:09 +0000199 bool tryT2IndexedLoad(SDNode *N);
Evan Cheng84c6cda2009-07-02 07:28:31 +0000200
Bob Wilson340861d2010-03-23 05:25:43 +0000201 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
202 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson12b47992009-10-14 17:28:52 +0000203 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson340861d2010-03-23 05:25:43 +0000204 /// For NumVecs <= 2, QOpcodes1 is not used.
Justin Bogner45571362016-05-12 00:31:09 +0000205 void SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
206 const uint16_t *DOpcodes, const uint16_t *QOpcodes0,
207 const uint16_t *QOpcodes1);
Bob Wilson12b47992009-10-14 17:28:52 +0000208
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000209 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000210 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000211 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000212 /// For NumVecs <= 2, QOpcodes1 is not used.
Justin Bogner45571362016-05-12 00:31:09 +0000213 void SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
214 const uint16_t *DOpcodes, const uint16_t *QOpcodes0,
215 const uint16_t *QOpcodes1);
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000216
Bob Wilson93117bc2009-10-14 16:46:45 +0000217 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilson4145e3a2009-10-14 16:19:03 +0000218 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsond5c57a52010-09-13 23:01:35 +0000219 /// load/store of D registers and Q registers.
Justin Bogner45571362016-05-12 00:31:09 +0000220 void SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
221 unsigned NumVecs, const uint16_t *DOpcodes,
222 const uint16_t *QOpcodes);
Bob Wilson4145e3a2009-10-14 16:19:03 +0000223
Bob Wilson2d790df2010-11-28 06:51:26 +0000224 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
225 /// should be 2, 3 or 4. The opcode array specifies the instructions used
226 /// for loading D registers. (Q registers are not supported.)
Justin Bogner45571362016-05-12 00:31:09 +0000227 void SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
228 const uint16_t *Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +0000229
Bob Wilson5bc8a792010-07-07 00:08:54 +0000230 /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2,
231 /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be
232 /// generated to force the table registers to be consecutive.
Justin Bogner45571362016-05-12 00:31:09 +0000233 void SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc);
Bob Wilson3ed511b2010-07-06 23:36:25 +0000234
Justin Bogner45571362016-05-12 00:31:09 +0000235 /// Try to select SBFX/UBFX instructions for ARM.
236 bool tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000237
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000238 // Select special operations if node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +0000239 bool tryABSOp(SDNode *N);
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000240
Justin Bogner45571362016-05-12 00:31:09 +0000241 bool tryReadRegister(SDNode *N);
242 bool tryWriteRegister(SDNode *N);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +0000243
Justin Bogner45571362016-05-12 00:31:09 +0000244 bool tryInlineAsm(SDNode *N);
Weiming Zhaoc5987002013-02-14 18:10:21 +0000245
Justin Bogner45571362016-05-12 00:31:09 +0000246 void SelectConcatVector(SDNode *N);
Evan Chengd85631e2010-05-05 18:28:36 +0000247
Justin Bogner45571362016-05-12 00:31:09 +0000248 bool trySMLAWSMULW(SDNode *N);
Sam Parker2d5126c2016-04-08 16:02:53 +0000249
Justin Bogner45571362016-05-12 00:31:09 +0000250 void SelectCMP_SWAP(SDNode *N);
Tim Northoverb629c772016-04-18 21:48:55 +0000251
Evan Chengd9c55362009-07-02 01:23:32 +0000252 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
253 /// inline asm expressions.
Daniel Sanders60f1db02015-03-13 12:45:09 +0000254 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Craig Topper6bc27bf2014-03-10 02:09:33 +0000255 std::vector<SDValue> &OutOps) override;
Bob Wilsone6b778d2009-10-06 22:01:59 +0000256
Weiming Zhao95782222012-11-17 00:23:35 +0000257 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhao8f56f882012-11-16 21:55:34 +0000258 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao95782222012-11-17 00:23:35 +0000259 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
260 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
261 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Chengc2ae5f52010-05-10 17:34:18 +0000262
Bob Wilsond8a9a042010-06-04 00:04:02 +0000263 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +0000264 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
265 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
266 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000267
268 // Get the alignment operand for a NEON VLD or VST instruction.
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000269 SDValue GetVLDSTAlign(SDValue Align, const SDLoc &dl, unsigned NumVecs,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000270 bool is64BitVector);
John Brawn056e6782015-09-14 15:19:41 +0000271
272 /// Returns the number of instructions required to materialize the given
273 /// constant in a register, or 3 if a literal pool load is needed.
274 unsigned ConstantMaterializationCost(unsigned Val) const;
275
276 /// Checks if N is a multiplication by a constant where we can extract out a
277 /// power of two from the constant so that it can be used in a shift, but only
278 /// if it simplifies the materialization of the constant. Returns true if it
279 /// is, and assigns to PowerOfTwo the power of two that should be extracted
280 /// out and to NewMulConst the new constant to be multiplied by.
281 bool canExtractShiftFromMul(const SDValue &N, unsigned MaxShift,
282 unsigned &PowerOfTwo, SDValue &NewMulConst) const;
283
284 /// Replace N with M in CurDAG, in a way that also ensures that M gets
285 /// selected when N would have been selected.
286 void replaceDAGValue(const SDValue &N, SDValue M);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000287};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000288}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000289
Sandeep Patel423e42b2009-10-13 18:59:48 +0000290/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
291/// operand. If so Imm will receive the 32-bit value.
292static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
293 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
294 Imm = cast<ConstantSDNode>(N)->getZExtValue();
295 return true;
296 }
297 return false;
298}
299
300// isInt32Immediate - This method tests to see if a constant operand.
301// If so Imm will receive the 32 bit value.
302static bool isInt32Immediate(SDValue N, unsigned &Imm) {
303 return isInt32Immediate(N.getNode(), Imm);
304}
305
306// isOpcWithIntImmediate - This method tests to see if the node is a specific
307// opcode and that it has a immediate integer right operand.
308// If so Imm will receive the 32 bit value.
309static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
310 return N->getOpcode() == Opc &&
311 isInt32Immediate(N->getOperand(1).getNode(), Imm);
312}
313
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000314/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000315/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000316///
317/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000318static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000319 int RangeMin, int RangeMax,
320 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000321 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000322
323 // Check that this is a constant.
324 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
325 if (!C)
326 return false;
327
328 ScaledConstant = (int) C->getZExtValue();
329 if ((ScaledConstant % Scale) != 0)
330 return false;
331
332 ScaledConstant /= Scale;
333 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
334}
335
Evan Chengeae6d2c2012-12-19 20:16:09 +0000336void ARMDAGToDAGISel::PreprocessISelDAG() {
337 if (!Subtarget->hasV6T2Ops())
338 return;
339
340 bool isThumb2 = Subtarget->isThumb();
341 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
342 E = CurDAG->allnodes_end(); I != E; ) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000343 SDNode *N = &*I++; // Preincrement iterator to avoid invalidation issues.
Evan Chengeae6d2c2012-12-19 20:16:09 +0000344
345 if (N->getOpcode() != ISD::ADD)
346 continue;
347
348 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
349 // leading zeros, followed by consecutive set bits, followed by 1 or 2
350 // trailing zeros, e.g. 1020.
351 // Transform the expression to
352 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
353 // of trailing zeros of c2. The left shift would be folded as an shifter
354 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
355 // node (UBFX).
356
357 SDValue N0 = N->getOperand(0);
358 SDValue N1 = N->getOperand(1);
359 unsigned And_imm = 0;
360 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
361 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
362 std::swap(N0, N1);
363 }
364 if (!And_imm)
365 continue;
366
367 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000368 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000369 if (TZ != 1 && TZ != 2)
370 // Be conservative here. Shifter operands aren't always free. e.g. On
371 // Swift, left shifter operand of 1 / 2 for free but others are not.
372 // e.g.
373 // ubfx r3, r1, #16, #8
374 // ldr.w r3, [r0, r3, lsl #2]
375 // vs.
376 // mov.w r9, #1020
377 // and.w r2, r9, r1, lsr #14
378 // ldr r2, [r0, r2]
379 continue;
380 And_imm >>= TZ;
381 if (And_imm & (And_imm + 1))
382 continue;
383
384 // Look for (and (srl X, c1), c2).
385 SDValue Srl = N1.getOperand(0);
386 unsigned Srl_imm = 0;
387 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
388 (Srl_imm <= 2))
389 continue;
390
391 // Make sure first operand is not a shifter operand which would prevent
392 // folding of the left shift.
393 SDValue CPTmp0;
394 SDValue CPTmp1;
395 SDValue CPTmp2;
396 if (isThumb2) {
John Brawnd8b405a2015-09-07 11:45:18 +0000397 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
Evan Chengeae6d2c2012-12-19 20:16:09 +0000398 continue;
399 } else {
400 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
401 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
402 continue;
403 }
404
405 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000406 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000407 Srl.getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000408 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl),
409 MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000410 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000411 Srl,
412 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000413 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000414 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32));
Evan Chengeae6d2c2012-12-19 20:16:09 +0000415 CurDAG->UpdateNodeOperands(N, N0, N1);
Jim Grosbach1a597112014-04-03 23:43:18 +0000416 }
Evan Chengeae6d2c2012-12-19 20:16:09 +0000417}
418
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000419/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
420/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
421/// least on current ARM implementations) which should be avoidded.
422bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
423 if (OptLevel == CodeGenOpt::None)
424 return true;
425
Diana Picus575f2bb2016-07-07 09:11:39 +0000426 if (!Subtarget->hasVMLxHazards())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000427 return true;
428
429 if (!N->hasOneUse())
430 return false;
431
432 SDNode *Use = *N->use_begin();
433 if (Use->getOpcode() == ISD::CopyToReg)
434 return true;
435 if (Use->isMachineOpcode()) {
Eric Christopher2f991c92014-07-03 22:24:49 +0000436 const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>(
Eric Christopherfc6de422014-08-05 02:39:49 +0000437 CurDAG->getSubtarget().getInstrInfo());
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000438
Evan Cheng6cc775f2011-06-28 19:10:37 +0000439 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
440 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000441 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000442 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000443 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
444 return true;
445 // vmlx feeding into another vmlx. We actually want to unfold
446 // the use later in the MLxExpansion pass. e.g.
447 // vmla
448 // vmla (stall 8 cycles)
449 //
450 // vmul (5 cycles)
451 // vadd (5 cycles)
452 // vmla
453 // This adds up to about 18 - 19 cycles.
454 //
455 // vmla
456 // vmul (stall 4 cycles)
457 // vadd adds up to about 14 cycles.
458 return TII->isFpMLxInstruction(Opcode);
459 }
460
461 return false;
462}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000463
Evan Cheng59bbc542010-10-27 23:41:30 +0000464bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
465 ARM_AM::ShiftOpc ShOpcVal,
466 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000467 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000468 return true;
469 if (Shift.hasOneUse())
470 return true;
471 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000472 return ShOpcVal == ARM_AM::lsl &&
473 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000474}
475
John Brawn056e6782015-09-14 15:19:41 +0000476unsigned ARMDAGToDAGISel::ConstantMaterializationCost(unsigned Val) const {
477 if (Subtarget->isThumb()) {
478 if (Val <= 255) return 1; // MOV
479 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
James Molloy65b6be12016-06-14 13:33:07 +0000480 if (Val <= 510) return 2; // MOV + ADDi8
John Brawn056e6782015-09-14 15:19:41 +0000481 if (~Val <= 255) return 2; // MOV + MVN
482 if (ARM_AM::isThumbImmShiftedVal(Val)) return 2; // MOV + LSL
483 } else {
484 if (ARM_AM::getSOImmVal(Val) != -1) return 1; // MOV
485 if (ARM_AM::getSOImmVal(~Val) != -1) return 1; // MVN
486 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
487 if (ARM_AM::isSOImmTwoPartVal(Val)) return 2; // two instrs
488 }
489 if (Subtarget->useMovt(*MF)) return 2; // MOVW + MOVT
490 return 3; // Literal pool load
491}
492
493bool ARMDAGToDAGISel::canExtractShiftFromMul(const SDValue &N,
494 unsigned MaxShift,
495 unsigned &PowerOfTwo,
496 SDValue &NewMulConst) const {
497 assert(N.getOpcode() == ISD::MUL);
498 assert(MaxShift > 0);
499
500 // If the multiply is used in more than one place then changing the constant
501 // will make other uses incorrect, so don't.
502 if (!N.hasOneUse()) return false;
503 // Check if the multiply is by a constant
504 ConstantSDNode *MulConst = dyn_cast<ConstantSDNode>(N.getOperand(1));
505 if (!MulConst) return false;
506 // If the constant is used in more than one place then modifying it will mean
507 // we need to materialize two constants instead of one, which is a bad idea.
508 if (!MulConst->hasOneUse()) return false;
509 unsigned MulConstVal = MulConst->getZExtValue();
510 if (MulConstVal == 0) return false;
511
512 // Find the largest power of 2 that MulConstVal is a multiple of
513 PowerOfTwo = MaxShift;
514 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
515 --PowerOfTwo;
516 if (PowerOfTwo == 0) return false;
517 }
518
519 // Only optimise if the new cost is better
520 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
521 NewMulConst = CurDAG->getConstant(NewMulConstVal, SDLoc(N), MVT::i32);
522 unsigned OldCost = ConstantMaterializationCost(MulConstVal);
523 unsigned NewCost = ConstantMaterializationCost(NewMulConstVal);
524 return NewCost < OldCost;
525}
526
527void ARMDAGToDAGISel::replaceDAGValue(const SDValue &N, SDValue M) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000528 CurDAG->RepositionNode(N.getNode()->getIterator(), M.getNode());
John Brawn056e6782015-09-14 15:19:41 +0000529 CurDAG->ReplaceAllUsesWith(N, M);
530}
531
Owen Andersonb595ed02011-07-21 18:54:16 +0000532bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000533 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000534 SDValue &Opc,
535 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000536 if (DisableShifterOp)
537 return false;
538
John Brawn056e6782015-09-14 15:19:41 +0000539 // If N is a multiply-by-constant and it's profitable to extract a shift and
540 // use it in a shifted operand do so.
541 if (N.getOpcode() == ISD::MUL) {
542 unsigned PowerOfTwo = 0;
543 SDValue NewMulConst;
544 if (canExtractShiftFromMul(N, 31, PowerOfTwo, NewMulConst)) {
Justin Bogner8752be72016-05-05 01:43:49 +0000545 HandleSDNode Handle(N);
John Brawn056e6782015-09-14 15:19:41 +0000546 replaceDAGValue(N.getOperand(1), NewMulConst);
Justin Bogner8752be72016-05-05 01:43:49 +0000547 BaseReg = Handle.getValue();
John Brawn056e6782015-09-14 15:19:41 +0000548 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ARM_AM::lsl,
549 PowerOfTwo),
550 SDLoc(N), MVT::i32);
551 return true;
552 }
553 }
554
Evan Chenga20cde32011-07-20 23:34:39 +0000555 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000556
557 // Don't match base register only case. That is matched to a separate
558 // lower complexity pattern with explicit register operand.
559 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000560
Evan Chengb23b50d2009-06-29 07:51:04 +0000561 BaseReg = N.getOperand(0);
562 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000563 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
564 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000565 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000566 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000567 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000568 return true;
569}
570
Owen Andersonb595ed02011-07-21 18:54:16 +0000571bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
572 SDValue &BaseReg,
573 SDValue &ShReg,
574 SDValue &Opc,
575 bool CheckProfitability) {
576 if (DisableShifterOp)
577 return false;
578
579 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
580
581 // Don't match base register only case. That is matched to a separate
582 // lower complexity pattern with explicit register operand.
583 if (ShOpcVal == ARM_AM::no_shift) return false;
584
585 BaseReg = N.getOperand(0);
586 unsigned ShImmVal = 0;
587 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
588 if (RHS) return false;
589
590 ShReg = N.getOperand(1);
591 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
592 return false;
593 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000594 SDLoc(N), MVT::i32);
Owen Andersonb595ed02011-07-21 18:54:16 +0000595 return true;
596}
597
598
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000599bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
600 SDValue &Base,
601 SDValue &OffImm) {
602 // Match simple R + imm12 operands.
603
604 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000605 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
606 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000607 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000608 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000609 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000610 Base = CurDAG->getTargetFrameIndex(
611 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000612 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000613 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000614 }
Owen Anderson6d557452011-03-18 19:46:58 +0000615
Chris Lattner46c01a32011-02-13 22:25:43 +0000616 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000617 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000618 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000619 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000620 Base = N.getOperand(0);
621 } else
622 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000623 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000624 return true;
625 }
626
627 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Renato Golin63e27982014-09-09 09:57:59 +0000628 int RHSC = (int)RHS->getSExtValue();
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000629 if (N.getOpcode() == ISD::SUB)
630 RHSC = -RHSC;
631
Renato Golin63e27982014-09-09 09:57:59 +0000632 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000633 Base = N.getOperand(0);
634 if (Base.getOpcode() == ISD::FrameIndex) {
635 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000636 Base = CurDAG->getTargetFrameIndex(
637 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000638 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000639 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000640 return true;
641 }
642 }
643
644 // Base only.
645 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000646 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000647 return true;
648}
649
650
651
652bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
653 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000654 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000655 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000656 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
657 // X * [3,5,9] -> X + X * [2,4,8] etc.
658 int RHSC = (int)RHS->getZExtValue();
659 if (RHSC & 1) {
660 RHSC = RHSC & ~1;
661 ARM_AM::AddrOpc AddSub = ARM_AM::add;
662 if (RHSC < 0) {
663 AddSub = ARM_AM::sub;
664 RHSC = - RHSC;
665 }
666 if (isPowerOf2_32(RHSC)) {
667 unsigned ShAmt = Log2_32(RHSC);
668 Base = Offset = N.getOperand(0);
669 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
670 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000671 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000672 return true;
673 }
674 }
675 }
676 }
677
Chris Lattner46c01a32011-02-13 22:25:43 +0000678 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
679 // ISD::OR that is equivalent to an ISD::ADD.
680 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000681 return false;
682
683 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000684 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000685 int RHSC;
686 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
687 -0x1000+1, 0x1000, RHSC)) // 12 bits.
688 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000689 }
690
691 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000692 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000693 ARM_AM::ShiftOpc ShOpcVal =
694 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000695 unsigned ShAmt = 0;
696
697 Base = N.getOperand(0);
698 Offset = N.getOperand(1);
699
700 if (ShOpcVal != ARM_AM::no_shift) {
701 // Check to see if the RHS of the shift is a constant, if not, we can't fold
702 // it.
703 if (ConstantSDNode *Sh =
704 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
705 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000706 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
707 Offset = N.getOperand(1).getOperand(0);
708 else {
709 ShAmt = 0;
710 ShOpcVal = ARM_AM::no_shift;
711 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000712 } else {
713 ShOpcVal = ARM_AM::no_shift;
714 }
715 }
716
717 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000718 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000719 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
720 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000721 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000722 if (ShOpcVal != ARM_AM::no_shift) {
723 // Check to see if the RHS of the shift is a constant, if not, we can't
724 // fold it.
725 if (ConstantSDNode *Sh =
726 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
727 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000728 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000729 Offset = N.getOperand(0).getOperand(0);
730 Base = N.getOperand(1);
731 } else {
732 ShAmt = 0;
733 ShOpcVal = ARM_AM::no_shift;
734 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000735 } else {
736 ShOpcVal = ARM_AM::no_shift;
737 }
738 }
739 }
740
John Brawn056e6782015-09-14 15:19:41 +0000741 // If Offset is a multiply-by-constant and it's profitable to extract a shift
742 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +0000743 if (Offset.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +0000744 unsigned PowerOfTwo = 0;
745 SDValue NewMulConst;
746 if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) {
747 replaceDAGValue(Offset.getOperand(1), NewMulConst);
748 ShAmt = PowerOfTwo;
749 ShOpcVal = ARM_AM::lsl;
750 }
751 }
752
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000753 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000754 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000755 return true;
756}
757
758
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000759//-----
760
Jim Grosbach08605202010-09-29 19:03:54 +0000761AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
762 SDValue &Base,
763 SDValue &Offset,
764 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000765 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000766 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000767 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
768 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmaneffb8942008-09-12 16:56:44 +0000769 int RHSC = (int)RHS->getZExtValue();
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000770 if (RHSC & 1) {
771 RHSC = RHSC & ~1;
772 ARM_AM::AddrOpc AddSub = ARM_AM::add;
773 if (RHSC < 0) {
774 AddSub = ARM_AM::sub;
775 RHSC = - RHSC;
776 }
777 if (isPowerOf2_32(RHSC)) {
778 unsigned ShAmt = Log2_32(RHSC);
779 Base = Offset = N.getOperand(0);
780 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
781 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000782 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000783 return AM2_SHOP;
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000784 }
785 }
786 }
787 }
788
Chris Lattner46c01a32011-02-13 22:25:43 +0000789 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
790 // ISD::OR that is equivalent to an ADD.
791 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000792 Base = N;
793 if (N.getOpcode() == ISD::FrameIndex) {
794 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000795 Base = CurDAG->getTargetFrameIndex(
796 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +0000797 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000798 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000799 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000800 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000801 Base = N.getOperand(0);
802 }
Owen Anderson9f944592009-08-11 20:47:22 +0000803 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000804 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
805 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000806 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000807 return AM2_BASE;
Rafael Espindola708cb602006-11-08 17:07:32 +0000808 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000809
Evan Cheng10043e22007-01-19 07:51:42 +0000810 // Match simple R +/- imm12 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +0000811 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000812 int RHSC;
813 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
814 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
815 Base = N.getOperand(0);
816 if (Base.getOpcode() == ISD::FrameIndex) {
817 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000818 Base = CurDAG->getTargetFrameIndex(
819 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Rafael Espindola708cb602006-11-08 17:07:32 +0000820 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000821 Offset = CurDAG->getRegister(0, MVT::i32);
822
823 ARM_AM::AddrOpc AddSub = ARM_AM::add;
824 if (RHSC < 0) {
825 AddSub = ARM_AM::sub;
826 RHSC = - RHSC;
827 }
828 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
829 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000830 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000831 return AM2_BASE;
Evan Cheng10043e22007-01-19 07:51:42 +0000832 }
Jim Grosbachc7b10f32010-09-29 17:32:29 +0000833 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000834
Bob Wilsone8a549c2012-09-29 21:43:49 +0000835 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000836 // Compute R +/- (R << N) and reuse it.
837 Base = N;
838 Offset = CurDAG->getRegister(0, MVT::i32);
839 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
840 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000841 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000842 return AM2_BASE;
843 }
844
Johnny Chenb678a562009-10-27 17:25:15 +0000845 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000846 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chenga20cde32011-07-20 23:34:39 +0000847 ARM_AM::ShiftOpc ShOpcVal =
848 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000849 unsigned ShAmt = 0;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000850
Evan Cheng10043e22007-01-19 07:51:42 +0000851 Base = N.getOperand(0);
852 Offset = N.getOperand(1);
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000853
Evan Cheng10043e22007-01-19 07:51:42 +0000854 if (ShOpcVal != ARM_AM::no_shift) {
855 // Check to see if the RHS of the shift is a constant, if not, we can't fold
856 // it.
857 if (ConstantSDNode *Sh =
858 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000859 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000860 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
861 Offset = N.getOperand(1).getOperand(0);
862 else {
863 ShAmt = 0;
864 ShOpcVal = ARM_AM::no_shift;
865 }
Evan Cheng10043e22007-01-19 07:51:42 +0000866 } else {
867 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola708cb602006-11-08 17:07:32 +0000868 }
869 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000870
Evan Cheng10043e22007-01-19 07:51:42 +0000871 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000872 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000873 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
874 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000875 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000876 if (ShOpcVal != ARM_AM::no_shift) {
877 // Check to see if the RHS of the shift is a constant, if not, we can't
878 // fold it.
879 if (ConstantSDNode *Sh =
880 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000881 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000882 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000883 Offset = N.getOperand(0).getOperand(0);
884 Base = N.getOperand(1);
885 } else {
886 ShAmt = 0;
887 ShOpcVal = ARM_AM::no_shift;
888 }
Evan Cheng10043e22007-01-19 07:51:42 +0000889 } else {
890 ShOpcVal = ARM_AM::no_shift;
891 }
892 }
893 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000894
Evan Cheng10043e22007-01-19 07:51:42 +0000895 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000896 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000897 return AM2_SHOP;
Rafael Espindola708cb602006-11-08 17:07:32 +0000898}
899
Owen Anderson2aedba62011-07-26 20:54:26 +0000900bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000901 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000902 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000903 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
904 ? cast<LoadSDNode>(Op)->getAddressingMode()
905 : cast<StoreSDNode>(Op)->getAddressingMode();
906 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
907 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000908 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000909 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
910 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000911
912 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000913 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000914 unsigned ShAmt = 0;
915 if (ShOpcVal != ARM_AM::no_shift) {
916 // Check to see if the RHS of the shift is a constant, if not, we can't fold
917 // it.
918 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000919 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000920 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
921 Offset = N.getOperand(0);
922 else {
923 ShAmt = 0;
924 ShOpcVal = ARM_AM::no_shift;
925 }
Evan Cheng10043e22007-01-19 07:51:42 +0000926 } else {
927 ShOpcVal = ARM_AM::no_shift;
928 }
929 }
930
931 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000932 SDLoc(N), MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000933 return true;
934}
935
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000936bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
937 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000938 unsigned Opcode = Op->getOpcode();
939 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
940 ? cast<LoadSDNode>(Op)->getAddressingMode()
941 : cast<StoreSDNode>(Op)->getAddressingMode();
942 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
943 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000944 int Val;
945 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000946 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000947 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000948 Opc = CurDAG->getTargetConstant(Val, SDLoc(Op), MVT::i32);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000949 return true;
950 }
951
952 return false;
953}
954
955
Owen Anderson2aedba62011-07-26 20:54:26 +0000956bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
957 SDValue &Offset, SDValue &Opc) {
958 unsigned Opcode = Op->getOpcode();
959 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
960 ? cast<LoadSDNode>(Op)->getAddressingMode()
961 : cast<StoreSDNode>(Op)->getAddressingMode();
962 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
963 ? ARM_AM::add : ARM_AM::sub;
964 int Val;
965 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
966 Offset = CurDAG->getRegister(0, MVT::i32);
967 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
968 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000969 SDLoc(Op), MVT::i32);
Owen Anderson2aedba62011-07-26 20:54:26 +0000970 return true;
971 }
972
973 return false;
974}
975
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000976bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
977 Base = N;
978 return true;
979}
Evan Cheng10043e22007-01-19 07:51:42 +0000980
Chris Lattner0e023ea2010-09-21 20:31:19 +0000981bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000982 SDValue &Base, SDValue &Offset,
983 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000984 if (N.getOpcode() == ISD::SUB) {
985 // X - C is canonicalize to X + -C, no need to handle it here.
986 Base = N.getOperand(0);
987 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000988 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0), SDLoc(N),
989 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000990 return true;
991 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000992
Chris Lattner46c01a32011-02-13 22:25:43 +0000993 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000994 Base = N;
995 if (N.getOpcode() == ISD::FrameIndex) {
996 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000997 Base = CurDAG->getTargetFrameIndex(
998 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +0000999 }
Owen Anderson9f944592009-08-11 20:47:22 +00001000 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001001 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1002 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001003 return true;
1004 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001005
Evan Cheng10043e22007-01-19 07:51:42 +00001006 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001007 int RHSC;
1008 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
1009 -256 + 1, 256, RHSC)) { // 8 bits.
1010 Base = N.getOperand(0);
1011 if (Base.getOpcode() == ISD::FrameIndex) {
1012 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001013 Base = CurDAG->getTargetFrameIndex(
1014 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001015 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001016 Offset = CurDAG->getRegister(0, MVT::i32);
1017
1018 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1019 if (RHSC < 0) {
1020 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001021 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001022 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001023 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC), SDLoc(N),
1024 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001025 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001026 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001027
Evan Cheng10043e22007-01-19 07:51:42 +00001028 Base = N.getOperand(0);
1029 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001030 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1031 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001032 return true;
1033}
1034
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001035bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001036 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001037 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +00001038 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1039 ? cast<LoadSDNode>(Op)->getAddressingMode()
1040 : cast<StoreSDNode>(Op)->getAddressingMode();
1041 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
1042 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001043 int Val;
1044 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
1045 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001046 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), SDLoc(Op),
1047 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001048 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001049 }
1050
1051 Offset = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001052 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), SDLoc(Op),
1053 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001054 return true;
1055}
1056
Jim Grosbachd37f0712010-10-21 19:38:40 +00001057bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001058 SDValue &Base, SDValue &Offset) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001059 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +00001060 Base = N;
1061 if (N.getOpcode() == ISD::FrameIndex) {
1062 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001063 Base = CurDAG->getTargetFrameIndex(
1064 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +00001065 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001066 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001067 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001068 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +00001069 Base = N.getOperand(0);
1070 }
1071 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001072 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001073 return true;
1074 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001075
Evan Cheng10043e22007-01-19 07:51:42 +00001076 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001077 int RHSC;
1078 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
1079 -256 + 1, 256, RHSC)) {
1080 Base = N.getOperand(0);
1081 if (Base.getOpcode() == ISD::FrameIndex) {
1082 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001083 Base = CurDAG->getTargetFrameIndex(
1084 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001085 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001086
1087 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1088 if (RHSC < 0) {
1089 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001090 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001091 }
1092 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001093 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001094 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001095 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001096
Evan Cheng10043e22007-01-19 07:51:42 +00001097 Base = N;
1098 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001099 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001100 return true;
1101}
1102
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001103bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
1104 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +00001105 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001106
1107 unsigned Alignment = 0;
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001108
1109 MemSDNode *MemN = cast<MemSDNode>(Parent);
1110
1111 if (isa<LSBaseSDNode>(MemN) ||
1112 ((MemN->getOpcode() == ARMISD::VST1_UPD ||
1113 MemN->getOpcode() == ARMISD::VLD1_UPD) &&
1114 MemN->getConstantOperandVal(MemN->getNumOperands() - 1) == 1)) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001115 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
1116 // The maximum alignment is equal to the memory size being referenced.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001117 unsigned MMOAlign = MemN->getAlignment();
1118 unsigned MemSize = MemN->getMemoryVT().getSizeInBits() / 8;
1119 if (MMOAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001120 Alignment = MemSize;
1121 } else {
1122 // All other uses of addrmode6 are for intrinsics. For now just record
1123 // the raw alignment value; it will be refined later based on the legal
1124 // alignment operands for the intrinsic.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001125 Alignment = MemN->getAlignment();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001126 }
1127
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001128 Align = CurDAG->getTargetConstant(Alignment, SDLoc(N), MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001129 return true;
1130}
1131
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001132bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1133 SDValue &Offset) {
1134 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1135 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1136 if (AM != ISD::POST_INC)
1137 return false;
1138 Offset = N;
1139 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1140 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1141 Offset = CurDAG->getRegister(0, MVT::i32);
1142 }
1143 return true;
1144}
1145
Chris Lattner0e023ea2010-09-21 20:31:19 +00001146bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001147 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001148 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1149 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001150 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001151 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001152 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001153 return true;
1154 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001155
Evan Cheng10043e22007-01-19 07:51:42 +00001156 return false;
1157}
1158
Bill Wendling092a7bd2010-12-14 03:36:38 +00001159
1160//===----------------------------------------------------------------------===//
1161// Thumb Addressing Modes
1162//===----------------------------------------------------------------------===//
1163
Chris Lattner0e023ea2010-09-21 20:31:19 +00001164bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001165 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001166 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001167 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001168 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001169 return false;
1170
1171 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001172 return true;
1173 }
1174
Evan Cheng10043e22007-01-19 07:51:42 +00001175 Base = N.getOperand(0);
1176 Offset = N.getOperand(1);
1177 return true;
1178}
1179
Evan Cheng139edae2007-01-24 02:21:22 +00001180bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001181ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1182 SDValue &Base, SDValue &OffImm) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001183 if (!CurDAG->isBaseWithConstantOffset(N)) {
John Brawn68acdcb2015-08-13 10:48:22 +00001184 if (N.getOpcode() == ISD::ADD) {
1185 return false; // We want to select register offset instead
1186 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001187 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001188 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001189 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001190 Base = N.getOperand(0);
1191 } else {
1192 Base = N;
1193 }
1194
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001195 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001196 return true;
1197 }
1198
Evan Cheng10043e22007-01-19 07:51:42 +00001199 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001200 int RHSC;
1201 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1202 Base = N.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001203 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001204 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001205 }
1206
John Brawn68acdcb2015-08-13 10:48:22 +00001207 // Offset is too large, so use register offset instead.
1208 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001209}
1210
Bill Wendling092a7bd2010-12-14 03:36:38 +00001211bool
1212ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1213 SDValue &OffImm) {
1214 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001215}
1216
Bill Wendling092a7bd2010-12-14 03:36:38 +00001217bool
1218ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1219 SDValue &OffImm) {
1220 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001221}
1222
Bill Wendling092a7bd2010-12-14 03:36:38 +00001223bool
1224ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1225 SDValue &OffImm) {
1226 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001227}
1228
Chris Lattner0e023ea2010-09-21 20:31:19 +00001229bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1230 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001231 if (N.getOpcode() == ISD::FrameIndex) {
1232 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001233 // Only multiples of 4 are allowed for the offset, so the frame object
1234 // alignment must be at least 4.
1235 MachineFrameInfo *MFI = MF->getFrameInfo();
1236 if (MFI->getObjectAlignment(FI) < 4)
1237 MFI->setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001238 Base = CurDAG->getTargetFrameIndex(
1239 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001240 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001241 return true;
1242 }
Evan Cheng139edae2007-01-24 02:21:22 +00001243
Chris Lattner46c01a32011-02-13 22:25:43 +00001244 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001245 return false;
1246
1247 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001248 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1249 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001250 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001251 int RHSC;
1252 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1253 Base = N.getOperand(0);
1254 if (Base.getOpcode() == ISD::FrameIndex) {
1255 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001256 // For LHS+RHS to result in an offset that's a multiple of 4 the object
1257 // indexed by the LHS must be 4-byte aligned.
1258 MachineFrameInfo *MFI = MF->getFrameInfo();
1259 if (MFI->getObjectAlignment(FI) < 4)
1260 MFI->setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001261 Base = CurDAG->getTargetFrameIndex(
1262 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng139edae2007-01-24 02:21:22 +00001263 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001264 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001265 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001266 }
1267 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001268
Evan Cheng10043e22007-01-19 07:51:42 +00001269 return false;
1270}
1271
Bill Wendling092a7bd2010-12-14 03:36:38 +00001272
1273//===----------------------------------------------------------------------===//
1274// Thumb 2 Addressing Modes
1275//===----------------------------------------------------------------------===//
1276
1277
Chris Lattner0e023ea2010-09-21 20:31:19 +00001278bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001279 SDValue &Base, SDValue &OffImm) {
1280 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001281
Evan Cheng36064672009-08-11 08:52:18 +00001282 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001283 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1284 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001285 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001286 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001287 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001288 Base = CurDAG->getTargetFrameIndex(
1289 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001290 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001291 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001292 }
Owen Anderson6d557452011-03-18 19:46:58 +00001293
Chris Lattner46c01a32011-02-13 22:25:43 +00001294 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001295 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001296 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001297 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng36064672009-08-11 08:52:18 +00001298 Base = N.getOperand(0);
1299 if (Base.getOpcode() == ISD::TargetConstantPool)
1300 return false; // We want to select t2LDRpci instead.
1301 } else
1302 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001303 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001304 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001305 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001306
1307 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001308 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001309 // Let t2LDRi8 handle (R - imm8).
1310 return false;
1311
Evan Chengb23b50d2009-06-29 07:51:04 +00001312 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001313 if (N.getOpcode() == ISD::SUB)
1314 RHSC = -RHSC;
1315
1316 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001317 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001318 if (Base.getOpcode() == ISD::FrameIndex) {
1319 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001320 Base = CurDAG->getTargetFrameIndex(
1321 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin79c079b2009-07-30 18:56:48 +00001322 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001323 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001324 return true;
1325 }
1326 }
1327
Evan Cheng36064672009-08-11 08:52:18 +00001328 // Base only.
1329 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001330 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001331 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001332}
1333
Chris Lattner0e023ea2010-09-21 20:31:19 +00001334bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001335 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001336 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001337 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1338 !CurDAG->isBaseWithConstantOffset(N))
1339 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001340
Chris Lattner46c01a32011-02-13 22:25:43 +00001341 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1342 int RHSC = (int)RHS->getSExtValue();
1343 if (N.getOpcode() == ISD::SUB)
1344 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001345
Chris Lattner46c01a32011-02-13 22:25:43 +00001346 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1347 Base = N.getOperand(0);
1348 if (Base.getOpcode() == ISD::FrameIndex) {
1349 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001350 Base = CurDAG->getTargetFrameIndex(
1351 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Chengb23b50d2009-06-29 07:51:04 +00001352 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001353 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Chris Lattner46c01a32011-02-13 22:25:43 +00001354 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001355 }
1356 }
1357
1358 return false;
1359}
1360
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001361bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001362 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001363 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001364 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1365 ? cast<LoadSDNode>(Op)->getAddressingMode()
1366 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001367 int RHSC;
1368 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1369 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001370 ? CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32)
1371 : CurDAG->getTargetConstant(-RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001372 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001373 }
1374
1375 return false;
1376}
1377
Chris Lattner0e023ea2010-09-21 20:31:19 +00001378bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001379 SDValue &Base,
1380 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001381 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001382 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001383 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001384
Evan Cheng36064672009-08-11 08:52:18 +00001385 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1386 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1387 int RHSC = (int)RHS->getZExtValue();
1388 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1389 return false;
1390 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001391 return false;
1392 }
1393
Evan Chengb23b50d2009-06-29 07:51:04 +00001394 // Look for (R + R) or (R + (R << [1,2,3])).
1395 unsigned ShAmt = 0;
1396 Base = N.getOperand(0);
1397 OffReg = N.getOperand(1);
1398
1399 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001400 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001401 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001402 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001403 if (ShOpcVal == ARM_AM::lsl)
1404 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001405 }
1406
Evan Chengb23b50d2009-06-29 07:51:04 +00001407 if (ShOpcVal == ARM_AM::lsl) {
1408 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1409 // it.
1410 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1411 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001412 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1413 OffReg = OffReg.getOperand(0);
1414 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001415 ShAmt = 0;
Evan Cheng59bbc542010-10-27 23:41:30 +00001416 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001417 }
David Goodwinf3912052009-07-15 15:50:19 +00001418 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001419
John Brawn056e6782015-09-14 15:19:41 +00001420 // If OffReg is a multiply-by-constant and it's profitable to extract a shift
1421 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +00001422 if (OffReg.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +00001423 unsigned PowerOfTwo = 0;
1424 SDValue NewMulConst;
1425 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
1426 replaceDAGValue(OffReg.getOperand(1), NewMulConst);
1427 ShAmt = PowerOfTwo;
1428 }
1429 }
1430
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001431 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001432
1433 return true;
1434}
1435
Tim Northovera7ecd242013-07-16 09:46:55 +00001436bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1437 SDValue &OffImm) {
Alp Tokercb402912014-01-24 17:20:08 +00001438 // This *must* succeed since it's used for the irreplaceable ldrex and strex
Tim Northovera7ecd242013-07-16 09:46:55 +00001439 // instructions.
1440 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001441 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001442
1443 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1444 return true;
1445
1446 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1447 if (!RHS)
1448 return true;
1449
1450 uint32_t RHSC = (int)RHS->getZExtValue();
1451 if (RHSC > 1020 || RHSC % 4 != 0)
1452 return true;
1453
1454 Base = N.getOperand(0);
1455 if (Base.getOpcode() == ISD::FrameIndex) {
1456 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001457 Base = CurDAG->getTargetFrameIndex(
1458 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Tim Northovera7ecd242013-07-16 09:46:55 +00001459 }
1460
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001461 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001462 return true;
1463}
1464
Evan Chengb23b50d2009-06-29 07:51:04 +00001465//===--------------------------------------------------------------------===//
1466
Evan Cheng7e90b112007-07-05 07:15:27 +00001467/// getAL - Returns a ARMCC::AL immediate node.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001468static inline SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001469 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001470}
1471
Justin Bogner45571362016-05-12 00:31:09 +00001472bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001473 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001474 ISD::MemIndexedMode AM = LD->getAddressingMode();
1475 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001476 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001477
Owen Anderson53aa7a92009-08-10 22:56:29 +00001478 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001479 SDValue Offset, AMOpc;
1480 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1481 unsigned Opcode = 0;
1482 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001483 if (LoadedVT == MVT::i32 && isPre &&
1484 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1485 Opcode = ARM::LDR_PRE_IMM;
1486 Match = true;
1487 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001488 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001489 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001490 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001491 } else if (LoadedVT == MVT::i32 &&
1492 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001493 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001494 Match = true;
1495
Owen Anderson9f944592009-08-11 20:47:22 +00001496 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001497 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001498 Match = true;
1499 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1500 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1501 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001502 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001503 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001504 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001505 Match = true;
1506 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1507 }
1508 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001509 if (isPre &&
1510 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001511 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001512 Opcode = ARM::LDRB_PRE_IMM;
1513 } else if (!isPre &&
1514 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1515 Match = true;
1516 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001517 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1518 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001519 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001520 }
1521 }
1522 }
1523
1524 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001525 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1526 SDValue Chain = LD->getChain();
1527 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001528 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001529 CurDAG->getRegister(0, MVT::i32), Chain };
Justin Bogner45571362016-05-12 00:31:09 +00001530 ReplaceNode(N, CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
1531 MVT::i32, MVT::Other, Ops));
1532 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001533 } else {
1534 SDValue Chain = LD->getChain();
1535 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001536 SDValue Ops[]= { Base, Offset, 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 }
Evan Chengd9c55362009-07-02 01:23:32 +00001542 }
1543
Justin Bogner45571362016-05-12 00:31:09 +00001544 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001545}
1546
James Molloyb3326df2016-07-15 08:03:56 +00001547bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *N) {
1548 LoadSDNode *LD = cast<LoadSDNode>(N);
1549 EVT LoadedVT = LD->getMemoryVT();
1550 ISD::MemIndexedMode AM = LD->getAddressingMode();
1551 if (AM == ISD::UNINDEXED || LD->getExtensionType() != ISD::NON_EXTLOAD ||
1552 AM != ISD::POST_INC || LoadedVT.getSimpleVT().SimpleTy != MVT::i32)
1553 return false;
1554
1555 auto *COffs = dyn_cast<ConstantSDNode>(LD->getOffset());
1556 if (!COffs || COffs->getZExtValue() != 4)
1557 return false;
1558
1559 // A T1 post-indexed load is just a single register LDM: LDM r0!, {r1}.
1560 // The encoding of LDM is not how the rest of ISel expects a post-inc load to
1561 // look however, so we use a pseudo here and switch it for a tLDMIA_UPD after
1562 // ISel.
1563 SDValue Chain = LD->getChain();
1564 SDValue Base = LD->getBasePtr();
1565 SDValue Ops[]= { Base, getAL(CurDAG, SDLoc(N)),
1566 CurDAG->getRegister(0, MVT::i32), Chain };
1567 ReplaceNode(N, CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(N), MVT::i32, MVT::i32,
1568 MVT::Other, Ops));
1569 return true;
1570}
1571
Justin Bogner45571362016-05-12 00:31:09 +00001572bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001573 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001574 ISD::MemIndexedMode AM = LD->getAddressingMode();
1575 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001576 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001577
Owen Anderson53aa7a92009-08-10 22:56:29 +00001578 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001579 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001580 SDValue Offset;
1581 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1582 unsigned Opcode = 0;
1583 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001584 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001585 switch (LoadedVT.getSimpleVT().SimpleTy) {
1586 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001587 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1588 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001589 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001590 if (isSExtLd)
1591 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1592 else
1593 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001594 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001595 case MVT::i8:
1596 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001597 if (isSExtLd)
1598 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1599 else
1600 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001601 break;
1602 default:
Justin Bogner45571362016-05-12 00:31:09 +00001603 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001604 }
1605 Match = true;
1606 }
1607
1608 if (Match) {
1609 SDValue Chain = LD->getChain();
1610 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001611 SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)),
Owen Anderson9f944592009-08-11 20:47:22 +00001612 CurDAG->getRegister(0, MVT::i32), Chain };
Justin Bogner45571362016-05-12 00:31:09 +00001613 ReplaceNode(N, CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1614 MVT::Other, Ops));
1615 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001616 }
1617
Justin Bogner45571362016-05-12 00:31:09 +00001618 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001619}
1620
Weiming Zhao8f56f882012-11-16 21:55:34 +00001621/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1622SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001623 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001624 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001625 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1626 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1627 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001628 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001629 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001630}
1631
Weiming Zhao95782222012-11-17 00:23:35 +00001632/// \brief Form a D register from a pair of S registers.
1633SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001634 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001635 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001636 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1637 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1638 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001639 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001640 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001641}
1642
Weiming Zhao95782222012-11-17 00:23:35 +00001643/// \brief Form a quad register from a pair of D registers.
1644SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001645 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001646 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1647 MVT::i32);
1648 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1649 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001650 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001651 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001652}
1653
Weiming Zhao95782222012-11-17 00:23:35 +00001654/// \brief Form 4 consecutive D registers from a pair of Q registers.
1655SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001656 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001657 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1658 MVT::i32);
1659 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1660 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001661 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001662 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001663}
1664
Weiming Zhao95782222012-11-17 00:23:35 +00001665/// \brief Form 4 consecutive S registers.
1666SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001667 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001668 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001669 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001670 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1671 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1672 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1673 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1674 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001675 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1676 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001677 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001678}
1679
Weiming Zhao95782222012-11-17 00:23:35 +00001680/// \brief Form 4 consecutive D registers.
1681SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001682 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001683 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001684 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1685 MVT::i32);
1686 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1687 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1688 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1689 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001690 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1691 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001692 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001693}
1694
Weiming Zhao95782222012-11-17 00:23:35 +00001695/// \brief Form 4 consecutive Q registers.
1696SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001697 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001698 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001699 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1700 MVT::i32);
1701 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1702 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1703 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1704 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001705 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1706 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001707 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001708}
1709
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001710/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1711/// of a NEON VLD or VST instruction. The supported values depend on the
1712/// number of registers being loaded.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001713SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, const SDLoc &dl,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001714 unsigned NumVecs, bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001715 unsigned NumRegs = NumVecs;
1716 if (!is64BitVector && NumVecs < 3)
1717 NumRegs *= 2;
1718
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001719 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001720 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001721 Alignment = 32;
1722 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1723 Alignment = 16;
1724 else if (Alignment >= 8)
1725 Alignment = 8;
1726 else
1727 Alignment = 0;
1728
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001729 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001730}
1731
Jiangning Liu4df23632014-01-16 09:16:13 +00001732static bool isVLDfixed(unsigned Opc)
1733{
1734 switch (Opc) {
1735 default: return false;
1736 case ARM::VLD1d8wb_fixed : return true;
1737 case ARM::VLD1d16wb_fixed : return true;
1738 case ARM::VLD1d64Qwb_fixed : return true;
1739 case ARM::VLD1d32wb_fixed : return true;
1740 case ARM::VLD1d64wb_fixed : return true;
1741 case ARM::VLD1d64TPseudoWB_fixed : return true;
1742 case ARM::VLD1d64QPseudoWB_fixed : return true;
1743 case ARM::VLD1q8wb_fixed : return true;
1744 case ARM::VLD1q16wb_fixed : return true;
1745 case ARM::VLD1q32wb_fixed : return true;
1746 case ARM::VLD1q64wb_fixed : return true;
1747 case ARM::VLD2d8wb_fixed : return true;
1748 case ARM::VLD2d16wb_fixed : return true;
1749 case ARM::VLD2d32wb_fixed : return true;
1750 case ARM::VLD2q8PseudoWB_fixed : return true;
1751 case ARM::VLD2q16PseudoWB_fixed : return true;
1752 case ARM::VLD2q32PseudoWB_fixed : return true;
1753 case ARM::VLD2DUPd8wb_fixed : return true;
1754 case ARM::VLD2DUPd16wb_fixed : return true;
1755 case ARM::VLD2DUPd32wb_fixed : return true;
1756 }
1757}
1758
1759static bool isVSTfixed(unsigned Opc)
1760{
1761 switch (Opc) {
1762 default: return false;
1763 case ARM::VST1d8wb_fixed : return true;
1764 case ARM::VST1d16wb_fixed : return true;
1765 case ARM::VST1d32wb_fixed : return true;
1766 case ARM::VST1d64wb_fixed : return true;
Jim Grosbach1a597112014-04-03 23:43:18 +00001767 case ARM::VST1q8wb_fixed : return true;
1768 case ARM::VST1q16wb_fixed : return true;
1769 case ARM::VST1q32wb_fixed : return true;
1770 case ARM::VST1q64wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001771 case ARM::VST1d64TPseudoWB_fixed : return true;
1772 case ARM::VST1d64QPseudoWB_fixed : return true;
1773 case ARM::VST2d8wb_fixed : return true;
1774 case ARM::VST2d16wb_fixed : return true;
1775 case ARM::VST2d32wb_fixed : return true;
1776 case ARM::VST2q8PseudoWB_fixed : return true;
1777 case ARM::VST2q16PseudoWB_fixed : return true;
1778 case ARM::VST2q32PseudoWB_fixed : return true;
1779 }
1780}
1781
Jim Grosbach2098cb12011-10-24 21:45:13 +00001782// Get the register stride update opcode of a VLD/VST instruction that
1783// is otherwise equivalent to the given fixed stride updating instruction.
1784static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
Jiangning Liu4df23632014-01-16 09:16:13 +00001785 assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1786 && "Incorrect fixed stride updating instruction.");
Jim Grosbach2098cb12011-10-24 21:45:13 +00001787 switch (Opc) {
1788 default: break;
1789 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1790 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1791 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1792 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1793 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1794 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1795 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1796 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jiangning Liu4df23632014-01-16 09:16:13 +00001797 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1798 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1799 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1800 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001801
1802 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1803 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1804 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1805 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1806 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1807 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1808 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1809 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001810 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001811 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001812
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001813 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1814 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1815 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001816 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1817 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1818 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1819
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001820 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1821 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1822 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001823 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1824 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1825 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001826
Jim Grosbach13a292c2012-03-06 22:01:44 +00001827 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1828 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1829 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001830 }
1831 return Opc; // If not one we handle, return it unchanged.
1832}
1833
Justin Bogner45571362016-05-12 00:31:09 +00001834void ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
1835 const uint16_t *DOpcodes,
1836 const uint16_t *QOpcodes0,
1837 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001838 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001839 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001840
Bob Wilsonae08a732010-03-20 22:13:40 +00001841 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001842 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1843 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001844 return;
Bob Wilson12b47992009-10-14 17:28:52 +00001845
1846 SDValue Chain = N->getOperand(0);
1847 EVT VT = N->getValueType(0);
1848 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001849 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001850
Bob Wilson12b47992009-10-14 17:28:52 +00001851 unsigned OpcodeIndex;
1852 switch (VT.getSimpleVT().SimpleTy) {
1853 default: llvm_unreachable("unhandled vld type");
1854 // Double-register operations:
1855 case MVT::v8i8: OpcodeIndex = 0; break;
1856 case MVT::v4i16: OpcodeIndex = 1; break;
1857 case MVT::v2f32:
1858 case MVT::v2i32: OpcodeIndex = 2; break;
1859 case MVT::v1i64: OpcodeIndex = 3; break;
1860 // Quad-register operations:
1861 case MVT::v16i8: OpcodeIndex = 0; break;
1862 case MVT::v8i16: OpcodeIndex = 1; break;
1863 case MVT::v4f32:
1864 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001865 case MVT::v2f64:
Bob Wilson340861d2010-03-23 05:25:43 +00001866 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001867 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson340861d2010-03-23 05:25:43 +00001868 break;
Bob Wilson12b47992009-10-14 17:28:52 +00001869 }
1870
Bob Wilson35fafca2010-09-03 18:16:02 +00001871 EVT ResTy;
1872 if (NumVecs == 1)
1873 ResTy = VT;
1874 else {
1875 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1876 if (!is64BitVector)
1877 ResTyElts *= 2;
1878 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1879 }
Bob Wilson06fce872011-02-07 17:43:21 +00001880 std::vector<EVT> ResTys;
1881 ResTys.push_back(ResTy);
1882 if (isUpdating)
1883 ResTys.push_back(MVT::i32);
1884 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001885
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001886 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001887 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001888 SDNode *VLd;
1889 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001890
Bob Wilson06fce872011-02-07 17:43:21 +00001891 // Double registers and VLD1/VLD2 quad registers are directly supported.
1892 if (is64BitVector || NumVecs <= 2) {
1893 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1894 QOpcodes0[OpcodeIndex]);
1895 Ops.push_back(MemAddr);
1896 Ops.push_back(Align);
1897 if (isUpdating) {
1898 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachd146a022011-12-09 21:28:25 +00001899 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach2098cb12011-10-24 21:45:13 +00001900 // case entirely when the rest are updated to that form, too.
Jiangning Liu4df23632014-01-16 09:16:13 +00001901 if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001902 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001903 // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001904 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00001905 if ((NumVecs > 2 && !isVLDfixed(Opc)) ||
Jim Grosbach05df4602011-10-31 21:50:31 +00001906 !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001907 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Evan Cheng630063a2010-05-10 21:26:24 +00001908 }
Bob Wilson06fce872011-02-07 17:43:21 +00001909 Ops.push_back(Pred);
1910 Ops.push_back(Reg0);
1911 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001912 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001913
Bob Wilson12b47992009-10-14 17:28:52 +00001914 } else {
1915 // Otherwise, quad registers are loaded with two separate instructions,
1916 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001917 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001918
Bob Wilson06fce872011-02-07 17:43:21 +00001919 // Load the even subregs. This is always an updating load, so that it
1920 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001921 SDValue ImplDef =
1922 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1923 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001924 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001925 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001926 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001927
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001928 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001929 Ops.push_back(SDValue(VLdA, 1));
1930 Ops.push_back(Align);
1931 if (isUpdating) {
1932 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1933 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1934 "only constant post-increment update allowed for VLD3/4");
1935 (void)Inc;
1936 Ops.push_back(Reg0);
1937 }
1938 Ops.push_back(SDValue(VLdA, 0));
1939 Ops.push_back(Pred);
1940 Ops.push_back(Reg0);
1941 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001942 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001943 }
Bob Wilson12b47992009-10-14 17:28:52 +00001944
Evan Cheng40791332011-04-19 00:04:03 +00001945 // Transfer memoperands.
1946 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1947 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1948 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1949
Justin Bogner45571362016-05-12 00:31:09 +00001950 if (NumVecs == 1) {
1951 ReplaceNode(N, VLd);
1952 return;
1953 }
Bob Wilson06fce872011-02-07 17:43:21 +00001954
1955 // Extract out the subregisters.
1956 SDValue SuperReg = SDValue(VLd, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00001957 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
1958 ARM::qsub_3 == ARM::qsub_0 + 3,
1959 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00001960 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1961 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1962 ReplaceUses(SDValue(N, Vec),
1963 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1964 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1965 if (isUpdating)
1966 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00001967 CurDAG->RemoveDeadNode(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001968}
1969
Justin Bogner45571362016-05-12 00:31:09 +00001970void ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
1971 const uint16_t *DOpcodes,
1972 const uint16_t *QOpcodes0,
1973 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001974 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001975 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001976
Bob Wilsonae08a732010-03-20 22:13:40 +00001977 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001978 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1979 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1980 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001981 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001982
Evan Cheng40791332011-04-19 00:04:03 +00001983 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1984 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1985
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001986 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00001987 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001988 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001989 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001990
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001991 unsigned OpcodeIndex;
1992 switch (VT.getSimpleVT().SimpleTy) {
1993 default: llvm_unreachable("unhandled vst type");
1994 // Double-register operations:
1995 case MVT::v8i8: OpcodeIndex = 0; break;
1996 case MVT::v4i16: OpcodeIndex = 1; break;
1997 case MVT::v2f32:
1998 case MVT::v2i32: OpcodeIndex = 2; break;
1999 case MVT::v1i64: OpcodeIndex = 3; break;
2000 // Quad-register operations:
2001 case MVT::v16i8: OpcodeIndex = 0; break;
2002 case MVT::v8i16: OpcodeIndex = 1; break;
2003 case MVT::v4f32:
2004 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00002005 case MVT::v2f64:
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00002006 case MVT::v2i64: OpcodeIndex = 3;
2007 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
2008 break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002009 }
2010
Bob Wilson06fce872011-02-07 17:43:21 +00002011 std::vector<EVT> ResTys;
2012 if (isUpdating)
2013 ResTys.push_back(MVT::i32);
2014 ResTys.push_back(MVT::Other);
2015
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002016 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002017 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00002018 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00002019
Bob Wilson06fce872011-02-07 17:43:21 +00002020 // Double registers and VST1/VST2 quad registers are directly supported.
2021 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00002022 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00002023 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00002024 SrcReg = N->getOperand(Vec0Idx);
2025 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00002026 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00002027 SDValue V0 = N->getOperand(Vec0Idx + 0);
2028 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00002029 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002030 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002031 else {
Bob Wilson06fce872011-02-07 17:43:21 +00002032 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00002033 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00002034 // an undef.
2035 SDValue V3 = (NumVecs == 3)
2036 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002037 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002038 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002039 }
Bob Wilson950882b2010-08-28 05:12:57 +00002040 } else {
2041 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00002042 SDValue Q0 = N->getOperand(Vec0Idx);
2043 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00002044 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002045 }
Bob Wilson06fce872011-02-07 17:43:21 +00002046
2047 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2048 QOpcodes0[OpcodeIndex]);
2049 Ops.push_back(MemAddr);
2050 Ops.push_back(Align);
2051 if (isUpdating) {
2052 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbach88ac7612011-12-14 21:32:11 +00002053 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach05df4602011-10-31 21:50:31 +00002054 // case entirely when the rest are updated to that form, too.
Jim Grosbach88ac7612011-12-14 21:32:11 +00002055 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach05df4602011-10-31 21:50:31 +00002056 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00002057 // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00002058 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00002059 if (!isa<ConstantSDNode>(Inc.getNode()))
2060 Ops.push_back(Inc);
2061 else if (NumVecs > 2 && !isVSTfixed(Opc))
2062 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002063 }
2064 Ops.push_back(SrcReg);
2065 Ops.push_back(Pred);
2066 Ops.push_back(Reg0);
2067 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00002068 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002069
2070 // Transfer memoperands.
2071 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
2072
Justin Bogner45571362016-05-12 00:31:09 +00002073 ReplaceNode(N, VSt);
2074 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002075 }
2076
2077 // Otherwise, quad registers are stored with two separate instructions,
2078 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00002079
Bob Wilson01ac8f92010-06-16 21:34:01 +00002080 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00002081 SDValue V0 = N->getOperand(Vec0Idx + 0);
2082 SDValue V1 = N->getOperand(Vec0Idx + 1);
2083 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00002084 SDValue V3 = (NumVecs == 3)
2085 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002086 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002087 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002088
Bob Wilson06fce872011-02-07 17:43:21 +00002089 // Store the even D registers. This is always an updating store, so that it
2090 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00002091 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2092 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2093 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00002094 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00002095 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002096 Chain = SDValue(VStA, 1);
2097
2098 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00002099 Ops.push_back(SDValue(VStA, 0));
2100 Ops.push_back(Align);
2101 if (isUpdating) {
2102 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2103 assert(isa<ConstantSDNode>(Inc.getNode()) &&
2104 "only constant post-increment update allowed for VST3/4");
2105 (void)Inc;
2106 Ops.push_back(Reg0);
2107 }
2108 Ops.push_back(RegSeq);
2109 Ops.push_back(Pred);
2110 Ops.push_back(Reg0);
2111 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00002112 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00002113 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002114 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002115 ReplaceNode(N, VStB);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002116}
2117
Justin Bogner45571362016-05-12 00:31:09 +00002118void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
2119 unsigned NumVecs,
2120 const uint16_t *DOpcodes,
2121 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002122 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002123 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002124
Bob Wilsonae08a732010-03-20 22:13:40 +00002125 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00002126 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2127 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2128 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002129 return;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002130
Evan Cheng40791332011-04-19 00:04:03 +00002131 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2132 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2133
Bob Wilson4145e3a2009-10-14 16:19:03 +00002134 SDValue Chain = N->getOperand(0);
2135 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002136 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2137 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002138 bool is64BitVector = VT.is64BitVector();
2139
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002140 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002141 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002142 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002143 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2144 if (Alignment > NumBytes)
2145 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002146 if (Alignment < 8 && Alignment < NumBytes)
2147 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002148 // Alignment must be a power of two; make sure of that.
2149 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002150 if (Alignment == 1)
2151 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002152 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002153 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002154
Bob Wilson4145e3a2009-10-14 16:19:03 +00002155 unsigned OpcodeIndex;
2156 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002157 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002158 // Double-register operations:
2159 case MVT::v8i8: OpcodeIndex = 0; break;
2160 case MVT::v4i16: OpcodeIndex = 1; break;
2161 case MVT::v2f32:
2162 case MVT::v2i32: OpcodeIndex = 2; break;
2163 // Quad-register operations:
2164 case MVT::v8i16: OpcodeIndex = 0; break;
2165 case MVT::v4f32:
2166 case MVT::v4i32: OpcodeIndex = 1; break;
2167 }
2168
Bob Wilson06fce872011-02-07 17:43:21 +00002169 std::vector<EVT> ResTys;
2170 if (IsLoad) {
2171 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2172 if (!is64BitVector)
2173 ResTyElts *= 2;
2174 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2175 MVT::i64, ResTyElts));
2176 }
2177 if (isUpdating)
2178 ResTys.push_back(MVT::i32);
2179 ResTys.push_back(MVT::Other);
2180
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002181 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002182 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002183
Bob Wilson06fce872011-02-07 17:43:21 +00002184 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002185 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002186 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002187 if (isUpdating) {
2188 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2189 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
2190 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002191
Bob Wilsond5c57a52010-09-13 23:01:35 +00002192 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002193 SDValue V0 = N->getOperand(Vec0Idx + 0);
2194 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002195 if (NumVecs == 2) {
2196 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002197 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002198 else
Weiming Zhao95782222012-11-17 00:23:35 +00002199 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002200 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002201 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002202 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002203 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2204 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002205 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002206 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002207 else
Weiming Zhao95782222012-11-17 00:23:35 +00002208 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002209 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002210 Ops.push_back(SuperReg);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002211 Ops.push_back(getI32Imm(Lane, dl));
Evan Chenga33fc862009-11-21 06:21:52 +00002212 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002213 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002214 Ops.push_back(Chain);
2215
Bob Wilson06fce872011-02-07 17:43:21 +00002216 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2217 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002218 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002219 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002220 if (!IsLoad) {
2221 ReplaceNode(N, VLdLn);
2222 return;
2223 }
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002224
Bob Wilsond5c57a52010-09-13 23:01:35 +00002225 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002226 SuperReg = SDValue(VLdLn, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00002227 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2228 ARM::qsub_3 == ARM::qsub_0 + 3,
2229 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00002230 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002231 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2232 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002233 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2234 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2235 if (isUpdating)
2236 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002237 CurDAG->RemoveDeadNode(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002238}
2239
Justin Bogner45571362016-05-12 00:31:09 +00002240void ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
2241 const uint16_t *Opcodes) {
Bob Wilson2d790df2010-11-28 06:51:26 +00002242 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002243 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002244
2245 SDValue MemAddr, Align;
2246 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002247 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00002248
Evan Cheng40791332011-04-19 00:04:03 +00002249 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2250 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2251
Bob Wilson2d790df2010-11-28 06:51:26 +00002252 SDValue Chain = N->getOperand(0);
2253 EVT VT = N->getValueType(0);
2254
2255 unsigned Alignment = 0;
2256 if (NumVecs != 3) {
2257 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2258 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2259 if (Alignment > NumBytes)
2260 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002261 if (Alignment < 8 && Alignment < NumBytes)
2262 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002263 // Alignment must be a power of two; make sure of that.
2264 Alignment = (Alignment & -Alignment);
2265 if (Alignment == 1)
2266 Alignment = 0;
2267 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002268 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson2d790df2010-11-28 06:51:26 +00002269
2270 unsigned OpcodeIndex;
2271 switch (VT.getSimpleVT().SimpleTy) {
2272 default: llvm_unreachable("unhandled vld-dup type");
2273 case MVT::v8i8: OpcodeIndex = 0; break;
2274 case MVT::v4i16: OpcodeIndex = 1; break;
2275 case MVT::v2f32:
2276 case MVT::v2i32: OpcodeIndex = 2; break;
2277 }
2278
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002279 SDValue Pred = getAL(CurDAG, dl);
Bob Wilson2d790df2010-11-28 06:51:26 +00002280 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2281 SDValue SuperReg;
2282 unsigned Opc = Opcodes[OpcodeIndex];
Bob Wilson06fce872011-02-07 17:43:21 +00002283 SmallVector<SDValue, 6> Ops;
2284 Ops.push_back(MemAddr);
2285 Ops.push_back(Align);
2286 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002287 // fixed-stride update instructions don't have an explicit writeback
2288 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002289 SDValue Inc = N->getOperand(2);
Jim Grosbachc80a2642011-12-21 19:40:55 +00002290 if (!isa<ConstantSDNode>(Inc.getNode()))
2291 Ops.push_back(Inc);
2292 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2293 else if (NumVecs > 2)
2294 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002295 }
2296 Ops.push_back(Pred);
2297 Ops.push_back(Reg0);
2298 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002299
2300 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002301 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002302 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002303 if (isUpdating)
2304 ResTys.push_back(MVT::i32);
2305 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002306 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002307 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002308 SuperReg = SDValue(VLdDup, 0);
Bob Wilson2d790df2010-11-28 06:51:26 +00002309
2310 // Extract the subregisters.
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00002311 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7, "Unexpected subreg numbering");
Bob Wilson2d790df2010-11-28 06:51:26 +00002312 unsigned SubIdx = ARM::dsub_0;
2313 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2314 ReplaceUses(SDValue(N, Vec),
2315 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Bob Wilson06fce872011-02-07 17:43:21 +00002316 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2317 if (isUpdating)
2318 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002319 CurDAG->RemoveDeadNode(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002320}
2321
Justin Bogner45571362016-05-12 00:31:09 +00002322void ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2323 unsigned Opc) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00002324 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002325 SDLoc dl(N);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002326 EVT VT = N->getValueType(0);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002327 unsigned FirstTblReg = IsExt ? 2 : 1;
Bob Wilson3ed511b2010-07-06 23:36:25 +00002328
2329 // Form a REG_SEQUENCE to force register allocation.
2330 SDValue RegSeq;
Bob Wilson5bc8a792010-07-07 00:08:54 +00002331 SDValue V0 = N->getOperand(FirstTblReg + 0);
2332 SDValue V1 = N->getOperand(FirstTblReg + 1);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002333 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002334 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002335 else {
Bob Wilson5bc8a792010-07-07 00:08:54 +00002336 SDValue V2 = N->getOperand(FirstTblReg + 2);
Jim Grosbachd37f0712010-10-21 19:38:40 +00002337 // If it's a vtbl3, form a quad D-register and leave the last part as
Bob Wilson3ed511b2010-07-06 23:36:25 +00002338 // an undef.
2339 SDValue V3 = (NumVecs == 3)
2340 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson5bc8a792010-07-07 00:08:54 +00002341 : N->getOperand(FirstTblReg + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002342 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002343 }
2344
Bob Wilson5bc8a792010-07-07 00:08:54 +00002345 SmallVector<SDValue, 6> Ops;
2346 if (IsExt)
2347 Ops.push_back(N->getOperand(1));
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00002348 Ops.push_back(RegSeq);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002349 Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002350 Ops.push_back(getAL(CurDAG, dl)); // predicate
Bob Wilson3ed511b2010-07-06 23:36:25 +00002351 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
Justin Bogner45571362016-05-12 00:31:09 +00002352 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
Bob Wilson3ed511b2010-07-06 23:36:25 +00002353}
2354
Justin Bogner45571362016-05-12 00:31:09 +00002355bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002356 if (!Subtarget->hasV6T2Ops())
Justin Bogner45571362016-05-12 00:31:09 +00002357 return false;
Bob Wilson93117bc2009-10-14 16:46:45 +00002358
Evan Chengeae6d2c2012-12-19 20:16:09 +00002359 unsigned Opc = isSigned
2360 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002361 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002362 SDLoc dl(N);
Jim Grosbach825cb292010-04-22 23:24:18 +00002363
Jim Grosbach825cb292010-04-22 23:24:18 +00002364 // For unsigned extracts, check for a shift right and mask
2365 unsigned And_imm = 0;
2366 if (N->getOpcode() == ISD::AND) {
2367 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2368
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002369 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002370 if (And_imm & (And_imm + 1))
Justin Bogner45571362016-05-12 00:31:09 +00002371 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002372
2373 unsigned Srl_imm = 0;
2374 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2375 Srl_imm)) {
2376 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2377
Jim Grosbach03f56d92011-07-27 21:09:25 +00002378 // Note: The width operand is encoded as width-1.
Benjamin Kramer5f6a9072015-02-12 15:35:40 +00002379 unsigned Width = countTrailingOnes(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002380 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002381
Jim Grosbach825cb292010-04-22 23:24:18 +00002382 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002383
2384 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2385 // It's cheaper to use a right shift to extract the top bits.
2386 if (Subtarget->isThumb()) {
2387 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2388 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002389 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2390 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002391 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2392 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002393 }
2394
2395 // ARM models shift instructions as MOVsi with shifter operand.
2396 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2397 SDValue ShOpc =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002398 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), dl,
Evan Chengeae6d2c2012-12-19 20:16:09 +00002399 MVT::i32);
2400 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002401 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002402 CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops);
2403 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002404 }
2405
Jim Grosbach825cb292010-04-22 23:24:18 +00002406 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002407 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2408 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2409 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002410 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2411 return true;
Jim Grosbach825cb292010-04-22 23:24:18 +00002412 }
2413 }
Justin Bogner45571362016-05-12 00:31:09 +00002414 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002415 }
2416
2417 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002418 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002419 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002420 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2421 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002422 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002423 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002424 // Note: The width operand is encoded as width-1.
2425 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002426 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002427 if (LSB < 0)
Justin Bogner45571362016-05-12 00:31:09 +00002428 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002429 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002430 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002431 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2432 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2433 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002434 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2435 return true;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002436 }
2437 }
Tim Northover14ff2df2014-07-23 13:59:12 +00002438
Oliver Stannard92ca83c2016-06-01 12:01:01 +00002439 // Or we are looking for a shift of an and, with a mask operand
2440 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, And_imm) &&
2441 isShiftedMask_32(And_imm)) {
2442 unsigned Srl_imm = 0;
2443 unsigned LSB = countTrailingZeros(And_imm);
2444 // Shift must be the same as the ands lsb
2445 if (isInt32Immediate(N->getOperand(1), Srl_imm) && Srl_imm == LSB) {
2446 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2447 unsigned MSB = 31 - countLeadingZeros(And_imm);
2448 // Note: The width operand is encoded as width-1.
2449 unsigned Width = MSB - LSB;
2450 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2451 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2452 CurDAG->getTargetConstant(Srl_imm, dl, MVT::i32),
2453 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2454 getAL(CurDAG, dl), Reg0 };
2455 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2456 return true;
2457 }
2458 }
2459
Tim Northover14ff2df2014-07-23 13:59:12 +00002460 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
2461 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2462 unsigned LSB = 0;
2463 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) &&
2464 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB))
Justin Bogner45571362016-05-12 00:31:09 +00002465 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002466
2467 if (LSB + Width > 32)
Justin Bogner45571362016-05-12 00:31:09 +00002468 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002469
2470 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2471 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002472 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2473 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
2474 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002475 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2476 return true;
Tim Northover14ff2df2014-07-23 13:59:12 +00002477 }
2478
Justin Bogner45571362016-05-12 00:31:09 +00002479 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002480}
2481
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002482/// Target-specific DAG combining for ISD::XOR.
2483/// Target-independent combining lowers SELECT_CC nodes of the form
2484/// select_cc setg[ge] X, 0, X, -X
2485/// select_cc setgt X, -1, X, -X
2486/// select_cc setl[te] X, 0, -X, X
2487/// select_cc setlt X, 1, -X, X
2488/// which represent Integer ABS into:
2489/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2490/// ARM instruction selection detects the latter and matches it to
2491/// ARM::ABS or ARM::t2ABS machine node.
Justin Bogner45571362016-05-12 00:31:09 +00002492bool ARMDAGToDAGISel::tryABSOp(SDNode *N){
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002493 SDValue XORSrc0 = N->getOperand(0);
2494 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002495 EVT VT = N->getValueType(0);
2496
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002497 if (Subtarget->isThumb1Only())
Justin Bogner45571362016-05-12 00:31:09 +00002498 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002499
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002500 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Justin Bogner45571362016-05-12 00:31:09 +00002501 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002502
2503 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2504 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2505 SDValue SRASrc0 = XORSrc1.getOperand(0);
2506 SDValue SRASrc1 = XORSrc1.getOperand(1);
2507 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2508 EVT XType = SRASrc0.getValueType();
2509 unsigned Size = XType.getSizeInBits() - 1;
2510
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002511 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
Craig Topper062a2ba2014-04-25 05:30:21 +00002512 XType.isInteger() && SRAConstant != nullptr &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002513 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002514 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Justin Bogner45571362016-05-12 00:31:09 +00002515 CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2516 return true;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002517 }
2518
Justin Bogner45571362016-05-12 00:31:09 +00002519 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002520}
2521
Sam Parker2d5126c2016-04-08 16:02:53 +00002522static bool SearchSignedMulShort(SDValue SignExt, unsigned *Opc, SDValue &Src1,
2523 bool Accumulate) {
2524 // For SM*WB, we need to some form of sext.
2525 // For SM*WT, we need to search for (sra X, 16)
2526 // Src1 then gets set to X.
2527 if ((SignExt.getOpcode() == ISD::SIGN_EXTEND ||
2528 SignExt.getOpcode() == ISD::SIGN_EXTEND_INREG ||
2529 SignExt.getOpcode() == ISD::AssertSext) &&
2530 SignExt.getValueType() == MVT::i32) {
2531
2532 *Opc = Accumulate ? ARM::SMLAWB : ARM::SMULWB;
2533 Src1 = SignExt.getOperand(0);
2534 return true;
2535 }
2536
2537 if (SignExt.getOpcode() != ISD::SRA)
2538 return false;
2539
2540 ConstantSDNode *SRASrc1 = dyn_cast<ConstantSDNode>(SignExt.getOperand(1));
2541 if (!SRASrc1 || SRASrc1->getZExtValue() != 16)
2542 return false;
2543
2544 SDValue Op0 = SignExt.getOperand(0);
2545
2546 // The sign extend operand for SM*WB could be generated by a shl and ashr.
2547 if (Op0.getOpcode() == ISD::SHL) {
2548 SDValue SHL = Op0;
2549 ConstantSDNode *SHLSrc1 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
2550 if (!SHLSrc1 || SHLSrc1->getZExtValue() != 16)
2551 return false;
2552
2553 *Opc = Accumulate ? ARM::SMLAWB : ARM::SMULWB;
2554 Src1 = Op0.getOperand(0);
2555 return true;
2556 }
2557 *Opc = Accumulate ? ARM::SMLAWT : ARM::SMULWT;
2558 Src1 = SignExt.getOperand(0);
2559 return true;
2560}
2561
2562static bool SearchSignedMulLong(SDValue OR, unsigned *Opc, SDValue &Src0,
2563 SDValue &Src1, bool Accumulate) {
2564 // First we look for:
2565 // (add (or (srl ?, 16), (shl ?, 16)))
2566 if (OR.getOpcode() != ISD::OR)
2567 return false;
2568
2569 SDValue SRL = OR.getOperand(0);
2570 SDValue SHL = OR.getOperand(1);
2571
2572 if (SRL.getOpcode() != ISD::SRL || SHL.getOpcode() != ISD::SHL) {
2573 SRL = OR.getOperand(1);
2574 SHL = OR.getOperand(0);
2575 if (SRL.getOpcode() != ISD::SRL || SHL.getOpcode() != ISD::SHL)
2576 return false;
2577 }
2578
2579 ConstantSDNode *SRLSrc1 = dyn_cast<ConstantSDNode>(SRL.getOperand(1));
2580 ConstantSDNode *SHLSrc1 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
2581 if (!SRLSrc1 || !SHLSrc1 || SRLSrc1->getZExtValue() != 16 ||
2582 SHLSrc1->getZExtValue() != 16)
2583 return false;
2584
2585 // The first operands to the shifts need to be the two results from the
2586 // same smul_lohi node.
2587 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
2588 SRL.getOperand(0).getOpcode() != ISD::SMUL_LOHI)
2589 return false;
2590
2591 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
2592 if (SRL.getOperand(0) != SDValue(SMULLOHI, 0) ||
2593 SHL.getOperand(0) != SDValue(SMULLOHI, 1))
2594 return false;
2595
2596 // Now we have:
2597 // (add (or (srl (smul_lohi ?, ?), 16), (shl (smul_lohi ?, ?), 16)))
2598 // For SMLAW[B|T] smul_lohi will take a 32-bit and a 16-bit arguments.
2599 // For SMLAWB the 16-bit value will signed extended somehow.
2600 // For SMLAWT only the SRA is required.
2601
2602 // Check both sides of SMUL_LOHI
2603 if (SearchSignedMulShort(SMULLOHI->getOperand(0), Opc, Src1, Accumulate)) {
2604 Src0 = SMULLOHI->getOperand(1);
2605 } else if (SearchSignedMulShort(SMULLOHI->getOperand(1), Opc, Src1,
2606 Accumulate)) {
2607 Src0 = SMULLOHI->getOperand(0);
2608 } else {
2609 return false;
2610 }
2611 return true;
2612}
2613
Justin Bogner45571362016-05-12 00:31:09 +00002614bool ARMDAGToDAGISel::trySMLAWSMULW(SDNode *N) {
Sam Parkerd5ca0a62016-07-25 10:11:00 +00002615 if (!Subtarget->hasV6Ops() ||
2616 (Subtarget->isThumb() && !Subtarget->hasThumb2()))
2617 return false;
2618
Sam Parker2d5126c2016-04-08 16:02:53 +00002619 SDLoc dl(N);
2620 SDValue Src0 = N->getOperand(0);
2621 SDValue Src1 = N->getOperand(1);
2622 SDValue A, B;
2623 unsigned Opc = 0;
2624
2625 if (N->getOpcode() == ISD::ADD) {
2626 if (Src0.getOpcode() != ISD::OR && Src1.getOpcode() != ISD::OR)
Justin Bogner45571362016-05-12 00:31:09 +00002627 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002628
2629 SDValue Acc;
2630 if (SearchSignedMulLong(Src0, &Opc, A, B, true)) {
2631 Acc = Src1;
2632 } else if (SearchSignedMulLong(Src1, &Opc, A, B, true)) {
2633 Acc = Src0;
2634 } else {
Justin Bogner45571362016-05-12 00:31:09 +00002635 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002636 }
2637 if (Opc == 0)
Justin Bogner45571362016-05-12 00:31:09 +00002638 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002639
2640 SDValue Ops[] = { A, B, Acc, getAL(CurDAG, dl),
2641 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002642 CurDAG->SelectNodeTo(N, Opc, MVT::i32, MVT::Other, Ops);
2643 return true;
Sam Parker2d5126c2016-04-08 16:02:53 +00002644 } else if (N->getOpcode() == ISD::OR &&
2645 SearchSignedMulLong(SDValue(N, 0), &Opc, A, B, false)) {
2646 if (Opc == 0)
Justin Bogner45571362016-05-12 00:31:09 +00002647 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002648
2649 SDValue Ops[] = { A, B, getAL(CurDAG, dl),
2650 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002651 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2652 return true;
Sam Parker2d5126c2016-04-08 16:02:53 +00002653 }
Justin Bogner45571362016-05-12 00:31:09 +00002654 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002655}
2656
Tim Northoverb629c772016-04-18 21:48:55 +00002657/// We've got special pseudo-instructions for these
Justin Bogner45571362016-05-12 00:31:09 +00002658void ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *N) {
Tim Northoverb629c772016-04-18 21:48:55 +00002659 unsigned Opcode;
2660 EVT MemTy = cast<MemSDNode>(N)->getMemoryVT();
2661 if (MemTy == MVT::i8)
2662 Opcode = ARM::CMP_SWAP_8;
2663 else if (MemTy == MVT::i16)
2664 Opcode = ARM::CMP_SWAP_16;
2665 else if (MemTy == MVT::i32)
2666 Opcode = ARM::CMP_SWAP_32;
2667 else
2668 llvm_unreachable("Unknown AtomicCmpSwap type");
2669
2670 SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3),
2671 N->getOperand(0)};
2672 SDNode *CmpSwap = CurDAG->getMachineNode(
2673 Opcode, SDLoc(N),
2674 CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other), Ops);
2675
2676 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2677 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
2678 cast<MachineSDNode>(CmpSwap)->setMemRefs(MemOp, MemOp + 1);
2679
2680 ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0));
2681 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002682 CurDAG->RemoveDeadNode(N);
Tim Northoverb629c772016-04-18 21:48:55 +00002683}
2684
Justin Bogner45571362016-05-12 00:31:09 +00002685void ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
Evan Chengd85631e2010-05-05 18:28:36 +00002686 // The only time a CONCAT_VECTORS operation can have legal types is when
2687 // two 64-bit vectors are concatenated to a 128-bit vector.
2688 EVT VT = N->getValueType(0);
2689 if (!VT.is128BitVector() || N->getNumOperands() != 2)
2690 llvm_unreachable("unexpected CONCAT_VECTORS");
Justin Bogner45571362016-05-12 00:31:09 +00002691 ReplaceNode(N, createDRegPairNode(VT, N->getOperand(0), N->getOperand(1)));
Evan Chengd85631e2010-05-05 18:28:36 +00002692}
2693
Justin Bogner45571362016-05-12 00:31:09 +00002694void ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002695 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002696
Tim Northover31d093c2013-09-22 08:21:56 +00002697 if (N->isMachineOpcode()) {
2698 N->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00002699 return; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00002700 }
Rafael Espindola4e760152006-06-12 12:28:08 +00002701
2702 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002703 default: break;
Sam Parker2d5126c2016-04-08 16:02:53 +00002704 case ISD::ADD:
Justin Bogner45571362016-05-12 00:31:09 +00002705 case ISD::OR:
2706 if (trySMLAWSMULW(N))
2707 return;
Sam Parker2d5126c2016-04-08 16:02:53 +00002708 break;
Justin Bogner45571362016-05-12 00:31:09 +00002709 case ISD::WRITE_REGISTER:
2710 if (tryWriteRegister(N))
2711 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002712 break;
Justin Bogner45571362016-05-12 00:31:09 +00002713 case ISD::READ_REGISTER:
2714 if (tryReadRegister(N))
2715 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002716 break;
Justin Bogner45571362016-05-12 00:31:09 +00002717 case ISD::INLINEASM:
2718 if (tryInlineAsm(N))
2719 return;
Weiming Zhaoc5987002013-02-14 18:10:21 +00002720 break;
Justin Bogner45571362016-05-12 00:31:09 +00002721 case ISD::XOR:
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002722 // Select special operations if XOR node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +00002723 if (tryABSOp(N))
2724 return;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002725 // Other cases are autogenerated.
2726 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002727 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002728 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
John Brawn056e6782015-09-14 15:19:41 +00002729 // If we can't materialize the constant we need to use a literal pool
2730 if (ConstantMaterializationCost(Val) > 2) {
Eric Christopherb17140d2014-10-08 07:32:17 +00002731 SDValue CPIdx = CurDAG->getTargetConstantPool(
2732 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
Mehdi Amini44ede332015-07-09 02:09:04 +00002733 TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng1526ba52007-01-24 08:53:17 +00002734
2735 SDNode *ResNode;
Tim Northover55c625f2014-01-23 13:43:47 +00002736 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002737 SDValue Pred = getAL(CurDAG, dl);
Owen Anderson9f944592009-08-11 20:47:22 +00002738 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002739 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002740 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002741 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002742 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002743 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002744 CPIdx,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002745 CurDAG->getTargetConstant(0, dl, MVT::i32),
2746 getAL(CurDAG, dl),
Owen Anderson9f944592009-08-11 20:47:22 +00002747 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002748 CurDAG->getEntryNode()
2749 };
Justin Bogner45571362016-05-12 00:31:09 +00002750 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
2751 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002752 }
Justin Bognered4f3782016-05-12 00:20:19 +00002753 ReplaceNode(N, ResNode);
Justin Bogner45571362016-05-12 00:31:09 +00002754 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002755 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002756
Evan Cheng10043e22007-01-19 07:51:42 +00002757 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002758 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002759 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002760 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002761 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002762 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00002763 SDValue TFI = CurDAG->getTargetFrameIndex(
2764 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin22c2fba2009-07-08 23:10:31 +00002765 if (Subtarget->isThumb1Only()) {
Renato Golinb9887ef2015-02-25 14:41:06 +00002766 // Set the alignment of the frame object to 4, to avoid having to generate
2767 // more than one ADD
2768 MachineFrameInfo *MFI = MF->getFrameInfo();
2769 if (MFI->getObjectAlignment(FI) < 4)
2770 MFI->setObjectAlignment(FI, 4);
Justin Bogner45571362016-05-12 00:31:09 +00002771 CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
2772 CurDAG->getTargetConstant(0, dl, MVT::i32));
2773 return;
Jim Grosbachfde21102009-04-07 20:34:09 +00002774 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002775 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2776 ARM::t2ADDri : ARM::ADDri);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002777 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
2778 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002779 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002780 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2781 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00002782 }
Evan Cheng10043e22007-01-19 07:51:42 +00002783 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002784 case ISD::SRL:
Justin Bogner45571362016-05-12 00:31:09 +00002785 if (tryV6T2BitfieldExtractOp(N, false))
2786 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002787 break;
Tim Northover14ff2df2014-07-23 13:59:12 +00002788 case ISD::SIGN_EXTEND_INREG:
Sandeep Patel423e42b2009-10-13 18:59:48 +00002789 case ISD::SRA:
Justin Bogner45571362016-05-12 00:31:09 +00002790 if (tryV6T2BitfieldExtractOp(N, true))
2791 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002792 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002793 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002794 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002795 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002796 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002797 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002798 if (!RHSV) break;
2799 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002800 unsigned ShImm = Log2_32(RHSV-1);
2801 if (ShImm >= 32)
2802 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002803 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002804 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002805 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002806 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002807 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002808 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002809 CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
2810 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002811 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002812 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2813 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002814 CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
2815 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002816 }
Evan Cheng10043e22007-01-19 07:51:42 +00002817 }
2818 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002819 unsigned ShImm = Log2_32(RHSV+1);
2820 if (ShImm >= 32)
2821 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002822 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002823 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002824 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002825 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002826 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002827 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002828 CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
2829 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002830 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002831 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2832 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002833 CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
2834 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002835 }
Evan Cheng10043e22007-01-19 07:51:42 +00002836 }
2837 }
2838 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002839 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002840 // Check for unsigned bitfield extract
Justin Bogner45571362016-05-12 00:31:09 +00002841 if (tryV6T2BitfieldExtractOp(N, false))
2842 return;
Jim Grosbach825cb292010-04-22 23:24:18 +00002843
James Molloyae5ff992016-07-05 12:37:13 +00002844 // If an immediate is used in an AND node, it is possible that the immediate
2845 // can be more optimally materialized when negated. If this is the case we
2846 // can negate the immediate and use a BIC instead.
2847 auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1));
2848 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
2849 uint32_t Imm = (uint32_t) N1C->getZExtValue();
2850
2851 // In Thumb2 mode, an AND can take a 12-bit immediate. If this
2852 // immediate can be negated and fit in the immediate operand of
2853 // a t2BIC, don't do any manual transform here as this can be
2854 // handled by the generic ISel machinery.
2855 bool PreferImmediateEncoding =
2856 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm));
2857 if (!PreferImmediateEncoding &&
2858 ConstantMaterializationCost(Imm) >
2859 ConstantMaterializationCost(~Imm)) {
2860 // The current immediate costs more to materialize than a negated
2861 // immediate, so negate the immediate and use a BIC.
2862 SDValue NewImm =
2863 CurDAG->getConstant(~N1C->getZExtValue(), dl, MVT::i32);
2864 // If the new constant didn't exist before, reposition it in the topological
2865 // ordering so it is just before N. Otherwise, don't touch its location.
2866 if (NewImm->getNodeId() == -1)
2867 CurDAG->RepositionNode(N->getIterator(), NewImm.getNode());
2868
2869 if (!Subtarget->hasThumb2()) {
2870 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
2871 N->getOperand(0), NewImm, getAL(CurDAG, dl),
2872 CurDAG->getRegister(0, MVT::i32)};
2873 ReplaceNode(N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32, Ops));
2874 return;
2875 } else {
2876 SDValue Ops[] = {N->getOperand(0), NewImm, getAL(CurDAG, dl),
2877 CurDAG->getRegister(0, MVT::i32),
2878 CurDAG->getRegister(0, MVT::i32)};
2879 ReplaceNode(N,
2880 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32, Ops));
2881 return;
2882 }
2883 }
2884 }
2885
Evan Cheng786b15f2009-10-21 08:15:52 +00002886 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2887 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2888 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2889 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2890 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002891 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002892 if (VT != MVT::i32)
2893 break;
2894 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2895 ? ARM::t2MOVTi16
2896 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2897 if (!Opc)
2898 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002899 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
James Molloyae5ff992016-07-05 12:37:13 +00002900 N1C = dyn_cast<ConstantSDNode>(N1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002901 if (!N1C)
2902 break;
2903 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2904 SDValue N2 = N0.getOperand(1);
2905 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2906 if (!N2C)
2907 break;
2908 unsigned N1CVal = N1C->getZExtValue();
2909 unsigned N2CVal = N2C->getZExtValue();
2910 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2911 (N1CVal & 0xffffU) == 0xffffU &&
2912 (N2CVal & 0xffffU) == 0x0U) {
2913 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002914 dl, MVT::i32);
Evan Cheng786b15f2009-10-21 08:15:52 +00002915 SDValue Ops[] = { N0.getOperand(0), Imm16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002916 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002917 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
2918 return;
Evan Cheng786b15f2009-10-21 08:15:52 +00002919 }
2920 }
2921 break;
2922 }
Jim Grosbachd7cf55c2009-11-09 00:11:35 +00002923 case ARMISD::VMOVRRD:
Justin Bogner45571362016-05-12 00:31:09 +00002924 ReplaceNode(N, CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
2925 N->getOperand(0), getAL(CurDAG, dl),
2926 CurDAG->getRegister(0, MVT::i32)));
2927 return;
Dan Gohmana1603612007-10-08 18:33:35 +00002928 case ISD::UMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002929 if (Subtarget->isThumb1Only())
2930 break;
2931 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002932 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002933 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002934 ReplaceNode(
2935 N, CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops));
2936 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002937 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002938 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002939 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002940 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002941 ReplaceNode(N, CurDAG->getMachineNode(
2942 Subtarget->hasV6Ops() ? ARM::UMULL : ARM::UMULLv5, dl,
2943 MVT::i32, MVT::i32, Ops));
2944 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002945 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002946 }
Dan Gohmana1603612007-10-08 18:33:35 +00002947 case ISD::SMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002948 if (Subtarget->isThumb1Only())
2949 break;
2950 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002951 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002952 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002953 ReplaceNode(
2954 N, CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops));
2955 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002956 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002957 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002958 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002959 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002960 ReplaceNode(N, CurDAG->getMachineNode(
2961 Subtarget->hasV6Ops() ? ARM::SMULL : ARM::SMULLv5, dl,
2962 MVT::i32, MVT::i32, Ops));
2963 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002964 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002965 }
Sam Parkerd616cf02016-06-20 16:47:09 +00002966 case ARMISD::UMAAL: {
2967 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
2968 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2969 N->getOperand(2), N->getOperand(3),
2970 getAL(CurDAG, dl),
2971 CurDAG->getRegister(0, MVT::i32) };
2972 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::i32, Ops));
2973 return;
2974 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002975 case ARMISD::UMLAL:{
Sam Parkerd616cf02016-06-20 16:47:09 +00002976 // UMAAL is similar to UMLAL but it adds two 32-bit values to the
2977 // 64-bit multiplication result.
2978 if (Subtarget->hasV6Ops() && N->getOperand(2).getOpcode() == ARMISD::ADDC &&
2979 N->getOperand(3).getOpcode() == ARMISD::ADDE) {
2980
2981 SDValue Addc = N->getOperand(2);
2982 SDValue Adde = N->getOperand(3);
2983
2984 if (Adde.getOperand(2).getNode() == Addc.getNode()) {
2985
2986 ConstantSDNode *Op0 = dyn_cast<ConstantSDNode>(Adde.getOperand(0));
2987 ConstantSDNode *Op1 = dyn_cast<ConstantSDNode>(Adde.getOperand(1));
2988
2989 if (Op0 && Op1 && Op0->getZExtValue() == 0 && Op1->getZExtValue() == 0)
2990 {
2991 // Select UMAAL instead: UMAAL RdLo, RdHi, Rn, Rm
2992 // RdLo = one operand to be added, lower 32-bits of res
2993 // RdHi = other operand to be added, upper 32-bits of res
2994 // Rn = first multiply operand
2995 // Rm = second multiply operand
2996 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2997 Addc.getOperand(0), Addc.getOperand(1),
2998 getAL(CurDAG, dl),
2999 CurDAG->getRegister(0, MVT::i32) };
3000 unsigned opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
3001 CurDAG->SelectNodeTo(N, opc, MVT::i32, MVT::i32, Ops);
3002 return;
3003 }
3004 }
3005 }
3006
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003007 if (Subtarget->isThumb()) {
3008 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003009 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003010 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00003011 ReplaceNode(
3012 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops));
3013 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003014 }else{
3015 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003016 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003017 CurDAG->getRegister(0, MVT::i32),
3018 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00003019 ReplaceNode(N, CurDAG->getMachineNode(
3020 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl,
3021 MVT::i32, MVT::i32, Ops));
3022 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003023 }
3024 }
3025 case ARMISD::SMLAL:{
3026 if (Subtarget->isThumb()) {
3027 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003028 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003029 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00003030 ReplaceNode(
3031 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops));
3032 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003033 }else{
3034 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003035 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003036 CurDAG->getRegister(0, MVT::i32),
3037 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00003038 ReplaceNode(N, CurDAG->getMachineNode(
3039 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl,
3040 MVT::i32, MVT::i32, Ops));
3041 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003042 }
3043 }
Sam Parker68c71cd2016-07-25 09:20:20 +00003044 case ARMISD::SUBE: {
3045 if (!Subtarget->hasV6Ops())
3046 break;
3047 // Look for a pattern to match SMMLS
3048 // (sube a, (smul_loHi a, b), (subc 0, (smul_LOhi(a, b))))
3049 if (N->getOperand(1).getOpcode() != ISD::SMUL_LOHI ||
3050 N->getOperand(2).getOpcode() != ARMISD::SUBC)
3051 break;
3052
3053 if (Subtarget->isThumb())
3054 assert(Subtarget->hasThumb2() &&
3055 "This pattern should not be generated for Thumb");
3056
3057 SDValue SmulLoHi = N->getOperand(1);
3058 SDValue Subc = N->getOperand(2);
3059 auto *Zero = dyn_cast<ConstantSDNode>(Subc.getOperand(0));
3060
3061 if (!Zero || Zero->getZExtValue() != 0 ||
3062 Subc.getOperand(1) != SmulLoHi.getValue(0) ||
3063 N->getOperand(1) != SmulLoHi.getValue(1) ||
3064 N->getOperand(2) != Subc.getValue(1))
3065 break;
3066
3067 unsigned Opc = Subtarget->isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
3068 SDValue Ops[] = { SmulLoHi.getOperand(0), SmulLoHi.getOperand(1),
3069 N->getOperand(0), getAL(CurDAG, dl),
3070 CurDAG->getRegister(0, MVT::i32) };
3071 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops));
3072 return;
3073 }
Evan Cheng10043e22007-01-19 07:51:42 +00003074 case ISD::LOAD: {
Justin Bogner45571362016-05-12 00:31:09 +00003075 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
3076 if (tryT2IndexedLoad(N))
3077 return;
James Molloyb3326df2016-07-15 08:03:56 +00003078 } else if (Subtarget->isThumb()) {
3079 if (tryT1IndexedLoad(N))
3080 return;
Justin Bogner45571362016-05-12 00:31:09 +00003081 } else if (tryARMIndexedLoad(N))
3082 return;
Evan Cheng10043e22007-01-19 07:51:42 +00003083 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00003084 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00003085 }
Evan Cheng7e90b112007-07-05 07:15:27 +00003086 case ARMISD::BRCOND: {
3087 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
3088 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
3089 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003090
Evan Cheng7e90b112007-07-05 07:15:27 +00003091 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
3092 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
3093 // Pattern complexity = 6 cost = 1 size = 0
3094
David Goodwin27303cd2009-06-30 18:04:13 +00003095 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
3096 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
3097 // Pattern complexity = 6 cost = 1 size = 0
3098
Jim Grosbachf24f9d92009-08-11 15:33:49 +00003099 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00003100 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003101 SDValue Chain = N->getOperand(0);
3102 SDValue N1 = N->getOperand(1);
3103 SDValue N2 = N->getOperand(2);
3104 SDValue N3 = N->getOperand(3);
3105 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00003106 assert(N1.getOpcode() == ISD::BasicBlock);
3107 assert(N2.getOpcode() == ISD::Constant);
3108 assert(N3.getOpcode() == ISD::Register);
3109
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003110 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003111 cast<ConstantSDNode>(N2)->getZExtValue()), dl,
Owen Anderson9f944592009-08-11 20:47:22 +00003112 MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003113 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00003114 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00003115 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003116 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003117 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003118 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003119 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00003120 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003121 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00003122 SDValue(Chain.getNode(), Chain.getResNo()));
Justin Bognered4f3782016-05-12 00:20:19 +00003123 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003124 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00003125 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003126 case ARMISD::VZIP: {
3127 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003128 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003129 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003130 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003131 case MVT::v8i8: Opc = ARM::VZIPd8; break;
3132 case MVT::v4i16: Opc = ARM::VZIPd16; break;
3133 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00003134 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3135 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003136 case MVT::v16i8: Opc = ARM::VZIPq8; break;
3137 case MVT::v8i16: Opc = ARM::VZIPq16; break;
3138 case MVT::v4f32:
3139 case MVT::v4i32: Opc = ARM::VZIPq32; break;
3140 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003141 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003142 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3143 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003144 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3145 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003146 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003147 case ARMISD::VUZP: {
3148 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003149 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003150 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003151 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003152 case MVT::v8i8: Opc = ARM::VUZPd8; break;
3153 case MVT::v4i16: Opc = ARM::VUZPd16; break;
3154 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00003155 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3156 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003157 case MVT::v16i8: Opc = ARM::VUZPq8; break;
3158 case MVT::v8i16: Opc = ARM::VUZPq16; break;
3159 case MVT::v4f32:
3160 case MVT::v4i32: Opc = ARM::VUZPq32; break;
3161 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003162 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003163 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3164 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003165 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3166 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003167 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003168 case ARMISD::VTRN: {
3169 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003170 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003171 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003172 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003173 case MVT::v8i8: Opc = ARM::VTRNd8; break;
3174 case MVT::v4i16: Opc = ARM::VTRNd16; break;
3175 case MVT::v2f32:
3176 case MVT::v2i32: Opc = ARM::VTRNd32; break;
3177 case MVT::v16i8: Opc = ARM::VTRNq8; break;
3178 case MVT::v8i16: Opc = ARM::VTRNq16; break;
3179 case MVT::v4f32:
3180 case MVT::v4i32: Opc = ARM::VTRNq32; break;
3181 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003182 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003183 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3184 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003185 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3186 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003187 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003188 case ARMISD::BUILD_VECTOR: {
3189 EVT VecVT = N->getValueType(0);
3190 EVT EltVT = VecVT.getVectorElementType();
3191 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00003192 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00003193 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003194 ReplaceNode(
3195 N, createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3196 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003197 }
Duncan Sands14627772010-11-03 12:17:33 +00003198 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003199 if (NumElts == 2) {
3200 ReplaceNode(
3201 N, createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3202 return;
3203 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003204 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003205 ReplaceNode(N,
3206 createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
3207 N->getOperand(2), N->getOperand(3)));
3208 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003209 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003210
Bob Wilson2d790df2010-11-28 06:51:26 +00003211 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003212 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
3213 ARM::VLD2DUPd32 };
Justin Bogner45571362016-05-12 00:31:09 +00003214 SelectVLDDup(N, false, 2, Opcodes);
3215 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00003216 }
3217
Bob Wilson77ab1652010-11-29 19:35:29 +00003218 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003219 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
3220 ARM::VLD3DUPd16Pseudo,
3221 ARM::VLD3DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003222 SelectVLDDup(N, false, 3, Opcodes);
3223 return;
Bob Wilson77ab1652010-11-29 19:35:29 +00003224 }
3225
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003226 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003227 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
3228 ARM::VLD4DUPd16Pseudo,
3229 ARM::VLD4DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003230 SelectVLDDup(N, false, 4, Opcodes);
3231 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003232 }
3233
3234 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003235 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
3236 ARM::VLD2DUPd16wb_fixed,
3237 ARM::VLD2DUPd32wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003238 SelectVLDDup(N, true, 2, Opcodes);
3239 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003240 }
3241
3242 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003243 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
3244 ARM::VLD3DUPd16Pseudo_UPD,
3245 ARM::VLD3DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003246 SelectVLDDup(N, true, 3, Opcodes);
3247 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003248 }
3249
3250 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003251 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
3252 ARM::VLD4DUPd16Pseudo_UPD,
3253 ARM::VLD4DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003254 SelectVLDDup(N, true, 4, Opcodes);
3255 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003256 }
3257
3258 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003259 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
3260 ARM::VLD1d16wb_fixed,
3261 ARM::VLD1d32wb_fixed,
3262 ARM::VLD1d64wb_fixed };
3263 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
3264 ARM::VLD1q16wb_fixed,
3265 ARM::VLD1q32wb_fixed,
3266 ARM::VLD1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003267 SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
3268 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003269 }
3270
3271 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003272 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
3273 ARM::VLD2d16wb_fixed,
3274 ARM::VLD2d32wb_fixed,
3275 ARM::VLD1q64wb_fixed};
3276 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
3277 ARM::VLD2q16PseudoWB_fixed,
3278 ARM::VLD2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003279 SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
3280 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003281 }
3282
3283 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003284 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
3285 ARM::VLD3d16Pseudo_UPD,
3286 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003287 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003288 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3289 ARM::VLD3q16Pseudo_UPD,
3290 ARM::VLD3q32Pseudo_UPD };
3291 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3292 ARM::VLD3q16oddPseudo_UPD,
3293 ARM::VLD3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003294 SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3295 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003296 }
3297
3298 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003299 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3300 ARM::VLD4d16Pseudo_UPD,
3301 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003302 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003303 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3304 ARM::VLD4q16Pseudo_UPD,
3305 ARM::VLD4q32Pseudo_UPD };
3306 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3307 ARM::VLD4q16oddPseudo_UPD,
3308 ARM::VLD4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003309 SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3310 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003311 }
3312
3313 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003314 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3315 ARM::VLD2LNd16Pseudo_UPD,
3316 ARM::VLD2LNd32Pseudo_UPD };
3317 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3318 ARM::VLD2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003319 SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3320 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003321 }
3322
3323 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003324 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3325 ARM::VLD3LNd16Pseudo_UPD,
3326 ARM::VLD3LNd32Pseudo_UPD };
3327 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3328 ARM::VLD3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003329 SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3330 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003331 }
3332
3333 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003334 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3335 ARM::VLD4LNd16Pseudo_UPD,
3336 ARM::VLD4LNd32Pseudo_UPD };
3337 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3338 ARM::VLD4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003339 SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3340 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003341 }
3342
3343 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003344 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3345 ARM::VST1d16wb_fixed,
3346 ARM::VST1d32wb_fixed,
3347 ARM::VST1d64wb_fixed };
3348 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3349 ARM::VST1q16wb_fixed,
3350 ARM::VST1q32wb_fixed,
3351 ARM::VST1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003352 SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
3353 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003354 }
3355
3356 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003357 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3358 ARM::VST2d16wb_fixed,
3359 ARM::VST2d32wb_fixed,
3360 ARM::VST1q64wb_fixed};
3361 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3362 ARM::VST2q16PseudoWB_fixed,
3363 ARM::VST2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003364 SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
3365 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003366 }
3367
3368 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003369 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3370 ARM::VST3d16Pseudo_UPD,
3371 ARM::VST3d32Pseudo_UPD,
3372 ARM::VST1d64TPseudoWB_fixed};
3373 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3374 ARM::VST3q16Pseudo_UPD,
3375 ARM::VST3q32Pseudo_UPD };
3376 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3377 ARM::VST3q16oddPseudo_UPD,
3378 ARM::VST3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003379 SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3380 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003381 }
3382
3383 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003384 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3385 ARM::VST4d16Pseudo_UPD,
3386 ARM::VST4d32Pseudo_UPD,
3387 ARM::VST1d64QPseudoWB_fixed};
3388 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3389 ARM::VST4q16Pseudo_UPD,
3390 ARM::VST4q32Pseudo_UPD };
3391 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3392 ARM::VST4q16oddPseudo_UPD,
3393 ARM::VST4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003394 SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3395 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003396 }
3397
3398 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003399 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3400 ARM::VST2LNd16Pseudo_UPD,
3401 ARM::VST2LNd32Pseudo_UPD };
3402 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3403 ARM::VST2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003404 SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3405 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003406 }
3407
3408 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003409 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3410 ARM::VST3LNd16Pseudo_UPD,
3411 ARM::VST3LNd32Pseudo_UPD };
3412 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3413 ARM::VST3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003414 SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3415 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003416 }
3417
3418 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003419 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3420 ARM::VST4LNd16Pseudo_UPD,
3421 ARM::VST4LNd32Pseudo_UPD };
3422 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3423 ARM::VST4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003424 SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
3425 return;
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003426 }
3427
Bob Wilsone0636a72009-08-26 17:39:53 +00003428 case ISD::INTRINSIC_VOID:
3429 case ISD::INTRINSIC_W_CHAIN: {
3430 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003431 switch (IntNo) {
3432 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003433 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003434
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003435 case Intrinsic::arm_mrrc:
3436 case Intrinsic::arm_mrrc2: {
3437 SDLoc dl(N);
3438 SDValue Chain = N->getOperand(0);
3439 unsigned Opc;
3440
3441 if (Subtarget->isThumb())
3442 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
3443 else
3444 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
3445
3446 SmallVector<SDValue, 5> Ops;
3447 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(), dl)); /* coproc */
3448 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(), dl)); /* opc */
3449 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(4))->getZExtValue(), dl)); /* CRm */
3450
3451 // The mrrc2 instruction in ARM doesn't allow predicates, the top 4 bits of the encoded
3452 // instruction will always be '1111' but it is possible in assembly language to specify
3453 // AL as a predicate to mrrc2 but it doesn't make any difference to the encoded instruction.
3454 if (Opc != ARM::MRRC2) {
3455 Ops.push_back(getAL(CurDAG, dl));
3456 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3457 }
3458
3459 Ops.push_back(Chain);
3460
3461 // Writes to two registers.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003462 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003463
3464 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, RetType, Ops));
3465 return;
3466 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003467 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003468 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003469 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003470 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003471 SDValue MemAddr = N->getOperand(2);
Bradley Smith433c22e2016-01-15 10:26:51 +00003472 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
Tim Northover1ff5f292014-03-26 14:39:31 +00003473
3474 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3475 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3476 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003477
3478 // arm_ldrexd returns a i64 value in {i32, i32}
3479 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003480 if (isThumb) {
3481 ResTys.push_back(MVT::i32);
3482 ResTys.push_back(MVT::i32);
3483 } else
3484 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003485 ResTys.push_back(MVT::Other);
3486
Weiming Zhao8f56f882012-11-16 21:55:34 +00003487 // Place arguments in the right order.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003488 SDValue Ops[] = {MemAddr, getAL(CurDAG, dl),
3489 CurDAG->getRegister(0, MVT::i32), Chain};
Michael Liaob53d8962013-04-19 22:22:57 +00003490 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003491 // Transfer memoperands.
3492 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3493 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3494 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3495
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003496 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003497 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003498 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003499 SDValue Result;
3500 if (isThumb)
3501 Result = SDValue(Ld, 0);
3502 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003503 SDValue SubRegIdx =
3504 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003505 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003506 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003507 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003508 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003509 ReplaceUses(SDValue(N, 0), Result);
3510 }
3511 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003512 SDValue Result;
3513 if (isThumb)
3514 Result = SDValue(Ld, 1);
3515 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003516 SDValue SubRegIdx =
3517 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003518 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003519 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003520 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003521 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003522 ReplaceUses(SDValue(N, 1), Result);
3523 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003524 ReplaceUses(SDValue(N, 2), OutChain);
Justin Bognered4f3782016-05-12 00:20:19 +00003525 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003526 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003527 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003528 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003529 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003530 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003531 SDValue Chain = N->getOperand(0);
3532 SDValue Val0 = N->getOperand(2);
3533 SDValue Val1 = N->getOperand(3);
3534 SDValue MemAddr = N->getOperand(4);
3535
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003536 // Store exclusive double return a i32 value which is the return status
3537 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003538 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003539
Weiming Zhao8f56f882012-11-16 21:55:34 +00003540 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3541 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003542 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003543 if (isThumb) {
3544 Ops.push_back(Val0);
3545 Ops.push_back(Val1);
3546 } else
3547 // arm_strexd uses GPRPair.
3548 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003549 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003550 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003551 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3552 Ops.push_back(Chain);
3553
Tim Northover1ff5f292014-03-26 14:39:31 +00003554 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3555 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3556 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003557
Michael Liaob53d8962013-04-19 22:22:57 +00003558 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003559 // Transfer memoperands.
3560 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3561 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3562 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3563
Justin Bogner45571362016-05-12 00:31:09 +00003564 ReplaceNode(N, St);
3565 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003566 }
3567
Bob Wilson340861d2010-03-23 05:25:43 +00003568 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003569 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3570 ARM::VLD1d32, ARM::VLD1d64 };
3571 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3572 ARM::VLD1q32, ARM::VLD1q64};
Justin Bogner45571362016-05-12 00:31:09 +00003573 SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
3574 return;
Bob Wilson340861d2010-03-23 05:25:43 +00003575 }
3576
Bob Wilsone0636a72009-08-26 17:39:53 +00003577 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003578 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3579 ARM::VLD2d32, ARM::VLD1q64 };
3580 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3581 ARM::VLD2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003582 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3583 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003584 }
3585
3586 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003587 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3588 ARM::VLD3d16Pseudo,
3589 ARM::VLD3d32Pseudo,
3590 ARM::VLD1d64TPseudo };
3591 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3592 ARM::VLD3q16Pseudo_UPD,
3593 ARM::VLD3q32Pseudo_UPD };
3594 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3595 ARM::VLD3q16oddPseudo,
3596 ARM::VLD3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003597 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3598 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003599 }
3600
3601 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003602 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3603 ARM::VLD4d16Pseudo,
3604 ARM::VLD4d32Pseudo,
3605 ARM::VLD1d64QPseudo };
3606 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3607 ARM::VLD4q16Pseudo_UPD,
3608 ARM::VLD4q32Pseudo_UPD };
3609 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3610 ARM::VLD4q16oddPseudo,
3611 ARM::VLD4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003612 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3613 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003614 }
3615
Bob Wilsonda9817c2009-09-01 04:26:28 +00003616 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003617 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3618 ARM::VLD2LNd16Pseudo,
3619 ARM::VLD2LNd32Pseudo };
3620 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3621 ARM::VLD2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003622 SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
3623 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003624 }
3625
3626 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003627 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3628 ARM::VLD3LNd16Pseudo,
3629 ARM::VLD3LNd32Pseudo };
3630 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3631 ARM::VLD3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003632 SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
3633 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003634 }
3635
3636 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003637 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3638 ARM::VLD4LNd16Pseudo,
3639 ARM::VLD4LNd32Pseudo };
3640 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3641 ARM::VLD4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003642 SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
3643 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003644 }
3645
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003646 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003647 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3648 ARM::VST1d32, ARM::VST1d64 };
3649 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3650 ARM::VST1q32, ARM::VST1q64 };
Justin Bogner45571362016-05-12 00:31:09 +00003651 SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
3652 return;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003653 }
3654
Bob Wilsone0636a72009-08-26 17:39:53 +00003655 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003656 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3657 ARM::VST2d32, ARM::VST1q64 };
Benjamin Kramerf690da42016-06-17 14:14:29 +00003658 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3659 ARM::VST2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003660 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3661 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003662 }
3663
3664 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003665 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3666 ARM::VST3d16Pseudo,
3667 ARM::VST3d32Pseudo,
3668 ARM::VST1d64TPseudo };
3669 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3670 ARM::VST3q16Pseudo_UPD,
3671 ARM::VST3q32Pseudo_UPD };
3672 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3673 ARM::VST3q16oddPseudo,
3674 ARM::VST3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003675 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3676 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003677 }
3678
3679 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003680 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3681 ARM::VST4d16Pseudo,
3682 ARM::VST4d32Pseudo,
3683 ARM::VST1d64QPseudo };
3684 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3685 ARM::VST4q16Pseudo_UPD,
3686 ARM::VST4q32Pseudo_UPD };
3687 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3688 ARM::VST4q16oddPseudo,
3689 ARM::VST4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003690 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3691 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003692 }
Bob Wilsond7797752009-09-01 18:51:56 +00003693
3694 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003695 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3696 ARM::VST2LNd16Pseudo,
3697 ARM::VST2LNd32Pseudo };
3698 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3699 ARM::VST2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003700 SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
3701 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003702 }
3703
3704 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003705 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3706 ARM::VST3LNd16Pseudo,
3707 ARM::VST3LNd32Pseudo };
3708 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3709 ARM::VST3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003710 SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
3711 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003712 }
3713
3714 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003715 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3716 ARM::VST4LNd16Pseudo,
3717 ARM::VST4LNd32Pseudo };
3718 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3719 ARM::VST4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003720 SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
3721 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003722 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003723 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003724 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003725 }
Evan Chengd85631e2010-05-05 18:28:36 +00003726
Bob Wilson3ed511b2010-07-06 23:36:25 +00003727 case ISD::INTRINSIC_WO_CHAIN: {
3728 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3729 switch (IntNo) {
3730 default:
3731 break;
3732
3733 case Intrinsic::arm_neon_vtbl2:
Justin Bogner45571362016-05-12 00:31:09 +00003734 SelectVTBL(N, false, 2, ARM::VTBL2);
3735 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003736 case Intrinsic::arm_neon_vtbl3:
Justin Bogner45571362016-05-12 00:31:09 +00003737 SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
3738 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003739 case Intrinsic::arm_neon_vtbl4:
Justin Bogner45571362016-05-12 00:31:09 +00003740 SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
3741 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003742
3743 case Intrinsic::arm_neon_vtbx2:
Justin Bogner45571362016-05-12 00:31:09 +00003744 SelectVTBL(N, true, 2, ARM::VTBX2);
3745 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003746 case Intrinsic::arm_neon_vtbx3:
Justin Bogner45571362016-05-12 00:31:09 +00003747 SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
3748 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003749 case Intrinsic::arm_neon_vtbx4:
Justin Bogner45571362016-05-12 00:31:09 +00003750 SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
3751 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003752 }
3753 break;
3754 }
3755
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003756 case ARMISD::VTBL1: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003757 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003758 EVT VT = N->getValueType(0);
Benjamin Kramerf690da42016-06-17 14:14:29 +00003759 SDValue Ops[] = {N->getOperand(0), N->getOperand(1),
3760 getAL(CurDAG, dl), // Predicate
3761 CurDAG->getRegister(0, MVT::i32)}; // Predicate Register
Justin Bogner45571362016-05-12 00:31:09 +00003762 ReplaceNode(N, CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops));
3763 return;
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003764 }
3765 case ARMISD::VTBL2: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003766 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003767 EVT VT = N->getValueType(0);
3768
3769 // Form a REG_SEQUENCE to force register allocation.
3770 SDValue V0 = N->getOperand(0);
3771 SDValue V1 = N->getOperand(1);
Weiming Zhao95782222012-11-17 00:23:35 +00003772 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003773
Benjamin Kramerf690da42016-06-17 14:14:29 +00003774 SDValue Ops[] = {RegSeq, N->getOperand(2), getAL(CurDAG, dl), // Predicate
3775 CurDAG->getRegister(0, MVT::i32)}; // Predicate Register
Justin Bogner45571362016-05-12 00:31:09 +00003776 ReplaceNode(N, CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops));
3777 return;
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003778 }
3779
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003780 case ISD::CONCAT_VECTORS:
Justin Bogner45571362016-05-12 00:31:09 +00003781 SelectConcatVector(N);
3782 return;
Tim Northoverb629c772016-04-18 21:48:55 +00003783
3784 case ISD::ATOMIC_CMP_SWAP:
Justin Bogner45571362016-05-12 00:31:09 +00003785 SelectCMP_SWAP(N);
3786 return;
Evan Chengd85631e2010-05-05 18:28:36 +00003787 }
Evan Chengd5021732008-12-10 21:54:21 +00003788
Justin Bogner45571362016-05-12 00:31:09 +00003789 SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003790}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003791
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003792// Inspect a register string of the form
3793// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3794// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3795// and obtain the integer operands from them, adding these operands to the
3796// provided vector.
3797static void getIntOperandsFromRegisterString(StringRef RegString,
Benjamin Kramerbdc49562016-06-12 15:39:02 +00003798 SelectionDAG *CurDAG,
3799 const SDLoc &DL,
3800 std::vector<SDValue> &Ops) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003801 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003802 RegString.split(Fields, ':');
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003803
3804 if (Fields.size() > 1) {
3805 bool AllIntFields = true;
3806
3807 for (StringRef Field : Fields) {
3808 // Need to trim out leading 'cp' characters and get the integer field.
3809 unsigned IntField;
3810 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3811 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3812 }
3813
3814 assert(AllIntFields &&
3815 "Unexpected non-integer value in special register string.");
3816 }
3817}
3818
3819// Maps a Banked Register string to its mask value. The mask value returned is
3820// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3821// mask operand, which expresses which register is to be used, e.g. r8, and in
3822// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3823// was invalid.
3824static inline int getBankedRegisterMask(StringRef RegString) {
3825 return StringSwitch<int>(RegString.lower())
3826 .Case("r8_usr", 0x00)
3827 .Case("r9_usr", 0x01)
3828 .Case("r10_usr", 0x02)
3829 .Case("r11_usr", 0x03)
3830 .Case("r12_usr", 0x04)
3831 .Case("sp_usr", 0x05)
3832 .Case("lr_usr", 0x06)
3833 .Case("r8_fiq", 0x08)
3834 .Case("r9_fiq", 0x09)
3835 .Case("r10_fiq", 0x0a)
3836 .Case("r11_fiq", 0x0b)
3837 .Case("r12_fiq", 0x0c)
3838 .Case("sp_fiq", 0x0d)
3839 .Case("lr_fiq", 0x0e)
3840 .Case("lr_irq", 0x10)
3841 .Case("sp_irq", 0x11)
3842 .Case("lr_svc", 0x12)
3843 .Case("sp_svc", 0x13)
3844 .Case("lr_abt", 0x14)
3845 .Case("sp_abt", 0x15)
3846 .Case("lr_und", 0x16)
3847 .Case("sp_und", 0x17)
3848 .Case("lr_mon", 0x1c)
3849 .Case("sp_mon", 0x1d)
3850 .Case("elr_hyp", 0x1e)
3851 .Case("sp_hyp", 0x1f)
3852 .Case("spsr_fiq", 0x2e)
3853 .Case("spsr_irq", 0x30)
3854 .Case("spsr_svc", 0x32)
3855 .Case("spsr_abt", 0x34)
3856 .Case("spsr_und", 0x36)
3857 .Case("spsr_mon", 0x3c)
3858 .Case("spsr_hyp", 0x3e)
3859 .Default(-1);
3860}
3861
3862// Maps a MClass special register string to its value for use in the
3863// t2MRS_M / t2MSR_M instruction nodes as the SYSm value operand.
3864// Returns -1 to signify that the string was invalid.
3865static inline int getMClassRegisterSYSmValueMask(StringRef RegString) {
3866 return StringSwitch<int>(RegString.lower())
3867 .Case("apsr", 0x0)
3868 .Case("iapsr", 0x1)
3869 .Case("eapsr", 0x2)
3870 .Case("xpsr", 0x3)
3871 .Case("ipsr", 0x5)
3872 .Case("epsr", 0x6)
3873 .Case("iepsr", 0x7)
3874 .Case("msp", 0x8)
3875 .Case("psp", 0x9)
3876 .Case("primask", 0x10)
3877 .Case("basepri", 0x11)
3878 .Case("basepri_max", 0x12)
3879 .Case("faultmask", 0x13)
3880 .Case("control", 0x14)
Bradley Smithf277c8a2016-01-25 11:25:36 +00003881 .Case("msplim", 0x0a)
3882 .Case("psplim", 0x0b)
3883 .Case("sp", 0x18)
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003884 .Default(-1);
3885}
3886
3887// The flags here are common to those allowed for apsr in the A class cores and
3888// those allowed for the special registers in the M class cores. Returns a
3889// value representing which flags were present, -1 if invalid.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003890static inline int getMClassFlagsMask(StringRef Flags, bool hasDSP) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003891 if (Flags.empty())
Artyom Skrobovcf296442015-09-24 17:31:16 +00003892 return 0x2 | (int)hasDSP;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003893
3894 return StringSwitch<int>(Flags)
3895 .Case("g", 0x1)
3896 .Case("nzcvq", 0x2)
3897 .Case("nzcvqg", 0x3)
3898 .Default(-1);
3899}
3900
3901static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead,
3902 const ARMSubtarget *Subtarget) {
3903 // Ensure that the register (without flags) was a valid M Class special
3904 // register.
3905 int SYSmvalue = getMClassRegisterSYSmValueMask(Reg);
3906 if (SYSmvalue == -1)
3907 return -1;
3908
3909 // basepri, basepri_max and faultmask are only valid for V7m.
3910 if (!Subtarget->hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
3911 return -1;
3912
Bradley Smithf277c8a2016-01-25 11:25:36 +00003913 if (Subtarget->has8MSecExt() && Flags.lower() == "ns") {
3914 Flags = "";
3915 SYSmvalue |= 0x80;
3916 }
3917
3918 if (!Subtarget->has8MSecExt() &&
3919 (SYSmvalue == 0xa || SYSmvalue == 0xb || SYSmvalue > 0x14))
3920 return -1;
3921
3922 if (!Subtarget->hasV8MMainlineOps() &&
3923 (SYSmvalue == 0x8a || SYSmvalue == 0x8b || SYSmvalue == 0x91 ||
3924 SYSmvalue == 0x93))
3925 return -1;
3926
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003927 // If it was a read then we won't be expecting flags and so at this point
3928 // we can return the mask.
3929 if (IsRead) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00003930 if (Flags.empty())
3931 return SYSmvalue;
3932 else
3933 return -1;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003934 }
3935
3936 // We know we are now handling a write so need to get the mask for the flags.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003937 int Mask = getMClassFlagsMask(Flags, Subtarget->hasDSP());
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003938
3939 // Only apsr, iapsr, eapsr, xpsr can have flags. The other register values
3940 // shouldn't have flags present.
3941 if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.empty()))
3942 return -1;
3943
3944 // The _g and _nzcvqg versions are only valid if the DSP extension is
3945 // available.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003946 if (!Subtarget->hasDSP() && (Mask & 0x1))
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003947 return -1;
3948
3949 // The register was valid so need to put the mask in the correct place
3950 // (the flags need to be in bits 11-10) and combine with the SYSmvalue to
3951 // construct the operand for the instruction node.
3952 if (SYSmvalue < 0x4)
3953 return SYSmvalue | Mask << 10;
3954
3955 return SYSmvalue;
3956}
3957
3958static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
3959 // The mask operand contains the special register (R Bit) in bit 4, whether
3960 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
3961 // bits 3-0 contains the fields to be accessed in the special register, set by
3962 // the flags provided with the register.
3963 int Mask = 0;
3964 if (Reg == "apsr") {
3965 // The flags permitted for apsr are the same flags that are allowed in
3966 // M class registers. We get the flag value and then shift the flags into
3967 // the correct place to combine with the mask.
Artyom Skrobov6fbef2a2015-08-05 11:02:14 +00003968 Mask = getMClassFlagsMask(Flags, true);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003969 if (Mask == -1)
3970 return -1;
3971 return Mask << 2;
3972 }
3973
3974 if (Reg != "cpsr" && Reg != "spsr") {
3975 return -1;
3976 }
3977
3978 // This is the same as if the flags were "fc"
3979 if (Flags.empty() || Flags == "all")
3980 return Mask | 0x9;
3981
3982 // Inspect the supplied flags string and set the bits in the mask for
3983 // the relevant and valid flags allowed for cpsr and spsr.
3984 for (char Flag : Flags) {
3985 int FlagVal;
3986 switch (Flag) {
3987 case 'c':
3988 FlagVal = 0x1;
3989 break;
3990 case 'x':
3991 FlagVal = 0x2;
3992 break;
3993 case 's':
3994 FlagVal = 0x4;
3995 break;
3996 case 'f':
3997 FlagVal = 0x8;
3998 break;
3999 default:
4000 FlagVal = 0;
4001 }
4002
4003 // This avoids allowing strings where the same flag bit appears twice.
4004 if (!FlagVal || (Mask & FlagVal))
4005 return -1;
4006 Mask |= FlagVal;
4007 }
4008
4009 // If the register is spsr then we need to set the R bit.
4010 if (Reg == "spsr")
4011 Mask |= 0x10;
4012
4013 return Mask;
4014}
4015
4016// Lower the read_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 construct as operands for the node.
Justin Bogner45571362016-05-12 00:31:09 +00004019bool ARMDAGToDAGISel::tryReadRegister(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 MRC node (32 bit) or
4031 // MRRC node(64 bit), we can make the distinction based on the number of
4032 // operands we have.
4033 unsigned Opcode;
4034 SmallVector<EVT, 3> ResTypes;
4035 if (Ops.size() == 5){
4036 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
4037 ResTypes.append({ MVT::i32, MVT::Other });
4038 } else {
4039 assert(Ops.size() == 3 &&
4040 "Invalid number of fields in special register string.");
4041 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
4042 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
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));
Justin Bogner45571362016-05-12 00:31:09 +00004048 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops));
4049 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004050 }
4051
4052 std::string SpecialReg = RegString->getString().lower();
4053
4054 int BankedReg = getBankedRegisterMask(SpecialReg);
4055 if (BankedReg != -1) {
4056 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
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::t2MRSbanked : ARM::MRSbanked,
4061 DL, MVT::i32, MVT::Other, Ops));
4062 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004063 }
4064
4065 // The VFP registers are read by creating SelectionDAG nodes with opcodes
4066 // corresponding to the register that is being read from. So we switch on the
4067 // string to find which opcode we need to use.
4068 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
4069 .Case("fpscr", ARM::VMRS)
4070 .Case("fpexc", ARM::VMRS_FPEXC)
4071 .Case("fpsid", ARM::VMRS_FPSID)
4072 .Case("mvfr0", ARM::VMRS_MVFR0)
4073 .Case("mvfr1", ARM::VMRS_MVFR1)
4074 .Case("mvfr2", ARM::VMRS_MVFR2)
4075 .Case("fpinst", ARM::VMRS_FPINST)
4076 .Case("fpinst2", ARM::VMRS_FPINST2)
4077 .Default(0);
4078
4079 // If an opcode was found then we can lower the read to a VFP instruction.
4080 if (Opcode) {
4081 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004082 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004083 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
Justin Bogner45571362016-05-12 00:31:09 +00004084 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004085
4086 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4087 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004088 ReplaceNode(N,
4089 CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops));
4090 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004091 }
4092
4093 // If the target is M Class then need to validate that the register string
4094 // is an acceptable value, so check that a mask can be constructed from the
4095 // string.
4096 if (Subtarget->isMClass()) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00004097 StringRef Flags = "", Reg = SpecialReg;
4098 if (Reg.endswith("_ns")) {
4099 Flags = "ns";
4100 Reg = Reg.drop_back(3);
4101 }
4102
4103 int SYSmValue = getMClassRegisterMask(Reg, Flags, true, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004104 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004105 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004106
4107 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4108 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4109 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004110 ReplaceNode(
4111 N, CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops));
4112 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004113 }
4114
4115 // Here we know the target is not M Class so we need to check if it is one
4116 // of the remaining possible values which are apsr, cpsr or spsr.
4117 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
4118 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4119 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004120 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
4121 DL, MVT::i32, MVT::Other, Ops));
4122 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004123 }
4124
4125 if (SpecialReg == "spsr") {
4126 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4127 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004128 ReplaceNode(
4129 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys, DL,
4130 MVT::i32, MVT::Other, Ops));
4131 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004132 }
4133
Justin Bogner45571362016-05-12 00:31:09 +00004134 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004135}
4136
4137// Lower the write_register intrinsic to ARM specific DAG nodes
4138// using the supplied metadata string to select the instruction node to use
4139// and the registers/masks to use in the nodes
Justin Bogner45571362016-05-12 00:31:09 +00004140bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004141 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
4142 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
4143 bool IsThumb2 = Subtarget->isThumb2();
4144 SDLoc DL(N);
4145
4146 std::vector<SDValue> Ops;
4147 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
4148
4149 if (!Ops.empty()) {
4150 // If the special register string was constructed of fields (as defined
4151 // in the ACLE) then need to lower to MCR node (32 bit) or
4152 // MCRR node(64 bit), we can make the distinction based on the number of
4153 // operands we have.
4154 unsigned Opcode;
4155 if (Ops.size() == 5) {
4156 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
4157 Ops.insert(Ops.begin()+2, N->getOperand(2));
4158 } else {
4159 assert(Ops.size() == 3 &&
4160 "Invalid number of fields in special register string.");
4161 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
4162 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
4163 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
4164 }
4165
4166 Ops.push_back(getAL(CurDAG, DL));
4167 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4168 Ops.push_back(N->getOperand(0));
4169
Justin Bogner45571362016-05-12 00:31:09 +00004170 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4171 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004172 }
4173
4174 std::string SpecialReg = RegString->getString().lower();
4175 int BankedReg = getBankedRegisterMask(SpecialReg);
4176 if (BankedReg != -1) {
4177 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
4178 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4179 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004180 ReplaceNode(
4181 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
4182 DL, MVT::Other, Ops));
4183 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004184 }
4185
4186 // The VFP registers are written to by creating SelectionDAG nodes with
4187 // opcodes corresponding to the register that is being written. So we switch
4188 // on the string to find which opcode we need to use.
4189 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
4190 .Case("fpscr", ARM::VMSR)
4191 .Case("fpexc", ARM::VMSR_FPEXC)
4192 .Case("fpsid", ARM::VMSR_FPSID)
4193 .Case("fpinst", ARM::VMSR_FPINST)
4194 .Case("fpinst2", ARM::VMSR_FPINST2)
4195 .Default(0);
4196
4197 if (Opcode) {
4198 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004199 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004200 Ops = { N->getOperand(2), getAL(CurDAG, DL),
4201 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004202 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4203 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004204 }
4205
Bradley Smithf277c8a2016-01-25 11:25:36 +00004206 std::pair<StringRef, StringRef> Fields;
4207 Fields = StringRef(SpecialReg).rsplit('_');
4208 std::string Reg = Fields.first.str();
4209 StringRef Flags = Fields.second;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004210
4211 // If the target was M Class then need to validate the special register value
4212 // and retrieve the mask for use in the instruction node.
4213 if (Subtarget->isMClass()) {
4214 // basepri_max gets split so need to correct Reg and Flags.
4215 if (SpecialReg == "basepri_max") {
4216 Reg = SpecialReg;
4217 Flags = "";
4218 }
4219 int SYSmValue = getMClassRegisterMask(Reg, Flags, false, Subtarget);
4220 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004221 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004222
4223 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4224 N->getOperand(2), getAL(CurDAG, DL),
4225 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004226 ReplaceNode(N, CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops));
4227 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004228 }
4229
4230 // We then check to see if a valid mask can be constructed for one of the
4231 // register string values permitted for the A and R class cores. These values
4232 // are apsr, spsr and cpsr; these are also valid on older cores.
4233 int Mask = getARClassRegisterMask(Reg, Flags);
4234 if (Mask != -1) {
4235 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
4236 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4237 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004238 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
4239 DL, MVT::Other, Ops));
4240 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004241 }
4242
Justin Bogner45571362016-05-12 00:31:09 +00004243 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004244}
4245
Justin Bogner45571362016-05-12 00:31:09 +00004246bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){
Weiming Zhaoc5987002013-02-14 18:10:21 +00004247 std::vector<SDValue> AsmNodeOperands;
4248 unsigned Flag, Kind;
4249 bool Changed = false;
4250 unsigned NumOps = N->getNumOperands();
4251
Weiming Zhaoc5987002013-02-14 18:10:21 +00004252 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
4253 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
4254 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
4255 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004256 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
4257 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
4258 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00004259
Andrew Trickef9de2a2013-05-25 02:42:55 +00004260 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00004261 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
4262 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004263
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004264 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004265 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004266 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00004267 SDValue op = N->getOperand(i);
4268 AsmNodeOperands.push_back(op);
4269
4270 if (i < InlineAsm::Op_FirstOperand)
4271 continue;
4272
4273 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
4274 Flag = C->getZExtValue();
4275 Kind = InlineAsm::getKind(Flag);
4276 }
4277 else
4278 continue;
4279
Joey Gouly392cdad2013-07-08 19:52:51 +00004280 // Immediate operands to inline asm in the SelectionDAG are modeled with
4281 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
4282 // the second is a constant with the value of the immediate. If we get here
4283 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00004284 if (Kind == InlineAsm::Kind_Imm) {
4285 SDValue op = N->getOperand(++i);
4286 AsmNodeOperands.push_back(op);
4287 continue;
4288 }
4289
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004290 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
4291 if (NumRegs)
4292 OpChanged.push_back(false);
4293
4294 unsigned DefIdx = 0;
4295 bool IsTiedToChangedOp = false;
4296 // If it's a use that is tied with a previous def, it has no
4297 // reg class constraint.
4298 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
4299 IsTiedToChangedOp = OpChanged[DefIdx];
4300
Diana Picusf345d402016-07-20 09:48:24 +00004301 // Memory operands to inline asm in the SelectionDAG are modeled with two
4302 // operands: a constant of value InlineAsm::Kind_Mem followed by the input
4303 // operand. If we get here and we have a Kind_Mem, skip the next operand (so
4304 // it doesn't get misinterpreted), and continue. We do this here because
4305 // it's important to update the OpChanged array correctly before moving on.
4306 if (Kind == InlineAsm::Kind_Mem) {
4307 SDValue op = N->getOperand(++i);
4308 AsmNodeOperands.push_back(op);
4309 continue;
4310 }
4311
Weiming Zhaoc5987002013-02-14 18:10:21 +00004312 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
4313 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
4314 continue;
4315
Weiming Zhaoc5987002013-02-14 18:10:21 +00004316 unsigned RC;
4317 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004318 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
4319 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00004320 continue;
4321
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004322 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00004323 SDValue V0 = N->getOperand(i+1);
4324 SDValue V1 = N->getOperand(i+2);
4325 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
4326 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
4327 SDValue PairedReg;
4328 MachineRegisterInfo &MRI = MF->getRegInfo();
4329
4330 if (Kind == InlineAsm::Kind_RegDef ||
4331 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
4332 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
4333 // the original GPRs.
4334
4335 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4336 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4337 SDValue Chain = SDValue(N,0);
4338
4339 SDNode *GU = N->getGluedUser();
4340 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
4341 Chain.getValue(1));
4342
4343 // Extract values from a GPRPair reg and copy to the original GPR reg.
4344 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4345 RegCopy);
4346 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4347 RegCopy);
4348 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
4349 RegCopy.getValue(1));
4350 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
4351
4352 // Update the original glue user.
4353 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
4354 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00004355 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004356 }
4357 else {
4358 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
4359 // GPRPair and then pass the GPRPair to the inline asm.
4360 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
4361
4362 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
4363 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
4364 Chain.getValue(1));
4365 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
4366 T0.getValue(1));
4367 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
4368
4369 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
4370 // i32 VRs of inline asm with it.
4371 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4372 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4373 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
4374
4375 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
4376 Glue = Chain.getValue(1);
4377 }
4378
4379 Changed = true;
4380
4381 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004382 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004383 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00004384 if (IsTiedToChangedOp)
4385 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
4386 else
4387 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004388 // Replace the current flag.
4389 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00004390 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004391 // Add the new register node and skip the original two GPRs.
4392 AsmNodeOperands.push_back(PairedReg);
4393 // Skip the next two GPRs.
4394 i += 2;
4395 }
4396 }
4397
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004398 if (Glue.getNode())
4399 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004400 if (!Changed)
Justin Bogner45571362016-05-12 00:31:09 +00004401 return false;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004402
Andrew Trickef9de2a2013-05-25 02:42:55 +00004403 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00004404 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004405 New->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00004406 ReplaceNode(N, New.getNode());
4407 return true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004408}
4409
4410
Bob Wilsona2c462b2009-05-19 05:53:42 +00004411bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00004412SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00004413 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004414 switch(ConstraintID) {
4415 default:
4416 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00004417 case InlineAsm::Constraint_i:
4418 // FIXME: It seems strange that 'i' is needed here since it's supposed to
4419 // be an immediate and not a memory constraint.
4420 // Fallthrough.
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004421 case InlineAsm::Constraint_m:
James Molloy72222f52015-10-26 10:04:52 +00004422 case InlineAsm::Constraint_o:
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004423 case InlineAsm::Constraint_Q:
4424 case InlineAsm::Constraint_Um:
4425 case InlineAsm::Constraint_Un:
4426 case InlineAsm::Constraint_Uq:
4427 case InlineAsm::Constraint_Us:
4428 case InlineAsm::Constraint_Ut:
4429 case InlineAsm::Constraint_Uv:
4430 case InlineAsm::Constraint_Uy:
4431 // Require the address to be in a register. That is safe for all ARM
4432 // variants and it is hard to do anything much smarter without knowing
4433 // how the operand is used.
4434 OutOps.push_back(Op);
4435 return false;
4436 }
4437 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00004438}
4439
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004440/// createARMISelDag - This pass converts a legalized DAG into a
4441/// ARM-specific DAG, ready for instruction scheduling.
4442///
Bob Wilson2dd957f2009-09-28 14:30:20 +00004443FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
4444 CodeGenOpt::Level OptLevel) {
4445 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004446}