blob: 30586aa253907afbcdb7969b0f0d681555bb643a [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);
James Molloy9790d8f2016-09-14 09:45:28 +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
Weiming Zhaof68a6a72016-08-05 20:58:29 +0000479 if (Subtarget->hasV6T2Ops() &&
480 (Val <= 0xffff || ARM_AM::getT2SOImmValSplatVal(Val) != -1))
481 return 1; // MOVW
James Molloy65b6be12016-06-14 13:33:07 +0000482 if (Val <= 510) return 2; // MOV + ADDi8
John Brawn056e6782015-09-14 15:19:41 +0000483 if (~Val <= 255) return 2; // MOV + MVN
484 if (ARM_AM::isThumbImmShiftedVal(Val)) return 2; // MOV + LSL
485 } else {
486 if (ARM_AM::getSOImmVal(Val) != -1) return 1; // MOV
487 if (ARM_AM::getSOImmVal(~Val) != -1) return 1; // MVN
488 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
489 if (ARM_AM::isSOImmTwoPartVal(Val)) return 2; // two instrs
490 }
491 if (Subtarget->useMovt(*MF)) return 2; // MOVW + MOVT
492 return 3; // Literal pool load
493}
494
495bool ARMDAGToDAGISel::canExtractShiftFromMul(const SDValue &N,
496 unsigned MaxShift,
497 unsigned &PowerOfTwo,
498 SDValue &NewMulConst) const {
499 assert(N.getOpcode() == ISD::MUL);
500 assert(MaxShift > 0);
501
502 // If the multiply is used in more than one place then changing the constant
503 // will make other uses incorrect, so don't.
504 if (!N.hasOneUse()) return false;
505 // Check if the multiply is by a constant
506 ConstantSDNode *MulConst = dyn_cast<ConstantSDNode>(N.getOperand(1));
507 if (!MulConst) return false;
508 // If the constant is used in more than one place then modifying it will mean
509 // we need to materialize two constants instead of one, which is a bad idea.
510 if (!MulConst->hasOneUse()) return false;
511 unsigned MulConstVal = MulConst->getZExtValue();
512 if (MulConstVal == 0) return false;
513
514 // Find the largest power of 2 that MulConstVal is a multiple of
515 PowerOfTwo = MaxShift;
516 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
517 --PowerOfTwo;
518 if (PowerOfTwo == 0) return false;
519 }
520
521 // Only optimise if the new cost is better
522 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
523 NewMulConst = CurDAG->getConstant(NewMulConstVal, SDLoc(N), MVT::i32);
524 unsigned OldCost = ConstantMaterializationCost(MulConstVal);
525 unsigned NewCost = ConstantMaterializationCost(NewMulConstVal);
526 return NewCost < OldCost;
527}
528
529void ARMDAGToDAGISel::replaceDAGValue(const SDValue &N, SDValue M) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000530 CurDAG->RepositionNode(N.getNode()->getIterator(), M.getNode());
John Brawn056e6782015-09-14 15:19:41 +0000531 CurDAG->ReplaceAllUsesWith(N, M);
532}
533
Owen Andersonb595ed02011-07-21 18:54:16 +0000534bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000535 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000536 SDValue &Opc,
537 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000538 if (DisableShifterOp)
539 return false;
540
John Brawn056e6782015-09-14 15:19:41 +0000541 // If N is a multiply-by-constant and it's profitable to extract a shift and
542 // use it in a shifted operand do so.
543 if (N.getOpcode() == ISD::MUL) {
544 unsigned PowerOfTwo = 0;
545 SDValue NewMulConst;
546 if (canExtractShiftFromMul(N, 31, PowerOfTwo, NewMulConst)) {
Justin Bogner8752be72016-05-05 01:43:49 +0000547 HandleSDNode Handle(N);
John Brawn056e6782015-09-14 15:19:41 +0000548 replaceDAGValue(N.getOperand(1), NewMulConst);
Justin Bogner8752be72016-05-05 01:43:49 +0000549 BaseReg = Handle.getValue();
John Brawn056e6782015-09-14 15:19:41 +0000550 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ARM_AM::lsl,
551 PowerOfTwo),
552 SDLoc(N), MVT::i32);
553 return true;
554 }
555 }
556
Evan Chenga20cde32011-07-20 23:34:39 +0000557 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000558
559 // Don't match base register only case. That is matched to a separate
560 // lower complexity pattern with explicit register operand.
561 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000562
Evan Chengb23b50d2009-06-29 07:51:04 +0000563 BaseReg = N.getOperand(0);
564 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000565 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
566 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000567 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000568 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000569 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000570 return true;
571}
572
Owen Andersonb595ed02011-07-21 18:54:16 +0000573bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
574 SDValue &BaseReg,
575 SDValue &ShReg,
576 SDValue &Opc,
577 bool CheckProfitability) {
578 if (DisableShifterOp)
579 return false;
580
581 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
582
583 // Don't match base register only case. That is matched to a separate
584 // lower complexity pattern with explicit register operand.
585 if (ShOpcVal == ARM_AM::no_shift) return false;
586
587 BaseReg = N.getOperand(0);
588 unsigned ShImmVal = 0;
589 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
590 if (RHS) return false;
591
592 ShReg = N.getOperand(1);
593 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
594 return false;
595 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000596 SDLoc(N), MVT::i32);
Owen Andersonb595ed02011-07-21 18:54:16 +0000597 return true;
598}
599
600
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000601bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
602 SDValue &Base,
603 SDValue &OffImm) {
604 // Match simple R + imm12 operands.
605
606 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000607 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
608 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000609 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000610 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000611 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000612 Base = CurDAG->getTargetFrameIndex(
613 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000614 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000615 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000616 }
Owen Anderson6d557452011-03-18 19:46:58 +0000617
Chris Lattner46c01a32011-02-13 22:25:43 +0000618 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000619 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000620 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000621 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000622 Base = N.getOperand(0);
623 } else
624 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000625 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000626 return true;
627 }
628
629 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Renato Golin63e27982014-09-09 09:57:59 +0000630 int RHSC = (int)RHS->getSExtValue();
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000631 if (N.getOpcode() == ISD::SUB)
632 RHSC = -RHSC;
633
Renato Golin63e27982014-09-09 09:57:59 +0000634 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000635 Base = N.getOperand(0);
636 if (Base.getOpcode() == ISD::FrameIndex) {
637 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000638 Base = CurDAG->getTargetFrameIndex(
639 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000640 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000641 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000642 return true;
643 }
644 }
645
646 // Base only.
647 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000648 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000649 return true;
650}
651
652
653
654bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
655 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000656 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000657 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000658 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
659 // X * [3,5,9] -> X + X * [2,4,8] etc.
660 int RHSC = (int)RHS->getZExtValue();
661 if (RHSC & 1) {
662 RHSC = RHSC & ~1;
663 ARM_AM::AddrOpc AddSub = ARM_AM::add;
664 if (RHSC < 0) {
665 AddSub = ARM_AM::sub;
666 RHSC = - RHSC;
667 }
668 if (isPowerOf2_32(RHSC)) {
669 unsigned ShAmt = Log2_32(RHSC);
670 Base = Offset = N.getOperand(0);
671 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
672 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000673 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000674 return true;
675 }
676 }
677 }
678 }
679
Chris Lattner46c01a32011-02-13 22:25:43 +0000680 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
681 // ISD::OR that is equivalent to an ISD::ADD.
682 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000683 return false;
684
685 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000686 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000687 int RHSC;
688 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
689 -0x1000+1, 0x1000, RHSC)) // 12 bits.
690 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000691 }
692
693 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000694 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000695 ARM_AM::ShiftOpc ShOpcVal =
696 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000697 unsigned ShAmt = 0;
698
699 Base = N.getOperand(0);
700 Offset = N.getOperand(1);
701
702 if (ShOpcVal != ARM_AM::no_shift) {
703 // Check to see if the RHS of the shift is a constant, if not, we can't fold
704 // it.
705 if (ConstantSDNode *Sh =
706 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
707 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000708 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
709 Offset = N.getOperand(1).getOperand(0);
710 else {
711 ShAmt = 0;
712 ShOpcVal = ARM_AM::no_shift;
713 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000714 } else {
715 ShOpcVal = ARM_AM::no_shift;
716 }
717 }
718
719 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000720 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000721 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
722 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000723 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000724 if (ShOpcVal != ARM_AM::no_shift) {
725 // Check to see if the RHS of the shift is a constant, if not, we can't
726 // fold it.
727 if (ConstantSDNode *Sh =
728 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
729 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000730 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000731 Offset = N.getOperand(0).getOperand(0);
732 Base = N.getOperand(1);
733 } else {
734 ShAmt = 0;
735 ShOpcVal = ARM_AM::no_shift;
736 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000737 } else {
738 ShOpcVal = ARM_AM::no_shift;
739 }
740 }
741 }
742
John Brawn056e6782015-09-14 15:19:41 +0000743 // If Offset is a multiply-by-constant and it's profitable to extract a shift
744 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +0000745 if (Offset.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +0000746 unsigned PowerOfTwo = 0;
747 SDValue NewMulConst;
748 if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) {
749 replaceDAGValue(Offset.getOperand(1), NewMulConst);
750 ShAmt = PowerOfTwo;
751 ShOpcVal = ARM_AM::lsl;
752 }
753 }
754
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000755 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000756 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000757 return true;
758}
759
760
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000761//-----
762
Jim Grosbach08605202010-09-29 19:03:54 +0000763AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
764 SDValue &Base,
765 SDValue &Offset,
766 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000767 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000768 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000769 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
770 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmaneffb8942008-09-12 16:56:44 +0000771 int RHSC = (int)RHS->getZExtValue();
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000772 if (RHSC & 1) {
773 RHSC = RHSC & ~1;
774 ARM_AM::AddrOpc AddSub = ARM_AM::add;
775 if (RHSC < 0) {
776 AddSub = ARM_AM::sub;
777 RHSC = - RHSC;
778 }
779 if (isPowerOf2_32(RHSC)) {
780 unsigned ShAmt = Log2_32(RHSC);
781 Base = Offset = N.getOperand(0);
782 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
783 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000784 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000785 return AM2_SHOP;
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000786 }
787 }
788 }
789 }
790
Chris Lattner46c01a32011-02-13 22:25:43 +0000791 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
792 // ISD::OR that is equivalent to an ADD.
793 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000794 Base = N;
795 if (N.getOpcode() == ISD::FrameIndex) {
796 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000797 Base = CurDAG->getTargetFrameIndex(
798 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +0000799 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000800 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000801 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000802 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000803 Base = N.getOperand(0);
804 }
Owen Anderson9f944592009-08-11 20:47:22 +0000805 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000806 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
807 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000808 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000809 return AM2_BASE;
Rafael Espindola708cb602006-11-08 17:07:32 +0000810 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000811
Evan Cheng10043e22007-01-19 07:51:42 +0000812 // Match simple R +/- imm12 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +0000813 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000814 int RHSC;
815 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
816 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
817 Base = N.getOperand(0);
818 if (Base.getOpcode() == ISD::FrameIndex) {
819 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000820 Base = CurDAG->getTargetFrameIndex(
821 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Rafael Espindola708cb602006-11-08 17:07:32 +0000822 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000823 Offset = CurDAG->getRegister(0, MVT::i32);
824
825 ARM_AM::AddrOpc AddSub = ARM_AM::add;
826 if (RHSC < 0) {
827 AddSub = ARM_AM::sub;
828 RHSC = - RHSC;
829 }
830 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
831 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000832 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000833 return AM2_BASE;
Evan Cheng10043e22007-01-19 07:51:42 +0000834 }
Jim Grosbachc7b10f32010-09-29 17:32:29 +0000835 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000836
Bob Wilsone8a549c2012-09-29 21:43:49 +0000837 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000838 // Compute R +/- (R << N) and reuse it.
839 Base = N;
840 Offset = CurDAG->getRegister(0, MVT::i32);
841 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
842 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000843 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000844 return AM2_BASE;
845 }
846
Johnny Chenb678a562009-10-27 17:25:15 +0000847 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000848 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chenga20cde32011-07-20 23:34:39 +0000849 ARM_AM::ShiftOpc ShOpcVal =
850 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000851 unsigned ShAmt = 0;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000852
Evan Cheng10043e22007-01-19 07:51:42 +0000853 Base = N.getOperand(0);
854 Offset = N.getOperand(1);
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000855
Evan Cheng10043e22007-01-19 07:51:42 +0000856 if (ShOpcVal != ARM_AM::no_shift) {
857 // Check to see if the RHS of the shift is a constant, if not, we can't fold
858 // it.
859 if (ConstantSDNode *Sh =
860 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000861 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000862 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
863 Offset = N.getOperand(1).getOperand(0);
864 else {
865 ShAmt = 0;
866 ShOpcVal = ARM_AM::no_shift;
867 }
Evan Cheng10043e22007-01-19 07:51:42 +0000868 } else {
869 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola708cb602006-11-08 17:07:32 +0000870 }
871 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000872
Evan Cheng10043e22007-01-19 07:51:42 +0000873 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000874 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000875 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
876 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000877 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000878 if (ShOpcVal != ARM_AM::no_shift) {
879 // Check to see if the RHS of the shift is a constant, if not, we can't
880 // fold it.
881 if (ConstantSDNode *Sh =
882 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000883 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000884 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000885 Offset = N.getOperand(0).getOperand(0);
886 Base = N.getOperand(1);
887 } else {
888 ShAmt = 0;
889 ShOpcVal = ARM_AM::no_shift;
890 }
Evan Cheng10043e22007-01-19 07:51:42 +0000891 } else {
892 ShOpcVal = ARM_AM::no_shift;
893 }
894 }
895 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000896
Evan Cheng10043e22007-01-19 07:51:42 +0000897 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000898 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000899 return AM2_SHOP;
Rafael Espindola708cb602006-11-08 17:07:32 +0000900}
901
Owen Anderson2aedba62011-07-26 20:54:26 +0000902bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000903 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000904 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000905 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
906 ? cast<LoadSDNode>(Op)->getAddressingMode()
907 : cast<StoreSDNode>(Op)->getAddressingMode();
908 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
909 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000910 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000911 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
912 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000913
914 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000915 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000916 unsigned ShAmt = 0;
917 if (ShOpcVal != ARM_AM::no_shift) {
918 // Check to see if the RHS of the shift is a constant, if not, we can't fold
919 // it.
920 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000921 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000922 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
923 Offset = N.getOperand(0);
924 else {
925 ShAmt = 0;
926 ShOpcVal = ARM_AM::no_shift;
927 }
Evan Cheng10043e22007-01-19 07:51:42 +0000928 } else {
929 ShOpcVal = ARM_AM::no_shift;
930 }
931 }
932
933 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000934 SDLoc(N), MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000935 return true;
936}
937
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000938bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
939 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000940 unsigned Opcode = Op->getOpcode();
941 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
942 ? cast<LoadSDNode>(Op)->getAddressingMode()
943 : cast<StoreSDNode>(Op)->getAddressingMode();
944 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
945 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000946 int Val;
947 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000948 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000949 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000950 Opc = CurDAG->getTargetConstant(Val, SDLoc(Op), MVT::i32);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000951 return true;
952 }
953
954 return false;
955}
956
957
Owen Anderson2aedba62011-07-26 20:54:26 +0000958bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
959 SDValue &Offset, SDValue &Opc) {
960 unsigned Opcode = Op->getOpcode();
961 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
962 ? cast<LoadSDNode>(Op)->getAddressingMode()
963 : cast<StoreSDNode>(Op)->getAddressingMode();
964 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
965 ? ARM_AM::add : ARM_AM::sub;
966 int Val;
967 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
968 Offset = CurDAG->getRegister(0, MVT::i32);
969 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
970 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000971 SDLoc(Op), MVT::i32);
Owen Anderson2aedba62011-07-26 20:54:26 +0000972 return true;
973 }
974
975 return false;
976}
977
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000978bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
979 Base = N;
980 return true;
981}
Evan Cheng10043e22007-01-19 07:51:42 +0000982
Chris Lattner0e023ea2010-09-21 20:31:19 +0000983bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000984 SDValue &Base, SDValue &Offset,
985 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000986 if (N.getOpcode() == ISD::SUB) {
987 // X - C is canonicalize to X + -C, no need to handle it here.
988 Base = N.getOperand(0);
989 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000990 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0), SDLoc(N),
991 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000992 return true;
993 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000994
Chris Lattner46c01a32011-02-13 22:25:43 +0000995 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000996 Base = N;
997 if (N.getOpcode() == ISD::FrameIndex) {
998 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000999 Base = CurDAG->getTargetFrameIndex(
1000 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001001 }
Owen Anderson9f944592009-08-11 20:47:22 +00001002 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001003 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1004 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001005 return true;
1006 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001007
Evan Cheng10043e22007-01-19 07:51:42 +00001008 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001009 int RHSC;
1010 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
1011 -256 + 1, 256, RHSC)) { // 8 bits.
1012 Base = N.getOperand(0);
1013 if (Base.getOpcode() == ISD::FrameIndex) {
1014 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001015 Base = CurDAG->getTargetFrameIndex(
1016 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001017 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001018 Offset = CurDAG->getRegister(0, MVT::i32);
1019
1020 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1021 if (RHSC < 0) {
1022 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001023 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001024 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001025 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC), SDLoc(N),
1026 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001027 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001028 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001029
Evan Cheng10043e22007-01-19 07:51:42 +00001030 Base = N.getOperand(0);
1031 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001032 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1033 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001034 return true;
1035}
1036
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001037bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001038 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001039 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +00001040 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1041 ? cast<LoadSDNode>(Op)->getAddressingMode()
1042 : cast<StoreSDNode>(Op)->getAddressingMode();
1043 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
1044 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001045 int Val;
1046 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
1047 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001048 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), SDLoc(Op),
1049 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001050 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001051 }
1052
1053 Offset = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001054 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), SDLoc(Op),
1055 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001056 return true;
1057}
1058
Jim Grosbachd37f0712010-10-21 19:38:40 +00001059bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001060 SDValue &Base, SDValue &Offset) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001061 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +00001062 Base = N;
1063 if (N.getOpcode() == ISD::FrameIndex) {
1064 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001065 Base = CurDAG->getTargetFrameIndex(
1066 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +00001067 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001068 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001069 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001070 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +00001071 Base = N.getOperand(0);
1072 }
1073 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001074 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001075 return true;
1076 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001077
Evan Cheng10043e22007-01-19 07:51:42 +00001078 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001079 int RHSC;
1080 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
1081 -256 + 1, 256, RHSC)) {
1082 Base = N.getOperand(0);
1083 if (Base.getOpcode() == ISD::FrameIndex) {
1084 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001085 Base = CurDAG->getTargetFrameIndex(
1086 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001087 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001088
1089 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1090 if (RHSC < 0) {
1091 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001092 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001093 }
1094 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001095 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001096 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001097 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001098
Evan Cheng10043e22007-01-19 07:51:42 +00001099 Base = N;
1100 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001101 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001102 return true;
1103}
1104
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001105bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
1106 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +00001107 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001108
1109 unsigned Alignment = 0;
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001110
1111 MemSDNode *MemN = cast<MemSDNode>(Parent);
1112
1113 if (isa<LSBaseSDNode>(MemN) ||
1114 ((MemN->getOpcode() == ARMISD::VST1_UPD ||
1115 MemN->getOpcode() == ARMISD::VLD1_UPD) &&
1116 MemN->getConstantOperandVal(MemN->getNumOperands() - 1) == 1)) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001117 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
1118 // The maximum alignment is equal to the memory size being referenced.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001119 unsigned MMOAlign = MemN->getAlignment();
1120 unsigned MemSize = MemN->getMemoryVT().getSizeInBits() / 8;
1121 if (MMOAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001122 Alignment = MemSize;
1123 } else {
1124 // All other uses of addrmode6 are for intrinsics. For now just record
1125 // the raw alignment value; it will be refined later based on the legal
1126 // alignment operands for the intrinsic.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001127 Alignment = MemN->getAlignment();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001128 }
1129
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001130 Align = CurDAG->getTargetConstant(Alignment, SDLoc(N), MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001131 return true;
1132}
1133
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001134bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1135 SDValue &Offset) {
1136 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1137 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1138 if (AM != ISD::POST_INC)
1139 return false;
1140 Offset = N;
1141 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1142 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1143 Offset = CurDAG->getRegister(0, MVT::i32);
1144 }
1145 return true;
1146}
1147
Chris Lattner0e023ea2010-09-21 20:31:19 +00001148bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001149 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001150 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1151 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001152 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001153 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001154 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001155 return true;
1156 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001157
Evan Cheng10043e22007-01-19 07:51:42 +00001158 return false;
1159}
1160
Bill Wendling092a7bd2010-12-14 03:36:38 +00001161
1162//===----------------------------------------------------------------------===//
1163// Thumb Addressing Modes
1164//===----------------------------------------------------------------------===//
1165
Chris Lattner0e023ea2010-09-21 20:31:19 +00001166bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001167 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001168 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001169 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001170 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001171 return false;
1172
1173 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001174 return true;
1175 }
1176
Evan Cheng10043e22007-01-19 07:51:42 +00001177 Base = N.getOperand(0);
1178 Offset = N.getOperand(1);
1179 return true;
1180}
1181
Evan Cheng139edae2007-01-24 02:21:22 +00001182bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001183ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1184 SDValue &Base, SDValue &OffImm) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001185 if (!CurDAG->isBaseWithConstantOffset(N)) {
John Brawn68acdcb2015-08-13 10:48:22 +00001186 if (N.getOpcode() == ISD::ADD) {
1187 return false; // We want to select register offset instead
1188 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001189 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001190 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001191 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001192 Base = N.getOperand(0);
1193 } else {
1194 Base = N;
1195 }
1196
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001197 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001198 return true;
1199 }
1200
Evan Cheng10043e22007-01-19 07:51:42 +00001201 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001202 int RHSC;
1203 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1204 Base = N.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001205 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001206 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001207 }
1208
John Brawn68acdcb2015-08-13 10:48:22 +00001209 // Offset is too large, so use register offset instead.
1210 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001211}
1212
Bill Wendling092a7bd2010-12-14 03:36:38 +00001213bool
1214ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1215 SDValue &OffImm) {
1216 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001217}
1218
Bill Wendling092a7bd2010-12-14 03:36:38 +00001219bool
1220ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1221 SDValue &OffImm) {
1222 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001223}
1224
Bill Wendling092a7bd2010-12-14 03:36:38 +00001225bool
1226ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1227 SDValue &OffImm) {
1228 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001229}
1230
Chris Lattner0e023ea2010-09-21 20:31:19 +00001231bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1232 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001233 if (N.getOpcode() == ISD::FrameIndex) {
1234 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001235 // Only multiples of 4 are allowed for the offset, so the frame object
1236 // alignment must be at least 4.
Matthias Braun941a7052016-07-28 18:40:00 +00001237 MachineFrameInfo &MFI = MF->getFrameInfo();
1238 if (MFI.getObjectAlignment(FI) < 4)
1239 MFI.setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001240 Base = CurDAG->getTargetFrameIndex(
1241 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001242 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001243 return true;
1244 }
Evan Cheng139edae2007-01-24 02:21:22 +00001245
Chris Lattner46c01a32011-02-13 22:25:43 +00001246 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001247 return false;
1248
1249 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001250 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1251 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001252 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001253 int RHSC;
1254 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1255 Base = N.getOperand(0);
1256 if (Base.getOpcode() == ISD::FrameIndex) {
1257 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001258 // For LHS+RHS to result in an offset that's a multiple of 4 the object
1259 // indexed by the LHS must be 4-byte aligned.
Matthias Braun941a7052016-07-28 18:40:00 +00001260 MachineFrameInfo &MFI = MF->getFrameInfo();
1261 if (MFI.getObjectAlignment(FI) < 4)
1262 MFI.setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001263 Base = CurDAG->getTargetFrameIndex(
1264 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng139edae2007-01-24 02:21:22 +00001265 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001266 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001267 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001268 }
1269 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001270
Evan Cheng10043e22007-01-19 07:51:42 +00001271 return false;
1272}
1273
Bill Wendling092a7bd2010-12-14 03:36:38 +00001274
1275//===----------------------------------------------------------------------===//
1276// Thumb 2 Addressing Modes
1277//===----------------------------------------------------------------------===//
1278
1279
Chris Lattner0e023ea2010-09-21 20:31:19 +00001280bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001281 SDValue &Base, SDValue &OffImm) {
1282 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001283
Evan Cheng36064672009-08-11 08:52:18 +00001284 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001285 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1286 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001287 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001288 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001289 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001290 Base = CurDAG->getTargetFrameIndex(
1291 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001292 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001293 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001294 }
Owen Anderson6d557452011-03-18 19:46:58 +00001295
Chris Lattner46c01a32011-02-13 22:25:43 +00001296 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001297 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001298 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001299 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng36064672009-08-11 08:52:18 +00001300 Base = N.getOperand(0);
1301 if (Base.getOpcode() == ISD::TargetConstantPool)
1302 return false; // We want to select t2LDRpci instead.
1303 } else
1304 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001305 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001306 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001307 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001308
1309 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001310 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001311 // Let t2LDRi8 handle (R - imm8).
1312 return false;
1313
Evan Chengb23b50d2009-06-29 07:51:04 +00001314 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001315 if (N.getOpcode() == ISD::SUB)
1316 RHSC = -RHSC;
1317
1318 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001319 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001320 if (Base.getOpcode() == ISD::FrameIndex) {
1321 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001322 Base = CurDAG->getTargetFrameIndex(
1323 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin79c079b2009-07-30 18:56:48 +00001324 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001325 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001326 return true;
1327 }
1328 }
1329
Evan Cheng36064672009-08-11 08:52:18 +00001330 // Base only.
1331 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001332 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001333 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001334}
1335
Chris Lattner0e023ea2010-09-21 20:31:19 +00001336bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001337 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001338 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001339 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1340 !CurDAG->isBaseWithConstantOffset(N))
1341 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001342
Chris Lattner46c01a32011-02-13 22:25:43 +00001343 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1344 int RHSC = (int)RHS->getSExtValue();
1345 if (N.getOpcode() == ISD::SUB)
1346 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001347
Chris Lattner46c01a32011-02-13 22:25:43 +00001348 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1349 Base = N.getOperand(0);
1350 if (Base.getOpcode() == ISD::FrameIndex) {
1351 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001352 Base = CurDAG->getTargetFrameIndex(
1353 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Chengb23b50d2009-06-29 07:51:04 +00001354 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001355 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Chris Lattner46c01a32011-02-13 22:25:43 +00001356 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001357 }
1358 }
1359
1360 return false;
1361}
1362
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001363bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001364 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001365 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001366 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1367 ? cast<LoadSDNode>(Op)->getAddressingMode()
1368 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001369 int RHSC;
1370 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1371 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001372 ? CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32)
1373 : CurDAG->getTargetConstant(-RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001374 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001375 }
1376
1377 return false;
1378}
1379
Chris Lattner0e023ea2010-09-21 20:31:19 +00001380bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001381 SDValue &Base,
1382 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001383 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001384 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001385 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001386
Evan Cheng36064672009-08-11 08:52:18 +00001387 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1388 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1389 int RHSC = (int)RHS->getZExtValue();
1390 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1391 return false;
1392 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001393 return false;
1394 }
1395
Evan Chengb23b50d2009-06-29 07:51:04 +00001396 // Look for (R + R) or (R + (R << [1,2,3])).
1397 unsigned ShAmt = 0;
1398 Base = N.getOperand(0);
1399 OffReg = N.getOperand(1);
1400
1401 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001402 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001403 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001404 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001405 if (ShOpcVal == ARM_AM::lsl)
1406 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001407 }
1408
Evan Chengb23b50d2009-06-29 07:51:04 +00001409 if (ShOpcVal == ARM_AM::lsl) {
1410 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1411 // it.
1412 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1413 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001414 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1415 OffReg = OffReg.getOperand(0);
1416 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001417 ShAmt = 0;
Evan Cheng59bbc542010-10-27 23:41:30 +00001418 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001419 }
David Goodwinf3912052009-07-15 15:50:19 +00001420 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001421
John Brawn056e6782015-09-14 15:19:41 +00001422 // If OffReg is a multiply-by-constant and it's profitable to extract a shift
1423 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +00001424 if (OffReg.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +00001425 unsigned PowerOfTwo = 0;
1426 SDValue NewMulConst;
1427 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
1428 replaceDAGValue(OffReg.getOperand(1), NewMulConst);
1429 ShAmt = PowerOfTwo;
1430 }
1431 }
1432
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001433 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001434
1435 return true;
1436}
1437
Tim Northovera7ecd242013-07-16 09:46:55 +00001438bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1439 SDValue &OffImm) {
Alp Tokercb402912014-01-24 17:20:08 +00001440 // This *must* succeed since it's used for the irreplaceable ldrex and strex
Tim Northovera7ecd242013-07-16 09:46:55 +00001441 // instructions.
1442 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001443 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001444
1445 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1446 return true;
1447
1448 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1449 if (!RHS)
1450 return true;
1451
1452 uint32_t RHSC = (int)RHS->getZExtValue();
1453 if (RHSC > 1020 || RHSC % 4 != 0)
1454 return true;
1455
1456 Base = N.getOperand(0);
1457 if (Base.getOpcode() == ISD::FrameIndex) {
1458 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001459 Base = CurDAG->getTargetFrameIndex(
1460 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Tim Northovera7ecd242013-07-16 09:46:55 +00001461 }
1462
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001463 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001464 return true;
1465}
1466
Evan Chengb23b50d2009-06-29 07:51:04 +00001467//===--------------------------------------------------------------------===//
1468
Evan Cheng7e90b112007-07-05 07:15:27 +00001469/// getAL - Returns a ARMCC::AL immediate node.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001470static inline SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001471 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001472}
1473
Justin Bogner45571362016-05-12 00:31:09 +00001474bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001475 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001476 ISD::MemIndexedMode AM = LD->getAddressingMode();
1477 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001478 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001479
Owen Anderson53aa7a92009-08-10 22:56:29 +00001480 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001481 SDValue Offset, AMOpc;
1482 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1483 unsigned Opcode = 0;
1484 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001485 if (LoadedVT == MVT::i32 && isPre &&
1486 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1487 Opcode = ARM::LDR_PRE_IMM;
1488 Match = true;
1489 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001490 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001491 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001492 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001493 } else if (LoadedVT == MVT::i32 &&
1494 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001495 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001496 Match = true;
1497
Owen Anderson9f944592009-08-11 20:47:22 +00001498 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001499 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001500 Match = true;
1501 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1502 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1503 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001504 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001505 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001506 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001507 Match = true;
1508 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1509 }
1510 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001511 if (isPre &&
1512 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001513 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001514 Opcode = ARM::LDRB_PRE_IMM;
1515 } else if (!isPre &&
1516 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1517 Match = true;
1518 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001519 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1520 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001521 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001522 }
1523 }
1524 }
1525
1526 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001527 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1528 SDValue Chain = LD->getChain();
1529 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001530 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001531 CurDAG->getRegister(0, MVT::i32), Chain };
Justin Bogner45571362016-05-12 00:31:09 +00001532 ReplaceNode(N, CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
1533 MVT::i32, MVT::Other, Ops));
1534 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001535 } else {
1536 SDValue Chain = LD->getChain();
1537 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001538 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001539 CurDAG->getRegister(0, MVT::i32), Chain };
Justin Bogner45571362016-05-12 00:31:09 +00001540 ReplaceNode(N, CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
1541 MVT::i32, MVT::Other, Ops));
1542 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001543 }
Evan Chengd9c55362009-07-02 01:23:32 +00001544 }
1545
Justin Bogner45571362016-05-12 00:31:09 +00001546 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001547}
1548
James Molloyb3326df2016-07-15 08:03:56 +00001549bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *N) {
1550 LoadSDNode *LD = cast<LoadSDNode>(N);
1551 EVT LoadedVT = LD->getMemoryVT();
1552 ISD::MemIndexedMode AM = LD->getAddressingMode();
1553 if (AM == ISD::UNINDEXED || LD->getExtensionType() != ISD::NON_EXTLOAD ||
1554 AM != ISD::POST_INC || LoadedVT.getSimpleVT().SimpleTy != MVT::i32)
1555 return false;
1556
1557 auto *COffs = dyn_cast<ConstantSDNode>(LD->getOffset());
1558 if (!COffs || COffs->getZExtValue() != 4)
1559 return false;
1560
1561 // A T1 post-indexed load is just a single register LDM: LDM r0!, {r1}.
1562 // The encoding of LDM is not how the rest of ISel expects a post-inc load to
1563 // look however, so we use a pseudo here and switch it for a tLDMIA_UPD after
1564 // ISel.
1565 SDValue Chain = LD->getChain();
1566 SDValue Base = LD->getBasePtr();
1567 SDValue Ops[]= { Base, getAL(CurDAG, SDLoc(N)),
1568 CurDAG->getRegister(0, MVT::i32), Chain };
1569 ReplaceNode(N, CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(N), MVT::i32, MVT::i32,
1570 MVT::Other, Ops));
1571 return true;
1572}
1573
Justin Bogner45571362016-05-12 00:31:09 +00001574bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001575 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001576 ISD::MemIndexedMode AM = LD->getAddressingMode();
1577 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001578 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001579
Owen Anderson53aa7a92009-08-10 22:56:29 +00001580 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001581 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001582 SDValue Offset;
1583 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1584 unsigned Opcode = 0;
1585 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001586 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001587 switch (LoadedVT.getSimpleVT().SimpleTy) {
1588 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001589 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1590 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001591 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001592 if (isSExtLd)
1593 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1594 else
1595 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001596 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001597 case MVT::i8:
1598 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001599 if (isSExtLd)
1600 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1601 else
1602 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001603 break;
1604 default:
Justin Bogner45571362016-05-12 00:31:09 +00001605 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001606 }
1607 Match = true;
1608 }
1609
1610 if (Match) {
1611 SDValue Chain = LD->getChain();
1612 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001613 SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)),
Owen Anderson9f944592009-08-11 20:47:22 +00001614 CurDAG->getRegister(0, MVT::i32), Chain };
Justin Bogner45571362016-05-12 00:31:09 +00001615 ReplaceNode(N, CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1616 MVT::Other, Ops));
1617 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001618 }
1619
Justin Bogner45571362016-05-12 00:31:09 +00001620 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001621}
1622
Weiming Zhao8f56f882012-11-16 21:55:34 +00001623/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1624SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001625 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001626 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001627 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1628 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1629 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001630 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001631 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001632}
1633
Weiming Zhao95782222012-11-17 00:23:35 +00001634/// \brief Form a D register from a pair of S registers.
1635SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001636 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001637 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001638 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1639 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1640 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001641 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001642 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001643}
1644
Weiming Zhao95782222012-11-17 00:23:35 +00001645/// \brief Form a quad register from a pair of D registers.
1646SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001647 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001648 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1649 MVT::i32);
1650 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1651 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001652 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001653 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001654}
1655
Weiming Zhao95782222012-11-17 00:23:35 +00001656/// \brief Form 4 consecutive D registers from a pair of Q registers.
1657SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001658 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001659 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1660 MVT::i32);
1661 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1662 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001663 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001664 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001665}
1666
Weiming Zhao95782222012-11-17 00:23:35 +00001667/// \brief Form 4 consecutive S registers.
1668SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001669 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001670 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001671 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001672 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1673 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1674 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1675 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1676 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001677 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1678 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001679 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001680}
1681
Weiming Zhao95782222012-11-17 00:23:35 +00001682/// \brief Form 4 consecutive D registers.
1683SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001684 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001685 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001686 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1687 MVT::i32);
1688 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1689 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1690 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1691 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001692 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1693 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001694 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001695}
1696
Weiming Zhao95782222012-11-17 00:23:35 +00001697/// \brief Form 4 consecutive Q registers.
1698SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001699 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001700 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001701 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1702 MVT::i32);
1703 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1704 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1705 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1706 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001707 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1708 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001709 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001710}
1711
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001712/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1713/// of a NEON VLD or VST instruction. The supported values depend on the
1714/// number of registers being loaded.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001715SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, const SDLoc &dl,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001716 unsigned NumVecs, bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001717 unsigned NumRegs = NumVecs;
1718 if (!is64BitVector && NumVecs < 3)
1719 NumRegs *= 2;
1720
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001721 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001722 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001723 Alignment = 32;
1724 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1725 Alignment = 16;
1726 else if (Alignment >= 8)
1727 Alignment = 8;
1728 else
1729 Alignment = 0;
1730
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001731 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001732}
1733
Jiangning Liu4df23632014-01-16 09:16:13 +00001734static bool isVLDfixed(unsigned Opc)
1735{
1736 switch (Opc) {
1737 default: return false;
1738 case ARM::VLD1d8wb_fixed : return true;
1739 case ARM::VLD1d16wb_fixed : return true;
1740 case ARM::VLD1d64Qwb_fixed : return true;
1741 case ARM::VLD1d32wb_fixed : return true;
1742 case ARM::VLD1d64wb_fixed : return true;
1743 case ARM::VLD1d64TPseudoWB_fixed : return true;
1744 case ARM::VLD1d64QPseudoWB_fixed : return true;
1745 case ARM::VLD1q8wb_fixed : return true;
1746 case ARM::VLD1q16wb_fixed : return true;
1747 case ARM::VLD1q32wb_fixed : return true;
1748 case ARM::VLD1q64wb_fixed : return true;
1749 case ARM::VLD2d8wb_fixed : return true;
1750 case ARM::VLD2d16wb_fixed : return true;
1751 case ARM::VLD2d32wb_fixed : return true;
1752 case ARM::VLD2q8PseudoWB_fixed : return true;
1753 case ARM::VLD2q16PseudoWB_fixed : return true;
1754 case ARM::VLD2q32PseudoWB_fixed : return true;
1755 case ARM::VLD2DUPd8wb_fixed : return true;
1756 case ARM::VLD2DUPd16wb_fixed : return true;
1757 case ARM::VLD2DUPd32wb_fixed : return true;
1758 }
1759}
1760
1761static bool isVSTfixed(unsigned Opc)
1762{
1763 switch (Opc) {
1764 default: return false;
1765 case ARM::VST1d8wb_fixed : return true;
1766 case ARM::VST1d16wb_fixed : return true;
1767 case ARM::VST1d32wb_fixed : return true;
1768 case ARM::VST1d64wb_fixed : return true;
Jim Grosbach1a597112014-04-03 23:43:18 +00001769 case ARM::VST1q8wb_fixed : return true;
1770 case ARM::VST1q16wb_fixed : return true;
1771 case ARM::VST1q32wb_fixed : return true;
1772 case ARM::VST1q64wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001773 case ARM::VST1d64TPseudoWB_fixed : return true;
1774 case ARM::VST1d64QPseudoWB_fixed : return true;
1775 case ARM::VST2d8wb_fixed : return true;
1776 case ARM::VST2d16wb_fixed : return true;
1777 case ARM::VST2d32wb_fixed : return true;
1778 case ARM::VST2q8PseudoWB_fixed : return true;
1779 case ARM::VST2q16PseudoWB_fixed : return true;
1780 case ARM::VST2q32PseudoWB_fixed : return true;
1781 }
1782}
1783
Jim Grosbach2098cb12011-10-24 21:45:13 +00001784// Get the register stride update opcode of a VLD/VST instruction that
1785// is otherwise equivalent to the given fixed stride updating instruction.
1786static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
Jiangning Liu4df23632014-01-16 09:16:13 +00001787 assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1788 && "Incorrect fixed stride updating instruction.");
Jim Grosbach2098cb12011-10-24 21:45:13 +00001789 switch (Opc) {
1790 default: break;
1791 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1792 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1793 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1794 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1795 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1796 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1797 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1798 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jiangning Liu4df23632014-01-16 09:16:13 +00001799 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1800 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1801 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1802 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001803
1804 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1805 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1806 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1807 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1808 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1809 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1810 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1811 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001812 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001813 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001814
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001815 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1816 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1817 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001818 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1819 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1820 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1821
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001822 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1823 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1824 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001825 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1826 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1827 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001828
Jim Grosbach13a292c2012-03-06 22:01:44 +00001829 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1830 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1831 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001832 }
1833 return Opc; // If not one we handle, return it unchanged.
1834}
1835
Justin Bogner45571362016-05-12 00:31:09 +00001836void ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
1837 const uint16_t *DOpcodes,
1838 const uint16_t *QOpcodes0,
1839 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001840 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001841 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001842
Bob Wilsonae08a732010-03-20 22:13:40 +00001843 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001844 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1845 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001846 return;
Bob Wilson12b47992009-10-14 17:28:52 +00001847
1848 SDValue Chain = N->getOperand(0);
1849 EVT VT = N->getValueType(0);
1850 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001851 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001852
Bob Wilson12b47992009-10-14 17:28:52 +00001853 unsigned OpcodeIndex;
1854 switch (VT.getSimpleVT().SimpleTy) {
1855 default: llvm_unreachable("unhandled vld type");
1856 // Double-register operations:
1857 case MVT::v8i8: OpcodeIndex = 0; break;
1858 case MVT::v4i16: OpcodeIndex = 1; break;
1859 case MVT::v2f32:
1860 case MVT::v2i32: OpcodeIndex = 2; break;
1861 case MVT::v1i64: OpcodeIndex = 3; break;
1862 // Quad-register operations:
1863 case MVT::v16i8: OpcodeIndex = 0; break;
1864 case MVT::v8i16: OpcodeIndex = 1; break;
1865 case MVT::v4f32:
1866 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001867 case MVT::v2f64:
Bob Wilson340861d2010-03-23 05:25:43 +00001868 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001869 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson340861d2010-03-23 05:25:43 +00001870 break;
Bob Wilson12b47992009-10-14 17:28:52 +00001871 }
1872
Bob Wilson35fafca2010-09-03 18:16:02 +00001873 EVT ResTy;
1874 if (NumVecs == 1)
1875 ResTy = VT;
1876 else {
1877 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1878 if (!is64BitVector)
1879 ResTyElts *= 2;
1880 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1881 }
Bob Wilson06fce872011-02-07 17:43:21 +00001882 std::vector<EVT> ResTys;
1883 ResTys.push_back(ResTy);
1884 if (isUpdating)
1885 ResTys.push_back(MVT::i32);
1886 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001887
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001888 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001889 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001890 SDNode *VLd;
1891 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001892
Bob Wilson06fce872011-02-07 17:43:21 +00001893 // Double registers and VLD1/VLD2 quad registers are directly supported.
1894 if (is64BitVector || NumVecs <= 2) {
1895 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1896 QOpcodes0[OpcodeIndex]);
1897 Ops.push_back(MemAddr);
1898 Ops.push_back(Align);
1899 if (isUpdating) {
1900 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachd146a022011-12-09 21:28:25 +00001901 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach2098cb12011-10-24 21:45:13 +00001902 // case entirely when the rest are updated to that form, too.
Jiangning Liu4df23632014-01-16 09:16:13 +00001903 if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001904 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001905 // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001906 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00001907 if ((NumVecs > 2 && !isVLDfixed(Opc)) ||
Jim Grosbach05df4602011-10-31 21:50:31 +00001908 !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001909 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Evan Cheng630063a2010-05-10 21:26:24 +00001910 }
Bob Wilson06fce872011-02-07 17:43:21 +00001911 Ops.push_back(Pred);
1912 Ops.push_back(Reg0);
1913 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001914 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001915
Bob Wilson12b47992009-10-14 17:28:52 +00001916 } else {
1917 // Otherwise, quad registers are loaded with two separate instructions,
1918 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001919 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001920
Bob Wilson06fce872011-02-07 17:43:21 +00001921 // Load the even subregs. This is always an updating load, so that it
1922 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001923 SDValue ImplDef =
1924 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1925 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001926 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001927 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001928 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001929
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001930 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001931 Ops.push_back(SDValue(VLdA, 1));
1932 Ops.push_back(Align);
1933 if (isUpdating) {
1934 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1935 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1936 "only constant post-increment update allowed for VLD3/4");
1937 (void)Inc;
1938 Ops.push_back(Reg0);
1939 }
1940 Ops.push_back(SDValue(VLdA, 0));
1941 Ops.push_back(Pred);
1942 Ops.push_back(Reg0);
1943 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001944 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001945 }
Bob Wilson12b47992009-10-14 17:28:52 +00001946
Evan Cheng40791332011-04-19 00:04:03 +00001947 // Transfer memoperands.
1948 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1949 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1950 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1951
Justin Bogner45571362016-05-12 00:31:09 +00001952 if (NumVecs == 1) {
1953 ReplaceNode(N, VLd);
1954 return;
1955 }
Bob Wilson06fce872011-02-07 17:43:21 +00001956
1957 // Extract out the subregisters.
1958 SDValue SuperReg = SDValue(VLd, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00001959 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
1960 ARM::qsub_3 == ARM::qsub_0 + 3,
1961 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00001962 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1963 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1964 ReplaceUses(SDValue(N, Vec),
1965 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1966 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1967 if (isUpdating)
1968 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00001969 CurDAG->RemoveDeadNode(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001970}
1971
Justin Bogner45571362016-05-12 00:31:09 +00001972void ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
1973 const uint16_t *DOpcodes,
1974 const uint16_t *QOpcodes0,
1975 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001976 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001977 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001978
Bob Wilsonae08a732010-03-20 22:13:40 +00001979 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001980 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1981 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1982 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001983 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001984
Evan Cheng40791332011-04-19 00:04:03 +00001985 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1986 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1987
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001988 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00001989 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001990 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001991 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001992
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001993 unsigned OpcodeIndex;
1994 switch (VT.getSimpleVT().SimpleTy) {
1995 default: llvm_unreachable("unhandled vst type");
1996 // Double-register operations:
1997 case MVT::v8i8: OpcodeIndex = 0; break;
1998 case MVT::v4i16: OpcodeIndex = 1; break;
1999 case MVT::v2f32:
2000 case MVT::v2i32: OpcodeIndex = 2; break;
2001 case MVT::v1i64: OpcodeIndex = 3; break;
2002 // Quad-register operations:
2003 case MVT::v16i8: OpcodeIndex = 0; break;
2004 case MVT::v8i16: OpcodeIndex = 1; break;
2005 case MVT::v4f32:
2006 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00002007 case MVT::v2f64:
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00002008 case MVT::v2i64: OpcodeIndex = 3;
2009 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
2010 break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002011 }
2012
Bob Wilson06fce872011-02-07 17:43:21 +00002013 std::vector<EVT> ResTys;
2014 if (isUpdating)
2015 ResTys.push_back(MVT::i32);
2016 ResTys.push_back(MVT::Other);
2017
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002018 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002019 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00002020 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00002021
Bob Wilson06fce872011-02-07 17:43:21 +00002022 // Double registers and VST1/VST2 quad registers are directly supported.
2023 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00002024 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00002025 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00002026 SrcReg = N->getOperand(Vec0Idx);
2027 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00002028 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00002029 SDValue V0 = N->getOperand(Vec0Idx + 0);
2030 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00002031 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002032 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002033 else {
Bob Wilson06fce872011-02-07 17:43:21 +00002034 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00002035 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00002036 // an undef.
2037 SDValue V3 = (NumVecs == 3)
2038 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002039 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002040 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002041 }
Bob Wilson950882b2010-08-28 05:12:57 +00002042 } else {
2043 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00002044 SDValue Q0 = N->getOperand(Vec0Idx);
2045 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00002046 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002047 }
Bob Wilson06fce872011-02-07 17:43:21 +00002048
2049 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2050 QOpcodes0[OpcodeIndex]);
2051 Ops.push_back(MemAddr);
2052 Ops.push_back(Align);
2053 if (isUpdating) {
2054 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbach88ac7612011-12-14 21:32:11 +00002055 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach05df4602011-10-31 21:50:31 +00002056 // case entirely when the rest are updated to that form, too.
Jim Grosbach88ac7612011-12-14 21:32:11 +00002057 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach05df4602011-10-31 21:50:31 +00002058 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00002059 // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00002060 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00002061 if (!isa<ConstantSDNode>(Inc.getNode()))
2062 Ops.push_back(Inc);
2063 else if (NumVecs > 2 && !isVSTfixed(Opc))
2064 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002065 }
2066 Ops.push_back(SrcReg);
2067 Ops.push_back(Pred);
2068 Ops.push_back(Reg0);
2069 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00002070 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002071
2072 // Transfer memoperands.
2073 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
2074
Justin Bogner45571362016-05-12 00:31:09 +00002075 ReplaceNode(N, VSt);
2076 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002077 }
2078
2079 // Otherwise, quad registers are stored with two separate instructions,
2080 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00002081
Bob Wilson01ac8f92010-06-16 21:34:01 +00002082 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00002083 SDValue V0 = N->getOperand(Vec0Idx + 0);
2084 SDValue V1 = N->getOperand(Vec0Idx + 1);
2085 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00002086 SDValue V3 = (NumVecs == 3)
2087 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002088 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002089 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002090
Bob Wilson06fce872011-02-07 17:43:21 +00002091 // Store the even D registers. This is always an updating store, so that it
2092 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00002093 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2094 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2095 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00002096 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00002097 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002098 Chain = SDValue(VStA, 1);
2099
2100 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00002101 Ops.push_back(SDValue(VStA, 0));
2102 Ops.push_back(Align);
2103 if (isUpdating) {
2104 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2105 assert(isa<ConstantSDNode>(Inc.getNode()) &&
2106 "only constant post-increment update allowed for VST3/4");
2107 (void)Inc;
2108 Ops.push_back(Reg0);
2109 }
2110 Ops.push_back(RegSeq);
2111 Ops.push_back(Pred);
2112 Ops.push_back(Reg0);
2113 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00002114 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00002115 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002116 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002117 ReplaceNode(N, VStB);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002118}
2119
Justin Bogner45571362016-05-12 00:31:09 +00002120void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
2121 unsigned NumVecs,
2122 const uint16_t *DOpcodes,
2123 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002124 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002125 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002126
Bob Wilsonae08a732010-03-20 22:13:40 +00002127 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00002128 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2129 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2130 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002131 return;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002132
Evan Cheng40791332011-04-19 00:04:03 +00002133 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2134 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2135
Bob Wilson4145e3a2009-10-14 16:19:03 +00002136 SDValue Chain = N->getOperand(0);
2137 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002138 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2139 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002140 bool is64BitVector = VT.is64BitVector();
2141
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002142 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002143 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002144 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002145 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2146 if (Alignment > NumBytes)
2147 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002148 if (Alignment < 8 && Alignment < NumBytes)
2149 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002150 // Alignment must be a power of two; make sure of that.
2151 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002152 if (Alignment == 1)
2153 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002154 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002155 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002156
Bob Wilson4145e3a2009-10-14 16:19:03 +00002157 unsigned OpcodeIndex;
2158 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002159 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002160 // Double-register operations:
2161 case MVT::v8i8: OpcodeIndex = 0; break;
2162 case MVT::v4i16: OpcodeIndex = 1; break;
2163 case MVT::v2f32:
2164 case MVT::v2i32: OpcodeIndex = 2; break;
2165 // Quad-register operations:
2166 case MVT::v8i16: OpcodeIndex = 0; break;
2167 case MVT::v4f32:
2168 case MVT::v4i32: OpcodeIndex = 1; break;
2169 }
2170
Bob Wilson06fce872011-02-07 17:43:21 +00002171 std::vector<EVT> ResTys;
2172 if (IsLoad) {
2173 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2174 if (!is64BitVector)
2175 ResTyElts *= 2;
2176 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2177 MVT::i64, ResTyElts));
2178 }
2179 if (isUpdating)
2180 ResTys.push_back(MVT::i32);
2181 ResTys.push_back(MVT::Other);
2182
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002183 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002184 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002185
Bob Wilson06fce872011-02-07 17:43:21 +00002186 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002187 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002188 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002189 if (isUpdating) {
2190 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2191 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
2192 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002193
Bob Wilsond5c57a52010-09-13 23:01:35 +00002194 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002195 SDValue V0 = N->getOperand(Vec0Idx + 0);
2196 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002197 if (NumVecs == 2) {
2198 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002199 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002200 else
Weiming Zhao95782222012-11-17 00:23:35 +00002201 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002202 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002203 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002204 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002205 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2206 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002207 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002208 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002209 else
Weiming Zhao95782222012-11-17 00:23:35 +00002210 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002211 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002212 Ops.push_back(SuperReg);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002213 Ops.push_back(getI32Imm(Lane, dl));
Evan Chenga33fc862009-11-21 06:21:52 +00002214 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002215 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002216 Ops.push_back(Chain);
2217
Bob Wilson06fce872011-02-07 17:43:21 +00002218 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2219 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002220 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002221 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002222 if (!IsLoad) {
2223 ReplaceNode(N, VLdLn);
2224 return;
2225 }
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002226
Bob Wilsond5c57a52010-09-13 23:01:35 +00002227 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002228 SuperReg = SDValue(VLdLn, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00002229 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2230 ARM::qsub_3 == ARM::qsub_0 + 3,
2231 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00002232 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002233 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2234 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002235 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2236 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2237 if (isUpdating)
2238 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002239 CurDAG->RemoveDeadNode(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002240}
2241
Justin Bogner45571362016-05-12 00:31:09 +00002242void ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
2243 const uint16_t *Opcodes) {
Bob Wilson2d790df2010-11-28 06:51:26 +00002244 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002245 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002246
2247 SDValue MemAddr, Align;
2248 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002249 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00002250
Evan Cheng40791332011-04-19 00:04:03 +00002251 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2252 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2253
Bob Wilson2d790df2010-11-28 06:51:26 +00002254 SDValue Chain = N->getOperand(0);
2255 EVT VT = N->getValueType(0);
2256
2257 unsigned Alignment = 0;
2258 if (NumVecs != 3) {
2259 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2260 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2261 if (Alignment > NumBytes)
2262 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002263 if (Alignment < 8 && Alignment < NumBytes)
2264 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002265 // Alignment must be a power of two; make sure of that.
2266 Alignment = (Alignment & -Alignment);
2267 if (Alignment == 1)
2268 Alignment = 0;
2269 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002270 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson2d790df2010-11-28 06:51:26 +00002271
2272 unsigned OpcodeIndex;
2273 switch (VT.getSimpleVT().SimpleTy) {
2274 default: llvm_unreachable("unhandled vld-dup type");
2275 case MVT::v8i8: OpcodeIndex = 0; break;
2276 case MVT::v4i16: OpcodeIndex = 1; break;
2277 case MVT::v2f32:
2278 case MVT::v2i32: OpcodeIndex = 2; break;
2279 }
2280
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002281 SDValue Pred = getAL(CurDAG, dl);
Bob Wilson2d790df2010-11-28 06:51:26 +00002282 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2283 SDValue SuperReg;
2284 unsigned Opc = Opcodes[OpcodeIndex];
Bob Wilson06fce872011-02-07 17:43:21 +00002285 SmallVector<SDValue, 6> Ops;
2286 Ops.push_back(MemAddr);
2287 Ops.push_back(Align);
2288 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002289 // fixed-stride update instructions don't have an explicit writeback
2290 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002291 SDValue Inc = N->getOperand(2);
Jim Grosbachc80a2642011-12-21 19:40:55 +00002292 if (!isa<ConstantSDNode>(Inc.getNode()))
2293 Ops.push_back(Inc);
2294 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2295 else if (NumVecs > 2)
2296 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002297 }
2298 Ops.push_back(Pred);
2299 Ops.push_back(Reg0);
2300 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002301
2302 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002303 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002304 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002305 if (isUpdating)
2306 ResTys.push_back(MVT::i32);
2307 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002308 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002309 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002310 SuperReg = SDValue(VLdDup, 0);
Bob Wilson2d790df2010-11-28 06:51:26 +00002311
2312 // Extract the subregisters.
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00002313 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7, "Unexpected subreg numbering");
Bob Wilson2d790df2010-11-28 06:51:26 +00002314 unsigned SubIdx = ARM::dsub_0;
2315 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2316 ReplaceUses(SDValue(N, Vec),
2317 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Bob Wilson06fce872011-02-07 17:43:21 +00002318 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2319 if (isUpdating)
2320 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002321 CurDAG->RemoveDeadNode(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002322}
2323
Justin Bogner45571362016-05-12 00:31:09 +00002324void ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2325 unsigned Opc) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00002326 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002327 SDLoc dl(N);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002328 EVT VT = N->getValueType(0);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002329 unsigned FirstTblReg = IsExt ? 2 : 1;
Bob Wilson3ed511b2010-07-06 23:36:25 +00002330
2331 // Form a REG_SEQUENCE to force register allocation.
2332 SDValue RegSeq;
Bob Wilson5bc8a792010-07-07 00:08:54 +00002333 SDValue V0 = N->getOperand(FirstTblReg + 0);
2334 SDValue V1 = N->getOperand(FirstTblReg + 1);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002335 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002336 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002337 else {
Bob Wilson5bc8a792010-07-07 00:08:54 +00002338 SDValue V2 = N->getOperand(FirstTblReg + 2);
Jim Grosbachd37f0712010-10-21 19:38:40 +00002339 // If it's a vtbl3, form a quad D-register and leave the last part as
Bob Wilson3ed511b2010-07-06 23:36:25 +00002340 // an undef.
2341 SDValue V3 = (NumVecs == 3)
2342 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson5bc8a792010-07-07 00:08:54 +00002343 : N->getOperand(FirstTblReg + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002344 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002345 }
2346
Bob Wilson5bc8a792010-07-07 00:08:54 +00002347 SmallVector<SDValue, 6> Ops;
2348 if (IsExt)
2349 Ops.push_back(N->getOperand(1));
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00002350 Ops.push_back(RegSeq);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002351 Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002352 Ops.push_back(getAL(CurDAG, dl)); // predicate
Bob Wilson3ed511b2010-07-06 23:36:25 +00002353 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
Justin Bogner45571362016-05-12 00:31:09 +00002354 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
Bob Wilson3ed511b2010-07-06 23:36:25 +00002355}
2356
Justin Bogner45571362016-05-12 00:31:09 +00002357bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002358 if (!Subtarget->hasV6T2Ops())
Justin Bogner45571362016-05-12 00:31:09 +00002359 return false;
Bob Wilson93117bc2009-10-14 16:46:45 +00002360
Evan Chengeae6d2c2012-12-19 20:16:09 +00002361 unsigned Opc = isSigned
2362 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002363 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002364 SDLoc dl(N);
Jim Grosbach825cb292010-04-22 23:24:18 +00002365
Jim Grosbach825cb292010-04-22 23:24:18 +00002366 // For unsigned extracts, check for a shift right and mask
2367 unsigned And_imm = 0;
2368 if (N->getOpcode() == ISD::AND) {
2369 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2370
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002371 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002372 if (And_imm & (And_imm + 1))
Justin Bogner45571362016-05-12 00:31:09 +00002373 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002374
2375 unsigned Srl_imm = 0;
2376 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2377 Srl_imm)) {
2378 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2379
Jim Grosbach03f56d92011-07-27 21:09:25 +00002380 // Note: The width operand is encoded as width-1.
Benjamin Kramer5f6a9072015-02-12 15:35:40 +00002381 unsigned Width = countTrailingOnes(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002382 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002383
Jim Grosbach825cb292010-04-22 23:24:18 +00002384 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002385
2386 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2387 // It's cheaper to use a right shift to extract the top bits.
2388 if (Subtarget->isThumb()) {
2389 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2390 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002391 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2392 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002393 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2394 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002395 }
2396
2397 // ARM models shift instructions as MOVsi with shifter operand.
2398 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2399 SDValue ShOpc =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002400 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), dl,
Evan Chengeae6d2c2012-12-19 20:16:09 +00002401 MVT::i32);
2402 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002403 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002404 CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops);
2405 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002406 }
2407
Jim Grosbach825cb292010-04-22 23:24:18 +00002408 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002409 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2410 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2411 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002412 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2413 return true;
Jim Grosbach825cb292010-04-22 23:24:18 +00002414 }
2415 }
Justin Bogner45571362016-05-12 00:31:09 +00002416 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002417 }
2418
2419 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002420 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002421 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002422 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2423 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002424 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002425 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002426 // Note: The width operand is encoded as width-1.
2427 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002428 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002429 if (LSB < 0)
Justin Bogner45571362016-05-12 00:31:09 +00002430 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002431 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002432 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002433 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2434 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2435 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002436 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2437 return true;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002438 }
2439 }
Tim Northover14ff2df2014-07-23 13:59:12 +00002440
Oliver Stannard92ca83c2016-06-01 12:01:01 +00002441 // Or we are looking for a shift of an and, with a mask operand
2442 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, And_imm) &&
2443 isShiftedMask_32(And_imm)) {
2444 unsigned Srl_imm = 0;
2445 unsigned LSB = countTrailingZeros(And_imm);
2446 // Shift must be the same as the ands lsb
2447 if (isInt32Immediate(N->getOperand(1), Srl_imm) && Srl_imm == LSB) {
2448 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2449 unsigned MSB = 31 - countLeadingZeros(And_imm);
2450 // Note: The width operand is encoded as width-1.
2451 unsigned Width = MSB - LSB;
2452 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2453 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2454 CurDAG->getTargetConstant(Srl_imm, dl, MVT::i32),
2455 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2456 getAL(CurDAG, dl), Reg0 };
2457 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2458 return true;
2459 }
2460 }
2461
Tim Northover14ff2df2014-07-23 13:59:12 +00002462 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
2463 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2464 unsigned LSB = 0;
2465 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) &&
2466 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB))
Justin Bogner45571362016-05-12 00:31:09 +00002467 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002468
2469 if (LSB + Width > 32)
Justin Bogner45571362016-05-12 00:31:09 +00002470 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002471
2472 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2473 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002474 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2475 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
2476 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002477 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2478 return true;
Tim Northover14ff2df2014-07-23 13:59:12 +00002479 }
2480
Justin Bogner45571362016-05-12 00:31:09 +00002481 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002482}
2483
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002484/// Target-specific DAG combining for ISD::XOR.
2485/// Target-independent combining lowers SELECT_CC nodes of the form
2486/// select_cc setg[ge] X, 0, X, -X
2487/// select_cc setgt X, -1, X, -X
2488/// select_cc setl[te] X, 0, -X, X
2489/// select_cc setlt X, 1, -X, X
2490/// which represent Integer ABS into:
2491/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2492/// ARM instruction selection detects the latter and matches it to
2493/// ARM::ABS or ARM::t2ABS machine node.
Justin Bogner45571362016-05-12 00:31:09 +00002494bool ARMDAGToDAGISel::tryABSOp(SDNode *N){
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002495 SDValue XORSrc0 = N->getOperand(0);
2496 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002497 EVT VT = N->getValueType(0);
2498
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002499 if (Subtarget->isThumb1Only())
Justin Bogner45571362016-05-12 00:31:09 +00002500 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002501
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002502 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Justin Bogner45571362016-05-12 00:31:09 +00002503 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002504
2505 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2506 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2507 SDValue SRASrc0 = XORSrc1.getOperand(0);
2508 SDValue SRASrc1 = XORSrc1.getOperand(1);
2509 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2510 EVT XType = SRASrc0.getValueType();
2511 unsigned Size = XType.getSizeInBits() - 1;
2512
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002513 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
Craig Topper062a2ba2014-04-25 05:30:21 +00002514 XType.isInteger() && SRAConstant != nullptr &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002515 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002516 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Justin Bogner45571362016-05-12 00:31:09 +00002517 CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2518 return true;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002519 }
2520
Justin Bogner45571362016-05-12 00:31:09 +00002521 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002522}
2523
Sam Parker2d5126c2016-04-08 16:02:53 +00002524static bool SearchSignedMulShort(SDValue SignExt, unsigned *Opc, SDValue &Src1,
2525 bool Accumulate) {
2526 // For SM*WB, we need to some form of sext.
2527 // For SM*WT, we need to search for (sra X, 16)
2528 // Src1 then gets set to X.
2529 if ((SignExt.getOpcode() == ISD::SIGN_EXTEND ||
2530 SignExt.getOpcode() == ISD::SIGN_EXTEND_INREG ||
2531 SignExt.getOpcode() == ISD::AssertSext) &&
2532 SignExt.getValueType() == MVT::i32) {
2533
2534 *Opc = Accumulate ? ARM::SMLAWB : ARM::SMULWB;
2535 Src1 = SignExt.getOperand(0);
2536 return true;
2537 }
2538
2539 if (SignExt.getOpcode() != ISD::SRA)
2540 return false;
2541
2542 ConstantSDNode *SRASrc1 = dyn_cast<ConstantSDNode>(SignExt.getOperand(1));
2543 if (!SRASrc1 || SRASrc1->getZExtValue() != 16)
2544 return false;
2545
2546 SDValue Op0 = SignExt.getOperand(0);
2547
2548 // The sign extend operand for SM*WB could be generated by a shl and ashr.
2549 if (Op0.getOpcode() == ISD::SHL) {
2550 SDValue SHL = Op0;
2551 ConstantSDNode *SHLSrc1 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
2552 if (!SHLSrc1 || SHLSrc1->getZExtValue() != 16)
2553 return false;
2554
2555 *Opc = Accumulate ? ARM::SMLAWB : ARM::SMULWB;
2556 Src1 = Op0.getOperand(0);
2557 return true;
2558 }
2559 *Opc = Accumulate ? ARM::SMLAWT : ARM::SMULWT;
2560 Src1 = SignExt.getOperand(0);
2561 return true;
2562}
2563
2564static bool SearchSignedMulLong(SDValue OR, unsigned *Opc, SDValue &Src0,
2565 SDValue &Src1, bool Accumulate) {
2566 // First we look for:
2567 // (add (or (srl ?, 16), (shl ?, 16)))
2568 if (OR.getOpcode() != ISD::OR)
2569 return false;
2570
2571 SDValue SRL = OR.getOperand(0);
2572 SDValue SHL = OR.getOperand(1);
2573
2574 if (SRL.getOpcode() != ISD::SRL || SHL.getOpcode() != ISD::SHL) {
2575 SRL = OR.getOperand(1);
2576 SHL = OR.getOperand(0);
2577 if (SRL.getOpcode() != ISD::SRL || SHL.getOpcode() != ISD::SHL)
2578 return false;
2579 }
2580
2581 ConstantSDNode *SRLSrc1 = dyn_cast<ConstantSDNode>(SRL.getOperand(1));
2582 ConstantSDNode *SHLSrc1 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
2583 if (!SRLSrc1 || !SHLSrc1 || SRLSrc1->getZExtValue() != 16 ||
2584 SHLSrc1->getZExtValue() != 16)
2585 return false;
2586
2587 // The first operands to the shifts need to be the two results from the
2588 // same smul_lohi node.
2589 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
2590 SRL.getOperand(0).getOpcode() != ISD::SMUL_LOHI)
2591 return false;
2592
2593 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
2594 if (SRL.getOperand(0) != SDValue(SMULLOHI, 0) ||
2595 SHL.getOperand(0) != SDValue(SMULLOHI, 1))
2596 return false;
2597
2598 // Now we have:
2599 // (add (or (srl (smul_lohi ?, ?), 16), (shl (smul_lohi ?, ?), 16)))
2600 // For SMLAW[B|T] smul_lohi will take a 32-bit and a 16-bit arguments.
2601 // For SMLAWB the 16-bit value will signed extended somehow.
2602 // For SMLAWT only the SRA is required.
2603
2604 // Check both sides of SMUL_LOHI
2605 if (SearchSignedMulShort(SMULLOHI->getOperand(0), Opc, Src1, Accumulate)) {
2606 Src0 = SMULLOHI->getOperand(1);
2607 } else if (SearchSignedMulShort(SMULLOHI->getOperand(1), Opc, Src1,
2608 Accumulate)) {
2609 Src0 = SMULLOHI->getOperand(0);
2610 } else {
2611 return false;
2612 }
2613 return true;
2614}
2615
Justin Bogner45571362016-05-12 00:31:09 +00002616bool ARMDAGToDAGISel::trySMLAWSMULW(SDNode *N) {
Sam Parkerd5ca0a62016-07-25 10:11:00 +00002617 if (!Subtarget->hasV6Ops() ||
2618 (Subtarget->isThumb() && !Subtarget->hasThumb2()))
2619 return false;
2620
Sam Parker2d5126c2016-04-08 16:02:53 +00002621 SDLoc dl(N);
2622 SDValue Src0 = N->getOperand(0);
2623 SDValue Src1 = N->getOperand(1);
2624 SDValue A, B;
2625 unsigned Opc = 0;
2626
2627 if (N->getOpcode() == ISD::ADD) {
2628 if (Src0.getOpcode() != ISD::OR && Src1.getOpcode() != ISD::OR)
Justin Bogner45571362016-05-12 00:31:09 +00002629 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002630
2631 SDValue Acc;
2632 if (SearchSignedMulLong(Src0, &Opc, A, B, true)) {
2633 Acc = Src1;
2634 } else if (SearchSignedMulLong(Src1, &Opc, A, B, true)) {
2635 Acc = Src0;
2636 } else {
Justin Bogner45571362016-05-12 00:31:09 +00002637 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002638 }
2639 if (Opc == 0)
Justin Bogner45571362016-05-12 00:31:09 +00002640 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002641
2642 SDValue Ops[] = { A, B, Acc, getAL(CurDAG, dl),
2643 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002644 CurDAG->SelectNodeTo(N, Opc, MVT::i32, MVT::Other, Ops);
2645 return true;
Sam Parker2d5126c2016-04-08 16:02:53 +00002646 } else if (N->getOpcode() == ISD::OR &&
2647 SearchSignedMulLong(SDValue(N, 0), &Opc, A, B, false)) {
2648 if (Opc == 0)
Justin Bogner45571362016-05-12 00:31:09 +00002649 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002650
2651 SDValue Ops[] = { A, B, getAL(CurDAG, dl),
2652 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002653 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2654 return true;
Sam Parker2d5126c2016-04-08 16:02:53 +00002655 }
Justin Bogner45571362016-05-12 00:31:09 +00002656 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002657}
2658
Tim Northoverb629c772016-04-18 21:48:55 +00002659/// We've got special pseudo-instructions for these
Justin Bogner45571362016-05-12 00:31:09 +00002660void ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *N) {
Tim Northoverb629c772016-04-18 21:48:55 +00002661 unsigned Opcode;
2662 EVT MemTy = cast<MemSDNode>(N)->getMemoryVT();
2663 if (MemTy == MVT::i8)
2664 Opcode = ARM::CMP_SWAP_8;
2665 else if (MemTy == MVT::i16)
2666 Opcode = ARM::CMP_SWAP_16;
2667 else if (MemTy == MVT::i32)
2668 Opcode = ARM::CMP_SWAP_32;
2669 else
2670 llvm_unreachable("Unknown AtomicCmpSwap type");
2671
2672 SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3),
2673 N->getOperand(0)};
2674 SDNode *CmpSwap = CurDAG->getMachineNode(
2675 Opcode, SDLoc(N),
2676 CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other), Ops);
2677
2678 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2679 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
2680 cast<MachineSDNode>(CmpSwap)->setMemRefs(MemOp, MemOp + 1);
2681
2682 ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0));
2683 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002684 CurDAG->RemoveDeadNode(N);
Tim Northoverb629c772016-04-18 21:48:55 +00002685}
2686
Justin Bogner45571362016-05-12 00:31:09 +00002687void ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
Evan Chengd85631e2010-05-05 18:28:36 +00002688 // The only time a CONCAT_VECTORS operation can have legal types is when
2689 // two 64-bit vectors are concatenated to a 128-bit vector.
2690 EVT VT = N->getValueType(0);
2691 if (!VT.is128BitVector() || N->getNumOperands() != 2)
2692 llvm_unreachable("unexpected CONCAT_VECTORS");
Justin Bogner45571362016-05-12 00:31:09 +00002693 ReplaceNode(N, createDRegPairNode(VT, N->getOperand(0), N->getOperand(1)));
Evan Chengd85631e2010-05-05 18:28:36 +00002694}
2695
Justin Bogner45571362016-05-12 00:31:09 +00002696void ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002697 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002698
Tim Northover31d093c2013-09-22 08:21:56 +00002699 if (N->isMachineOpcode()) {
2700 N->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00002701 return; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00002702 }
Rafael Espindola4e760152006-06-12 12:28:08 +00002703
2704 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002705 default: break;
Sam Parker2d5126c2016-04-08 16:02:53 +00002706 case ISD::ADD:
Justin Bogner45571362016-05-12 00:31:09 +00002707 case ISD::OR:
2708 if (trySMLAWSMULW(N))
2709 return;
Sam Parker2d5126c2016-04-08 16:02:53 +00002710 break;
Justin Bogner45571362016-05-12 00:31:09 +00002711 case ISD::WRITE_REGISTER:
2712 if (tryWriteRegister(N))
2713 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002714 break;
Justin Bogner45571362016-05-12 00:31:09 +00002715 case ISD::READ_REGISTER:
2716 if (tryReadRegister(N))
2717 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002718 break;
Justin Bogner45571362016-05-12 00:31:09 +00002719 case ISD::INLINEASM:
2720 if (tryInlineAsm(N))
2721 return;
Weiming Zhaoc5987002013-02-14 18:10:21 +00002722 break;
Justin Bogner45571362016-05-12 00:31:09 +00002723 case ISD::XOR:
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002724 // Select special operations if XOR node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +00002725 if (tryABSOp(N))
2726 return;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002727 // Other cases are autogenerated.
2728 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002729 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002730 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
John Brawn056e6782015-09-14 15:19:41 +00002731 // If we can't materialize the constant we need to use a literal pool
2732 if (ConstantMaterializationCost(Val) > 2) {
Eric Christopherb17140d2014-10-08 07:32:17 +00002733 SDValue CPIdx = CurDAG->getTargetConstantPool(
2734 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
Mehdi Amini44ede332015-07-09 02:09:04 +00002735 TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng1526ba52007-01-24 08:53:17 +00002736
2737 SDNode *ResNode;
Tim Northover55c625f2014-01-23 13:43:47 +00002738 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002739 SDValue Pred = getAL(CurDAG, dl);
Owen Anderson9f944592009-08-11 20:47:22 +00002740 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002741 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002742 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002743 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002744 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002745 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002746 CPIdx,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002747 CurDAG->getTargetConstant(0, dl, MVT::i32),
2748 getAL(CurDAG, dl),
Owen Anderson9f944592009-08-11 20:47:22 +00002749 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002750 CurDAG->getEntryNode()
2751 };
Justin Bogner45571362016-05-12 00:31:09 +00002752 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
2753 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002754 }
Justin Bognered4f3782016-05-12 00:20:19 +00002755 ReplaceNode(N, ResNode);
Justin Bogner45571362016-05-12 00:31:09 +00002756 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002757 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002758
Evan Cheng10043e22007-01-19 07:51:42 +00002759 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002760 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002761 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002762 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002763 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002764 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00002765 SDValue TFI = CurDAG->getTargetFrameIndex(
2766 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin22c2fba2009-07-08 23:10:31 +00002767 if (Subtarget->isThumb1Only()) {
Renato Golinb9887ef2015-02-25 14:41:06 +00002768 // Set the alignment of the frame object to 4, to avoid having to generate
2769 // more than one ADD
Matthias Braun941a7052016-07-28 18:40:00 +00002770 MachineFrameInfo &MFI = MF->getFrameInfo();
2771 if (MFI.getObjectAlignment(FI) < 4)
2772 MFI.setObjectAlignment(FI, 4);
Justin Bogner45571362016-05-12 00:31:09 +00002773 CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
2774 CurDAG->getTargetConstant(0, dl, MVT::i32));
2775 return;
Jim Grosbachfde21102009-04-07 20:34:09 +00002776 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002777 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2778 ARM::t2ADDri : ARM::ADDri);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002779 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
2780 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002781 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002782 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2783 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00002784 }
Evan Cheng10043e22007-01-19 07:51:42 +00002785 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002786 case ISD::SRL:
Justin Bogner45571362016-05-12 00:31:09 +00002787 if (tryV6T2BitfieldExtractOp(N, false))
2788 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002789 break;
Tim Northover14ff2df2014-07-23 13:59:12 +00002790 case ISD::SIGN_EXTEND_INREG:
Sandeep Patel423e42b2009-10-13 18:59:48 +00002791 case ISD::SRA:
Justin Bogner45571362016-05-12 00:31:09 +00002792 if (tryV6T2BitfieldExtractOp(N, true))
2793 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002794 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002795 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002796 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002797 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002798 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002799 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002800 if (!RHSV) break;
2801 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002802 unsigned ShImm = Log2_32(RHSV-1);
2803 if (ShImm >= 32)
2804 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002805 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002806 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002807 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002808 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002809 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002810 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002811 CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
2812 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002813 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002814 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2815 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002816 CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
2817 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002818 }
Evan Cheng10043e22007-01-19 07:51:42 +00002819 }
2820 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002821 unsigned ShImm = Log2_32(RHSV+1);
2822 if (ShImm >= 32)
2823 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002824 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002825 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002826 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002827 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002828 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002829 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002830 CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
2831 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002832 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002833 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2834 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002835 CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
2836 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002837 }
Evan Cheng10043e22007-01-19 07:51:42 +00002838 }
2839 }
2840 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002841 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002842 // Check for unsigned bitfield extract
Justin Bogner45571362016-05-12 00:31:09 +00002843 if (tryV6T2BitfieldExtractOp(N, false))
2844 return;
Jim Grosbach825cb292010-04-22 23:24:18 +00002845
James Molloyae5ff992016-07-05 12:37:13 +00002846 // If an immediate is used in an AND node, it is possible that the immediate
2847 // can be more optimally materialized when negated. If this is the case we
2848 // can negate the immediate and use a BIC instead.
2849 auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1));
2850 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
2851 uint32_t Imm = (uint32_t) N1C->getZExtValue();
2852
2853 // In Thumb2 mode, an AND can take a 12-bit immediate. If this
2854 // immediate can be negated and fit in the immediate operand of
2855 // a t2BIC, don't do any manual transform here as this can be
2856 // handled by the generic ISel machinery.
2857 bool PreferImmediateEncoding =
2858 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm));
2859 if (!PreferImmediateEncoding &&
2860 ConstantMaterializationCost(Imm) >
2861 ConstantMaterializationCost(~Imm)) {
2862 // The current immediate costs more to materialize than a negated
2863 // immediate, so negate the immediate and use a BIC.
2864 SDValue NewImm =
2865 CurDAG->getConstant(~N1C->getZExtValue(), dl, MVT::i32);
2866 // If the new constant didn't exist before, reposition it in the topological
2867 // ordering so it is just before N. Otherwise, don't touch its location.
2868 if (NewImm->getNodeId() == -1)
2869 CurDAG->RepositionNode(N->getIterator(), NewImm.getNode());
2870
2871 if (!Subtarget->hasThumb2()) {
2872 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
2873 N->getOperand(0), NewImm, getAL(CurDAG, dl),
2874 CurDAG->getRegister(0, MVT::i32)};
2875 ReplaceNode(N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32, Ops));
2876 return;
2877 } else {
2878 SDValue Ops[] = {N->getOperand(0), NewImm, getAL(CurDAG, dl),
2879 CurDAG->getRegister(0, MVT::i32),
2880 CurDAG->getRegister(0, MVT::i32)};
2881 ReplaceNode(N,
2882 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32, Ops));
2883 return;
2884 }
2885 }
2886 }
2887
Evan Cheng786b15f2009-10-21 08:15:52 +00002888 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2889 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2890 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2891 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2892 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002893 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002894 if (VT != MVT::i32)
2895 break;
2896 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2897 ? ARM::t2MOVTi16
2898 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2899 if (!Opc)
2900 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002901 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
James Molloyae5ff992016-07-05 12:37:13 +00002902 N1C = dyn_cast<ConstantSDNode>(N1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002903 if (!N1C)
2904 break;
2905 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2906 SDValue N2 = N0.getOperand(1);
2907 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2908 if (!N2C)
2909 break;
2910 unsigned N1CVal = N1C->getZExtValue();
2911 unsigned N2CVal = N2C->getZExtValue();
2912 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2913 (N1CVal & 0xffffU) == 0xffffU &&
2914 (N2CVal & 0xffffU) == 0x0U) {
2915 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002916 dl, MVT::i32);
Evan Cheng786b15f2009-10-21 08:15:52 +00002917 SDValue Ops[] = { N0.getOperand(0), Imm16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002918 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002919 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
2920 return;
Evan Cheng786b15f2009-10-21 08:15:52 +00002921 }
2922 }
2923 break;
2924 }
Jim Grosbachd7cf55c2009-11-09 00:11:35 +00002925 case ARMISD::VMOVRRD:
Justin Bogner45571362016-05-12 00:31:09 +00002926 ReplaceNode(N, CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
2927 N->getOperand(0), getAL(CurDAG, dl),
2928 CurDAG->getRegister(0, MVT::i32)));
2929 return;
Dan Gohmana1603612007-10-08 18:33:35 +00002930 case ISD::UMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002931 if (Subtarget->isThumb1Only())
2932 break;
2933 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002934 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002935 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002936 ReplaceNode(
2937 N, CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops));
2938 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002939 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002940 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002941 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002942 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002943 ReplaceNode(N, CurDAG->getMachineNode(
2944 Subtarget->hasV6Ops() ? ARM::UMULL : ARM::UMULLv5, dl,
2945 MVT::i32, MVT::i32, Ops));
2946 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002947 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002948 }
Dan Gohmana1603612007-10-08 18:33:35 +00002949 case ISD::SMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002950 if (Subtarget->isThumb1Only())
2951 break;
2952 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002953 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002954 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002955 ReplaceNode(
2956 N, CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops));
2957 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002958 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002959 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002960 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002961 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002962 ReplaceNode(N, CurDAG->getMachineNode(
2963 Subtarget->hasV6Ops() ? ARM::SMULL : ARM::SMULLv5, dl,
2964 MVT::i32, MVT::i32, Ops));
2965 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002966 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002967 }
Sam Parkerd616cf02016-06-20 16:47:09 +00002968 case ARMISD::UMAAL: {
2969 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
2970 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2971 N->getOperand(2), N->getOperand(3),
2972 getAL(CurDAG, dl),
2973 CurDAG->getRegister(0, MVT::i32) };
2974 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::i32, Ops));
2975 return;
2976 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002977 case ARMISD::UMLAL:{
Sam Parkerd616cf02016-06-20 16:47:09 +00002978 // UMAAL is similar to UMLAL but it adds two 32-bit values to the
2979 // 64-bit multiplication result.
2980 if (Subtarget->hasV6Ops() && N->getOperand(2).getOpcode() == ARMISD::ADDC &&
2981 N->getOperand(3).getOpcode() == ARMISD::ADDE) {
2982
2983 SDValue Addc = N->getOperand(2);
2984 SDValue Adde = N->getOperand(3);
2985
2986 if (Adde.getOperand(2).getNode() == Addc.getNode()) {
2987
2988 ConstantSDNode *Op0 = dyn_cast<ConstantSDNode>(Adde.getOperand(0));
2989 ConstantSDNode *Op1 = dyn_cast<ConstantSDNode>(Adde.getOperand(1));
2990
2991 if (Op0 && Op1 && Op0->getZExtValue() == 0 && Op1->getZExtValue() == 0)
2992 {
2993 // Select UMAAL instead: UMAAL RdLo, RdHi, Rn, Rm
2994 // RdLo = one operand to be added, lower 32-bits of res
2995 // RdHi = other operand to be added, upper 32-bits of res
2996 // Rn = first multiply operand
2997 // Rm = second multiply operand
2998 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2999 Addc.getOperand(0), Addc.getOperand(1),
3000 getAL(CurDAG, dl),
3001 CurDAG->getRegister(0, MVT::i32) };
3002 unsigned opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
3003 CurDAG->SelectNodeTo(N, opc, MVT::i32, MVT::i32, Ops);
3004 return;
3005 }
3006 }
3007 }
3008
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003009 if (Subtarget->isThumb()) {
3010 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003011 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003012 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00003013 ReplaceNode(
3014 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops));
3015 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003016 }else{
3017 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003018 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003019 CurDAG->getRegister(0, MVT::i32),
3020 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00003021 ReplaceNode(N, CurDAG->getMachineNode(
3022 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl,
3023 MVT::i32, MVT::i32, Ops));
3024 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003025 }
3026 }
3027 case ARMISD::SMLAL:{
3028 if (Subtarget->isThumb()) {
3029 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003030 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003031 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00003032 ReplaceNode(
3033 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops));
3034 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003035 }else{
3036 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003037 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003038 CurDAG->getRegister(0, MVT::i32),
3039 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00003040 ReplaceNode(N, CurDAG->getMachineNode(
3041 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl,
3042 MVT::i32, MVT::i32, Ops));
3043 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003044 }
3045 }
Sam Parker68c71cd2016-07-25 09:20:20 +00003046 case ARMISD::SUBE: {
3047 if (!Subtarget->hasV6Ops())
3048 break;
3049 // Look for a pattern to match SMMLS
3050 // (sube a, (smul_loHi a, b), (subc 0, (smul_LOhi(a, b))))
3051 if (N->getOperand(1).getOpcode() != ISD::SMUL_LOHI ||
Tim Northover765777c2016-08-02 23:12:36 +00003052 N->getOperand(2).getOpcode() != ARMISD::SUBC ||
3053 !SDValue(N, 1).use_empty())
Sam Parker68c71cd2016-07-25 09:20:20 +00003054 break;
3055
3056 if (Subtarget->isThumb())
3057 assert(Subtarget->hasThumb2() &&
3058 "This pattern should not be generated for Thumb");
3059
3060 SDValue SmulLoHi = N->getOperand(1);
3061 SDValue Subc = N->getOperand(2);
3062 auto *Zero = dyn_cast<ConstantSDNode>(Subc.getOperand(0));
3063
3064 if (!Zero || Zero->getZExtValue() != 0 ||
3065 Subc.getOperand(1) != SmulLoHi.getValue(0) ||
3066 N->getOperand(1) != SmulLoHi.getValue(1) ||
3067 N->getOperand(2) != Subc.getValue(1))
3068 break;
3069
3070 unsigned Opc = Subtarget->isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
3071 SDValue Ops[] = { SmulLoHi.getOperand(0), SmulLoHi.getOperand(1),
3072 N->getOperand(0), getAL(CurDAG, dl),
3073 CurDAG->getRegister(0, MVT::i32) };
3074 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops));
3075 return;
3076 }
Evan Cheng10043e22007-01-19 07:51:42 +00003077 case ISD::LOAD: {
Justin Bogner45571362016-05-12 00:31:09 +00003078 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
3079 if (tryT2IndexedLoad(N))
3080 return;
James Molloyb3326df2016-07-15 08:03:56 +00003081 } else if (Subtarget->isThumb()) {
3082 if (tryT1IndexedLoad(N))
3083 return;
Justin Bogner45571362016-05-12 00:31:09 +00003084 } else if (tryARMIndexedLoad(N))
3085 return;
Evan Cheng10043e22007-01-19 07:51:42 +00003086 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00003087 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00003088 }
Evan Cheng7e90b112007-07-05 07:15:27 +00003089 case ARMISD::BRCOND: {
3090 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
3091 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
3092 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003093
Evan Cheng7e90b112007-07-05 07:15:27 +00003094 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
3095 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
3096 // Pattern complexity = 6 cost = 1 size = 0
3097
David Goodwin27303cd2009-06-30 18:04:13 +00003098 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
3099 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
3100 // Pattern complexity = 6 cost = 1 size = 0
3101
Jim Grosbachf24f9d92009-08-11 15:33:49 +00003102 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00003103 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003104 SDValue Chain = N->getOperand(0);
3105 SDValue N1 = N->getOperand(1);
3106 SDValue N2 = N->getOperand(2);
3107 SDValue N3 = N->getOperand(3);
3108 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00003109 assert(N1.getOpcode() == ISD::BasicBlock);
3110 assert(N2.getOpcode() == ISD::Constant);
3111 assert(N3.getOpcode() == ISD::Register);
3112
James Molloy9790d8f2016-09-14 09:45:28 +00003113 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
3114 cast<ConstantSDNode>(N2)->getZExtValue()), dl,
3115 MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003116 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00003117 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00003118 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003119 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003120 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003121 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003122 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00003123 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003124 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00003125 SDValue(Chain.getNode(), Chain.getResNo()));
Justin Bognered4f3782016-05-12 00:20:19 +00003126 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003127 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00003128 }
James Molloy4d86bed2016-09-09 12:52:24 +00003129
3130 case ARMISD::CMPZ: {
3131 // select (CMPZ X, #-C) -> (CMPZ (ADDS X, #C), #0)
3132 // This allows us to avoid materializing the expensive negative constant.
3133 // The CMPZ #0 is useless and will be peepholed away but we need to keep it
3134 // for its glue output.
3135 SDValue X = N->getOperand(0);
3136 auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1).getNode());
3137 if (C && C->getSExtValue() < 0 && Subtarget->isThumb()) {
3138 int64_t Addend = -C->getSExtValue();
3139
3140 SDNode *Add = nullptr;
3141 // In T2 mode, ADDS can be better than CMN if the immediate fits in a
3142 // 16-bit ADDS, which means either [0,256) for tADDi8 or [0,8) for tADDi3.
3143 // Outside that range we can just use a CMN which is 32-bit but has a
3144 // 12-bit immediate range.
3145 if (Subtarget->isThumb2() && Addend < 1<<8) {
3146 SDValue Ops[] = { X, CurDAG->getTargetConstant(Addend, dl, MVT::i32),
3147 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
3148 CurDAG->getRegister(0, MVT::i32) };
3149 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl, MVT::i32, Ops);
3150 } else if (!Subtarget->isThumb2() && Addend < 1<<8) {
3151 // FIXME: Add T1 tADDi8 code.
3152 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), X,
3153 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
3154 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
3155 Add = CurDAG->getMachineNode(ARM::tADDi8, dl, MVT::i32, Ops);
3156 } else if (!Subtarget->isThumb2() && Addend < 1<<3) {
3157 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), X,
3158 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
3159 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
3160 Add = CurDAG->getMachineNode(ARM::tADDi3, dl, MVT::i32, Ops);
3161 }
3162 if (Add) {
3163 SDValue Ops2[] = {SDValue(Add, 0), CurDAG->getConstant(0, dl, MVT::i32)};
3164 CurDAG->MorphNodeTo(N, ARMISD::CMPZ, CurDAG->getVTList(MVT::Glue), Ops2);
3165 }
3166 }
3167 // Other cases are autogenerated.
3168 break;
3169 }
3170
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003171 case ARMISD::VZIP: {
3172 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003173 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003174 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003175 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003176 case MVT::v8i8: Opc = ARM::VZIPd8; break;
3177 case MVT::v4i16: Opc = ARM::VZIPd16; break;
3178 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00003179 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3180 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003181 case MVT::v16i8: Opc = ARM::VZIPq8; break;
3182 case MVT::v8i16: Opc = ARM::VZIPq16; break;
3183 case MVT::v4f32:
3184 case MVT::v4i32: Opc = ARM::VZIPq32; break;
3185 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003186 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003187 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3188 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003189 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3190 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003191 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003192 case ARMISD::VUZP: {
3193 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003194 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003195 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003196 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003197 case MVT::v8i8: Opc = ARM::VUZPd8; break;
3198 case MVT::v4i16: Opc = ARM::VUZPd16; break;
3199 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00003200 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3201 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003202 case MVT::v16i8: Opc = ARM::VUZPq8; break;
3203 case MVT::v8i16: Opc = ARM::VUZPq16; break;
3204 case MVT::v4f32:
3205 case MVT::v4i32: Opc = ARM::VUZPq32; break;
3206 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003207 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003208 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3209 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003210 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3211 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003212 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003213 case ARMISD::VTRN: {
3214 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003215 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003216 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003217 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003218 case MVT::v8i8: Opc = ARM::VTRNd8; break;
3219 case MVT::v4i16: Opc = ARM::VTRNd16; break;
3220 case MVT::v2f32:
3221 case MVT::v2i32: Opc = ARM::VTRNd32; break;
3222 case MVT::v16i8: Opc = ARM::VTRNq8; break;
3223 case MVT::v8i16: Opc = ARM::VTRNq16; break;
3224 case MVT::v4f32:
3225 case MVT::v4i32: Opc = ARM::VTRNq32; break;
3226 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003227 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003228 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3229 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003230 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3231 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003232 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003233 case ARMISD::BUILD_VECTOR: {
3234 EVT VecVT = N->getValueType(0);
3235 EVT EltVT = VecVT.getVectorElementType();
3236 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00003237 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00003238 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003239 ReplaceNode(
3240 N, createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3241 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003242 }
Duncan Sands14627772010-11-03 12:17:33 +00003243 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003244 if (NumElts == 2) {
3245 ReplaceNode(
3246 N, createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3247 return;
3248 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003249 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003250 ReplaceNode(N,
3251 createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
3252 N->getOperand(2), N->getOperand(3)));
3253 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003254 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003255
Bob Wilson2d790df2010-11-28 06:51:26 +00003256 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003257 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
3258 ARM::VLD2DUPd32 };
Justin Bogner45571362016-05-12 00:31:09 +00003259 SelectVLDDup(N, false, 2, Opcodes);
3260 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00003261 }
3262
Bob Wilson77ab1652010-11-29 19:35:29 +00003263 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003264 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
3265 ARM::VLD3DUPd16Pseudo,
3266 ARM::VLD3DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003267 SelectVLDDup(N, false, 3, Opcodes);
3268 return;
Bob Wilson77ab1652010-11-29 19:35:29 +00003269 }
3270
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003271 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003272 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
3273 ARM::VLD4DUPd16Pseudo,
3274 ARM::VLD4DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003275 SelectVLDDup(N, false, 4, Opcodes);
3276 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003277 }
3278
3279 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003280 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
3281 ARM::VLD2DUPd16wb_fixed,
3282 ARM::VLD2DUPd32wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003283 SelectVLDDup(N, true, 2, Opcodes);
3284 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003285 }
3286
3287 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003288 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
3289 ARM::VLD3DUPd16Pseudo_UPD,
3290 ARM::VLD3DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003291 SelectVLDDup(N, true, 3, Opcodes);
3292 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003293 }
3294
3295 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003296 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
3297 ARM::VLD4DUPd16Pseudo_UPD,
3298 ARM::VLD4DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003299 SelectVLDDup(N, true, 4, Opcodes);
3300 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003301 }
3302
3303 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003304 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
3305 ARM::VLD1d16wb_fixed,
3306 ARM::VLD1d32wb_fixed,
3307 ARM::VLD1d64wb_fixed };
3308 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
3309 ARM::VLD1q16wb_fixed,
3310 ARM::VLD1q32wb_fixed,
3311 ARM::VLD1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003312 SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
3313 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003314 }
3315
3316 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003317 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
3318 ARM::VLD2d16wb_fixed,
3319 ARM::VLD2d32wb_fixed,
3320 ARM::VLD1q64wb_fixed};
3321 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
3322 ARM::VLD2q16PseudoWB_fixed,
3323 ARM::VLD2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003324 SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
3325 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003326 }
3327
3328 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003329 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
3330 ARM::VLD3d16Pseudo_UPD,
3331 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003332 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003333 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3334 ARM::VLD3q16Pseudo_UPD,
3335 ARM::VLD3q32Pseudo_UPD };
3336 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3337 ARM::VLD3q16oddPseudo_UPD,
3338 ARM::VLD3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003339 SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3340 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003341 }
3342
3343 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003344 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3345 ARM::VLD4d16Pseudo_UPD,
3346 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003347 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003348 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3349 ARM::VLD4q16Pseudo_UPD,
3350 ARM::VLD4q32Pseudo_UPD };
3351 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3352 ARM::VLD4q16oddPseudo_UPD,
3353 ARM::VLD4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003354 SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3355 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003356 }
3357
3358 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003359 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3360 ARM::VLD2LNd16Pseudo_UPD,
3361 ARM::VLD2LNd32Pseudo_UPD };
3362 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3363 ARM::VLD2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003364 SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3365 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003366 }
3367
3368 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003369 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3370 ARM::VLD3LNd16Pseudo_UPD,
3371 ARM::VLD3LNd32Pseudo_UPD };
3372 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3373 ARM::VLD3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003374 SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3375 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003376 }
3377
3378 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003379 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3380 ARM::VLD4LNd16Pseudo_UPD,
3381 ARM::VLD4LNd32Pseudo_UPD };
3382 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3383 ARM::VLD4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003384 SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3385 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003386 }
3387
3388 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003389 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3390 ARM::VST1d16wb_fixed,
3391 ARM::VST1d32wb_fixed,
3392 ARM::VST1d64wb_fixed };
3393 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3394 ARM::VST1q16wb_fixed,
3395 ARM::VST1q32wb_fixed,
3396 ARM::VST1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003397 SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
3398 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003399 }
3400
3401 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003402 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3403 ARM::VST2d16wb_fixed,
3404 ARM::VST2d32wb_fixed,
3405 ARM::VST1q64wb_fixed};
3406 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3407 ARM::VST2q16PseudoWB_fixed,
3408 ARM::VST2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003409 SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
3410 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003411 }
3412
3413 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003414 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3415 ARM::VST3d16Pseudo_UPD,
3416 ARM::VST3d32Pseudo_UPD,
3417 ARM::VST1d64TPseudoWB_fixed};
3418 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3419 ARM::VST3q16Pseudo_UPD,
3420 ARM::VST3q32Pseudo_UPD };
3421 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3422 ARM::VST3q16oddPseudo_UPD,
3423 ARM::VST3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003424 SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3425 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003426 }
3427
3428 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003429 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3430 ARM::VST4d16Pseudo_UPD,
3431 ARM::VST4d32Pseudo_UPD,
3432 ARM::VST1d64QPseudoWB_fixed};
3433 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3434 ARM::VST4q16Pseudo_UPD,
3435 ARM::VST4q32Pseudo_UPD };
3436 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3437 ARM::VST4q16oddPseudo_UPD,
3438 ARM::VST4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003439 SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3440 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003441 }
3442
3443 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003444 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3445 ARM::VST2LNd16Pseudo_UPD,
3446 ARM::VST2LNd32Pseudo_UPD };
3447 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3448 ARM::VST2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003449 SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3450 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003451 }
3452
3453 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003454 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3455 ARM::VST3LNd16Pseudo_UPD,
3456 ARM::VST3LNd32Pseudo_UPD };
3457 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3458 ARM::VST3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003459 SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3460 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003461 }
3462
3463 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003464 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3465 ARM::VST4LNd16Pseudo_UPD,
3466 ARM::VST4LNd32Pseudo_UPD };
3467 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3468 ARM::VST4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003469 SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
3470 return;
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003471 }
3472
Bob Wilsone0636a72009-08-26 17:39:53 +00003473 case ISD::INTRINSIC_VOID:
3474 case ISD::INTRINSIC_W_CHAIN: {
3475 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003476 switch (IntNo) {
3477 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003478 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003479
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003480 case Intrinsic::arm_mrrc:
3481 case Intrinsic::arm_mrrc2: {
3482 SDLoc dl(N);
3483 SDValue Chain = N->getOperand(0);
3484 unsigned Opc;
3485
3486 if (Subtarget->isThumb())
3487 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
3488 else
3489 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
3490
3491 SmallVector<SDValue, 5> Ops;
3492 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(), dl)); /* coproc */
3493 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(), dl)); /* opc */
3494 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(4))->getZExtValue(), dl)); /* CRm */
3495
3496 // The mrrc2 instruction in ARM doesn't allow predicates, the top 4 bits of the encoded
3497 // instruction will always be '1111' but it is possible in assembly language to specify
3498 // AL as a predicate to mrrc2 but it doesn't make any difference to the encoded instruction.
3499 if (Opc != ARM::MRRC2) {
3500 Ops.push_back(getAL(CurDAG, dl));
3501 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3502 }
3503
3504 Ops.push_back(Chain);
3505
3506 // Writes to two registers.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003507 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003508
3509 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, RetType, Ops));
3510 return;
3511 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003512 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003513 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003514 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003515 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003516 SDValue MemAddr = N->getOperand(2);
Bradley Smith433c22e2016-01-15 10:26:51 +00003517 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
Tim Northover1ff5f292014-03-26 14:39:31 +00003518
3519 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3520 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3521 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003522
3523 // arm_ldrexd returns a i64 value in {i32, i32}
3524 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003525 if (isThumb) {
3526 ResTys.push_back(MVT::i32);
3527 ResTys.push_back(MVT::i32);
3528 } else
3529 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003530 ResTys.push_back(MVT::Other);
3531
Weiming Zhao8f56f882012-11-16 21:55:34 +00003532 // Place arguments in the right order.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003533 SDValue Ops[] = {MemAddr, getAL(CurDAG, dl),
3534 CurDAG->getRegister(0, MVT::i32), Chain};
Michael Liaob53d8962013-04-19 22:22:57 +00003535 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003536 // Transfer memoperands.
3537 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3538 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3539 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3540
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003541 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003542 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003543 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003544 SDValue Result;
3545 if (isThumb)
3546 Result = SDValue(Ld, 0);
3547 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003548 SDValue SubRegIdx =
3549 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003550 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003551 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003552 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003553 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003554 ReplaceUses(SDValue(N, 0), Result);
3555 }
3556 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003557 SDValue Result;
3558 if (isThumb)
3559 Result = SDValue(Ld, 1);
3560 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003561 SDValue SubRegIdx =
3562 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003563 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003564 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003565 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003566 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003567 ReplaceUses(SDValue(N, 1), Result);
3568 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003569 ReplaceUses(SDValue(N, 2), OutChain);
Justin Bognered4f3782016-05-12 00:20:19 +00003570 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003571 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003572 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003573 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003574 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003575 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003576 SDValue Chain = N->getOperand(0);
3577 SDValue Val0 = N->getOperand(2);
3578 SDValue Val1 = N->getOperand(3);
3579 SDValue MemAddr = N->getOperand(4);
3580
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003581 // Store exclusive double return a i32 value which is the return status
3582 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003583 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003584
Weiming Zhao8f56f882012-11-16 21:55:34 +00003585 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3586 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003587 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003588 if (isThumb) {
3589 Ops.push_back(Val0);
3590 Ops.push_back(Val1);
3591 } else
3592 // arm_strexd uses GPRPair.
3593 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003594 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003595 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003596 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3597 Ops.push_back(Chain);
3598
Tim Northover1ff5f292014-03-26 14:39:31 +00003599 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3600 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3601 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003602
Michael Liaob53d8962013-04-19 22:22:57 +00003603 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003604 // Transfer memoperands.
3605 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3606 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3607 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3608
Justin Bogner45571362016-05-12 00:31:09 +00003609 ReplaceNode(N, St);
3610 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003611 }
3612
Bob Wilson340861d2010-03-23 05:25:43 +00003613 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003614 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3615 ARM::VLD1d32, ARM::VLD1d64 };
3616 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3617 ARM::VLD1q32, ARM::VLD1q64};
Justin Bogner45571362016-05-12 00:31:09 +00003618 SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
3619 return;
Bob Wilson340861d2010-03-23 05:25:43 +00003620 }
3621
Bob Wilsone0636a72009-08-26 17:39:53 +00003622 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003623 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3624 ARM::VLD2d32, ARM::VLD1q64 };
3625 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3626 ARM::VLD2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003627 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3628 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003629 }
3630
3631 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003632 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3633 ARM::VLD3d16Pseudo,
3634 ARM::VLD3d32Pseudo,
3635 ARM::VLD1d64TPseudo };
3636 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3637 ARM::VLD3q16Pseudo_UPD,
3638 ARM::VLD3q32Pseudo_UPD };
3639 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3640 ARM::VLD3q16oddPseudo,
3641 ARM::VLD3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003642 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3643 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003644 }
3645
3646 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003647 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3648 ARM::VLD4d16Pseudo,
3649 ARM::VLD4d32Pseudo,
3650 ARM::VLD1d64QPseudo };
3651 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3652 ARM::VLD4q16Pseudo_UPD,
3653 ARM::VLD4q32Pseudo_UPD };
3654 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3655 ARM::VLD4q16oddPseudo,
3656 ARM::VLD4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003657 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3658 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003659 }
3660
Bob Wilsonda9817c2009-09-01 04:26:28 +00003661 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003662 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3663 ARM::VLD2LNd16Pseudo,
3664 ARM::VLD2LNd32Pseudo };
3665 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3666 ARM::VLD2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003667 SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
3668 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003669 }
3670
3671 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003672 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3673 ARM::VLD3LNd16Pseudo,
3674 ARM::VLD3LNd32Pseudo };
3675 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3676 ARM::VLD3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003677 SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
3678 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003679 }
3680
3681 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003682 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3683 ARM::VLD4LNd16Pseudo,
3684 ARM::VLD4LNd32Pseudo };
3685 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3686 ARM::VLD4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003687 SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
3688 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003689 }
3690
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003691 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003692 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3693 ARM::VST1d32, ARM::VST1d64 };
3694 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3695 ARM::VST1q32, ARM::VST1q64 };
Justin Bogner45571362016-05-12 00:31:09 +00003696 SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
3697 return;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003698 }
3699
Bob Wilsone0636a72009-08-26 17:39:53 +00003700 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003701 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3702 ARM::VST2d32, ARM::VST1q64 };
Benjamin Kramerf690da42016-06-17 14:14:29 +00003703 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3704 ARM::VST2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003705 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3706 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003707 }
3708
3709 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003710 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3711 ARM::VST3d16Pseudo,
3712 ARM::VST3d32Pseudo,
3713 ARM::VST1d64TPseudo };
3714 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3715 ARM::VST3q16Pseudo_UPD,
3716 ARM::VST3q32Pseudo_UPD };
3717 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3718 ARM::VST3q16oddPseudo,
3719 ARM::VST3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003720 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3721 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003722 }
3723
3724 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003725 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3726 ARM::VST4d16Pseudo,
3727 ARM::VST4d32Pseudo,
3728 ARM::VST1d64QPseudo };
3729 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3730 ARM::VST4q16Pseudo_UPD,
3731 ARM::VST4q32Pseudo_UPD };
3732 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3733 ARM::VST4q16oddPseudo,
3734 ARM::VST4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003735 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3736 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003737 }
Bob Wilsond7797752009-09-01 18:51:56 +00003738
3739 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003740 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3741 ARM::VST2LNd16Pseudo,
3742 ARM::VST2LNd32Pseudo };
3743 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3744 ARM::VST2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003745 SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
3746 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003747 }
3748
3749 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003750 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3751 ARM::VST3LNd16Pseudo,
3752 ARM::VST3LNd32Pseudo };
3753 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3754 ARM::VST3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003755 SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
3756 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003757 }
3758
3759 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003760 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3761 ARM::VST4LNd16Pseudo,
3762 ARM::VST4LNd32Pseudo };
3763 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3764 ARM::VST4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003765 SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
3766 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003767 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003768 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003769 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003770 }
Evan Chengd85631e2010-05-05 18:28:36 +00003771
Bob Wilson3ed511b2010-07-06 23:36:25 +00003772 case ISD::INTRINSIC_WO_CHAIN: {
3773 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3774 switch (IntNo) {
3775 default:
3776 break;
3777
3778 case Intrinsic::arm_neon_vtbl2:
Justin Bogner45571362016-05-12 00:31:09 +00003779 SelectVTBL(N, false, 2, ARM::VTBL2);
3780 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003781 case Intrinsic::arm_neon_vtbl3:
Justin Bogner45571362016-05-12 00:31:09 +00003782 SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
3783 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003784 case Intrinsic::arm_neon_vtbl4:
Justin Bogner45571362016-05-12 00:31:09 +00003785 SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
3786 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003787
3788 case Intrinsic::arm_neon_vtbx2:
Justin Bogner45571362016-05-12 00:31:09 +00003789 SelectVTBL(N, true, 2, ARM::VTBX2);
3790 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003791 case Intrinsic::arm_neon_vtbx3:
Justin Bogner45571362016-05-12 00:31:09 +00003792 SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
3793 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003794 case Intrinsic::arm_neon_vtbx4:
Justin Bogner45571362016-05-12 00:31:09 +00003795 SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
3796 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003797 }
3798 break;
3799 }
3800
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003801 case ARMISD::VTBL1: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003802 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003803 EVT VT = N->getValueType(0);
Benjamin Kramerf690da42016-06-17 14:14:29 +00003804 SDValue Ops[] = {N->getOperand(0), N->getOperand(1),
3805 getAL(CurDAG, dl), // Predicate
3806 CurDAG->getRegister(0, MVT::i32)}; // Predicate Register
Justin Bogner45571362016-05-12 00:31:09 +00003807 ReplaceNode(N, CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops));
3808 return;
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003809 }
3810 case ARMISD::VTBL2: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003811 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003812 EVT VT = N->getValueType(0);
3813
3814 // Form a REG_SEQUENCE to force register allocation.
3815 SDValue V0 = N->getOperand(0);
3816 SDValue V1 = N->getOperand(1);
Weiming Zhao95782222012-11-17 00:23:35 +00003817 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003818
Benjamin Kramerf690da42016-06-17 14:14:29 +00003819 SDValue Ops[] = {RegSeq, N->getOperand(2), getAL(CurDAG, dl), // Predicate
3820 CurDAG->getRegister(0, MVT::i32)}; // Predicate Register
Justin Bogner45571362016-05-12 00:31:09 +00003821 ReplaceNode(N, CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops));
3822 return;
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003823 }
3824
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003825 case ISD::CONCAT_VECTORS:
Justin Bogner45571362016-05-12 00:31:09 +00003826 SelectConcatVector(N);
3827 return;
Tim Northoverb629c772016-04-18 21:48:55 +00003828
3829 case ISD::ATOMIC_CMP_SWAP:
Justin Bogner45571362016-05-12 00:31:09 +00003830 SelectCMP_SWAP(N);
3831 return;
Evan Chengd85631e2010-05-05 18:28:36 +00003832 }
Evan Chengd5021732008-12-10 21:54:21 +00003833
Justin Bogner45571362016-05-12 00:31:09 +00003834 SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003835}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003836
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003837// Inspect a register string of the form
3838// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3839// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3840// and obtain the integer operands from them, adding these operands to the
3841// provided vector.
3842static void getIntOperandsFromRegisterString(StringRef RegString,
Benjamin Kramerbdc49562016-06-12 15:39:02 +00003843 SelectionDAG *CurDAG,
3844 const SDLoc &DL,
3845 std::vector<SDValue> &Ops) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003846 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003847 RegString.split(Fields, ':');
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003848
3849 if (Fields.size() > 1) {
3850 bool AllIntFields = true;
3851
3852 for (StringRef Field : Fields) {
3853 // Need to trim out leading 'cp' characters and get the integer field.
3854 unsigned IntField;
3855 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3856 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3857 }
3858
3859 assert(AllIntFields &&
3860 "Unexpected non-integer value in special register string.");
3861 }
3862}
3863
3864// Maps a Banked Register string to its mask value. The mask value returned is
3865// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3866// mask operand, which expresses which register is to be used, e.g. r8, and in
3867// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3868// was invalid.
3869static inline int getBankedRegisterMask(StringRef RegString) {
3870 return StringSwitch<int>(RegString.lower())
3871 .Case("r8_usr", 0x00)
3872 .Case("r9_usr", 0x01)
3873 .Case("r10_usr", 0x02)
3874 .Case("r11_usr", 0x03)
3875 .Case("r12_usr", 0x04)
3876 .Case("sp_usr", 0x05)
3877 .Case("lr_usr", 0x06)
3878 .Case("r8_fiq", 0x08)
3879 .Case("r9_fiq", 0x09)
3880 .Case("r10_fiq", 0x0a)
3881 .Case("r11_fiq", 0x0b)
3882 .Case("r12_fiq", 0x0c)
3883 .Case("sp_fiq", 0x0d)
3884 .Case("lr_fiq", 0x0e)
3885 .Case("lr_irq", 0x10)
3886 .Case("sp_irq", 0x11)
3887 .Case("lr_svc", 0x12)
3888 .Case("sp_svc", 0x13)
3889 .Case("lr_abt", 0x14)
3890 .Case("sp_abt", 0x15)
3891 .Case("lr_und", 0x16)
3892 .Case("sp_und", 0x17)
3893 .Case("lr_mon", 0x1c)
3894 .Case("sp_mon", 0x1d)
3895 .Case("elr_hyp", 0x1e)
3896 .Case("sp_hyp", 0x1f)
3897 .Case("spsr_fiq", 0x2e)
3898 .Case("spsr_irq", 0x30)
3899 .Case("spsr_svc", 0x32)
3900 .Case("spsr_abt", 0x34)
3901 .Case("spsr_und", 0x36)
3902 .Case("spsr_mon", 0x3c)
3903 .Case("spsr_hyp", 0x3e)
3904 .Default(-1);
3905}
3906
3907// Maps a MClass special register string to its value for use in the
3908// t2MRS_M / t2MSR_M instruction nodes as the SYSm value operand.
3909// Returns -1 to signify that the string was invalid.
3910static inline int getMClassRegisterSYSmValueMask(StringRef RegString) {
3911 return StringSwitch<int>(RegString.lower())
3912 .Case("apsr", 0x0)
3913 .Case("iapsr", 0x1)
3914 .Case("eapsr", 0x2)
3915 .Case("xpsr", 0x3)
3916 .Case("ipsr", 0x5)
3917 .Case("epsr", 0x6)
3918 .Case("iepsr", 0x7)
3919 .Case("msp", 0x8)
3920 .Case("psp", 0x9)
3921 .Case("primask", 0x10)
3922 .Case("basepri", 0x11)
3923 .Case("basepri_max", 0x12)
3924 .Case("faultmask", 0x13)
3925 .Case("control", 0x14)
Bradley Smithf277c8a2016-01-25 11:25:36 +00003926 .Case("msplim", 0x0a)
3927 .Case("psplim", 0x0b)
3928 .Case("sp", 0x18)
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003929 .Default(-1);
3930}
3931
3932// The flags here are common to those allowed for apsr in the A class cores and
3933// those allowed for the special registers in the M class cores. Returns a
3934// value representing which flags were present, -1 if invalid.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003935static inline int getMClassFlagsMask(StringRef Flags, bool hasDSP) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003936 if (Flags.empty())
Artyom Skrobovcf296442015-09-24 17:31:16 +00003937 return 0x2 | (int)hasDSP;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003938
3939 return StringSwitch<int>(Flags)
3940 .Case("g", 0x1)
3941 .Case("nzcvq", 0x2)
3942 .Case("nzcvqg", 0x3)
3943 .Default(-1);
3944}
3945
3946static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead,
3947 const ARMSubtarget *Subtarget) {
3948 // Ensure that the register (without flags) was a valid M Class special
3949 // register.
3950 int SYSmvalue = getMClassRegisterSYSmValueMask(Reg);
3951 if (SYSmvalue == -1)
3952 return -1;
3953
3954 // basepri, basepri_max and faultmask are only valid for V7m.
3955 if (!Subtarget->hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
3956 return -1;
3957
Bradley Smithf277c8a2016-01-25 11:25:36 +00003958 if (Subtarget->has8MSecExt() && Flags.lower() == "ns") {
3959 Flags = "";
3960 SYSmvalue |= 0x80;
3961 }
3962
3963 if (!Subtarget->has8MSecExt() &&
3964 (SYSmvalue == 0xa || SYSmvalue == 0xb || SYSmvalue > 0x14))
3965 return -1;
3966
3967 if (!Subtarget->hasV8MMainlineOps() &&
3968 (SYSmvalue == 0x8a || SYSmvalue == 0x8b || SYSmvalue == 0x91 ||
3969 SYSmvalue == 0x93))
3970 return -1;
3971
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003972 // If it was a read then we won't be expecting flags and so at this point
3973 // we can return the mask.
3974 if (IsRead) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00003975 if (Flags.empty())
3976 return SYSmvalue;
3977 else
3978 return -1;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003979 }
3980
3981 // We know we are now handling a write so need to get the mask for the flags.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003982 int Mask = getMClassFlagsMask(Flags, Subtarget->hasDSP());
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003983
3984 // Only apsr, iapsr, eapsr, xpsr can have flags. The other register values
3985 // shouldn't have flags present.
3986 if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.empty()))
3987 return -1;
3988
3989 // The _g and _nzcvqg versions are only valid if the DSP extension is
3990 // available.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003991 if (!Subtarget->hasDSP() && (Mask & 0x1))
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003992 return -1;
3993
3994 // The register was valid so need to put the mask in the correct place
3995 // (the flags need to be in bits 11-10) and combine with the SYSmvalue to
3996 // construct the operand for the instruction node.
3997 if (SYSmvalue < 0x4)
3998 return SYSmvalue | Mask << 10;
3999
4000 return SYSmvalue;
4001}
4002
4003static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
4004 // The mask operand contains the special register (R Bit) in bit 4, whether
4005 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
4006 // bits 3-0 contains the fields to be accessed in the special register, set by
4007 // the flags provided with the register.
4008 int Mask = 0;
4009 if (Reg == "apsr") {
4010 // The flags permitted for apsr are the same flags that are allowed in
4011 // M class registers. We get the flag value and then shift the flags into
4012 // the correct place to combine with the mask.
Artyom Skrobov6fbef2a2015-08-05 11:02:14 +00004013 Mask = getMClassFlagsMask(Flags, true);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004014 if (Mask == -1)
4015 return -1;
4016 return Mask << 2;
4017 }
4018
4019 if (Reg != "cpsr" && Reg != "spsr") {
4020 return -1;
4021 }
4022
4023 // This is the same as if the flags were "fc"
4024 if (Flags.empty() || Flags == "all")
4025 return Mask | 0x9;
4026
4027 // Inspect the supplied flags string and set the bits in the mask for
4028 // the relevant and valid flags allowed for cpsr and spsr.
4029 for (char Flag : Flags) {
4030 int FlagVal;
4031 switch (Flag) {
4032 case 'c':
4033 FlagVal = 0x1;
4034 break;
4035 case 'x':
4036 FlagVal = 0x2;
4037 break;
4038 case 's':
4039 FlagVal = 0x4;
4040 break;
4041 case 'f':
4042 FlagVal = 0x8;
4043 break;
4044 default:
4045 FlagVal = 0;
4046 }
4047
4048 // This avoids allowing strings where the same flag bit appears twice.
4049 if (!FlagVal || (Mask & FlagVal))
4050 return -1;
4051 Mask |= FlagVal;
4052 }
4053
4054 // If the register is spsr then we need to set the R bit.
4055 if (Reg == "spsr")
4056 Mask |= 0x10;
4057
4058 return Mask;
4059}
4060
4061// Lower the read_register intrinsic to ARM specific DAG nodes
4062// using the supplied metadata string to select the instruction node to use
4063// and the registers/masks to construct as operands for the node.
Justin Bogner45571362016-05-12 00:31:09 +00004064bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004065 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
4066 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
4067 bool IsThumb2 = Subtarget->isThumb2();
4068 SDLoc DL(N);
4069
4070 std::vector<SDValue> Ops;
4071 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
4072
4073 if (!Ops.empty()) {
4074 // If the special register string was constructed of fields (as defined
4075 // in the ACLE) then need to lower to MRC node (32 bit) or
4076 // MRRC node(64 bit), we can make the distinction based on the number of
4077 // operands we have.
4078 unsigned Opcode;
4079 SmallVector<EVT, 3> ResTypes;
4080 if (Ops.size() == 5){
4081 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
4082 ResTypes.append({ MVT::i32, MVT::Other });
4083 } else {
4084 assert(Ops.size() == 3 &&
4085 "Invalid number of fields in special register string.");
4086 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
4087 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
4088 }
4089
4090 Ops.push_back(getAL(CurDAG, DL));
4091 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4092 Ops.push_back(N->getOperand(0));
Justin Bogner45571362016-05-12 00:31:09 +00004093 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops));
4094 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004095 }
4096
4097 std::string SpecialReg = RegString->getString().lower();
4098
4099 int BankedReg = getBankedRegisterMask(SpecialReg);
4100 if (BankedReg != -1) {
4101 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
4102 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4103 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004104 ReplaceNode(
4105 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
4106 DL, MVT::i32, MVT::Other, Ops));
4107 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004108 }
4109
4110 // The VFP registers are read by creating SelectionDAG nodes with opcodes
4111 // corresponding to the register that is being read from. So we switch on the
4112 // string to find which opcode we need to use.
4113 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
4114 .Case("fpscr", ARM::VMRS)
4115 .Case("fpexc", ARM::VMRS_FPEXC)
4116 .Case("fpsid", ARM::VMRS_FPSID)
4117 .Case("mvfr0", ARM::VMRS_MVFR0)
4118 .Case("mvfr1", ARM::VMRS_MVFR1)
4119 .Case("mvfr2", ARM::VMRS_MVFR2)
4120 .Case("fpinst", ARM::VMRS_FPINST)
4121 .Case("fpinst2", ARM::VMRS_FPINST2)
4122 .Default(0);
4123
4124 // If an opcode was found then we can lower the read to a VFP instruction.
4125 if (Opcode) {
4126 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004127 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004128 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
Justin Bogner45571362016-05-12 00:31:09 +00004129 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004130
4131 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4132 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004133 ReplaceNode(N,
4134 CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops));
4135 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004136 }
4137
4138 // If the target is M Class then need to validate that the register string
4139 // is an acceptable value, so check that a mask can be constructed from the
4140 // string.
4141 if (Subtarget->isMClass()) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00004142 StringRef Flags = "", Reg = SpecialReg;
4143 if (Reg.endswith("_ns")) {
4144 Flags = "ns";
4145 Reg = Reg.drop_back(3);
4146 }
4147
4148 int SYSmValue = getMClassRegisterMask(Reg, Flags, true, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004149 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004150 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004151
4152 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4153 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4154 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004155 ReplaceNode(
4156 N, CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops));
4157 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004158 }
4159
4160 // Here we know the target is not M Class so we need to check if it is one
4161 // of the remaining possible values which are apsr, cpsr or spsr.
4162 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
4163 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4164 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004165 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
4166 DL, MVT::i32, MVT::Other, Ops));
4167 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004168 }
4169
4170 if (SpecialReg == "spsr") {
4171 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4172 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004173 ReplaceNode(
4174 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys, DL,
4175 MVT::i32, MVT::Other, Ops));
4176 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004177 }
4178
Justin Bogner45571362016-05-12 00:31:09 +00004179 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004180}
4181
4182// Lower the write_register intrinsic to ARM specific DAG nodes
4183// using the supplied metadata string to select the instruction node to use
4184// and the registers/masks to use in the nodes
Justin Bogner45571362016-05-12 00:31:09 +00004185bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004186 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
4187 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
4188 bool IsThumb2 = Subtarget->isThumb2();
4189 SDLoc DL(N);
4190
4191 std::vector<SDValue> Ops;
4192 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
4193
4194 if (!Ops.empty()) {
4195 // If the special register string was constructed of fields (as defined
4196 // in the ACLE) then need to lower to MCR node (32 bit) or
4197 // MCRR node(64 bit), we can make the distinction based on the number of
4198 // operands we have.
4199 unsigned Opcode;
4200 if (Ops.size() == 5) {
4201 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
4202 Ops.insert(Ops.begin()+2, N->getOperand(2));
4203 } else {
4204 assert(Ops.size() == 3 &&
4205 "Invalid number of fields in special register string.");
4206 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
4207 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
4208 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
4209 }
4210
4211 Ops.push_back(getAL(CurDAG, DL));
4212 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4213 Ops.push_back(N->getOperand(0));
4214
Justin Bogner45571362016-05-12 00:31:09 +00004215 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4216 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004217 }
4218
4219 std::string SpecialReg = RegString->getString().lower();
4220 int BankedReg = getBankedRegisterMask(SpecialReg);
4221 if (BankedReg != -1) {
4222 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
4223 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4224 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004225 ReplaceNode(
4226 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
4227 DL, MVT::Other, Ops));
4228 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004229 }
4230
4231 // The VFP registers are written to by creating SelectionDAG nodes with
4232 // opcodes corresponding to the register that is being written. So we switch
4233 // on the string to find which opcode we need to use.
4234 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
4235 .Case("fpscr", ARM::VMSR)
4236 .Case("fpexc", ARM::VMSR_FPEXC)
4237 .Case("fpsid", ARM::VMSR_FPSID)
4238 .Case("fpinst", ARM::VMSR_FPINST)
4239 .Case("fpinst2", ARM::VMSR_FPINST2)
4240 .Default(0);
4241
4242 if (Opcode) {
4243 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004244 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004245 Ops = { N->getOperand(2), getAL(CurDAG, DL),
4246 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004247 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4248 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004249 }
4250
Bradley Smithf277c8a2016-01-25 11:25:36 +00004251 std::pair<StringRef, StringRef> Fields;
4252 Fields = StringRef(SpecialReg).rsplit('_');
4253 std::string Reg = Fields.first.str();
4254 StringRef Flags = Fields.second;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004255
4256 // If the target was M Class then need to validate the special register value
4257 // and retrieve the mask for use in the instruction node.
4258 if (Subtarget->isMClass()) {
4259 // basepri_max gets split so need to correct Reg and Flags.
4260 if (SpecialReg == "basepri_max") {
4261 Reg = SpecialReg;
4262 Flags = "";
4263 }
4264 int SYSmValue = getMClassRegisterMask(Reg, Flags, false, Subtarget);
4265 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004266 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004267
4268 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4269 N->getOperand(2), getAL(CurDAG, DL),
4270 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004271 ReplaceNode(N, CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops));
4272 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004273 }
4274
4275 // We then check to see if a valid mask can be constructed for one of the
4276 // register string values permitted for the A and R class cores. These values
4277 // are apsr, spsr and cpsr; these are also valid on older cores.
4278 int Mask = getARClassRegisterMask(Reg, Flags);
4279 if (Mask != -1) {
4280 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
4281 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4282 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004283 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
4284 DL, MVT::Other, Ops));
4285 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004286 }
4287
Justin Bogner45571362016-05-12 00:31:09 +00004288 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004289}
4290
Justin Bogner45571362016-05-12 00:31:09 +00004291bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){
Weiming Zhaoc5987002013-02-14 18:10:21 +00004292 std::vector<SDValue> AsmNodeOperands;
4293 unsigned Flag, Kind;
4294 bool Changed = false;
4295 unsigned NumOps = N->getNumOperands();
4296
Weiming Zhaoc5987002013-02-14 18:10:21 +00004297 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
4298 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
4299 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
4300 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004301 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
4302 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
4303 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00004304
Andrew Trickef9de2a2013-05-25 02:42:55 +00004305 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00004306 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
4307 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004308
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004309 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004310 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004311 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00004312 SDValue op = N->getOperand(i);
4313 AsmNodeOperands.push_back(op);
4314
4315 if (i < InlineAsm::Op_FirstOperand)
4316 continue;
4317
4318 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
4319 Flag = C->getZExtValue();
4320 Kind = InlineAsm::getKind(Flag);
4321 }
4322 else
4323 continue;
4324
Joey Gouly392cdad2013-07-08 19:52:51 +00004325 // Immediate operands to inline asm in the SelectionDAG are modeled with
4326 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
4327 // the second is a constant with the value of the immediate. If we get here
4328 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00004329 if (Kind == InlineAsm::Kind_Imm) {
4330 SDValue op = N->getOperand(++i);
4331 AsmNodeOperands.push_back(op);
4332 continue;
4333 }
4334
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004335 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
4336 if (NumRegs)
4337 OpChanged.push_back(false);
4338
4339 unsigned DefIdx = 0;
4340 bool IsTiedToChangedOp = false;
4341 // If it's a use that is tied with a previous def, it has no
4342 // reg class constraint.
4343 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
4344 IsTiedToChangedOp = OpChanged[DefIdx];
4345
Diana Picusf345d402016-07-20 09:48:24 +00004346 // Memory operands to inline asm in the SelectionDAG are modeled with two
4347 // operands: a constant of value InlineAsm::Kind_Mem followed by the input
4348 // operand. If we get here and we have a Kind_Mem, skip the next operand (so
4349 // it doesn't get misinterpreted), and continue. We do this here because
4350 // it's important to update the OpChanged array correctly before moving on.
4351 if (Kind == InlineAsm::Kind_Mem) {
4352 SDValue op = N->getOperand(++i);
4353 AsmNodeOperands.push_back(op);
4354 continue;
4355 }
4356
Weiming Zhaoc5987002013-02-14 18:10:21 +00004357 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
4358 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
4359 continue;
4360
Weiming Zhaoc5987002013-02-14 18:10:21 +00004361 unsigned RC;
4362 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004363 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
4364 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00004365 continue;
4366
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004367 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00004368 SDValue V0 = N->getOperand(i+1);
4369 SDValue V1 = N->getOperand(i+2);
4370 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
4371 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
4372 SDValue PairedReg;
4373 MachineRegisterInfo &MRI = MF->getRegInfo();
4374
4375 if (Kind == InlineAsm::Kind_RegDef ||
4376 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
4377 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
4378 // the original GPRs.
4379
4380 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4381 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4382 SDValue Chain = SDValue(N,0);
4383
4384 SDNode *GU = N->getGluedUser();
4385 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
4386 Chain.getValue(1));
4387
4388 // Extract values from a GPRPair reg and copy to the original GPR reg.
4389 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4390 RegCopy);
4391 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4392 RegCopy);
4393 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
4394 RegCopy.getValue(1));
4395 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
4396
4397 // Update the original glue user.
4398 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
4399 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00004400 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004401 }
4402 else {
4403 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
4404 // GPRPair and then pass the GPRPair to the inline asm.
4405 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
4406
4407 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
4408 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
4409 Chain.getValue(1));
4410 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
4411 T0.getValue(1));
4412 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
4413
4414 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
4415 // i32 VRs of inline asm with it.
4416 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4417 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4418 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
4419
4420 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
4421 Glue = Chain.getValue(1);
4422 }
4423
4424 Changed = true;
4425
4426 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004427 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004428 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00004429 if (IsTiedToChangedOp)
4430 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
4431 else
4432 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004433 // Replace the current flag.
4434 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00004435 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004436 // Add the new register node and skip the original two GPRs.
4437 AsmNodeOperands.push_back(PairedReg);
4438 // Skip the next two GPRs.
4439 i += 2;
4440 }
4441 }
4442
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004443 if (Glue.getNode())
4444 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004445 if (!Changed)
Justin Bogner45571362016-05-12 00:31:09 +00004446 return false;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004447
Andrew Trickef9de2a2013-05-25 02:42:55 +00004448 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00004449 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004450 New->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00004451 ReplaceNode(N, New.getNode());
4452 return true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004453}
4454
4455
Bob Wilsona2c462b2009-05-19 05:53:42 +00004456bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00004457SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00004458 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004459 switch(ConstraintID) {
4460 default:
4461 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00004462 case InlineAsm::Constraint_i:
4463 // FIXME: It seems strange that 'i' is needed here since it's supposed to
4464 // be an immediate and not a memory constraint.
Justin Bognerb03fd122016-08-17 05:10:15 +00004465 LLVM_FALLTHROUGH;
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004466 case InlineAsm::Constraint_m:
James Molloy72222f52015-10-26 10:04:52 +00004467 case InlineAsm::Constraint_o:
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004468 case InlineAsm::Constraint_Q:
4469 case InlineAsm::Constraint_Um:
4470 case InlineAsm::Constraint_Un:
4471 case InlineAsm::Constraint_Uq:
4472 case InlineAsm::Constraint_Us:
4473 case InlineAsm::Constraint_Ut:
4474 case InlineAsm::Constraint_Uv:
4475 case InlineAsm::Constraint_Uy:
4476 // Require the address to be in a register. That is safe for all ARM
4477 // variants and it is hard to do anything much smarter without knowing
4478 // how the operand is used.
4479 OutOps.push_back(Op);
4480 return false;
4481 }
4482 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00004483}
4484
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004485/// createARMISelDag - This pass converts a legalized DAG into a
4486/// ARM-specific DAG, ready for instruction scheduling.
4487///
Bob Wilson2dd957f2009-09-28 14:30:20 +00004488FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
4489 CodeGenOpt::Level OptLevel) {
4490 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004491}