blob: 977a08200a45b96f1cea07d4deac14c48e0319e5 [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:
Tim Northovereaee28b2016-09-19 09:11:09 +0000196 void transferMemOperands(SDNode *Src, SDNode *Dst);
197
Justin Bogner45571362016-05-12 00:31:09 +0000198 /// Indexed (pre/post inc/dec) load matching code for ARM.
199 bool tryARMIndexedLoad(SDNode *N);
James Molloyb3326df2016-07-15 08:03:56 +0000200 bool tryT1IndexedLoad(SDNode *N);
Justin Bogner45571362016-05-12 00:31:09 +0000201 bool tryT2IndexedLoad(SDNode *N);
Evan Cheng84c6cda2009-07-02 07:28:31 +0000202
Bob Wilson340861d2010-03-23 05:25:43 +0000203 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
204 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson12b47992009-10-14 17:28:52 +0000205 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson340861d2010-03-23 05:25:43 +0000206 /// For NumVecs <= 2, QOpcodes1 is not used.
Justin Bogner45571362016-05-12 00:31:09 +0000207 void SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
208 const uint16_t *DOpcodes, const uint16_t *QOpcodes0,
209 const uint16_t *QOpcodes1);
Bob Wilson12b47992009-10-14 17:28:52 +0000210
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000211 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000212 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000213 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000214 /// For NumVecs <= 2, QOpcodes1 is not used.
Justin Bogner45571362016-05-12 00:31:09 +0000215 void SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
216 const uint16_t *DOpcodes, const uint16_t *QOpcodes0,
217 const uint16_t *QOpcodes1);
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000218
Bob Wilson93117bc2009-10-14 16:46:45 +0000219 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilson4145e3a2009-10-14 16:19:03 +0000220 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsond5c57a52010-09-13 23:01:35 +0000221 /// load/store of D registers and Q registers.
Justin Bogner45571362016-05-12 00:31:09 +0000222 void SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
223 unsigned NumVecs, const uint16_t *DOpcodes,
224 const uint16_t *QOpcodes);
Bob Wilson4145e3a2009-10-14 16:19:03 +0000225
Bob Wilson2d790df2010-11-28 06:51:26 +0000226 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
227 /// should be 2, 3 or 4. The opcode array specifies the instructions used
228 /// for loading D registers. (Q registers are not supported.)
Justin Bogner45571362016-05-12 00:31:09 +0000229 void SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
230 const uint16_t *Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +0000231
Bob Wilson5bc8a792010-07-07 00:08:54 +0000232 /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2,
233 /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be
234 /// generated to force the table registers to be consecutive.
Justin Bogner45571362016-05-12 00:31:09 +0000235 void SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc);
Bob Wilson3ed511b2010-07-06 23:36:25 +0000236
Justin Bogner45571362016-05-12 00:31:09 +0000237 /// Try to select SBFX/UBFX instructions for ARM.
238 bool tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000239
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000240 // Select special operations if node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +0000241 bool tryABSOp(SDNode *N);
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000242
Justin Bogner45571362016-05-12 00:31:09 +0000243 bool tryReadRegister(SDNode *N);
244 bool tryWriteRegister(SDNode *N);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +0000245
Justin Bogner45571362016-05-12 00:31:09 +0000246 bool tryInlineAsm(SDNode *N);
Weiming Zhaoc5987002013-02-14 18:10:21 +0000247
Justin Bogner45571362016-05-12 00:31:09 +0000248 void SelectConcatVector(SDNode *N);
James Molloy9790d8f2016-09-14 09:45:28 +0000249
Justin Bogner45571362016-05-12 00:31:09 +0000250 bool trySMLAWSMULW(SDNode *N);
Sam Parker2d5126c2016-04-08 16:02:53 +0000251
Justin Bogner45571362016-05-12 00:31:09 +0000252 void SelectCMP_SWAP(SDNode *N);
Tim Northoverb629c772016-04-18 21:48:55 +0000253
Evan Chengd9c55362009-07-02 01:23:32 +0000254 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
255 /// inline asm expressions.
Daniel Sanders60f1db02015-03-13 12:45:09 +0000256 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Craig Topper6bc27bf2014-03-10 02:09:33 +0000257 std::vector<SDValue> &OutOps) override;
Bob Wilsone6b778d2009-10-06 22:01:59 +0000258
Weiming Zhao95782222012-11-17 00:23:35 +0000259 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhao8f56f882012-11-16 21:55:34 +0000260 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao95782222012-11-17 00:23:35 +0000261 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
262 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
263 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Chengc2ae5f52010-05-10 17:34:18 +0000264
Bob Wilsond8a9a042010-06-04 00:04:02 +0000265 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +0000266 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
267 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
268 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000269
270 // Get the alignment operand for a NEON VLD or VST instruction.
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000271 SDValue GetVLDSTAlign(SDValue Align, const SDLoc &dl, unsigned NumVecs,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000272 bool is64BitVector);
John Brawn056e6782015-09-14 15:19:41 +0000273
274 /// Returns the number of instructions required to materialize the given
275 /// constant in a register, or 3 if a literal pool load is needed.
276 unsigned ConstantMaterializationCost(unsigned Val) const;
277
278 /// Checks if N is a multiplication by a constant where we can extract out a
279 /// power of two from the constant so that it can be used in a shift, but only
280 /// if it simplifies the materialization of the constant. Returns true if it
281 /// is, and assigns to PowerOfTwo the power of two that should be extracted
282 /// out and to NewMulConst the new constant to be multiplied by.
283 bool canExtractShiftFromMul(const SDValue &N, unsigned MaxShift,
284 unsigned &PowerOfTwo, SDValue &NewMulConst) const;
285
286 /// Replace N with M in CurDAG, in a way that also ensures that M gets
287 /// selected when N would have been selected.
288 void replaceDAGValue(const SDValue &N, SDValue M);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000289};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000290}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000291
Sandeep Patel423e42b2009-10-13 18:59:48 +0000292/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
293/// operand. If so Imm will receive the 32-bit value.
294static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
295 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
296 Imm = cast<ConstantSDNode>(N)->getZExtValue();
297 return true;
298 }
299 return false;
300}
301
302// isInt32Immediate - This method tests to see if a constant operand.
303// If so Imm will receive the 32 bit value.
304static bool isInt32Immediate(SDValue N, unsigned &Imm) {
305 return isInt32Immediate(N.getNode(), Imm);
306}
307
308// isOpcWithIntImmediate - This method tests to see if the node is a specific
309// opcode and that it has a immediate integer right operand.
310// If so Imm will receive the 32 bit value.
311static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
312 return N->getOpcode() == Opc &&
313 isInt32Immediate(N->getOperand(1).getNode(), Imm);
314}
315
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000316/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000317/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000318///
319/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000320static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000321 int RangeMin, int RangeMax,
322 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000323 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000324
325 // Check that this is a constant.
326 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
327 if (!C)
328 return false;
329
330 ScaledConstant = (int) C->getZExtValue();
331 if ((ScaledConstant % Scale) != 0)
332 return false;
333
334 ScaledConstant /= Scale;
335 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
336}
337
Evan Chengeae6d2c2012-12-19 20:16:09 +0000338void ARMDAGToDAGISel::PreprocessISelDAG() {
339 if (!Subtarget->hasV6T2Ops())
340 return;
341
342 bool isThumb2 = Subtarget->isThumb();
343 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
344 E = CurDAG->allnodes_end(); I != E; ) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000345 SDNode *N = &*I++; // Preincrement iterator to avoid invalidation issues.
Evan Chengeae6d2c2012-12-19 20:16:09 +0000346
347 if (N->getOpcode() != ISD::ADD)
348 continue;
349
350 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
351 // leading zeros, followed by consecutive set bits, followed by 1 or 2
352 // trailing zeros, e.g. 1020.
353 // Transform the expression to
354 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
355 // of trailing zeros of c2. The left shift would be folded as an shifter
356 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
357 // node (UBFX).
358
359 SDValue N0 = N->getOperand(0);
360 SDValue N1 = N->getOperand(1);
361 unsigned And_imm = 0;
362 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
363 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
364 std::swap(N0, N1);
365 }
366 if (!And_imm)
367 continue;
368
369 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000370 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000371 if (TZ != 1 && TZ != 2)
372 // Be conservative here. Shifter operands aren't always free. e.g. On
373 // Swift, left shifter operand of 1 / 2 for free but others are not.
374 // e.g.
375 // ubfx r3, r1, #16, #8
376 // ldr.w r3, [r0, r3, lsl #2]
377 // vs.
378 // mov.w r9, #1020
379 // and.w r2, r9, r1, lsr #14
380 // ldr r2, [r0, r2]
381 continue;
382 And_imm >>= TZ;
383 if (And_imm & (And_imm + 1))
384 continue;
385
386 // Look for (and (srl X, c1), c2).
387 SDValue Srl = N1.getOperand(0);
388 unsigned Srl_imm = 0;
389 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
390 (Srl_imm <= 2))
391 continue;
392
393 // Make sure first operand is not a shifter operand which would prevent
394 // folding of the left shift.
395 SDValue CPTmp0;
396 SDValue CPTmp1;
397 SDValue CPTmp2;
398 if (isThumb2) {
John Brawnd8b405a2015-09-07 11:45:18 +0000399 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
Evan Chengeae6d2c2012-12-19 20:16:09 +0000400 continue;
401 } else {
402 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
403 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
404 continue;
405 }
406
407 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000408 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000409 Srl.getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000410 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl),
411 MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000412 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000413 Srl,
414 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000415 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000416 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32));
Evan Chengeae6d2c2012-12-19 20:16:09 +0000417 CurDAG->UpdateNodeOperands(N, N0, N1);
Jim Grosbach1a597112014-04-03 23:43:18 +0000418 }
Evan Chengeae6d2c2012-12-19 20:16:09 +0000419}
420
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000421/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
422/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
423/// least on current ARM implementations) which should be avoidded.
424bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
425 if (OptLevel == CodeGenOpt::None)
426 return true;
427
Diana Picus575f2bb2016-07-07 09:11:39 +0000428 if (!Subtarget->hasVMLxHazards())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000429 return true;
430
431 if (!N->hasOneUse())
432 return false;
433
434 SDNode *Use = *N->use_begin();
435 if (Use->getOpcode() == ISD::CopyToReg)
436 return true;
437 if (Use->isMachineOpcode()) {
Eric Christopher2f991c92014-07-03 22:24:49 +0000438 const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>(
Eric Christopherfc6de422014-08-05 02:39:49 +0000439 CurDAG->getSubtarget().getInstrInfo());
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000440
Evan Cheng6cc775f2011-06-28 19:10:37 +0000441 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
442 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000443 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000444 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000445 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
446 return true;
447 // vmlx feeding into another vmlx. We actually want to unfold
448 // the use later in the MLxExpansion pass. e.g.
449 // vmla
450 // vmla (stall 8 cycles)
451 //
452 // vmul (5 cycles)
453 // vadd (5 cycles)
454 // vmla
455 // This adds up to about 18 - 19 cycles.
456 //
457 // vmla
458 // vmul (stall 4 cycles)
459 // vadd adds up to about 14 cycles.
460 return TII->isFpMLxInstruction(Opcode);
461 }
462
463 return false;
464}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000465
Evan Cheng59bbc542010-10-27 23:41:30 +0000466bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
467 ARM_AM::ShiftOpc ShOpcVal,
468 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000469 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000470 return true;
471 if (Shift.hasOneUse())
472 return true;
473 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000474 return ShOpcVal == ARM_AM::lsl &&
475 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000476}
477
John Brawn056e6782015-09-14 15:19:41 +0000478unsigned ARMDAGToDAGISel::ConstantMaterializationCost(unsigned Val) const {
479 if (Subtarget->isThumb()) {
480 if (Val <= 255) return 1; // MOV
Weiming Zhaof68a6a72016-08-05 20:58:29 +0000481 if (Subtarget->hasV6T2Ops() &&
482 (Val <= 0xffff || ARM_AM::getT2SOImmValSplatVal(Val) != -1))
483 return 1; // MOVW
James Molloy65b6be12016-06-14 13:33:07 +0000484 if (Val <= 510) return 2; // MOV + ADDi8
John Brawn056e6782015-09-14 15:19:41 +0000485 if (~Val <= 255) return 2; // MOV + MVN
486 if (ARM_AM::isThumbImmShiftedVal(Val)) return 2; // MOV + LSL
487 } else {
488 if (ARM_AM::getSOImmVal(Val) != -1) return 1; // MOV
489 if (ARM_AM::getSOImmVal(~Val) != -1) return 1; // MVN
490 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
491 if (ARM_AM::isSOImmTwoPartVal(Val)) return 2; // two instrs
492 }
493 if (Subtarget->useMovt(*MF)) return 2; // MOVW + MOVT
494 return 3; // Literal pool load
495}
496
497bool ARMDAGToDAGISel::canExtractShiftFromMul(const SDValue &N,
498 unsigned MaxShift,
499 unsigned &PowerOfTwo,
500 SDValue &NewMulConst) const {
501 assert(N.getOpcode() == ISD::MUL);
502 assert(MaxShift > 0);
503
504 // If the multiply is used in more than one place then changing the constant
505 // will make other uses incorrect, so don't.
506 if (!N.hasOneUse()) return false;
507 // Check if the multiply is by a constant
508 ConstantSDNode *MulConst = dyn_cast<ConstantSDNode>(N.getOperand(1));
509 if (!MulConst) return false;
510 // If the constant is used in more than one place then modifying it will mean
511 // we need to materialize two constants instead of one, which is a bad idea.
512 if (!MulConst->hasOneUse()) return false;
513 unsigned MulConstVal = MulConst->getZExtValue();
514 if (MulConstVal == 0) return false;
515
516 // Find the largest power of 2 that MulConstVal is a multiple of
517 PowerOfTwo = MaxShift;
518 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
519 --PowerOfTwo;
520 if (PowerOfTwo == 0) return false;
521 }
522
523 // Only optimise if the new cost is better
524 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
525 NewMulConst = CurDAG->getConstant(NewMulConstVal, SDLoc(N), MVT::i32);
526 unsigned OldCost = ConstantMaterializationCost(MulConstVal);
527 unsigned NewCost = ConstantMaterializationCost(NewMulConstVal);
528 return NewCost < OldCost;
529}
530
531void ARMDAGToDAGISel::replaceDAGValue(const SDValue &N, SDValue M) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000532 CurDAG->RepositionNode(N.getNode()->getIterator(), M.getNode());
John Brawn056e6782015-09-14 15:19:41 +0000533 CurDAG->ReplaceAllUsesWith(N, M);
534}
535
Owen Andersonb595ed02011-07-21 18:54:16 +0000536bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000537 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000538 SDValue &Opc,
539 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000540 if (DisableShifterOp)
541 return false;
542
John Brawn056e6782015-09-14 15:19:41 +0000543 // If N is a multiply-by-constant and it's profitable to extract a shift and
544 // use it in a shifted operand do so.
545 if (N.getOpcode() == ISD::MUL) {
546 unsigned PowerOfTwo = 0;
547 SDValue NewMulConst;
548 if (canExtractShiftFromMul(N, 31, PowerOfTwo, NewMulConst)) {
Justin Bogner8752be72016-05-05 01:43:49 +0000549 HandleSDNode Handle(N);
John Brawn056e6782015-09-14 15:19:41 +0000550 replaceDAGValue(N.getOperand(1), NewMulConst);
Justin Bogner8752be72016-05-05 01:43:49 +0000551 BaseReg = Handle.getValue();
John Brawn056e6782015-09-14 15:19:41 +0000552 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ARM_AM::lsl,
553 PowerOfTwo),
554 SDLoc(N), MVT::i32);
555 return true;
556 }
557 }
558
Evan Chenga20cde32011-07-20 23:34:39 +0000559 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000560
561 // Don't match base register only case. That is matched to a separate
562 // lower complexity pattern with explicit register operand.
563 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000564
Evan Chengb23b50d2009-06-29 07:51:04 +0000565 BaseReg = N.getOperand(0);
566 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000567 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
568 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000569 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000570 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000571 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000572 return true;
573}
574
Owen Andersonb595ed02011-07-21 18:54:16 +0000575bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
576 SDValue &BaseReg,
577 SDValue &ShReg,
578 SDValue &Opc,
579 bool CheckProfitability) {
580 if (DisableShifterOp)
581 return false;
582
583 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
584
585 // Don't match base register only case. That is matched to a separate
586 // lower complexity pattern with explicit register operand.
587 if (ShOpcVal == ARM_AM::no_shift) return false;
588
589 BaseReg = N.getOperand(0);
590 unsigned ShImmVal = 0;
591 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
592 if (RHS) return false;
593
594 ShReg = N.getOperand(1);
595 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
596 return false;
597 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000598 SDLoc(N), MVT::i32);
Owen Andersonb595ed02011-07-21 18:54:16 +0000599 return true;
600}
601
602
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000603bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
604 SDValue &Base,
605 SDValue &OffImm) {
606 // Match simple R + imm12 operands.
607
608 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000609 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
610 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000611 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000612 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000613 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000614 Base = CurDAG->getTargetFrameIndex(
615 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000616 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000617 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000618 }
Owen Anderson6d557452011-03-18 19:46:58 +0000619
Chris Lattner46c01a32011-02-13 22:25:43 +0000620 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000621 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000622 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000623 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000624 Base = N.getOperand(0);
625 } else
626 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000627 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000628 return true;
629 }
630
631 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Renato Golin63e27982014-09-09 09:57:59 +0000632 int RHSC = (int)RHS->getSExtValue();
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000633 if (N.getOpcode() == ISD::SUB)
634 RHSC = -RHSC;
635
Renato Golin63e27982014-09-09 09:57:59 +0000636 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000637 Base = N.getOperand(0);
638 if (Base.getOpcode() == ISD::FrameIndex) {
639 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000640 Base = CurDAG->getTargetFrameIndex(
641 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000642 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000643 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000644 return true;
645 }
646 }
647
648 // Base only.
649 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000650 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000651 return true;
652}
653
654
655
656bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
657 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000658 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000659 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000660 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
661 // X * [3,5,9] -> X + X * [2,4,8] etc.
662 int RHSC = (int)RHS->getZExtValue();
663 if (RHSC & 1) {
664 RHSC = RHSC & ~1;
665 ARM_AM::AddrOpc AddSub = ARM_AM::add;
666 if (RHSC < 0) {
667 AddSub = ARM_AM::sub;
668 RHSC = - RHSC;
669 }
670 if (isPowerOf2_32(RHSC)) {
671 unsigned ShAmt = Log2_32(RHSC);
672 Base = Offset = N.getOperand(0);
673 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
674 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000675 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000676 return true;
677 }
678 }
679 }
680 }
681
Chris Lattner46c01a32011-02-13 22:25:43 +0000682 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
683 // ISD::OR that is equivalent to an ISD::ADD.
684 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000685 return false;
686
687 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000688 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000689 int RHSC;
690 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
691 -0x1000+1, 0x1000, RHSC)) // 12 bits.
692 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000693 }
694
695 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000696 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000697 ARM_AM::ShiftOpc ShOpcVal =
698 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000699 unsigned ShAmt = 0;
700
701 Base = N.getOperand(0);
702 Offset = N.getOperand(1);
703
704 if (ShOpcVal != ARM_AM::no_shift) {
705 // Check to see if the RHS of the shift is a constant, if not, we can't fold
706 // it.
707 if (ConstantSDNode *Sh =
708 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
709 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000710 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
711 Offset = N.getOperand(1).getOperand(0);
712 else {
713 ShAmt = 0;
714 ShOpcVal = ARM_AM::no_shift;
715 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000716 } else {
717 ShOpcVal = ARM_AM::no_shift;
718 }
719 }
720
721 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000722 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000723 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
724 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000725 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000726 if (ShOpcVal != ARM_AM::no_shift) {
727 // Check to see if the RHS of the shift is a constant, if not, we can't
728 // fold it.
729 if (ConstantSDNode *Sh =
730 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
731 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000732 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000733 Offset = N.getOperand(0).getOperand(0);
734 Base = N.getOperand(1);
735 } else {
736 ShAmt = 0;
737 ShOpcVal = ARM_AM::no_shift;
738 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000739 } else {
740 ShOpcVal = ARM_AM::no_shift;
741 }
742 }
743 }
744
John Brawn056e6782015-09-14 15:19:41 +0000745 // If Offset is a multiply-by-constant and it's profitable to extract a shift
746 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +0000747 if (Offset.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +0000748 unsigned PowerOfTwo = 0;
749 SDValue NewMulConst;
750 if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) {
751 replaceDAGValue(Offset.getOperand(1), NewMulConst);
752 ShAmt = PowerOfTwo;
753 ShOpcVal = ARM_AM::lsl;
754 }
755 }
756
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000757 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000758 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000759 return true;
760}
761
762
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000763//-----
764
Jim Grosbach08605202010-09-29 19:03:54 +0000765AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
766 SDValue &Base,
767 SDValue &Offset,
768 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000769 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000770 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000771 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
772 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmaneffb8942008-09-12 16:56:44 +0000773 int RHSC = (int)RHS->getZExtValue();
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000774 if (RHSC & 1) {
775 RHSC = RHSC & ~1;
776 ARM_AM::AddrOpc AddSub = ARM_AM::add;
777 if (RHSC < 0) {
778 AddSub = ARM_AM::sub;
779 RHSC = - RHSC;
780 }
781 if (isPowerOf2_32(RHSC)) {
782 unsigned ShAmt = Log2_32(RHSC);
783 Base = Offset = N.getOperand(0);
784 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
785 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000786 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000787 return AM2_SHOP;
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000788 }
789 }
790 }
791 }
792
Chris Lattner46c01a32011-02-13 22:25:43 +0000793 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
794 // ISD::OR that is equivalent to an ADD.
795 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000796 Base = N;
797 if (N.getOpcode() == ISD::FrameIndex) {
798 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000799 Base = CurDAG->getTargetFrameIndex(
800 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +0000801 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000802 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000803 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000804 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000805 Base = N.getOperand(0);
806 }
Owen Anderson9f944592009-08-11 20:47:22 +0000807 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000808 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
809 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000810 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000811 return AM2_BASE;
Rafael Espindola708cb602006-11-08 17:07:32 +0000812 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000813
Evan Cheng10043e22007-01-19 07:51:42 +0000814 // Match simple R +/- imm12 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +0000815 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000816 int RHSC;
817 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
818 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
819 Base = N.getOperand(0);
820 if (Base.getOpcode() == ISD::FrameIndex) {
821 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000822 Base = CurDAG->getTargetFrameIndex(
823 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Rafael Espindola708cb602006-11-08 17:07:32 +0000824 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000825 Offset = CurDAG->getRegister(0, MVT::i32);
826
827 ARM_AM::AddrOpc AddSub = ARM_AM::add;
828 if (RHSC < 0) {
829 AddSub = ARM_AM::sub;
830 RHSC = - RHSC;
831 }
832 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
833 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000834 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000835 return AM2_BASE;
Evan Cheng10043e22007-01-19 07:51:42 +0000836 }
Jim Grosbachc7b10f32010-09-29 17:32:29 +0000837 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000838
Bob Wilsone8a549c2012-09-29 21:43:49 +0000839 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000840 // Compute R +/- (R << N) and reuse it.
841 Base = N;
842 Offset = CurDAG->getRegister(0, MVT::i32);
843 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
844 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000845 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000846 return AM2_BASE;
847 }
848
Johnny Chenb678a562009-10-27 17:25:15 +0000849 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000850 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chenga20cde32011-07-20 23:34:39 +0000851 ARM_AM::ShiftOpc ShOpcVal =
852 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000853 unsigned ShAmt = 0;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000854
Evan Cheng10043e22007-01-19 07:51:42 +0000855 Base = N.getOperand(0);
856 Offset = N.getOperand(1);
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000857
Evan Cheng10043e22007-01-19 07:51:42 +0000858 if (ShOpcVal != ARM_AM::no_shift) {
859 // Check to see if the RHS of the shift is a constant, if not, we can't fold
860 // it.
861 if (ConstantSDNode *Sh =
862 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000863 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000864 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
865 Offset = N.getOperand(1).getOperand(0);
866 else {
867 ShAmt = 0;
868 ShOpcVal = ARM_AM::no_shift;
869 }
Evan Cheng10043e22007-01-19 07:51:42 +0000870 } else {
871 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola708cb602006-11-08 17:07:32 +0000872 }
873 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000874
Evan Cheng10043e22007-01-19 07:51:42 +0000875 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000876 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000877 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
878 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000879 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000880 if (ShOpcVal != ARM_AM::no_shift) {
881 // Check to see if the RHS of the shift is a constant, if not, we can't
882 // fold it.
883 if (ConstantSDNode *Sh =
884 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000885 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000886 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000887 Offset = N.getOperand(0).getOperand(0);
888 Base = N.getOperand(1);
889 } else {
890 ShAmt = 0;
891 ShOpcVal = ARM_AM::no_shift;
892 }
Evan Cheng10043e22007-01-19 07:51:42 +0000893 } else {
894 ShOpcVal = ARM_AM::no_shift;
895 }
896 }
897 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000898
Evan Cheng10043e22007-01-19 07:51:42 +0000899 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000900 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000901 return AM2_SHOP;
Rafael Espindola708cb602006-11-08 17:07:32 +0000902}
903
Owen Anderson2aedba62011-07-26 20:54:26 +0000904bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000905 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000906 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000907 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
908 ? cast<LoadSDNode>(Op)->getAddressingMode()
909 : cast<StoreSDNode>(Op)->getAddressingMode();
910 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
911 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000912 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000913 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
914 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000915
916 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000917 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000918 unsigned ShAmt = 0;
919 if (ShOpcVal != ARM_AM::no_shift) {
920 // Check to see if the RHS of the shift is a constant, if not, we can't fold
921 // it.
922 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000923 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000924 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
925 Offset = N.getOperand(0);
926 else {
927 ShAmt = 0;
928 ShOpcVal = ARM_AM::no_shift;
929 }
Evan Cheng10043e22007-01-19 07:51:42 +0000930 } else {
931 ShOpcVal = ARM_AM::no_shift;
932 }
933 }
934
935 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000936 SDLoc(N), MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000937 return true;
938}
939
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000940bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
941 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000942 unsigned Opcode = Op->getOpcode();
943 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
944 ? cast<LoadSDNode>(Op)->getAddressingMode()
945 : cast<StoreSDNode>(Op)->getAddressingMode();
946 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
947 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000948 int Val;
949 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000950 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000951 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000952 Opc = CurDAG->getTargetConstant(Val, SDLoc(Op), MVT::i32);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000953 return true;
954 }
955
956 return false;
957}
958
959
Owen Anderson2aedba62011-07-26 20:54:26 +0000960bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
961 SDValue &Offset, SDValue &Opc) {
962 unsigned Opcode = Op->getOpcode();
963 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
964 ? cast<LoadSDNode>(Op)->getAddressingMode()
965 : cast<StoreSDNode>(Op)->getAddressingMode();
966 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
967 ? ARM_AM::add : ARM_AM::sub;
968 int Val;
969 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
970 Offset = CurDAG->getRegister(0, MVT::i32);
971 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
972 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000973 SDLoc(Op), MVT::i32);
Owen Anderson2aedba62011-07-26 20:54:26 +0000974 return true;
975 }
976
977 return false;
978}
979
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000980bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
981 Base = N;
982 return true;
983}
Evan Cheng10043e22007-01-19 07:51:42 +0000984
Chris Lattner0e023ea2010-09-21 20:31:19 +0000985bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000986 SDValue &Base, SDValue &Offset,
987 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000988 if (N.getOpcode() == ISD::SUB) {
989 // X - C is canonicalize to X + -C, no need to handle it here.
990 Base = N.getOperand(0);
991 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000992 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0), SDLoc(N),
993 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000994 return true;
995 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000996
Chris Lattner46c01a32011-02-13 22:25:43 +0000997 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000998 Base = N;
999 if (N.getOpcode() == ISD::FrameIndex) {
1000 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001001 Base = CurDAG->getTargetFrameIndex(
1002 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001003 }
Owen Anderson9f944592009-08-11 20:47:22 +00001004 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001005 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1006 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001007 return true;
1008 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001009
Evan Cheng10043e22007-01-19 07:51:42 +00001010 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001011 int RHSC;
1012 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
1013 -256 + 1, 256, RHSC)) { // 8 bits.
1014 Base = N.getOperand(0);
1015 if (Base.getOpcode() == ISD::FrameIndex) {
1016 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001017 Base = CurDAG->getTargetFrameIndex(
1018 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001019 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001020 Offset = CurDAG->getRegister(0, MVT::i32);
1021
1022 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1023 if (RHSC < 0) {
1024 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001025 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001026 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001027 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC), SDLoc(N),
1028 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001029 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001030 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001031
Evan Cheng10043e22007-01-19 07:51:42 +00001032 Base = N.getOperand(0);
1033 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001034 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1035 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001036 return true;
1037}
1038
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001039bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001040 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001041 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +00001042 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1043 ? cast<LoadSDNode>(Op)->getAddressingMode()
1044 : cast<StoreSDNode>(Op)->getAddressingMode();
1045 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
1046 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001047 int Val;
1048 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
1049 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001050 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), SDLoc(Op),
1051 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001052 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001053 }
1054
1055 Offset = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001056 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), SDLoc(Op),
1057 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001058 return true;
1059}
1060
Jim Grosbachd37f0712010-10-21 19:38:40 +00001061bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001062 SDValue &Base, SDValue &Offset) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001063 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +00001064 Base = N;
1065 if (N.getOpcode() == ISD::FrameIndex) {
1066 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001067 Base = CurDAG->getTargetFrameIndex(
1068 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +00001069 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001070 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001071 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001072 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +00001073 Base = N.getOperand(0);
1074 }
1075 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001076 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001077 return true;
1078 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001079
Evan Cheng10043e22007-01-19 07:51:42 +00001080 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001081 int RHSC;
1082 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
1083 -256 + 1, 256, RHSC)) {
1084 Base = N.getOperand(0);
1085 if (Base.getOpcode() == ISD::FrameIndex) {
1086 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001087 Base = CurDAG->getTargetFrameIndex(
1088 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001089 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001090
1091 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1092 if (RHSC < 0) {
1093 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001094 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001095 }
1096 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001097 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001098 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001099 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001100
Evan Cheng10043e22007-01-19 07:51:42 +00001101 Base = N;
1102 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001103 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001104 return true;
1105}
1106
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001107bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
1108 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +00001109 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001110
1111 unsigned Alignment = 0;
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001112
1113 MemSDNode *MemN = cast<MemSDNode>(Parent);
1114
1115 if (isa<LSBaseSDNode>(MemN) ||
1116 ((MemN->getOpcode() == ARMISD::VST1_UPD ||
1117 MemN->getOpcode() == ARMISD::VLD1_UPD) &&
1118 MemN->getConstantOperandVal(MemN->getNumOperands() - 1) == 1)) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001119 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
1120 // The maximum alignment is equal to the memory size being referenced.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001121 unsigned MMOAlign = MemN->getAlignment();
1122 unsigned MemSize = MemN->getMemoryVT().getSizeInBits() / 8;
1123 if (MMOAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001124 Alignment = MemSize;
1125 } else {
1126 // All other uses of addrmode6 are for intrinsics. For now just record
1127 // the raw alignment value; it will be refined later based on the legal
1128 // alignment operands for the intrinsic.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001129 Alignment = MemN->getAlignment();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001130 }
1131
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001132 Align = CurDAG->getTargetConstant(Alignment, SDLoc(N), MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001133 return true;
1134}
1135
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001136bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1137 SDValue &Offset) {
1138 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1139 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1140 if (AM != ISD::POST_INC)
1141 return false;
1142 Offset = N;
1143 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1144 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1145 Offset = CurDAG->getRegister(0, MVT::i32);
1146 }
1147 return true;
1148}
1149
Chris Lattner0e023ea2010-09-21 20:31:19 +00001150bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001151 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001152 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1153 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001154 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001155 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001156 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001157 return true;
1158 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001159
Evan Cheng10043e22007-01-19 07:51:42 +00001160 return false;
1161}
1162
Bill Wendling092a7bd2010-12-14 03:36:38 +00001163
1164//===----------------------------------------------------------------------===//
1165// Thumb Addressing Modes
1166//===----------------------------------------------------------------------===//
1167
Chris Lattner0e023ea2010-09-21 20:31:19 +00001168bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001169 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001170 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001171 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001172 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001173 return false;
1174
1175 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001176 return true;
1177 }
1178
Evan Cheng10043e22007-01-19 07:51:42 +00001179 Base = N.getOperand(0);
1180 Offset = N.getOperand(1);
1181 return true;
1182}
1183
Evan Cheng139edae2007-01-24 02:21:22 +00001184bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001185ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1186 SDValue &Base, SDValue &OffImm) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001187 if (!CurDAG->isBaseWithConstantOffset(N)) {
John Brawn68acdcb2015-08-13 10:48:22 +00001188 if (N.getOpcode() == ISD::ADD) {
1189 return false; // We want to select register offset instead
1190 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001191 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001192 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001193 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001194 Base = N.getOperand(0);
1195 } else {
1196 Base = N;
1197 }
1198
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001199 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001200 return true;
1201 }
1202
Evan Cheng10043e22007-01-19 07:51:42 +00001203 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001204 int RHSC;
1205 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1206 Base = N.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001207 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001208 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001209 }
1210
John Brawn68acdcb2015-08-13 10:48:22 +00001211 // Offset is too large, so use register offset instead.
1212 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001213}
1214
Bill Wendling092a7bd2010-12-14 03:36:38 +00001215bool
1216ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1217 SDValue &OffImm) {
1218 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001219}
1220
Bill Wendling092a7bd2010-12-14 03:36:38 +00001221bool
1222ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1223 SDValue &OffImm) {
1224 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001225}
1226
Bill Wendling092a7bd2010-12-14 03:36:38 +00001227bool
1228ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1229 SDValue &OffImm) {
1230 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001231}
1232
Chris Lattner0e023ea2010-09-21 20:31:19 +00001233bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1234 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001235 if (N.getOpcode() == ISD::FrameIndex) {
1236 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001237 // Only multiples of 4 are allowed for the offset, so the frame object
1238 // alignment must be at least 4.
Matthias Braun941a7052016-07-28 18:40:00 +00001239 MachineFrameInfo &MFI = MF->getFrameInfo();
1240 if (MFI.getObjectAlignment(FI) < 4)
1241 MFI.setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001242 Base = CurDAG->getTargetFrameIndex(
1243 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001244 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001245 return true;
1246 }
Evan Cheng139edae2007-01-24 02:21:22 +00001247
Chris Lattner46c01a32011-02-13 22:25:43 +00001248 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001249 return false;
1250
1251 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001252 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1253 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001254 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001255 int RHSC;
1256 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1257 Base = N.getOperand(0);
1258 if (Base.getOpcode() == ISD::FrameIndex) {
1259 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001260 // For LHS+RHS to result in an offset that's a multiple of 4 the object
1261 // indexed by the LHS must be 4-byte aligned.
Matthias Braun941a7052016-07-28 18:40:00 +00001262 MachineFrameInfo &MFI = MF->getFrameInfo();
1263 if (MFI.getObjectAlignment(FI) < 4)
1264 MFI.setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001265 Base = CurDAG->getTargetFrameIndex(
1266 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng139edae2007-01-24 02:21:22 +00001267 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001268 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001269 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001270 }
1271 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001272
Evan Cheng10043e22007-01-19 07:51:42 +00001273 return false;
1274}
1275
Bill Wendling092a7bd2010-12-14 03:36:38 +00001276
1277//===----------------------------------------------------------------------===//
1278// Thumb 2 Addressing Modes
1279//===----------------------------------------------------------------------===//
1280
1281
Chris Lattner0e023ea2010-09-21 20:31:19 +00001282bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001283 SDValue &Base, SDValue &OffImm) {
1284 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001285
Evan Cheng36064672009-08-11 08:52:18 +00001286 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001287 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1288 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001289 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001290 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001291 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001292 Base = CurDAG->getTargetFrameIndex(
1293 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001294 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001295 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001296 }
Owen Anderson6d557452011-03-18 19:46:58 +00001297
Chris Lattner46c01a32011-02-13 22:25:43 +00001298 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001299 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001300 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001301 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng36064672009-08-11 08:52:18 +00001302 Base = N.getOperand(0);
1303 if (Base.getOpcode() == ISD::TargetConstantPool)
1304 return false; // We want to select t2LDRpci instead.
1305 } else
1306 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001307 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001308 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001309 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001310
1311 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001312 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001313 // Let t2LDRi8 handle (R - imm8).
1314 return false;
1315
Evan Chengb23b50d2009-06-29 07:51:04 +00001316 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001317 if (N.getOpcode() == ISD::SUB)
1318 RHSC = -RHSC;
1319
1320 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001321 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001322 if (Base.getOpcode() == ISD::FrameIndex) {
1323 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001324 Base = CurDAG->getTargetFrameIndex(
1325 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin79c079b2009-07-30 18:56:48 +00001326 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001327 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001328 return true;
1329 }
1330 }
1331
Evan Cheng36064672009-08-11 08:52:18 +00001332 // Base only.
1333 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001334 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001335 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001336}
1337
Chris Lattner0e023ea2010-09-21 20:31:19 +00001338bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001339 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001340 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001341 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1342 !CurDAG->isBaseWithConstantOffset(N))
1343 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001344
Chris Lattner46c01a32011-02-13 22:25:43 +00001345 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1346 int RHSC = (int)RHS->getSExtValue();
1347 if (N.getOpcode() == ISD::SUB)
1348 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001349
Chris Lattner46c01a32011-02-13 22:25:43 +00001350 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1351 Base = N.getOperand(0);
1352 if (Base.getOpcode() == ISD::FrameIndex) {
1353 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001354 Base = CurDAG->getTargetFrameIndex(
1355 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Chengb23b50d2009-06-29 07:51:04 +00001356 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001357 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Chris Lattner46c01a32011-02-13 22:25:43 +00001358 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001359 }
1360 }
1361
1362 return false;
1363}
1364
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001365bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001366 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001367 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001368 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1369 ? cast<LoadSDNode>(Op)->getAddressingMode()
1370 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001371 int RHSC;
1372 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1373 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001374 ? CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32)
1375 : CurDAG->getTargetConstant(-RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001376 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001377 }
1378
1379 return false;
1380}
1381
Chris Lattner0e023ea2010-09-21 20:31:19 +00001382bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001383 SDValue &Base,
1384 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001385 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001386 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001387 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001388
Evan Cheng36064672009-08-11 08:52:18 +00001389 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1390 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1391 int RHSC = (int)RHS->getZExtValue();
1392 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1393 return false;
1394 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001395 return false;
1396 }
1397
Evan Chengb23b50d2009-06-29 07:51:04 +00001398 // Look for (R + R) or (R + (R << [1,2,3])).
1399 unsigned ShAmt = 0;
1400 Base = N.getOperand(0);
1401 OffReg = N.getOperand(1);
1402
1403 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001404 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001405 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001406 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001407 if (ShOpcVal == ARM_AM::lsl)
1408 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001409 }
1410
Evan Chengb23b50d2009-06-29 07:51:04 +00001411 if (ShOpcVal == ARM_AM::lsl) {
1412 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1413 // it.
1414 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1415 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001416 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1417 OffReg = OffReg.getOperand(0);
1418 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001419 ShAmt = 0;
Evan Cheng59bbc542010-10-27 23:41:30 +00001420 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001421 }
David Goodwinf3912052009-07-15 15:50:19 +00001422 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001423
John Brawn056e6782015-09-14 15:19:41 +00001424 // If OffReg is a multiply-by-constant and it's profitable to extract a shift
1425 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +00001426 if (OffReg.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +00001427 unsigned PowerOfTwo = 0;
1428 SDValue NewMulConst;
1429 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
1430 replaceDAGValue(OffReg.getOperand(1), NewMulConst);
1431 ShAmt = PowerOfTwo;
1432 }
1433 }
1434
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001435 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001436
1437 return true;
1438}
1439
Tim Northovera7ecd242013-07-16 09:46:55 +00001440bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1441 SDValue &OffImm) {
Alp Tokercb402912014-01-24 17:20:08 +00001442 // This *must* succeed since it's used for the irreplaceable ldrex and strex
Tim Northovera7ecd242013-07-16 09:46:55 +00001443 // instructions.
1444 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001445 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001446
1447 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1448 return true;
1449
1450 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1451 if (!RHS)
1452 return true;
1453
1454 uint32_t RHSC = (int)RHS->getZExtValue();
1455 if (RHSC > 1020 || RHSC % 4 != 0)
1456 return true;
1457
1458 Base = N.getOperand(0);
1459 if (Base.getOpcode() == ISD::FrameIndex) {
1460 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001461 Base = CurDAG->getTargetFrameIndex(
1462 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Tim Northovera7ecd242013-07-16 09:46:55 +00001463 }
1464
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001465 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001466 return true;
1467}
1468
Evan Chengb23b50d2009-06-29 07:51:04 +00001469//===--------------------------------------------------------------------===//
1470
Evan Cheng7e90b112007-07-05 07:15:27 +00001471/// getAL - Returns a ARMCC::AL immediate node.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001472static inline SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001473 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001474}
1475
Tim Northovereaee28b2016-09-19 09:11:09 +00001476void ARMDAGToDAGISel::transferMemOperands(SDNode *N, SDNode *Result) {
1477 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1478 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
1479 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
1480}
1481
Justin Bogner45571362016-05-12 00:31:09 +00001482bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001483 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001484 ISD::MemIndexedMode AM = LD->getAddressingMode();
1485 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001486 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001487
Owen Anderson53aa7a92009-08-10 22:56:29 +00001488 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001489 SDValue Offset, AMOpc;
1490 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1491 unsigned Opcode = 0;
1492 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001493 if (LoadedVT == MVT::i32 && isPre &&
1494 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1495 Opcode = ARM::LDR_PRE_IMM;
1496 Match = true;
1497 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001498 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001499 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001500 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001501 } else if (LoadedVT == MVT::i32 &&
1502 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001503 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001504 Match = true;
1505
Owen Anderson9f944592009-08-11 20:47:22 +00001506 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001507 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001508 Match = true;
1509 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1510 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1511 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001512 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001513 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001514 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001515 Match = true;
1516 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1517 }
1518 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001519 if (isPre &&
1520 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001521 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001522 Opcode = ARM::LDRB_PRE_IMM;
1523 } else if (!isPre &&
1524 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1525 Match = true;
1526 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001527 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1528 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001529 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001530 }
1531 }
1532 }
1533
1534 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001535 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1536 SDValue Chain = LD->getChain();
1537 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001538 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001539 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001540 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1541 MVT::Other, Ops);
1542 transferMemOperands(N, New);
1543 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001544 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001545 } else {
1546 SDValue Chain = LD->getChain();
1547 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001548 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001549 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001550 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1551 MVT::Other, Ops);
1552 transferMemOperands(N, New);
1553 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001554 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001555 }
Evan Chengd9c55362009-07-02 01:23:32 +00001556 }
1557
Justin Bogner45571362016-05-12 00:31:09 +00001558 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001559}
1560
James Molloyb3326df2016-07-15 08:03:56 +00001561bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *N) {
1562 LoadSDNode *LD = cast<LoadSDNode>(N);
1563 EVT LoadedVT = LD->getMemoryVT();
1564 ISD::MemIndexedMode AM = LD->getAddressingMode();
1565 if (AM == ISD::UNINDEXED || LD->getExtensionType() != ISD::NON_EXTLOAD ||
1566 AM != ISD::POST_INC || LoadedVT.getSimpleVT().SimpleTy != MVT::i32)
1567 return false;
1568
1569 auto *COffs = dyn_cast<ConstantSDNode>(LD->getOffset());
1570 if (!COffs || COffs->getZExtValue() != 4)
1571 return false;
1572
1573 // A T1 post-indexed load is just a single register LDM: LDM r0!, {r1}.
1574 // The encoding of LDM is not how the rest of ISel expects a post-inc load to
1575 // look however, so we use a pseudo here and switch it for a tLDMIA_UPD after
1576 // ISel.
1577 SDValue Chain = LD->getChain();
1578 SDValue Base = LD->getBasePtr();
1579 SDValue Ops[]= { Base, getAL(CurDAG, SDLoc(N)),
1580 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001581 SDNode *New = CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(N), MVT::i32,
1582 MVT::i32, MVT::Other, Ops);
1583 transferMemOperands(N, New);
1584 ReplaceNode(N, New);
James Molloyb3326df2016-07-15 08:03:56 +00001585 return true;
1586}
1587
Justin Bogner45571362016-05-12 00:31:09 +00001588bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001589 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001590 ISD::MemIndexedMode AM = LD->getAddressingMode();
1591 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001592 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001593
Owen Anderson53aa7a92009-08-10 22:56:29 +00001594 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001595 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001596 SDValue Offset;
1597 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1598 unsigned Opcode = 0;
1599 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001600 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001601 switch (LoadedVT.getSimpleVT().SimpleTy) {
1602 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001603 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1604 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001605 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001606 if (isSExtLd)
1607 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1608 else
1609 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001610 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001611 case MVT::i8:
1612 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001613 if (isSExtLd)
1614 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1615 else
1616 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001617 break;
1618 default:
Justin Bogner45571362016-05-12 00:31:09 +00001619 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001620 }
1621 Match = true;
1622 }
1623
1624 if (Match) {
1625 SDValue Chain = LD->getChain();
1626 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001627 SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)),
Owen Anderson9f944592009-08-11 20:47:22 +00001628 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001629 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1630 MVT::Other, Ops);
1631 transferMemOperands(N, New);
1632 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001633 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001634 }
1635
Justin Bogner45571362016-05-12 00:31:09 +00001636 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001637}
1638
Weiming Zhao8f56f882012-11-16 21:55:34 +00001639/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1640SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001641 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001642 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001643 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1644 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1645 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001646 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001647 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001648}
1649
Weiming Zhao95782222012-11-17 00:23:35 +00001650/// \brief Form a D register from a pair of S registers.
1651SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001652 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001653 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001654 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1655 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1656 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001657 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001658 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001659}
1660
Weiming Zhao95782222012-11-17 00:23:35 +00001661/// \brief Form a quad register from a pair of D registers.
1662SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001663 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001664 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1665 MVT::i32);
1666 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1667 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001668 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001669 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001670}
1671
Weiming Zhao95782222012-11-17 00:23:35 +00001672/// \brief Form 4 consecutive D registers from a pair of Q registers.
1673SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001674 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001675 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1676 MVT::i32);
1677 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1678 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001679 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001680 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001681}
1682
Weiming Zhao95782222012-11-17 00:23:35 +00001683/// \brief Form 4 consecutive S registers.
1684SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001685 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001686 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001687 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001688 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1689 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1690 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1691 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1692 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001693 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1694 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001695 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001696}
1697
Weiming Zhao95782222012-11-17 00:23:35 +00001698/// \brief Form 4 consecutive D registers.
1699SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001700 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001701 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001702 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1703 MVT::i32);
1704 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1705 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1706 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1707 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001708 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1709 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001710 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001711}
1712
Weiming Zhao95782222012-11-17 00:23:35 +00001713/// \brief Form 4 consecutive Q registers.
1714SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001715 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001716 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001717 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1718 MVT::i32);
1719 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1720 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1721 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1722 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001723 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1724 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001725 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001726}
1727
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001728/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1729/// of a NEON VLD or VST instruction. The supported values depend on the
1730/// number of registers being loaded.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001731SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, const SDLoc &dl,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001732 unsigned NumVecs, bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001733 unsigned NumRegs = NumVecs;
1734 if (!is64BitVector && NumVecs < 3)
1735 NumRegs *= 2;
1736
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001737 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001738 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001739 Alignment = 32;
1740 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1741 Alignment = 16;
1742 else if (Alignment >= 8)
1743 Alignment = 8;
1744 else
1745 Alignment = 0;
1746
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001747 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001748}
1749
Jiangning Liu4df23632014-01-16 09:16:13 +00001750static bool isVLDfixed(unsigned Opc)
1751{
1752 switch (Opc) {
1753 default: return false;
1754 case ARM::VLD1d8wb_fixed : return true;
1755 case ARM::VLD1d16wb_fixed : return true;
1756 case ARM::VLD1d64Qwb_fixed : return true;
1757 case ARM::VLD1d32wb_fixed : return true;
1758 case ARM::VLD1d64wb_fixed : return true;
1759 case ARM::VLD1d64TPseudoWB_fixed : return true;
1760 case ARM::VLD1d64QPseudoWB_fixed : return true;
1761 case ARM::VLD1q8wb_fixed : return true;
1762 case ARM::VLD1q16wb_fixed : return true;
1763 case ARM::VLD1q32wb_fixed : return true;
1764 case ARM::VLD1q64wb_fixed : return true;
1765 case ARM::VLD2d8wb_fixed : return true;
1766 case ARM::VLD2d16wb_fixed : return true;
1767 case ARM::VLD2d32wb_fixed : return true;
1768 case ARM::VLD2q8PseudoWB_fixed : return true;
1769 case ARM::VLD2q16PseudoWB_fixed : return true;
1770 case ARM::VLD2q32PseudoWB_fixed : return true;
1771 case ARM::VLD2DUPd8wb_fixed : return true;
1772 case ARM::VLD2DUPd16wb_fixed : return true;
1773 case ARM::VLD2DUPd32wb_fixed : return true;
1774 }
1775}
1776
1777static bool isVSTfixed(unsigned Opc)
1778{
1779 switch (Opc) {
1780 default: return false;
1781 case ARM::VST1d8wb_fixed : return true;
1782 case ARM::VST1d16wb_fixed : return true;
1783 case ARM::VST1d32wb_fixed : return true;
1784 case ARM::VST1d64wb_fixed : return true;
Jim Grosbach1a597112014-04-03 23:43:18 +00001785 case ARM::VST1q8wb_fixed : return true;
1786 case ARM::VST1q16wb_fixed : return true;
1787 case ARM::VST1q32wb_fixed : return true;
1788 case ARM::VST1q64wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001789 case ARM::VST1d64TPseudoWB_fixed : return true;
1790 case ARM::VST1d64QPseudoWB_fixed : return true;
1791 case ARM::VST2d8wb_fixed : return true;
1792 case ARM::VST2d16wb_fixed : return true;
1793 case ARM::VST2d32wb_fixed : return true;
1794 case ARM::VST2q8PseudoWB_fixed : return true;
1795 case ARM::VST2q16PseudoWB_fixed : return true;
1796 case ARM::VST2q32PseudoWB_fixed : return true;
1797 }
1798}
1799
Jim Grosbach2098cb12011-10-24 21:45:13 +00001800// Get the register stride update opcode of a VLD/VST instruction that
1801// is otherwise equivalent to the given fixed stride updating instruction.
1802static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
Jiangning Liu4df23632014-01-16 09:16:13 +00001803 assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1804 && "Incorrect fixed stride updating instruction.");
Jim Grosbach2098cb12011-10-24 21:45:13 +00001805 switch (Opc) {
1806 default: break;
1807 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1808 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1809 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1810 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1811 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1812 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1813 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1814 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jiangning Liu4df23632014-01-16 09:16:13 +00001815 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1816 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1817 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1818 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001819
1820 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1821 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1822 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1823 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1824 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1825 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1826 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1827 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001828 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001829 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001830
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001831 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1832 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1833 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001834 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1835 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1836 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1837
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001838 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1839 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1840 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001841 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1842 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1843 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001844
Jim Grosbach13a292c2012-03-06 22:01:44 +00001845 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1846 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1847 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001848 }
1849 return Opc; // If not one we handle, return it unchanged.
1850}
1851
Justin Bogner45571362016-05-12 00:31:09 +00001852void ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
1853 const uint16_t *DOpcodes,
1854 const uint16_t *QOpcodes0,
1855 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001856 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001857 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001858
Bob Wilsonae08a732010-03-20 22:13:40 +00001859 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001860 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1861 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001862 return;
Bob Wilson12b47992009-10-14 17:28:52 +00001863
1864 SDValue Chain = N->getOperand(0);
1865 EVT VT = N->getValueType(0);
1866 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001867 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001868
Bob Wilson12b47992009-10-14 17:28:52 +00001869 unsigned OpcodeIndex;
1870 switch (VT.getSimpleVT().SimpleTy) {
1871 default: llvm_unreachable("unhandled vld type");
1872 // Double-register operations:
1873 case MVT::v8i8: OpcodeIndex = 0; break;
1874 case MVT::v4i16: OpcodeIndex = 1; break;
1875 case MVT::v2f32:
1876 case MVT::v2i32: OpcodeIndex = 2; break;
1877 case MVT::v1i64: OpcodeIndex = 3; break;
1878 // Quad-register operations:
1879 case MVT::v16i8: OpcodeIndex = 0; break;
1880 case MVT::v8i16: OpcodeIndex = 1; break;
1881 case MVT::v4f32:
1882 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001883 case MVT::v2f64:
Bob Wilson340861d2010-03-23 05:25:43 +00001884 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001885 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson340861d2010-03-23 05:25:43 +00001886 break;
Bob Wilson12b47992009-10-14 17:28:52 +00001887 }
1888
Bob Wilson35fafca2010-09-03 18:16:02 +00001889 EVT ResTy;
1890 if (NumVecs == 1)
1891 ResTy = VT;
1892 else {
1893 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1894 if (!is64BitVector)
1895 ResTyElts *= 2;
1896 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1897 }
Bob Wilson06fce872011-02-07 17:43:21 +00001898 std::vector<EVT> ResTys;
1899 ResTys.push_back(ResTy);
1900 if (isUpdating)
1901 ResTys.push_back(MVT::i32);
1902 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001903
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001904 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001905 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001906 SDNode *VLd;
1907 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001908
Bob Wilson06fce872011-02-07 17:43:21 +00001909 // Double registers and VLD1/VLD2 quad registers are directly supported.
1910 if (is64BitVector || NumVecs <= 2) {
1911 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1912 QOpcodes0[OpcodeIndex]);
1913 Ops.push_back(MemAddr);
1914 Ops.push_back(Align);
1915 if (isUpdating) {
1916 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachd146a022011-12-09 21:28:25 +00001917 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach2098cb12011-10-24 21:45:13 +00001918 // case entirely when the rest are updated to that form, too.
Jiangning Liu4df23632014-01-16 09:16:13 +00001919 if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001920 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001921 // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001922 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00001923 if ((NumVecs > 2 && !isVLDfixed(Opc)) ||
Jim Grosbach05df4602011-10-31 21:50:31 +00001924 !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001925 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Evan Cheng630063a2010-05-10 21:26:24 +00001926 }
Bob Wilson06fce872011-02-07 17:43:21 +00001927 Ops.push_back(Pred);
1928 Ops.push_back(Reg0);
1929 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001930 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001931
Bob Wilson12b47992009-10-14 17:28:52 +00001932 } else {
1933 // Otherwise, quad registers are loaded with two separate instructions,
1934 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001935 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001936
Bob Wilson06fce872011-02-07 17:43:21 +00001937 // Load the even subregs. This is always an updating load, so that it
1938 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001939 SDValue ImplDef =
1940 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1941 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001942 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001943 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001944 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001945
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001946 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001947 Ops.push_back(SDValue(VLdA, 1));
1948 Ops.push_back(Align);
1949 if (isUpdating) {
1950 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1951 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1952 "only constant post-increment update allowed for VLD3/4");
1953 (void)Inc;
1954 Ops.push_back(Reg0);
1955 }
1956 Ops.push_back(SDValue(VLdA, 0));
1957 Ops.push_back(Pred);
1958 Ops.push_back(Reg0);
1959 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001960 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001961 }
Bob Wilson12b47992009-10-14 17:28:52 +00001962
Evan Cheng40791332011-04-19 00:04:03 +00001963 // Transfer memoperands.
1964 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1965 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1966 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1967
Justin Bogner45571362016-05-12 00:31:09 +00001968 if (NumVecs == 1) {
1969 ReplaceNode(N, VLd);
1970 return;
1971 }
Bob Wilson06fce872011-02-07 17:43:21 +00001972
1973 // Extract out the subregisters.
1974 SDValue SuperReg = SDValue(VLd, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00001975 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
1976 ARM::qsub_3 == ARM::qsub_0 + 3,
1977 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00001978 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1979 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1980 ReplaceUses(SDValue(N, Vec),
1981 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1982 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1983 if (isUpdating)
1984 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00001985 CurDAG->RemoveDeadNode(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001986}
1987
Justin Bogner45571362016-05-12 00:31:09 +00001988void ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
1989 const uint16_t *DOpcodes,
1990 const uint16_t *QOpcodes0,
1991 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001992 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001993 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001994
Bob Wilsonae08a732010-03-20 22:13:40 +00001995 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001996 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1997 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1998 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001999 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002000
Evan Cheng40791332011-04-19 00:04:03 +00002001 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2002 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2003
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002004 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00002005 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002006 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002007 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00002008
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002009 unsigned OpcodeIndex;
2010 switch (VT.getSimpleVT().SimpleTy) {
2011 default: llvm_unreachable("unhandled vst type");
2012 // Double-register operations:
2013 case MVT::v8i8: OpcodeIndex = 0; break;
2014 case MVT::v4i16: OpcodeIndex = 1; break;
2015 case MVT::v2f32:
2016 case MVT::v2i32: OpcodeIndex = 2; break;
2017 case MVT::v1i64: OpcodeIndex = 3; break;
2018 // Quad-register operations:
2019 case MVT::v16i8: OpcodeIndex = 0; break;
2020 case MVT::v8i16: OpcodeIndex = 1; break;
2021 case MVT::v4f32:
2022 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00002023 case MVT::v2f64:
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00002024 case MVT::v2i64: OpcodeIndex = 3;
2025 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
2026 break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002027 }
2028
Bob Wilson06fce872011-02-07 17:43:21 +00002029 std::vector<EVT> ResTys;
2030 if (isUpdating)
2031 ResTys.push_back(MVT::i32);
2032 ResTys.push_back(MVT::Other);
2033
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002034 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002035 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00002036 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00002037
Bob Wilson06fce872011-02-07 17:43:21 +00002038 // Double registers and VST1/VST2 quad registers are directly supported.
2039 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00002040 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00002041 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00002042 SrcReg = N->getOperand(Vec0Idx);
2043 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00002044 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00002045 SDValue V0 = N->getOperand(Vec0Idx + 0);
2046 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00002047 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002048 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002049 else {
Bob Wilson06fce872011-02-07 17:43:21 +00002050 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00002051 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00002052 // an undef.
2053 SDValue V3 = (NumVecs == 3)
2054 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002055 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002056 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002057 }
Bob Wilson950882b2010-08-28 05:12:57 +00002058 } else {
2059 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00002060 SDValue Q0 = N->getOperand(Vec0Idx);
2061 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00002062 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002063 }
Bob Wilson06fce872011-02-07 17:43:21 +00002064
2065 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2066 QOpcodes0[OpcodeIndex]);
2067 Ops.push_back(MemAddr);
2068 Ops.push_back(Align);
2069 if (isUpdating) {
2070 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbach88ac7612011-12-14 21:32:11 +00002071 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach05df4602011-10-31 21:50:31 +00002072 // case entirely when the rest are updated to that form, too.
Jim Grosbach88ac7612011-12-14 21:32:11 +00002073 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach05df4602011-10-31 21:50:31 +00002074 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00002075 // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00002076 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00002077 if (!isa<ConstantSDNode>(Inc.getNode()))
2078 Ops.push_back(Inc);
2079 else if (NumVecs > 2 && !isVSTfixed(Opc))
2080 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002081 }
2082 Ops.push_back(SrcReg);
2083 Ops.push_back(Pred);
2084 Ops.push_back(Reg0);
2085 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00002086 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002087
2088 // Transfer memoperands.
2089 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
2090
Justin Bogner45571362016-05-12 00:31:09 +00002091 ReplaceNode(N, VSt);
2092 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002093 }
2094
2095 // Otherwise, quad registers are stored with two separate instructions,
2096 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00002097
Bob Wilson01ac8f92010-06-16 21:34:01 +00002098 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00002099 SDValue V0 = N->getOperand(Vec0Idx + 0);
2100 SDValue V1 = N->getOperand(Vec0Idx + 1);
2101 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00002102 SDValue V3 = (NumVecs == 3)
2103 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002104 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002105 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002106
Bob Wilson06fce872011-02-07 17:43:21 +00002107 // Store the even D registers. This is always an updating store, so that it
2108 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00002109 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2110 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2111 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00002112 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00002113 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002114 Chain = SDValue(VStA, 1);
2115
2116 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00002117 Ops.push_back(SDValue(VStA, 0));
2118 Ops.push_back(Align);
2119 if (isUpdating) {
2120 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2121 assert(isa<ConstantSDNode>(Inc.getNode()) &&
2122 "only constant post-increment update allowed for VST3/4");
2123 (void)Inc;
2124 Ops.push_back(Reg0);
2125 }
2126 Ops.push_back(RegSeq);
2127 Ops.push_back(Pred);
2128 Ops.push_back(Reg0);
2129 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00002130 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00002131 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002132 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002133 ReplaceNode(N, VStB);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002134}
2135
Justin Bogner45571362016-05-12 00:31:09 +00002136void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
2137 unsigned NumVecs,
2138 const uint16_t *DOpcodes,
2139 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002140 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002141 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002142
Bob Wilsonae08a732010-03-20 22:13:40 +00002143 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00002144 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2145 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2146 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002147 return;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002148
Evan Cheng40791332011-04-19 00:04:03 +00002149 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2150 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2151
Bob Wilson4145e3a2009-10-14 16:19:03 +00002152 SDValue Chain = N->getOperand(0);
2153 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002154 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2155 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002156 bool is64BitVector = VT.is64BitVector();
2157
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002158 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002159 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002160 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Sanjay Patel1ed771f2016-09-14 16:37:15 +00002161 unsigned NumBytes = NumVecs * VT.getScalarSizeInBits() / 8;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002162 if (Alignment > NumBytes)
2163 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002164 if (Alignment < 8 && Alignment < NumBytes)
2165 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002166 // Alignment must be a power of two; make sure of that.
2167 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002168 if (Alignment == 1)
2169 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002170 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002171 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002172
Bob Wilson4145e3a2009-10-14 16:19:03 +00002173 unsigned OpcodeIndex;
2174 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002175 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002176 // Double-register operations:
2177 case MVT::v8i8: OpcodeIndex = 0; break;
2178 case MVT::v4i16: OpcodeIndex = 1; break;
2179 case MVT::v2f32:
2180 case MVT::v2i32: OpcodeIndex = 2; break;
2181 // Quad-register operations:
2182 case MVT::v8i16: OpcodeIndex = 0; break;
2183 case MVT::v4f32:
2184 case MVT::v4i32: OpcodeIndex = 1; break;
2185 }
2186
Bob Wilson06fce872011-02-07 17:43:21 +00002187 std::vector<EVT> ResTys;
2188 if (IsLoad) {
2189 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2190 if (!is64BitVector)
2191 ResTyElts *= 2;
2192 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2193 MVT::i64, ResTyElts));
2194 }
2195 if (isUpdating)
2196 ResTys.push_back(MVT::i32);
2197 ResTys.push_back(MVT::Other);
2198
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002199 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002200 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002201
Bob Wilson06fce872011-02-07 17:43:21 +00002202 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002203 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002204 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002205 if (isUpdating) {
2206 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2207 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
2208 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002209
Bob Wilsond5c57a52010-09-13 23:01:35 +00002210 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002211 SDValue V0 = N->getOperand(Vec0Idx + 0);
2212 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002213 if (NumVecs == 2) {
2214 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002215 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002216 else
Weiming Zhao95782222012-11-17 00:23:35 +00002217 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002218 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002219 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002220 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002221 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2222 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002223 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002224 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002225 else
Weiming Zhao95782222012-11-17 00:23:35 +00002226 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002227 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002228 Ops.push_back(SuperReg);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002229 Ops.push_back(getI32Imm(Lane, dl));
Evan Chenga33fc862009-11-21 06:21:52 +00002230 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002231 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002232 Ops.push_back(Chain);
2233
Bob Wilson06fce872011-02-07 17:43:21 +00002234 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2235 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002236 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002237 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002238 if (!IsLoad) {
2239 ReplaceNode(N, VLdLn);
2240 return;
2241 }
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002242
Bob Wilsond5c57a52010-09-13 23:01:35 +00002243 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002244 SuperReg = SDValue(VLdLn, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00002245 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2246 ARM::qsub_3 == ARM::qsub_0 + 3,
2247 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00002248 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002249 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2250 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002251 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2252 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2253 if (isUpdating)
2254 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002255 CurDAG->RemoveDeadNode(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002256}
2257
Justin Bogner45571362016-05-12 00:31:09 +00002258void ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
2259 const uint16_t *Opcodes) {
Bob Wilson2d790df2010-11-28 06:51:26 +00002260 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002261 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002262
2263 SDValue MemAddr, Align;
2264 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002265 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00002266
Evan Cheng40791332011-04-19 00:04:03 +00002267 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2268 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2269
Bob Wilson2d790df2010-11-28 06:51:26 +00002270 SDValue Chain = N->getOperand(0);
2271 EVT VT = N->getValueType(0);
2272
2273 unsigned Alignment = 0;
2274 if (NumVecs != 3) {
2275 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Sanjay Patel1ed771f2016-09-14 16:37:15 +00002276 unsigned NumBytes = NumVecs * VT.getScalarSizeInBits() / 8;
Bob Wilson2d790df2010-11-28 06:51:26 +00002277 if (Alignment > NumBytes)
2278 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002279 if (Alignment < 8 && Alignment < NumBytes)
2280 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002281 // Alignment must be a power of two; make sure of that.
2282 Alignment = (Alignment & -Alignment);
2283 if (Alignment == 1)
2284 Alignment = 0;
2285 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002286 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson2d790df2010-11-28 06:51:26 +00002287
2288 unsigned OpcodeIndex;
2289 switch (VT.getSimpleVT().SimpleTy) {
2290 default: llvm_unreachable("unhandled vld-dup type");
2291 case MVT::v8i8: OpcodeIndex = 0; break;
2292 case MVT::v4i16: OpcodeIndex = 1; break;
2293 case MVT::v2f32:
2294 case MVT::v2i32: OpcodeIndex = 2; break;
2295 }
2296
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002297 SDValue Pred = getAL(CurDAG, dl);
Bob Wilson2d790df2010-11-28 06:51:26 +00002298 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2299 SDValue SuperReg;
2300 unsigned Opc = Opcodes[OpcodeIndex];
Bob Wilson06fce872011-02-07 17:43:21 +00002301 SmallVector<SDValue, 6> Ops;
2302 Ops.push_back(MemAddr);
2303 Ops.push_back(Align);
2304 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002305 // fixed-stride update instructions don't have an explicit writeback
2306 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002307 SDValue Inc = N->getOperand(2);
Jim Grosbachc80a2642011-12-21 19:40:55 +00002308 if (!isa<ConstantSDNode>(Inc.getNode()))
2309 Ops.push_back(Inc);
2310 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2311 else if (NumVecs > 2)
2312 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002313 }
2314 Ops.push_back(Pred);
2315 Ops.push_back(Reg0);
2316 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002317
2318 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002319 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002320 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002321 if (isUpdating)
2322 ResTys.push_back(MVT::i32);
2323 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002324 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002325 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002326 SuperReg = SDValue(VLdDup, 0);
Bob Wilson2d790df2010-11-28 06:51:26 +00002327
2328 // Extract the subregisters.
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00002329 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7, "Unexpected subreg numbering");
Bob Wilson2d790df2010-11-28 06:51:26 +00002330 unsigned SubIdx = ARM::dsub_0;
2331 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2332 ReplaceUses(SDValue(N, Vec),
2333 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Bob Wilson06fce872011-02-07 17:43:21 +00002334 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2335 if (isUpdating)
2336 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002337 CurDAG->RemoveDeadNode(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002338}
2339
Justin Bogner45571362016-05-12 00:31:09 +00002340void ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2341 unsigned Opc) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00002342 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002343 SDLoc dl(N);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002344 EVT VT = N->getValueType(0);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002345 unsigned FirstTblReg = IsExt ? 2 : 1;
Bob Wilson3ed511b2010-07-06 23:36:25 +00002346
2347 // Form a REG_SEQUENCE to force register allocation.
2348 SDValue RegSeq;
Bob Wilson5bc8a792010-07-07 00:08:54 +00002349 SDValue V0 = N->getOperand(FirstTblReg + 0);
2350 SDValue V1 = N->getOperand(FirstTblReg + 1);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002351 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002352 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002353 else {
Bob Wilson5bc8a792010-07-07 00:08:54 +00002354 SDValue V2 = N->getOperand(FirstTblReg + 2);
Jim Grosbachd37f0712010-10-21 19:38:40 +00002355 // If it's a vtbl3, form a quad D-register and leave the last part as
Bob Wilson3ed511b2010-07-06 23:36:25 +00002356 // an undef.
2357 SDValue V3 = (NumVecs == 3)
2358 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson5bc8a792010-07-07 00:08:54 +00002359 : N->getOperand(FirstTblReg + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002360 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002361 }
2362
Bob Wilson5bc8a792010-07-07 00:08:54 +00002363 SmallVector<SDValue, 6> Ops;
2364 if (IsExt)
2365 Ops.push_back(N->getOperand(1));
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00002366 Ops.push_back(RegSeq);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002367 Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002368 Ops.push_back(getAL(CurDAG, dl)); // predicate
Bob Wilson3ed511b2010-07-06 23:36:25 +00002369 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
Justin Bogner45571362016-05-12 00:31:09 +00002370 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
Bob Wilson3ed511b2010-07-06 23:36:25 +00002371}
2372
Justin Bogner45571362016-05-12 00:31:09 +00002373bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002374 if (!Subtarget->hasV6T2Ops())
Justin Bogner45571362016-05-12 00:31:09 +00002375 return false;
Bob Wilson93117bc2009-10-14 16:46:45 +00002376
Evan Chengeae6d2c2012-12-19 20:16:09 +00002377 unsigned Opc = isSigned
2378 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002379 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002380 SDLoc dl(N);
Jim Grosbach825cb292010-04-22 23:24:18 +00002381
Jim Grosbach825cb292010-04-22 23:24:18 +00002382 // For unsigned extracts, check for a shift right and mask
2383 unsigned And_imm = 0;
2384 if (N->getOpcode() == ISD::AND) {
2385 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2386
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002387 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002388 if (And_imm & (And_imm + 1))
Justin Bogner45571362016-05-12 00:31:09 +00002389 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002390
2391 unsigned Srl_imm = 0;
2392 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2393 Srl_imm)) {
2394 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2395
Jim Grosbach03f56d92011-07-27 21:09:25 +00002396 // Note: The width operand is encoded as width-1.
Benjamin Kramer5f6a9072015-02-12 15:35:40 +00002397 unsigned Width = countTrailingOnes(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002398 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002399
Jim Grosbach825cb292010-04-22 23:24:18 +00002400 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002401
2402 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2403 // It's cheaper to use a right shift to extract the top bits.
2404 if (Subtarget->isThumb()) {
2405 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2406 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002407 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2408 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002409 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2410 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002411 }
2412
2413 // ARM models shift instructions as MOVsi with shifter operand.
2414 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2415 SDValue ShOpc =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002416 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), dl,
Evan Chengeae6d2c2012-12-19 20:16:09 +00002417 MVT::i32);
2418 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002419 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002420 CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops);
2421 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002422 }
2423
Jim Grosbach825cb292010-04-22 23:24:18 +00002424 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002425 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2426 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2427 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002428 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2429 return true;
Jim Grosbach825cb292010-04-22 23:24:18 +00002430 }
2431 }
Justin Bogner45571362016-05-12 00:31:09 +00002432 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002433 }
2434
2435 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002436 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002437 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002438 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2439 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002440 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002441 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002442 // Note: The width operand is encoded as width-1.
2443 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002444 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002445 if (LSB < 0)
Justin Bogner45571362016-05-12 00:31:09 +00002446 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002447 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002448 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002449 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2450 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2451 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002452 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2453 return true;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002454 }
2455 }
Tim Northover14ff2df2014-07-23 13:59:12 +00002456
Oliver Stannard92ca83c2016-06-01 12:01:01 +00002457 // Or we are looking for a shift of an and, with a mask operand
2458 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, And_imm) &&
2459 isShiftedMask_32(And_imm)) {
2460 unsigned Srl_imm = 0;
2461 unsigned LSB = countTrailingZeros(And_imm);
2462 // Shift must be the same as the ands lsb
2463 if (isInt32Immediate(N->getOperand(1), Srl_imm) && Srl_imm == LSB) {
2464 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2465 unsigned MSB = 31 - countLeadingZeros(And_imm);
2466 // Note: The width operand is encoded as width-1.
2467 unsigned Width = MSB - LSB;
2468 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2469 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2470 CurDAG->getTargetConstant(Srl_imm, dl, MVT::i32),
2471 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2472 getAL(CurDAG, dl), Reg0 };
2473 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2474 return true;
2475 }
2476 }
2477
Tim Northover14ff2df2014-07-23 13:59:12 +00002478 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
2479 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2480 unsigned LSB = 0;
2481 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) &&
2482 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB))
Justin Bogner45571362016-05-12 00:31:09 +00002483 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002484
2485 if (LSB + Width > 32)
Justin Bogner45571362016-05-12 00:31:09 +00002486 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002487
2488 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2489 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002490 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2491 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
2492 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002493 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2494 return true;
Tim Northover14ff2df2014-07-23 13:59:12 +00002495 }
2496
Justin Bogner45571362016-05-12 00:31:09 +00002497 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002498}
2499
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002500/// Target-specific DAG combining for ISD::XOR.
2501/// Target-independent combining lowers SELECT_CC nodes of the form
2502/// select_cc setg[ge] X, 0, X, -X
2503/// select_cc setgt X, -1, X, -X
2504/// select_cc setl[te] X, 0, -X, X
2505/// select_cc setlt X, 1, -X, X
2506/// which represent Integer ABS into:
2507/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2508/// ARM instruction selection detects the latter and matches it to
2509/// ARM::ABS or ARM::t2ABS machine node.
Justin Bogner45571362016-05-12 00:31:09 +00002510bool ARMDAGToDAGISel::tryABSOp(SDNode *N){
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002511 SDValue XORSrc0 = N->getOperand(0);
2512 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002513 EVT VT = N->getValueType(0);
2514
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002515 if (Subtarget->isThumb1Only())
Justin Bogner45571362016-05-12 00:31:09 +00002516 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002517
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002518 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Justin Bogner45571362016-05-12 00:31:09 +00002519 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002520
2521 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2522 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2523 SDValue SRASrc0 = XORSrc1.getOperand(0);
2524 SDValue SRASrc1 = XORSrc1.getOperand(1);
2525 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2526 EVT XType = SRASrc0.getValueType();
2527 unsigned Size = XType.getSizeInBits() - 1;
2528
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002529 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
Craig Topper062a2ba2014-04-25 05:30:21 +00002530 XType.isInteger() && SRAConstant != nullptr &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002531 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002532 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Justin Bogner45571362016-05-12 00:31:09 +00002533 CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2534 return true;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002535 }
2536
Justin Bogner45571362016-05-12 00:31:09 +00002537 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002538}
2539
Sam Parker2d5126c2016-04-08 16:02:53 +00002540static bool SearchSignedMulShort(SDValue SignExt, unsigned *Opc, SDValue &Src1,
2541 bool Accumulate) {
2542 // For SM*WB, we need to some form of sext.
2543 // For SM*WT, we need to search for (sra X, 16)
2544 // Src1 then gets set to X.
2545 if ((SignExt.getOpcode() == ISD::SIGN_EXTEND ||
2546 SignExt.getOpcode() == ISD::SIGN_EXTEND_INREG ||
2547 SignExt.getOpcode() == ISD::AssertSext) &&
2548 SignExt.getValueType() == MVT::i32) {
2549
2550 *Opc = Accumulate ? ARM::SMLAWB : ARM::SMULWB;
2551 Src1 = SignExt.getOperand(0);
2552 return true;
2553 }
2554
2555 if (SignExt.getOpcode() != ISD::SRA)
2556 return false;
2557
2558 ConstantSDNode *SRASrc1 = dyn_cast<ConstantSDNode>(SignExt.getOperand(1));
2559 if (!SRASrc1 || SRASrc1->getZExtValue() != 16)
2560 return false;
2561
2562 SDValue Op0 = SignExt.getOperand(0);
2563
2564 // The sign extend operand for SM*WB could be generated by a shl and ashr.
2565 if (Op0.getOpcode() == ISD::SHL) {
2566 SDValue SHL = Op0;
2567 ConstantSDNode *SHLSrc1 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
2568 if (!SHLSrc1 || SHLSrc1->getZExtValue() != 16)
2569 return false;
2570
2571 *Opc = Accumulate ? ARM::SMLAWB : ARM::SMULWB;
2572 Src1 = Op0.getOperand(0);
2573 return true;
2574 }
2575 *Opc = Accumulate ? ARM::SMLAWT : ARM::SMULWT;
2576 Src1 = SignExt.getOperand(0);
2577 return true;
2578}
2579
2580static bool SearchSignedMulLong(SDValue OR, unsigned *Opc, SDValue &Src0,
2581 SDValue &Src1, bool Accumulate) {
2582 // First we look for:
2583 // (add (or (srl ?, 16), (shl ?, 16)))
2584 if (OR.getOpcode() != ISD::OR)
2585 return false;
2586
2587 SDValue SRL = OR.getOperand(0);
2588 SDValue SHL = OR.getOperand(1);
2589
2590 if (SRL.getOpcode() != ISD::SRL || SHL.getOpcode() != ISD::SHL) {
2591 SRL = OR.getOperand(1);
2592 SHL = OR.getOperand(0);
2593 if (SRL.getOpcode() != ISD::SRL || SHL.getOpcode() != ISD::SHL)
2594 return false;
2595 }
2596
2597 ConstantSDNode *SRLSrc1 = dyn_cast<ConstantSDNode>(SRL.getOperand(1));
2598 ConstantSDNode *SHLSrc1 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
2599 if (!SRLSrc1 || !SHLSrc1 || SRLSrc1->getZExtValue() != 16 ||
2600 SHLSrc1->getZExtValue() != 16)
2601 return false;
2602
2603 // The first operands to the shifts need to be the two results from the
2604 // same smul_lohi node.
2605 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
2606 SRL.getOperand(0).getOpcode() != ISD::SMUL_LOHI)
2607 return false;
2608
2609 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
2610 if (SRL.getOperand(0) != SDValue(SMULLOHI, 0) ||
2611 SHL.getOperand(0) != SDValue(SMULLOHI, 1))
2612 return false;
2613
2614 // Now we have:
2615 // (add (or (srl (smul_lohi ?, ?), 16), (shl (smul_lohi ?, ?), 16)))
2616 // For SMLAW[B|T] smul_lohi will take a 32-bit and a 16-bit arguments.
2617 // For SMLAWB the 16-bit value will signed extended somehow.
2618 // For SMLAWT only the SRA is required.
2619
2620 // Check both sides of SMUL_LOHI
2621 if (SearchSignedMulShort(SMULLOHI->getOperand(0), Opc, Src1, Accumulate)) {
2622 Src0 = SMULLOHI->getOperand(1);
2623 } else if (SearchSignedMulShort(SMULLOHI->getOperand(1), Opc, Src1,
2624 Accumulate)) {
2625 Src0 = SMULLOHI->getOperand(0);
2626 } else {
2627 return false;
2628 }
2629 return true;
2630}
2631
Justin Bogner45571362016-05-12 00:31:09 +00002632bool ARMDAGToDAGISel::trySMLAWSMULW(SDNode *N) {
Sam Parkerd5ca0a62016-07-25 10:11:00 +00002633 if (!Subtarget->hasV6Ops() ||
2634 (Subtarget->isThumb() && !Subtarget->hasThumb2()))
2635 return false;
2636
Sam Parker2d5126c2016-04-08 16:02:53 +00002637 SDLoc dl(N);
2638 SDValue Src0 = N->getOperand(0);
2639 SDValue Src1 = N->getOperand(1);
2640 SDValue A, B;
2641 unsigned Opc = 0;
2642
2643 if (N->getOpcode() == ISD::ADD) {
2644 if (Src0.getOpcode() != ISD::OR && Src1.getOpcode() != ISD::OR)
Justin Bogner45571362016-05-12 00:31:09 +00002645 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002646
2647 SDValue Acc;
2648 if (SearchSignedMulLong(Src0, &Opc, A, B, true)) {
2649 Acc = Src1;
2650 } else if (SearchSignedMulLong(Src1, &Opc, A, B, true)) {
2651 Acc = Src0;
2652 } else {
Justin Bogner45571362016-05-12 00:31:09 +00002653 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002654 }
2655 if (Opc == 0)
Justin Bogner45571362016-05-12 00:31:09 +00002656 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002657
2658 SDValue Ops[] = { A, B, Acc, getAL(CurDAG, dl),
2659 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002660 CurDAG->SelectNodeTo(N, Opc, MVT::i32, MVT::Other, Ops);
2661 return true;
Sam Parker2d5126c2016-04-08 16:02:53 +00002662 } else if (N->getOpcode() == ISD::OR &&
2663 SearchSignedMulLong(SDValue(N, 0), &Opc, A, B, false)) {
2664 if (Opc == 0)
Justin Bogner45571362016-05-12 00:31:09 +00002665 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002666
2667 SDValue Ops[] = { A, B, getAL(CurDAG, dl),
2668 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002669 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2670 return true;
Sam Parker2d5126c2016-04-08 16:02:53 +00002671 }
Justin Bogner45571362016-05-12 00:31:09 +00002672 return false;
Sam Parker2d5126c2016-04-08 16:02:53 +00002673}
2674
Tim Northoverb629c772016-04-18 21:48:55 +00002675/// We've got special pseudo-instructions for these
Justin Bogner45571362016-05-12 00:31:09 +00002676void ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *N) {
Tim Northoverb629c772016-04-18 21:48:55 +00002677 unsigned Opcode;
2678 EVT MemTy = cast<MemSDNode>(N)->getMemoryVT();
2679 if (MemTy == MVT::i8)
2680 Opcode = ARM::CMP_SWAP_8;
2681 else if (MemTy == MVT::i16)
2682 Opcode = ARM::CMP_SWAP_16;
2683 else if (MemTy == MVT::i32)
2684 Opcode = ARM::CMP_SWAP_32;
2685 else
2686 llvm_unreachable("Unknown AtomicCmpSwap type");
2687
2688 SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3),
2689 N->getOperand(0)};
2690 SDNode *CmpSwap = CurDAG->getMachineNode(
2691 Opcode, SDLoc(N),
2692 CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other), Ops);
2693
2694 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2695 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
2696 cast<MachineSDNode>(CmpSwap)->setMemRefs(MemOp, MemOp + 1);
2697
2698 ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0));
2699 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002700 CurDAG->RemoveDeadNode(N);
Tim Northoverb629c772016-04-18 21:48:55 +00002701}
2702
Justin Bogner45571362016-05-12 00:31:09 +00002703void ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
Evan Chengd85631e2010-05-05 18:28:36 +00002704 // The only time a CONCAT_VECTORS operation can have legal types is when
2705 // two 64-bit vectors are concatenated to a 128-bit vector.
2706 EVT VT = N->getValueType(0);
2707 if (!VT.is128BitVector() || N->getNumOperands() != 2)
2708 llvm_unreachable("unexpected CONCAT_VECTORS");
Justin Bogner45571362016-05-12 00:31:09 +00002709 ReplaceNode(N, createDRegPairNode(VT, N->getOperand(0), N->getOperand(1)));
Evan Chengd85631e2010-05-05 18:28:36 +00002710}
2711
Justin Bogner45571362016-05-12 00:31:09 +00002712void ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002713 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002714
Tim Northover31d093c2013-09-22 08:21:56 +00002715 if (N->isMachineOpcode()) {
2716 N->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00002717 return; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00002718 }
Rafael Espindola4e760152006-06-12 12:28:08 +00002719
2720 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002721 default: break;
Sam Parker2d5126c2016-04-08 16:02:53 +00002722 case ISD::ADD:
Justin Bogner45571362016-05-12 00:31:09 +00002723 case ISD::OR:
2724 if (trySMLAWSMULW(N))
2725 return;
Sam Parker2d5126c2016-04-08 16:02:53 +00002726 break;
Justin Bogner45571362016-05-12 00:31:09 +00002727 case ISD::WRITE_REGISTER:
2728 if (tryWriteRegister(N))
2729 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002730 break;
Justin Bogner45571362016-05-12 00:31:09 +00002731 case ISD::READ_REGISTER:
2732 if (tryReadRegister(N))
2733 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002734 break;
Justin Bogner45571362016-05-12 00:31:09 +00002735 case ISD::INLINEASM:
2736 if (tryInlineAsm(N))
2737 return;
Weiming Zhaoc5987002013-02-14 18:10:21 +00002738 break;
Justin Bogner45571362016-05-12 00:31:09 +00002739 case ISD::XOR:
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002740 // Select special operations if XOR node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +00002741 if (tryABSOp(N))
2742 return;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002743 // Other cases are autogenerated.
2744 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002745 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002746 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
John Brawn056e6782015-09-14 15:19:41 +00002747 // If we can't materialize the constant we need to use a literal pool
2748 if (ConstantMaterializationCost(Val) > 2) {
Eric Christopherb17140d2014-10-08 07:32:17 +00002749 SDValue CPIdx = CurDAG->getTargetConstantPool(
2750 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
Mehdi Amini44ede332015-07-09 02:09:04 +00002751 TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng1526ba52007-01-24 08:53:17 +00002752
2753 SDNode *ResNode;
Tim Northover55c625f2014-01-23 13:43:47 +00002754 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002755 SDValue Pred = getAL(CurDAG, dl);
Owen Anderson9f944592009-08-11 20:47:22 +00002756 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002757 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002758 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002759 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002760 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002761 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002762 CPIdx,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002763 CurDAG->getTargetConstant(0, dl, MVT::i32),
2764 getAL(CurDAG, dl),
Owen Anderson9f944592009-08-11 20:47:22 +00002765 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002766 CurDAG->getEntryNode()
2767 };
Justin Bogner45571362016-05-12 00:31:09 +00002768 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
2769 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002770 }
Justin Bognered4f3782016-05-12 00:20:19 +00002771 ReplaceNode(N, ResNode);
Justin Bogner45571362016-05-12 00:31:09 +00002772 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002773 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002774
Evan Cheng10043e22007-01-19 07:51:42 +00002775 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002776 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002777 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002778 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002779 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002780 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00002781 SDValue TFI = CurDAG->getTargetFrameIndex(
2782 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin22c2fba2009-07-08 23:10:31 +00002783 if (Subtarget->isThumb1Only()) {
Renato Golinb9887ef2015-02-25 14:41:06 +00002784 // Set the alignment of the frame object to 4, to avoid having to generate
2785 // more than one ADD
Matthias Braun941a7052016-07-28 18:40:00 +00002786 MachineFrameInfo &MFI = MF->getFrameInfo();
2787 if (MFI.getObjectAlignment(FI) < 4)
2788 MFI.setObjectAlignment(FI, 4);
Justin Bogner45571362016-05-12 00:31:09 +00002789 CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
2790 CurDAG->getTargetConstant(0, dl, MVT::i32));
2791 return;
Jim Grosbachfde21102009-04-07 20:34:09 +00002792 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002793 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2794 ARM::t2ADDri : ARM::ADDri);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002795 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
2796 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002797 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002798 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2799 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00002800 }
Evan Cheng10043e22007-01-19 07:51:42 +00002801 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002802 case ISD::SRL:
Justin Bogner45571362016-05-12 00:31:09 +00002803 if (tryV6T2BitfieldExtractOp(N, false))
2804 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002805 break;
Tim Northover14ff2df2014-07-23 13:59:12 +00002806 case ISD::SIGN_EXTEND_INREG:
Sandeep Patel423e42b2009-10-13 18:59:48 +00002807 case ISD::SRA:
Justin Bogner45571362016-05-12 00:31:09 +00002808 if (tryV6T2BitfieldExtractOp(N, true))
2809 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002810 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002811 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002812 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002813 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002814 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002815 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002816 if (!RHSV) break;
2817 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002818 unsigned ShImm = Log2_32(RHSV-1);
2819 if (ShImm >= 32)
2820 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002821 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002822 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002823 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002824 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002825 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002826 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002827 CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
2828 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002829 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002830 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2831 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002832 CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
2833 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002834 }
Evan Cheng10043e22007-01-19 07:51:42 +00002835 }
2836 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002837 unsigned ShImm = Log2_32(RHSV+1);
2838 if (ShImm >= 32)
2839 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002840 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002841 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002842 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002843 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002844 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002845 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002846 CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
2847 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002848 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002849 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2850 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002851 CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
2852 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002853 }
Evan Cheng10043e22007-01-19 07:51:42 +00002854 }
2855 }
2856 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002857 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002858 // Check for unsigned bitfield extract
Justin Bogner45571362016-05-12 00:31:09 +00002859 if (tryV6T2BitfieldExtractOp(N, false))
2860 return;
Jim Grosbach825cb292010-04-22 23:24:18 +00002861
James Molloyae5ff992016-07-05 12:37:13 +00002862 // If an immediate is used in an AND node, it is possible that the immediate
2863 // can be more optimally materialized when negated. If this is the case we
2864 // can negate the immediate and use a BIC instead.
2865 auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1));
2866 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
2867 uint32_t Imm = (uint32_t) N1C->getZExtValue();
2868
2869 // In Thumb2 mode, an AND can take a 12-bit immediate. If this
2870 // immediate can be negated and fit in the immediate operand of
2871 // a t2BIC, don't do any manual transform here as this can be
2872 // handled by the generic ISel machinery.
2873 bool PreferImmediateEncoding =
2874 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm));
2875 if (!PreferImmediateEncoding &&
2876 ConstantMaterializationCost(Imm) >
2877 ConstantMaterializationCost(~Imm)) {
2878 // The current immediate costs more to materialize than a negated
2879 // immediate, so negate the immediate and use a BIC.
2880 SDValue NewImm =
2881 CurDAG->getConstant(~N1C->getZExtValue(), dl, MVT::i32);
2882 // If the new constant didn't exist before, reposition it in the topological
2883 // ordering so it is just before N. Otherwise, don't touch its location.
2884 if (NewImm->getNodeId() == -1)
2885 CurDAG->RepositionNode(N->getIterator(), NewImm.getNode());
2886
2887 if (!Subtarget->hasThumb2()) {
2888 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
2889 N->getOperand(0), NewImm, getAL(CurDAG, dl),
2890 CurDAG->getRegister(0, MVT::i32)};
2891 ReplaceNode(N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32, Ops));
2892 return;
2893 } else {
2894 SDValue Ops[] = {N->getOperand(0), NewImm, getAL(CurDAG, dl),
2895 CurDAG->getRegister(0, MVT::i32),
2896 CurDAG->getRegister(0, MVT::i32)};
2897 ReplaceNode(N,
2898 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32, Ops));
2899 return;
2900 }
2901 }
2902 }
2903
Evan Cheng786b15f2009-10-21 08:15:52 +00002904 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2905 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2906 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2907 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2908 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002909 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002910 if (VT != MVT::i32)
2911 break;
2912 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2913 ? ARM::t2MOVTi16
2914 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2915 if (!Opc)
2916 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002917 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
James Molloyae5ff992016-07-05 12:37:13 +00002918 N1C = dyn_cast<ConstantSDNode>(N1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002919 if (!N1C)
2920 break;
2921 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2922 SDValue N2 = N0.getOperand(1);
2923 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2924 if (!N2C)
2925 break;
2926 unsigned N1CVal = N1C->getZExtValue();
2927 unsigned N2CVal = N2C->getZExtValue();
2928 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2929 (N1CVal & 0xffffU) == 0xffffU &&
2930 (N2CVal & 0xffffU) == 0x0U) {
2931 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002932 dl, MVT::i32);
Evan Cheng786b15f2009-10-21 08:15:52 +00002933 SDValue Ops[] = { N0.getOperand(0), Imm16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002934 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002935 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
2936 return;
Evan Cheng786b15f2009-10-21 08:15:52 +00002937 }
2938 }
2939 break;
2940 }
Jim Grosbachd7cf55c2009-11-09 00:11:35 +00002941 case ARMISD::VMOVRRD:
Justin Bogner45571362016-05-12 00:31:09 +00002942 ReplaceNode(N, CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
2943 N->getOperand(0), getAL(CurDAG, dl),
2944 CurDAG->getRegister(0, MVT::i32)));
2945 return;
Dan Gohmana1603612007-10-08 18:33:35 +00002946 case ISD::UMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002947 if (Subtarget->isThumb1Only())
2948 break;
2949 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002950 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002951 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002952 ReplaceNode(
2953 N, CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops));
2954 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002955 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002956 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002957 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002958 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002959 ReplaceNode(N, CurDAG->getMachineNode(
2960 Subtarget->hasV6Ops() ? ARM::UMULL : ARM::UMULLv5, dl,
2961 MVT::i32, MVT::i32, Ops));
2962 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002963 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002964 }
Dan Gohmana1603612007-10-08 18:33:35 +00002965 case ISD::SMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002966 if (Subtarget->isThumb1Only())
2967 break;
2968 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002969 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002970 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002971 ReplaceNode(
2972 N, CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops));
2973 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002974 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002975 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002976 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002977 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002978 ReplaceNode(N, CurDAG->getMachineNode(
2979 Subtarget->hasV6Ops() ? ARM::SMULL : ARM::SMULLv5, dl,
2980 MVT::i32, MVT::i32, Ops));
2981 return;
Evan Chengb24e51e2009-07-07 01:17:28 +00002982 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002983 }
Sam Parkerd616cf02016-06-20 16:47:09 +00002984 case ARMISD::UMAAL: {
2985 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
2986 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2987 N->getOperand(2), N->getOperand(3),
2988 getAL(CurDAG, dl),
2989 CurDAG->getRegister(0, MVT::i32) };
2990 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::i32, Ops));
2991 return;
2992 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002993 case ARMISD::UMLAL:{
Sam Parkerd616cf02016-06-20 16:47:09 +00002994 // UMAAL is similar to UMLAL but it adds two 32-bit values to the
2995 // 64-bit multiplication result.
2996 if (Subtarget->hasV6Ops() && N->getOperand(2).getOpcode() == ARMISD::ADDC &&
2997 N->getOperand(3).getOpcode() == ARMISD::ADDE) {
2998
2999 SDValue Addc = N->getOperand(2);
3000 SDValue Adde = N->getOperand(3);
3001
3002 if (Adde.getOperand(2).getNode() == Addc.getNode()) {
3003
3004 ConstantSDNode *Op0 = dyn_cast<ConstantSDNode>(Adde.getOperand(0));
3005 ConstantSDNode *Op1 = dyn_cast<ConstantSDNode>(Adde.getOperand(1));
3006
3007 if (Op0 && Op1 && Op0->getZExtValue() == 0 && Op1->getZExtValue() == 0)
3008 {
3009 // Select UMAAL instead: UMAAL RdLo, RdHi, Rn, Rm
3010 // RdLo = one operand to be added, lower 32-bits of res
3011 // RdHi = other operand to be added, upper 32-bits of res
3012 // Rn = first multiply operand
3013 // Rm = second multiply operand
3014 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
3015 Addc.getOperand(0), Addc.getOperand(1),
3016 getAL(CurDAG, dl),
3017 CurDAG->getRegister(0, MVT::i32) };
3018 unsigned opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
3019 CurDAG->SelectNodeTo(N, opc, MVT::i32, MVT::i32, Ops);
3020 return;
3021 }
3022 }
3023 }
3024
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003025 if (Subtarget->isThumb()) {
3026 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003027 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003028 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00003029 ReplaceNode(
3030 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops));
3031 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003032 }else{
3033 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003034 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003035 CurDAG->getRegister(0, MVT::i32),
3036 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00003037 ReplaceNode(N, CurDAG->getMachineNode(
3038 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl,
3039 MVT::i32, MVT::i32, Ops));
3040 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003041 }
3042 }
3043 case ARMISD::SMLAL:{
3044 if (Subtarget->isThumb()) {
3045 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003046 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003047 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00003048 ReplaceNode(
3049 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops));
3050 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003051 }else{
3052 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003053 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003054 CurDAG->getRegister(0, MVT::i32),
3055 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00003056 ReplaceNode(N, CurDAG->getMachineNode(
3057 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl,
3058 MVT::i32, MVT::i32, Ops));
3059 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00003060 }
3061 }
Sam Parker68c71cd2016-07-25 09:20:20 +00003062 case ARMISD::SUBE: {
3063 if (!Subtarget->hasV6Ops())
3064 break;
3065 // Look for a pattern to match SMMLS
3066 // (sube a, (smul_loHi a, b), (subc 0, (smul_LOhi(a, b))))
3067 if (N->getOperand(1).getOpcode() != ISD::SMUL_LOHI ||
Tim Northover765777c2016-08-02 23:12:36 +00003068 N->getOperand(2).getOpcode() != ARMISD::SUBC ||
3069 !SDValue(N, 1).use_empty())
Sam Parker68c71cd2016-07-25 09:20:20 +00003070 break;
3071
3072 if (Subtarget->isThumb())
3073 assert(Subtarget->hasThumb2() &&
3074 "This pattern should not be generated for Thumb");
3075
3076 SDValue SmulLoHi = N->getOperand(1);
3077 SDValue Subc = N->getOperand(2);
3078 auto *Zero = dyn_cast<ConstantSDNode>(Subc.getOperand(0));
3079
3080 if (!Zero || Zero->getZExtValue() != 0 ||
3081 Subc.getOperand(1) != SmulLoHi.getValue(0) ||
3082 N->getOperand(1) != SmulLoHi.getValue(1) ||
3083 N->getOperand(2) != Subc.getValue(1))
3084 break;
3085
3086 unsigned Opc = Subtarget->isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
3087 SDValue Ops[] = { SmulLoHi.getOperand(0), SmulLoHi.getOperand(1),
3088 N->getOperand(0), getAL(CurDAG, dl),
3089 CurDAG->getRegister(0, MVT::i32) };
3090 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops));
3091 return;
3092 }
Evan Cheng10043e22007-01-19 07:51:42 +00003093 case ISD::LOAD: {
Justin Bogner45571362016-05-12 00:31:09 +00003094 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
3095 if (tryT2IndexedLoad(N))
3096 return;
James Molloyb3326df2016-07-15 08:03:56 +00003097 } else if (Subtarget->isThumb()) {
3098 if (tryT1IndexedLoad(N))
3099 return;
Justin Bogner45571362016-05-12 00:31:09 +00003100 } else if (tryARMIndexedLoad(N))
3101 return;
Evan Cheng10043e22007-01-19 07:51:42 +00003102 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00003103 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00003104 }
Evan Cheng7e90b112007-07-05 07:15:27 +00003105 case ARMISD::BRCOND: {
3106 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
3107 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
3108 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003109
Evan Cheng7e90b112007-07-05 07:15:27 +00003110 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
3111 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
3112 // Pattern complexity = 6 cost = 1 size = 0
3113
David Goodwin27303cd2009-06-30 18:04:13 +00003114 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
3115 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
3116 // Pattern complexity = 6 cost = 1 size = 0
3117
Jim Grosbachf24f9d92009-08-11 15:33:49 +00003118 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00003119 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003120 SDValue Chain = N->getOperand(0);
3121 SDValue N1 = N->getOperand(1);
3122 SDValue N2 = N->getOperand(2);
3123 SDValue N3 = N->getOperand(3);
3124 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00003125 assert(N1.getOpcode() == ISD::BasicBlock);
3126 assert(N2.getOpcode() == ISD::Constant);
3127 assert(N3.getOpcode() == ISD::Register);
3128
James Molloy9790d8f2016-09-14 09:45:28 +00003129 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
3130 cast<ConstantSDNode>(N2)->getZExtValue()), dl,
3131 MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003132 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00003133 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00003134 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003135 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003136 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003137 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003138 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00003139 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003140 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00003141 SDValue(Chain.getNode(), Chain.getResNo()));
Justin Bognered4f3782016-05-12 00:20:19 +00003142 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003143 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00003144 }
James Molloy4d86bed2016-09-09 12:52:24 +00003145
3146 case ARMISD::CMPZ: {
3147 // select (CMPZ X, #-C) -> (CMPZ (ADDS X, #C), #0)
3148 // This allows us to avoid materializing the expensive negative constant.
3149 // The CMPZ #0 is useless and will be peepholed away but we need to keep it
3150 // for its glue output.
3151 SDValue X = N->getOperand(0);
3152 auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1).getNode());
3153 if (C && C->getSExtValue() < 0 && Subtarget->isThumb()) {
3154 int64_t Addend = -C->getSExtValue();
3155
3156 SDNode *Add = nullptr;
3157 // In T2 mode, ADDS can be better than CMN if the immediate fits in a
3158 // 16-bit ADDS, which means either [0,256) for tADDi8 or [0,8) for tADDi3.
3159 // Outside that range we can just use a CMN which is 32-bit but has a
3160 // 12-bit immediate range.
3161 if (Subtarget->isThumb2() && Addend < 1<<8) {
3162 SDValue Ops[] = { X, CurDAG->getTargetConstant(Addend, dl, MVT::i32),
3163 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
3164 CurDAG->getRegister(0, MVT::i32) };
3165 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl, MVT::i32, Ops);
3166 } else if (!Subtarget->isThumb2() && Addend < 1<<8) {
3167 // FIXME: Add T1 tADDi8 code.
3168 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), X,
3169 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
3170 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
3171 Add = CurDAG->getMachineNode(ARM::tADDi8, dl, MVT::i32, Ops);
3172 } else if (!Subtarget->isThumb2() && Addend < 1<<3) {
3173 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), X,
3174 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
3175 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
3176 Add = CurDAG->getMachineNode(ARM::tADDi3, dl, MVT::i32, Ops);
3177 }
3178 if (Add) {
3179 SDValue Ops2[] = {SDValue(Add, 0), CurDAG->getConstant(0, dl, MVT::i32)};
3180 CurDAG->MorphNodeTo(N, ARMISD::CMPZ, CurDAG->getVTList(MVT::Glue), Ops2);
3181 }
3182 }
3183 // Other cases are autogenerated.
3184 break;
3185 }
3186
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003187 case ARMISD::VZIP: {
3188 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003189 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003190 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003191 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003192 case MVT::v8i8: Opc = ARM::VZIPd8; break;
3193 case MVT::v4i16: Opc = ARM::VZIPd16; break;
3194 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00003195 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3196 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003197 case MVT::v16i8: Opc = ARM::VZIPq8; break;
3198 case MVT::v8i16: Opc = ARM::VZIPq16; break;
3199 case MVT::v4f32:
3200 case MVT::v4i32: Opc = ARM::VZIPq32; break;
3201 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003202 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003203 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3204 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003205 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3206 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003207 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003208 case ARMISD::VUZP: {
3209 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003210 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003211 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003212 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003213 case MVT::v8i8: Opc = ARM::VUZPd8; break;
3214 case MVT::v4i16: Opc = ARM::VUZPd16; break;
3215 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00003216 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3217 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003218 case MVT::v16i8: Opc = ARM::VUZPq8; break;
3219 case MVT::v8i16: Opc = ARM::VUZPq16; break;
3220 case MVT::v4f32:
3221 case MVT::v4i32: Opc = ARM::VUZPq32; break;
3222 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003223 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003224 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3225 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003226 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3227 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003228 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003229 case ARMISD::VTRN: {
3230 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003231 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003232 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003233 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003234 case MVT::v8i8: Opc = ARM::VTRNd8; break;
3235 case MVT::v4i16: Opc = ARM::VTRNd16; break;
3236 case MVT::v2f32:
3237 case MVT::v2i32: Opc = ARM::VTRNd32; break;
3238 case MVT::v16i8: Opc = ARM::VTRNq8; break;
3239 case MVT::v8i16: Opc = ARM::VTRNq16; break;
3240 case MVT::v4f32:
3241 case MVT::v4i32: Opc = ARM::VTRNq32; break;
3242 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003243 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003244 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3245 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003246 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3247 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003248 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003249 case ARMISD::BUILD_VECTOR: {
3250 EVT VecVT = N->getValueType(0);
3251 EVT EltVT = VecVT.getVectorElementType();
3252 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00003253 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00003254 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003255 ReplaceNode(
3256 N, createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3257 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003258 }
Duncan Sands14627772010-11-03 12:17:33 +00003259 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003260 if (NumElts == 2) {
3261 ReplaceNode(
3262 N, createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3263 return;
3264 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003265 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003266 ReplaceNode(N,
3267 createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
3268 N->getOperand(2), N->getOperand(3)));
3269 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003270 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003271
Bob Wilson2d790df2010-11-28 06:51:26 +00003272 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003273 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
3274 ARM::VLD2DUPd32 };
Justin Bogner45571362016-05-12 00:31:09 +00003275 SelectVLDDup(N, false, 2, Opcodes);
3276 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00003277 }
3278
Bob Wilson77ab1652010-11-29 19:35:29 +00003279 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003280 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
3281 ARM::VLD3DUPd16Pseudo,
3282 ARM::VLD3DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003283 SelectVLDDup(N, false, 3, Opcodes);
3284 return;
Bob Wilson77ab1652010-11-29 19:35:29 +00003285 }
3286
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003287 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003288 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
3289 ARM::VLD4DUPd16Pseudo,
3290 ARM::VLD4DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003291 SelectVLDDup(N, false, 4, Opcodes);
3292 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003293 }
3294
3295 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003296 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
3297 ARM::VLD2DUPd16wb_fixed,
3298 ARM::VLD2DUPd32wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003299 SelectVLDDup(N, true, 2, Opcodes);
3300 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003301 }
3302
3303 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003304 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
3305 ARM::VLD3DUPd16Pseudo_UPD,
3306 ARM::VLD3DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003307 SelectVLDDup(N, true, 3, Opcodes);
3308 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003309 }
3310
3311 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003312 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
3313 ARM::VLD4DUPd16Pseudo_UPD,
3314 ARM::VLD4DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003315 SelectVLDDup(N, true, 4, Opcodes);
3316 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003317 }
3318
3319 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003320 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
3321 ARM::VLD1d16wb_fixed,
3322 ARM::VLD1d32wb_fixed,
3323 ARM::VLD1d64wb_fixed };
3324 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
3325 ARM::VLD1q16wb_fixed,
3326 ARM::VLD1q32wb_fixed,
3327 ARM::VLD1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003328 SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
3329 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003330 }
3331
3332 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003333 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
3334 ARM::VLD2d16wb_fixed,
3335 ARM::VLD2d32wb_fixed,
3336 ARM::VLD1q64wb_fixed};
3337 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
3338 ARM::VLD2q16PseudoWB_fixed,
3339 ARM::VLD2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003340 SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
3341 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003342 }
3343
3344 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003345 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
3346 ARM::VLD3d16Pseudo_UPD,
3347 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003348 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003349 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3350 ARM::VLD3q16Pseudo_UPD,
3351 ARM::VLD3q32Pseudo_UPD };
3352 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3353 ARM::VLD3q16oddPseudo_UPD,
3354 ARM::VLD3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003355 SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3356 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003357 }
3358
3359 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003360 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3361 ARM::VLD4d16Pseudo_UPD,
3362 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003363 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003364 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3365 ARM::VLD4q16Pseudo_UPD,
3366 ARM::VLD4q32Pseudo_UPD };
3367 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3368 ARM::VLD4q16oddPseudo_UPD,
3369 ARM::VLD4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003370 SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3371 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003372 }
3373
3374 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003375 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3376 ARM::VLD2LNd16Pseudo_UPD,
3377 ARM::VLD2LNd32Pseudo_UPD };
3378 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3379 ARM::VLD2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003380 SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3381 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003382 }
3383
3384 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003385 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3386 ARM::VLD3LNd16Pseudo_UPD,
3387 ARM::VLD3LNd32Pseudo_UPD };
3388 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3389 ARM::VLD3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003390 SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3391 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003392 }
3393
3394 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003395 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3396 ARM::VLD4LNd16Pseudo_UPD,
3397 ARM::VLD4LNd32Pseudo_UPD };
3398 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3399 ARM::VLD4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003400 SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3401 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003402 }
3403
3404 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003405 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3406 ARM::VST1d16wb_fixed,
3407 ARM::VST1d32wb_fixed,
3408 ARM::VST1d64wb_fixed };
3409 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3410 ARM::VST1q16wb_fixed,
3411 ARM::VST1q32wb_fixed,
3412 ARM::VST1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003413 SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
3414 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003415 }
3416
3417 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003418 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3419 ARM::VST2d16wb_fixed,
3420 ARM::VST2d32wb_fixed,
3421 ARM::VST1q64wb_fixed};
3422 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3423 ARM::VST2q16PseudoWB_fixed,
3424 ARM::VST2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003425 SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
3426 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003427 }
3428
3429 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003430 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3431 ARM::VST3d16Pseudo_UPD,
3432 ARM::VST3d32Pseudo_UPD,
3433 ARM::VST1d64TPseudoWB_fixed};
3434 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3435 ARM::VST3q16Pseudo_UPD,
3436 ARM::VST3q32Pseudo_UPD };
3437 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3438 ARM::VST3q16oddPseudo_UPD,
3439 ARM::VST3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003440 SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3441 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003442 }
3443
3444 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003445 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3446 ARM::VST4d16Pseudo_UPD,
3447 ARM::VST4d32Pseudo_UPD,
3448 ARM::VST1d64QPseudoWB_fixed};
3449 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3450 ARM::VST4q16Pseudo_UPD,
3451 ARM::VST4q32Pseudo_UPD };
3452 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3453 ARM::VST4q16oddPseudo_UPD,
3454 ARM::VST4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003455 SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3456 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003457 }
3458
3459 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003460 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3461 ARM::VST2LNd16Pseudo_UPD,
3462 ARM::VST2LNd32Pseudo_UPD };
3463 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3464 ARM::VST2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003465 SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3466 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003467 }
3468
3469 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003470 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3471 ARM::VST3LNd16Pseudo_UPD,
3472 ARM::VST3LNd32Pseudo_UPD };
3473 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3474 ARM::VST3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003475 SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3476 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003477 }
3478
3479 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003480 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3481 ARM::VST4LNd16Pseudo_UPD,
3482 ARM::VST4LNd32Pseudo_UPD };
3483 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3484 ARM::VST4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003485 SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
3486 return;
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003487 }
3488
Bob Wilsone0636a72009-08-26 17:39:53 +00003489 case ISD::INTRINSIC_VOID:
3490 case ISD::INTRINSIC_W_CHAIN: {
3491 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003492 switch (IntNo) {
3493 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003494 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003495
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003496 case Intrinsic::arm_mrrc:
3497 case Intrinsic::arm_mrrc2: {
3498 SDLoc dl(N);
3499 SDValue Chain = N->getOperand(0);
3500 unsigned Opc;
3501
3502 if (Subtarget->isThumb())
3503 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
3504 else
3505 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
3506
3507 SmallVector<SDValue, 5> Ops;
3508 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(), dl)); /* coproc */
3509 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(), dl)); /* opc */
3510 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(4))->getZExtValue(), dl)); /* CRm */
3511
3512 // The mrrc2 instruction in ARM doesn't allow predicates, the top 4 bits of the encoded
3513 // instruction will always be '1111' but it is possible in assembly language to specify
3514 // AL as a predicate to mrrc2 but it doesn't make any difference to the encoded instruction.
3515 if (Opc != ARM::MRRC2) {
3516 Ops.push_back(getAL(CurDAG, dl));
3517 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3518 }
3519
3520 Ops.push_back(Chain);
3521
3522 // Writes to two registers.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003523 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003524
3525 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, RetType, Ops));
3526 return;
3527 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003528 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003529 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003530 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003531 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003532 SDValue MemAddr = N->getOperand(2);
Bradley Smith433c22e2016-01-15 10:26:51 +00003533 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
Tim Northover1ff5f292014-03-26 14:39:31 +00003534
3535 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3536 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3537 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003538
3539 // arm_ldrexd returns a i64 value in {i32, i32}
3540 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003541 if (isThumb) {
3542 ResTys.push_back(MVT::i32);
3543 ResTys.push_back(MVT::i32);
3544 } else
3545 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003546 ResTys.push_back(MVT::Other);
3547
Weiming Zhao8f56f882012-11-16 21:55:34 +00003548 // Place arguments in the right order.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003549 SDValue Ops[] = {MemAddr, getAL(CurDAG, dl),
3550 CurDAG->getRegister(0, MVT::i32), Chain};
Michael Liaob53d8962013-04-19 22:22:57 +00003551 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003552 // Transfer memoperands.
3553 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3554 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3555 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3556
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003557 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003558 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003559 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003560 SDValue Result;
3561 if (isThumb)
3562 Result = SDValue(Ld, 0);
3563 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003564 SDValue SubRegIdx =
3565 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003566 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003567 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003568 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003569 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003570 ReplaceUses(SDValue(N, 0), Result);
3571 }
3572 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003573 SDValue Result;
3574 if (isThumb)
3575 Result = SDValue(Ld, 1);
3576 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003577 SDValue SubRegIdx =
3578 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003579 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003580 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003581 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003582 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003583 ReplaceUses(SDValue(N, 1), Result);
3584 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003585 ReplaceUses(SDValue(N, 2), OutChain);
Justin Bognered4f3782016-05-12 00:20:19 +00003586 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003587 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003588 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003589 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003590 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003591 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003592 SDValue Chain = N->getOperand(0);
3593 SDValue Val0 = N->getOperand(2);
3594 SDValue Val1 = N->getOperand(3);
3595 SDValue MemAddr = N->getOperand(4);
3596
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003597 // Store exclusive double return a i32 value which is the return status
3598 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003599 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003600
Weiming Zhao8f56f882012-11-16 21:55:34 +00003601 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3602 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003603 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003604 if (isThumb) {
3605 Ops.push_back(Val0);
3606 Ops.push_back(Val1);
3607 } else
3608 // arm_strexd uses GPRPair.
3609 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003610 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003611 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003612 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3613 Ops.push_back(Chain);
3614
Tim Northover1ff5f292014-03-26 14:39:31 +00003615 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3616 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3617 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003618
Michael Liaob53d8962013-04-19 22:22:57 +00003619 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003620 // Transfer memoperands.
3621 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3622 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3623 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3624
Justin Bogner45571362016-05-12 00:31:09 +00003625 ReplaceNode(N, St);
3626 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003627 }
3628
Bob Wilson340861d2010-03-23 05:25:43 +00003629 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003630 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3631 ARM::VLD1d32, ARM::VLD1d64 };
3632 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3633 ARM::VLD1q32, ARM::VLD1q64};
Justin Bogner45571362016-05-12 00:31:09 +00003634 SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
3635 return;
Bob Wilson340861d2010-03-23 05:25:43 +00003636 }
3637
Bob Wilsone0636a72009-08-26 17:39:53 +00003638 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003639 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3640 ARM::VLD2d32, ARM::VLD1q64 };
3641 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3642 ARM::VLD2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003643 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3644 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003645 }
3646
3647 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003648 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3649 ARM::VLD3d16Pseudo,
3650 ARM::VLD3d32Pseudo,
3651 ARM::VLD1d64TPseudo };
3652 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3653 ARM::VLD3q16Pseudo_UPD,
3654 ARM::VLD3q32Pseudo_UPD };
3655 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3656 ARM::VLD3q16oddPseudo,
3657 ARM::VLD3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003658 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3659 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003660 }
3661
3662 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003663 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3664 ARM::VLD4d16Pseudo,
3665 ARM::VLD4d32Pseudo,
3666 ARM::VLD1d64QPseudo };
3667 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3668 ARM::VLD4q16Pseudo_UPD,
3669 ARM::VLD4q32Pseudo_UPD };
3670 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3671 ARM::VLD4q16oddPseudo,
3672 ARM::VLD4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003673 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3674 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003675 }
3676
Bob Wilsonda9817c2009-09-01 04:26:28 +00003677 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003678 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3679 ARM::VLD2LNd16Pseudo,
3680 ARM::VLD2LNd32Pseudo };
3681 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3682 ARM::VLD2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003683 SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
3684 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003685 }
3686
3687 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003688 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3689 ARM::VLD3LNd16Pseudo,
3690 ARM::VLD3LNd32Pseudo };
3691 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3692 ARM::VLD3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003693 SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
3694 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003695 }
3696
3697 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003698 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3699 ARM::VLD4LNd16Pseudo,
3700 ARM::VLD4LNd32Pseudo };
3701 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3702 ARM::VLD4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003703 SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
3704 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003705 }
3706
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003707 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003708 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3709 ARM::VST1d32, ARM::VST1d64 };
3710 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3711 ARM::VST1q32, ARM::VST1q64 };
Justin Bogner45571362016-05-12 00:31:09 +00003712 SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
3713 return;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003714 }
3715
Bob Wilsone0636a72009-08-26 17:39:53 +00003716 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003717 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3718 ARM::VST2d32, ARM::VST1q64 };
Benjamin Kramerf690da42016-06-17 14:14:29 +00003719 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3720 ARM::VST2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003721 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3722 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003723 }
3724
3725 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003726 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3727 ARM::VST3d16Pseudo,
3728 ARM::VST3d32Pseudo,
3729 ARM::VST1d64TPseudo };
3730 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3731 ARM::VST3q16Pseudo_UPD,
3732 ARM::VST3q32Pseudo_UPD };
3733 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3734 ARM::VST3q16oddPseudo,
3735 ARM::VST3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003736 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3737 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003738 }
3739
3740 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003741 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3742 ARM::VST4d16Pseudo,
3743 ARM::VST4d32Pseudo,
3744 ARM::VST1d64QPseudo };
3745 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3746 ARM::VST4q16Pseudo_UPD,
3747 ARM::VST4q32Pseudo_UPD };
3748 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3749 ARM::VST4q16oddPseudo,
3750 ARM::VST4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003751 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3752 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003753 }
Bob Wilsond7797752009-09-01 18:51:56 +00003754
3755 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003756 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3757 ARM::VST2LNd16Pseudo,
3758 ARM::VST2LNd32Pseudo };
3759 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3760 ARM::VST2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003761 SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
3762 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003763 }
3764
3765 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003766 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3767 ARM::VST3LNd16Pseudo,
3768 ARM::VST3LNd32Pseudo };
3769 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3770 ARM::VST3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003771 SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
3772 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003773 }
3774
3775 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003776 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3777 ARM::VST4LNd16Pseudo,
3778 ARM::VST4LNd32Pseudo };
3779 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3780 ARM::VST4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003781 SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
3782 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003783 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003784 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003785 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003786 }
Evan Chengd85631e2010-05-05 18:28:36 +00003787
Bob Wilson3ed511b2010-07-06 23:36:25 +00003788 case ISD::INTRINSIC_WO_CHAIN: {
3789 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3790 switch (IntNo) {
3791 default:
3792 break;
3793
3794 case Intrinsic::arm_neon_vtbl2:
Justin Bogner45571362016-05-12 00:31:09 +00003795 SelectVTBL(N, false, 2, ARM::VTBL2);
3796 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003797 case Intrinsic::arm_neon_vtbl3:
Justin Bogner45571362016-05-12 00:31:09 +00003798 SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
3799 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003800 case Intrinsic::arm_neon_vtbl4:
Justin Bogner45571362016-05-12 00:31:09 +00003801 SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
3802 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003803
3804 case Intrinsic::arm_neon_vtbx2:
Justin Bogner45571362016-05-12 00:31:09 +00003805 SelectVTBL(N, true, 2, ARM::VTBX2);
3806 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003807 case Intrinsic::arm_neon_vtbx3:
Justin Bogner45571362016-05-12 00:31:09 +00003808 SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
3809 return;
Bob Wilson5bc8a792010-07-07 00:08:54 +00003810 case Intrinsic::arm_neon_vtbx4:
Justin Bogner45571362016-05-12 00:31:09 +00003811 SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
3812 return;
Bob Wilson3ed511b2010-07-06 23:36:25 +00003813 }
3814 break;
3815 }
3816
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003817 case ARMISD::VTBL1: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003818 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003819 EVT VT = N->getValueType(0);
Benjamin Kramerf690da42016-06-17 14:14:29 +00003820 SDValue Ops[] = {N->getOperand(0), N->getOperand(1),
3821 getAL(CurDAG, dl), // Predicate
3822 CurDAG->getRegister(0, MVT::i32)}; // Predicate Register
Justin Bogner45571362016-05-12 00:31:09 +00003823 ReplaceNode(N, CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops));
3824 return;
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003825 }
3826 case ARMISD::VTBL2: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003827 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003828 EVT VT = N->getValueType(0);
3829
3830 // Form a REG_SEQUENCE to force register allocation.
3831 SDValue V0 = N->getOperand(0);
3832 SDValue V1 = N->getOperand(1);
Weiming Zhao95782222012-11-17 00:23:35 +00003833 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003834
Benjamin Kramerf690da42016-06-17 14:14:29 +00003835 SDValue Ops[] = {RegSeq, N->getOperand(2), getAL(CurDAG, dl), // Predicate
3836 CurDAG->getRegister(0, MVT::i32)}; // Predicate Register
Justin Bogner45571362016-05-12 00:31:09 +00003837 ReplaceNode(N, CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops));
3838 return;
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003839 }
3840
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003841 case ISD::CONCAT_VECTORS:
Justin Bogner45571362016-05-12 00:31:09 +00003842 SelectConcatVector(N);
3843 return;
Tim Northoverb629c772016-04-18 21:48:55 +00003844
3845 case ISD::ATOMIC_CMP_SWAP:
Justin Bogner45571362016-05-12 00:31:09 +00003846 SelectCMP_SWAP(N);
3847 return;
Evan Chengd85631e2010-05-05 18:28:36 +00003848 }
Evan Chengd5021732008-12-10 21:54:21 +00003849
Justin Bogner45571362016-05-12 00:31:09 +00003850 SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003851}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003852
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003853// Inspect a register string of the form
3854// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3855// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3856// and obtain the integer operands from them, adding these operands to the
3857// provided vector.
3858static void getIntOperandsFromRegisterString(StringRef RegString,
Benjamin Kramerbdc49562016-06-12 15:39:02 +00003859 SelectionDAG *CurDAG,
3860 const SDLoc &DL,
3861 std::vector<SDValue> &Ops) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003862 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003863 RegString.split(Fields, ':');
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003864
3865 if (Fields.size() > 1) {
3866 bool AllIntFields = true;
3867
3868 for (StringRef Field : Fields) {
3869 // Need to trim out leading 'cp' characters and get the integer field.
3870 unsigned IntField;
3871 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3872 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3873 }
3874
3875 assert(AllIntFields &&
3876 "Unexpected non-integer value in special register string.");
3877 }
3878}
3879
3880// Maps a Banked Register string to its mask value. The mask value returned is
3881// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3882// mask operand, which expresses which register is to be used, e.g. r8, and in
3883// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3884// was invalid.
3885static inline int getBankedRegisterMask(StringRef RegString) {
3886 return StringSwitch<int>(RegString.lower())
3887 .Case("r8_usr", 0x00)
3888 .Case("r9_usr", 0x01)
3889 .Case("r10_usr", 0x02)
3890 .Case("r11_usr", 0x03)
3891 .Case("r12_usr", 0x04)
3892 .Case("sp_usr", 0x05)
3893 .Case("lr_usr", 0x06)
3894 .Case("r8_fiq", 0x08)
3895 .Case("r9_fiq", 0x09)
3896 .Case("r10_fiq", 0x0a)
3897 .Case("r11_fiq", 0x0b)
3898 .Case("r12_fiq", 0x0c)
3899 .Case("sp_fiq", 0x0d)
3900 .Case("lr_fiq", 0x0e)
3901 .Case("lr_irq", 0x10)
3902 .Case("sp_irq", 0x11)
3903 .Case("lr_svc", 0x12)
3904 .Case("sp_svc", 0x13)
3905 .Case("lr_abt", 0x14)
3906 .Case("sp_abt", 0x15)
3907 .Case("lr_und", 0x16)
3908 .Case("sp_und", 0x17)
3909 .Case("lr_mon", 0x1c)
3910 .Case("sp_mon", 0x1d)
3911 .Case("elr_hyp", 0x1e)
3912 .Case("sp_hyp", 0x1f)
3913 .Case("spsr_fiq", 0x2e)
3914 .Case("spsr_irq", 0x30)
3915 .Case("spsr_svc", 0x32)
3916 .Case("spsr_abt", 0x34)
3917 .Case("spsr_und", 0x36)
3918 .Case("spsr_mon", 0x3c)
3919 .Case("spsr_hyp", 0x3e)
3920 .Default(-1);
3921}
3922
3923// Maps a MClass special register string to its value for use in the
3924// t2MRS_M / t2MSR_M instruction nodes as the SYSm value operand.
3925// Returns -1 to signify that the string was invalid.
3926static inline int getMClassRegisterSYSmValueMask(StringRef RegString) {
3927 return StringSwitch<int>(RegString.lower())
3928 .Case("apsr", 0x0)
3929 .Case("iapsr", 0x1)
3930 .Case("eapsr", 0x2)
3931 .Case("xpsr", 0x3)
3932 .Case("ipsr", 0x5)
3933 .Case("epsr", 0x6)
3934 .Case("iepsr", 0x7)
3935 .Case("msp", 0x8)
3936 .Case("psp", 0x9)
3937 .Case("primask", 0x10)
3938 .Case("basepri", 0x11)
3939 .Case("basepri_max", 0x12)
3940 .Case("faultmask", 0x13)
3941 .Case("control", 0x14)
Bradley Smithf277c8a2016-01-25 11:25:36 +00003942 .Case("msplim", 0x0a)
3943 .Case("psplim", 0x0b)
3944 .Case("sp", 0x18)
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003945 .Default(-1);
3946}
3947
3948// The flags here are common to those allowed for apsr in the A class cores and
3949// those allowed for the special registers in the M class cores. Returns a
3950// value representing which flags were present, -1 if invalid.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003951static inline int getMClassFlagsMask(StringRef Flags, bool hasDSP) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003952 if (Flags.empty())
Artyom Skrobovcf296442015-09-24 17:31:16 +00003953 return 0x2 | (int)hasDSP;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003954
3955 return StringSwitch<int>(Flags)
3956 .Case("g", 0x1)
3957 .Case("nzcvq", 0x2)
3958 .Case("nzcvqg", 0x3)
3959 .Default(-1);
3960}
3961
3962static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead,
3963 const ARMSubtarget *Subtarget) {
3964 // Ensure that the register (without flags) was a valid M Class special
3965 // register.
3966 int SYSmvalue = getMClassRegisterSYSmValueMask(Reg);
3967 if (SYSmvalue == -1)
3968 return -1;
3969
3970 // basepri, basepri_max and faultmask are only valid for V7m.
3971 if (!Subtarget->hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
3972 return -1;
3973
Bradley Smithf277c8a2016-01-25 11:25:36 +00003974 if (Subtarget->has8MSecExt() && Flags.lower() == "ns") {
3975 Flags = "";
3976 SYSmvalue |= 0x80;
3977 }
3978
3979 if (!Subtarget->has8MSecExt() &&
3980 (SYSmvalue == 0xa || SYSmvalue == 0xb || SYSmvalue > 0x14))
3981 return -1;
3982
3983 if (!Subtarget->hasV8MMainlineOps() &&
3984 (SYSmvalue == 0x8a || SYSmvalue == 0x8b || SYSmvalue == 0x91 ||
3985 SYSmvalue == 0x93))
3986 return -1;
3987
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003988 // If it was a read then we won't be expecting flags and so at this point
3989 // we can return the mask.
3990 if (IsRead) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00003991 if (Flags.empty())
3992 return SYSmvalue;
3993 else
3994 return -1;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003995 }
3996
3997 // We know we are now handling a write so need to get the mask for the flags.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003998 int Mask = getMClassFlagsMask(Flags, Subtarget->hasDSP());
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003999
4000 // Only apsr, iapsr, eapsr, xpsr can have flags. The other register values
4001 // shouldn't have flags present.
4002 if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.empty()))
4003 return -1;
4004
4005 // The _g and _nzcvqg versions are only valid if the DSP extension is
4006 // available.
Artyom Skrobovcf296442015-09-24 17:31:16 +00004007 if (!Subtarget->hasDSP() && (Mask & 0x1))
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004008 return -1;
4009
4010 // The register was valid so need to put the mask in the correct place
4011 // (the flags need to be in bits 11-10) and combine with the SYSmvalue to
4012 // construct the operand for the instruction node.
4013 if (SYSmvalue < 0x4)
4014 return SYSmvalue | Mask << 10;
4015
4016 return SYSmvalue;
4017}
4018
4019static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
4020 // The mask operand contains the special register (R Bit) in bit 4, whether
4021 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
4022 // bits 3-0 contains the fields to be accessed in the special register, set by
4023 // the flags provided with the register.
4024 int Mask = 0;
4025 if (Reg == "apsr") {
4026 // The flags permitted for apsr are the same flags that are allowed in
4027 // M class registers. We get the flag value and then shift the flags into
4028 // the correct place to combine with the mask.
Artyom Skrobov6fbef2a2015-08-05 11:02:14 +00004029 Mask = getMClassFlagsMask(Flags, true);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004030 if (Mask == -1)
4031 return -1;
4032 return Mask << 2;
4033 }
4034
4035 if (Reg != "cpsr" && Reg != "spsr") {
4036 return -1;
4037 }
4038
4039 // This is the same as if the flags were "fc"
4040 if (Flags.empty() || Flags == "all")
4041 return Mask | 0x9;
4042
4043 // Inspect the supplied flags string and set the bits in the mask for
4044 // the relevant and valid flags allowed for cpsr and spsr.
4045 for (char Flag : Flags) {
4046 int FlagVal;
4047 switch (Flag) {
4048 case 'c':
4049 FlagVal = 0x1;
4050 break;
4051 case 'x':
4052 FlagVal = 0x2;
4053 break;
4054 case 's':
4055 FlagVal = 0x4;
4056 break;
4057 case 'f':
4058 FlagVal = 0x8;
4059 break;
4060 default:
4061 FlagVal = 0;
4062 }
4063
4064 // This avoids allowing strings where the same flag bit appears twice.
4065 if (!FlagVal || (Mask & FlagVal))
4066 return -1;
4067 Mask |= FlagVal;
4068 }
4069
4070 // If the register is spsr then we need to set the R bit.
4071 if (Reg == "spsr")
4072 Mask |= 0x10;
4073
4074 return Mask;
4075}
4076
4077// Lower the read_register intrinsic to ARM specific DAG nodes
4078// using the supplied metadata string to select the instruction node to use
4079// and the registers/masks to construct as operands for the node.
Justin Bogner45571362016-05-12 00:31:09 +00004080bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004081 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
4082 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
4083 bool IsThumb2 = Subtarget->isThumb2();
4084 SDLoc DL(N);
4085
4086 std::vector<SDValue> Ops;
4087 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
4088
4089 if (!Ops.empty()) {
4090 // If the special register string was constructed of fields (as defined
4091 // in the ACLE) then need to lower to MRC node (32 bit) or
4092 // MRRC node(64 bit), we can make the distinction based on the number of
4093 // operands we have.
4094 unsigned Opcode;
4095 SmallVector<EVT, 3> ResTypes;
4096 if (Ops.size() == 5){
4097 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
4098 ResTypes.append({ MVT::i32, MVT::Other });
4099 } else {
4100 assert(Ops.size() == 3 &&
4101 "Invalid number of fields in special register string.");
4102 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
4103 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
4104 }
4105
4106 Ops.push_back(getAL(CurDAG, DL));
4107 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4108 Ops.push_back(N->getOperand(0));
Justin Bogner45571362016-05-12 00:31:09 +00004109 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops));
4110 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004111 }
4112
4113 std::string SpecialReg = RegString->getString().lower();
4114
4115 int BankedReg = getBankedRegisterMask(SpecialReg);
4116 if (BankedReg != -1) {
4117 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
4118 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4119 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004120 ReplaceNode(
4121 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
4122 DL, MVT::i32, MVT::Other, Ops));
4123 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004124 }
4125
4126 // The VFP registers are read by creating SelectionDAG nodes with opcodes
4127 // corresponding to the register that is being read from. So we switch on the
4128 // string to find which opcode we need to use.
4129 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
4130 .Case("fpscr", ARM::VMRS)
4131 .Case("fpexc", ARM::VMRS_FPEXC)
4132 .Case("fpsid", ARM::VMRS_FPSID)
4133 .Case("mvfr0", ARM::VMRS_MVFR0)
4134 .Case("mvfr1", ARM::VMRS_MVFR1)
4135 .Case("mvfr2", ARM::VMRS_MVFR2)
4136 .Case("fpinst", ARM::VMRS_FPINST)
4137 .Case("fpinst2", ARM::VMRS_FPINST2)
4138 .Default(0);
4139
4140 // If an opcode was found then we can lower the read to a VFP instruction.
4141 if (Opcode) {
4142 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004143 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004144 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
Justin Bogner45571362016-05-12 00:31:09 +00004145 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004146
4147 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4148 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004149 ReplaceNode(N,
4150 CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops));
4151 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004152 }
4153
4154 // If the target is M Class then need to validate that the register string
4155 // is an acceptable value, so check that a mask can be constructed from the
4156 // string.
4157 if (Subtarget->isMClass()) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00004158 StringRef Flags = "", Reg = SpecialReg;
4159 if (Reg.endswith("_ns")) {
4160 Flags = "ns";
4161 Reg = Reg.drop_back(3);
4162 }
4163
4164 int SYSmValue = getMClassRegisterMask(Reg, Flags, true, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004165 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004166 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004167
4168 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4169 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4170 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004171 ReplaceNode(
4172 N, CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops));
4173 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004174 }
4175
4176 // Here we know the target is not M Class so we need to check if it is one
4177 // of the remaining possible values which are apsr, cpsr or spsr.
4178 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
4179 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4180 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004181 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
4182 DL, MVT::i32, MVT::Other, Ops));
4183 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004184 }
4185
4186 if (SpecialReg == "spsr") {
4187 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4188 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004189 ReplaceNode(
4190 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys, DL,
4191 MVT::i32, MVT::Other, Ops));
4192 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004193 }
4194
Justin Bogner45571362016-05-12 00:31:09 +00004195 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004196}
4197
4198// Lower the write_register intrinsic to ARM specific DAG nodes
4199// using the supplied metadata string to select the instruction node to use
4200// and the registers/masks to use in the nodes
Justin Bogner45571362016-05-12 00:31:09 +00004201bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004202 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
4203 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
4204 bool IsThumb2 = Subtarget->isThumb2();
4205 SDLoc DL(N);
4206
4207 std::vector<SDValue> Ops;
4208 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
4209
4210 if (!Ops.empty()) {
4211 // If the special register string was constructed of fields (as defined
4212 // in the ACLE) then need to lower to MCR node (32 bit) or
4213 // MCRR node(64 bit), we can make the distinction based on the number of
4214 // operands we have.
4215 unsigned Opcode;
4216 if (Ops.size() == 5) {
4217 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
4218 Ops.insert(Ops.begin()+2, N->getOperand(2));
4219 } else {
4220 assert(Ops.size() == 3 &&
4221 "Invalid number of fields in special register string.");
4222 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
4223 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
4224 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
4225 }
4226
4227 Ops.push_back(getAL(CurDAG, DL));
4228 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4229 Ops.push_back(N->getOperand(0));
4230
Justin Bogner45571362016-05-12 00:31:09 +00004231 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4232 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004233 }
4234
4235 std::string SpecialReg = RegString->getString().lower();
4236 int BankedReg = getBankedRegisterMask(SpecialReg);
4237 if (BankedReg != -1) {
4238 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
4239 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4240 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004241 ReplaceNode(
4242 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
4243 DL, MVT::Other, Ops));
4244 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004245 }
4246
4247 // The VFP registers are written to by creating SelectionDAG nodes with
4248 // opcodes corresponding to the register that is being written. So we switch
4249 // on the string to find which opcode we need to use.
4250 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
4251 .Case("fpscr", ARM::VMSR)
4252 .Case("fpexc", ARM::VMSR_FPEXC)
4253 .Case("fpsid", ARM::VMSR_FPSID)
4254 .Case("fpinst", ARM::VMSR_FPINST)
4255 .Case("fpinst2", ARM::VMSR_FPINST2)
4256 .Default(0);
4257
4258 if (Opcode) {
4259 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004260 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004261 Ops = { N->getOperand(2), getAL(CurDAG, DL),
4262 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004263 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4264 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004265 }
4266
Bradley Smithf277c8a2016-01-25 11:25:36 +00004267 std::pair<StringRef, StringRef> Fields;
4268 Fields = StringRef(SpecialReg).rsplit('_');
4269 std::string Reg = Fields.first.str();
4270 StringRef Flags = Fields.second;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004271
4272 // If the target was M Class then need to validate the special register value
4273 // and retrieve the mask for use in the instruction node.
4274 if (Subtarget->isMClass()) {
4275 // basepri_max gets split so need to correct Reg and Flags.
4276 if (SpecialReg == "basepri_max") {
4277 Reg = SpecialReg;
4278 Flags = "";
4279 }
4280 int SYSmValue = getMClassRegisterMask(Reg, Flags, false, Subtarget);
4281 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004282 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004283
4284 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4285 N->getOperand(2), getAL(CurDAG, DL),
4286 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004287 ReplaceNode(N, CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops));
4288 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004289 }
4290
4291 // We then check to see if a valid mask can be constructed for one of the
4292 // register string values permitted for the A and R class cores. These values
4293 // are apsr, spsr and cpsr; these are also valid on older cores.
4294 int Mask = getARClassRegisterMask(Reg, Flags);
4295 if (Mask != -1) {
4296 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
4297 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4298 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004299 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
4300 DL, MVT::Other, Ops));
4301 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004302 }
4303
Justin Bogner45571362016-05-12 00:31:09 +00004304 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004305}
4306
Justin Bogner45571362016-05-12 00:31:09 +00004307bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){
Weiming Zhaoc5987002013-02-14 18:10:21 +00004308 std::vector<SDValue> AsmNodeOperands;
4309 unsigned Flag, Kind;
4310 bool Changed = false;
4311 unsigned NumOps = N->getNumOperands();
4312
Weiming Zhaoc5987002013-02-14 18:10:21 +00004313 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
4314 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
4315 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
4316 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004317 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
4318 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
4319 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00004320
Andrew Trickef9de2a2013-05-25 02:42:55 +00004321 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00004322 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
4323 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004324
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004325 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004326 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004327 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00004328 SDValue op = N->getOperand(i);
4329 AsmNodeOperands.push_back(op);
4330
4331 if (i < InlineAsm::Op_FirstOperand)
4332 continue;
4333
4334 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
4335 Flag = C->getZExtValue();
4336 Kind = InlineAsm::getKind(Flag);
4337 }
4338 else
4339 continue;
4340
Joey Gouly392cdad2013-07-08 19:52:51 +00004341 // Immediate operands to inline asm in the SelectionDAG are modeled with
4342 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
4343 // the second is a constant with the value of the immediate. If we get here
4344 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00004345 if (Kind == InlineAsm::Kind_Imm) {
4346 SDValue op = N->getOperand(++i);
4347 AsmNodeOperands.push_back(op);
4348 continue;
4349 }
4350
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004351 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
4352 if (NumRegs)
4353 OpChanged.push_back(false);
4354
4355 unsigned DefIdx = 0;
4356 bool IsTiedToChangedOp = false;
4357 // If it's a use that is tied with a previous def, it has no
4358 // reg class constraint.
4359 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
4360 IsTiedToChangedOp = OpChanged[DefIdx];
4361
Diana Picusf345d402016-07-20 09:48:24 +00004362 // Memory operands to inline asm in the SelectionDAG are modeled with two
4363 // operands: a constant of value InlineAsm::Kind_Mem followed by the input
4364 // operand. If we get here and we have a Kind_Mem, skip the next operand (so
4365 // it doesn't get misinterpreted), and continue. We do this here because
4366 // it's important to update the OpChanged array correctly before moving on.
4367 if (Kind == InlineAsm::Kind_Mem) {
4368 SDValue op = N->getOperand(++i);
4369 AsmNodeOperands.push_back(op);
4370 continue;
4371 }
4372
Weiming Zhaoc5987002013-02-14 18:10:21 +00004373 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
4374 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
4375 continue;
4376
Weiming Zhaoc5987002013-02-14 18:10:21 +00004377 unsigned RC;
4378 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004379 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
4380 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00004381 continue;
4382
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004383 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00004384 SDValue V0 = N->getOperand(i+1);
4385 SDValue V1 = N->getOperand(i+2);
4386 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
4387 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
4388 SDValue PairedReg;
4389 MachineRegisterInfo &MRI = MF->getRegInfo();
4390
4391 if (Kind == InlineAsm::Kind_RegDef ||
4392 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
4393 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
4394 // the original GPRs.
4395
4396 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4397 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4398 SDValue Chain = SDValue(N,0);
4399
4400 SDNode *GU = N->getGluedUser();
4401 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
4402 Chain.getValue(1));
4403
4404 // Extract values from a GPRPair reg and copy to the original GPR reg.
4405 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4406 RegCopy);
4407 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4408 RegCopy);
4409 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
4410 RegCopy.getValue(1));
4411 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
4412
4413 // Update the original glue user.
4414 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
4415 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00004416 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004417 }
4418 else {
4419 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
4420 // GPRPair and then pass the GPRPair to the inline asm.
4421 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
4422
4423 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
4424 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
4425 Chain.getValue(1));
4426 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
4427 T0.getValue(1));
4428 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
4429
4430 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
4431 // i32 VRs of inline asm with it.
4432 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4433 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4434 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
4435
4436 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
4437 Glue = Chain.getValue(1);
4438 }
4439
4440 Changed = true;
4441
4442 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004443 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004444 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00004445 if (IsTiedToChangedOp)
4446 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
4447 else
4448 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004449 // Replace the current flag.
4450 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00004451 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004452 // Add the new register node and skip the original two GPRs.
4453 AsmNodeOperands.push_back(PairedReg);
4454 // Skip the next two GPRs.
4455 i += 2;
4456 }
4457 }
4458
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004459 if (Glue.getNode())
4460 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004461 if (!Changed)
Justin Bogner45571362016-05-12 00:31:09 +00004462 return false;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004463
Andrew Trickef9de2a2013-05-25 02:42:55 +00004464 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00004465 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004466 New->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00004467 ReplaceNode(N, New.getNode());
4468 return true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004469}
4470
4471
Bob Wilsona2c462b2009-05-19 05:53:42 +00004472bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00004473SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00004474 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004475 switch(ConstraintID) {
4476 default:
4477 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00004478 case InlineAsm::Constraint_i:
4479 // FIXME: It seems strange that 'i' is needed here since it's supposed to
4480 // be an immediate and not a memory constraint.
Justin Bognerb03fd122016-08-17 05:10:15 +00004481 LLVM_FALLTHROUGH;
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004482 case InlineAsm::Constraint_m:
James Molloy72222f52015-10-26 10:04:52 +00004483 case InlineAsm::Constraint_o:
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004484 case InlineAsm::Constraint_Q:
4485 case InlineAsm::Constraint_Um:
4486 case InlineAsm::Constraint_Un:
4487 case InlineAsm::Constraint_Uq:
4488 case InlineAsm::Constraint_Us:
4489 case InlineAsm::Constraint_Ut:
4490 case InlineAsm::Constraint_Uv:
4491 case InlineAsm::Constraint_Uy:
4492 // Require the address to be in a register. That is safe for all ARM
4493 // variants and it is hard to do anything much smarter without knowing
4494 // how the operand is used.
4495 OutOps.push_back(Op);
4496 return false;
4497 }
4498 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00004499}
4500
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004501/// createARMISelDag - This pass converts a legalized DAG into a
4502/// ARM-specific DAG, ready for instruction scheduling.
4503///
Bob Wilson2dd957f2009-09-28 14:30:20 +00004504FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
4505 CodeGenOpt::Level OptLevel) {
4506 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004507}