blob: 7f9fe55a5c38b54c26d7cf984e6bf2115a1c1887 [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
Mehdi Amini117296c2016-10-01 02:56:57 +000073 StringRef getPassName() const override { return "ARM Instruction Selection"; }
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000074
Craig Topper6bc27bf2014-03-10 02:09:33 +000075 void PreprocessISelDAG() override;
Evan Chengeae6d2c2012-12-19 20:16:09 +000076
Bob Wilson4facd962009-10-08 18:51:31 +000077 /// getI32Imm - Return a target constant of type i32 with the specified
78 /// value.
Benjamin Kramerbdc49562016-06-12 15:39:02 +000079 inline SDValue getI32Imm(unsigned Imm, const SDLoc &dl) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +000080 return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000081 }
82
Justin Bogner45571362016-05-12 00:31:09 +000083 void Select(SDNode *N) override;
Evan Cheng62c7b5b2010-12-05 22:04:16 +000084
85 bool hasNoVMLxHazardUse(SDNode *N) const;
Evan Cheng59bbc542010-10-27 23:41:30 +000086 bool isShifterOpProfitable(const SDValue &Shift,
87 ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt);
Owen Andersonb595ed02011-07-21 18:54:16 +000088 bool SelectRegShifterOperand(SDValue N, SDValue &A,
89 SDValue &B, SDValue &C,
90 bool CheckProfitability = true);
91 bool SelectImmShifterOperand(SDValue N, SDValue &A,
Owen Anderson04912702011-07-21 23:38:37 +000092 SDValue &B, bool CheckProfitability = true);
93 bool SelectShiftRegShifterOperand(SDValue N, SDValue &A,
Owen Anderson6d557452011-03-18 19:46:58 +000094 SDValue &B, SDValue &C) {
95 // Don't apply the profitability check
Owen Anderson04912702011-07-21 23:38:37 +000096 return SelectRegShifterOperand(N, A, B, C, false);
97 }
98 bool SelectShiftImmShifterOperand(SDValue N, SDValue &A,
99 SDValue &B) {
100 // Don't apply the profitability check
101 return SelectImmShifterOperand(N, A, B, false);
Owen Anderson6d557452011-03-18 19:46:58 +0000102 }
103
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000104 bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
105 bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);
106
Jim Grosbach08605202010-09-29 19:03:54 +0000107 AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base,
108 SDValue &Offset, SDValue &Opc);
109 bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset,
110 SDValue &Opc) {
111 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE;
112 }
113
114 bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset,
115 SDValue &Opc) {
116 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP;
117 }
118
119 bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset,
120 SDValue &Opc) {
121 SelectAddrMode2Worker(N, Base, Offset, Opc);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000122// return SelectAddrMode2ShOp(N, Base, Offset, Opc);
Jim Grosbach08605202010-09-29 19:03:54 +0000123 // This always matches one way or another.
124 return true;
125 }
126
Tim Northover42180442013-08-22 09:57:11 +0000127 bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) {
128 const ConstantSDNode *CN = cast<ConstantSDNode>(N);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000129 Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32);
Tim Northover42180442013-08-22 09:57:11 +0000130 Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32);
131 return true;
132 }
133
Owen Anderson2aedba62011-07-26 20:54:26 +0000134 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
135 SDValue &Offset, SDValue &Opc);
136 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000137 SDValue &Offset, SDValue &Opc);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000138 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
139 SDValue &Offset, SDValue &Opc);
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000140 bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000141 bool SelectAddrMode3(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000142 SDValue &Offset, SDValue &Opc);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000143 bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000144 SDValue &Offset, SDValue &Opc);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000145 bool SelectAddrMode5(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000146 SDValue &Offset);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000147 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
Bob Wilsone3ecd5f2011-02-25 06:42:42 +0000148 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000149
Evan Chengdfce83c2011-01-17 08:03:18 +0000150 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
Evan Cheng10043e22007-01-19 07:51:42 +0000151
Bill Wendling092a7bd2010-12-14 03:36:38 +0000152 // Thumb Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000153 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
Bill Wendling092a7bd2010-12-14 03:36:38 +0000154 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
155 SDValue &OffImm);
156 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
157 SDValue &OffImm);
158 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
159 SDValue &OffImm);
160 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
161 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000162 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +0000163
Bill Wendling092a7bd2010-12-14 03:36:38 +0000164 // Thumb 2 Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000165 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
166 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000167 SDValue &OffImm);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000168 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +0000169 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000170 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000171 SDValue &OffReg, SDValue &ShImm);
Tim Northovera7ecd242013-07-16 09:46:55 +0000172 bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Chengb23b50d2009-06-29 07:51:04 +0000173
Evan Cheng0fc80842010-11-12 22:42:47 +0000174 inline bool is_so_imm(unsigned Imm) const {
175 return ARM_AM::getSOImmVal(Imm) != -1;
176 }
177
178 inline bool is_so_imm_not(unsigned Imm) const {
179 return ARM_AM::getSOImmVal(~Imm) != -1;
180 }
181
182 inline bool is_t2_so_imm(unsigned Imm) const {
183 return ARM_AM::getT2SOImmVal(Imm) != -1;
184 }
185
186 inline bool is_t2_so_imm_not(unsigned Imm) const {
187 return ARM_AM::getT2SOImmVal(~Imm) != -1;
188 }
189
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000190 // Include the pieces autogenerated from the target description.
191#include "ARMGenDAGISel.inc"
Bob Wilsona2c462b2009-05-19 05:53:42 +0000192
193private:
Tim Northovereaee28b2016-09-19 09:11:09 +0000194 void transferMemOperands(SDNode *Src, SDNode *Dst);
195
Justin Bogner45571362016-05-12 00:31:09 +0000196 /// Indexed (pre/post inc/dec) load matching code for ARM.
197 bool tryARMIndexedLoad(SDNode *N);
James Molloyb3326df2016-07-15 08:03:56 +0000198 bool tryT1IndexedLoad(SDNode *N);
Justin Bogner45571362016-05-12 00:31:09 +0000199 bool tryT2IndexedLoad(SDNode *N);
Evan Cheng84c6cda2009-07-02 07:28:31 +0000200
Bob Wilson340861d2010-03-23 05:25:43 +0000201 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
202 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson12b47992009-10-14 17:28:52 +0000203 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson340861d2010-03-23 05:25:43 +0000204 /// For NumVecs <= 2, QOpcodes1 is not used.
Justin Bogner45571362016-05-12 00:31:09 +0000205 void SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
206 const uint16_t *DOpcodes, const uint16_t *QOpcodes0,
207 const uint16_t *QOpcodes1);
Bob Wilson12b47992009-10-14 17:28:52 +0000208
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000209 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000210 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000211 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000212 /// For NumVecs <= 2, QOpcodes1 is not used.
Justin Bogner45571362016-05-12 00:31:09 +0000213 void SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
214 const uint16_t *DOpcodes, const uint16_t *QOpcodes0,
215 const uint16_t *QOpcodes1);
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000216
Bob Wilson93117bc2009-10-14 16:46:45 +0000217 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilson4145e3a2009-10-14 16:19:03 +0000218 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsond5c57a52010-09-13 23:01:35 +0000219 /// load/store of D registers and Q registers.
Justin Bogner45571362016-05-12 00:31:09 +0000220 void SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
221 unsigned NumVecs, const uint16_t *DOpcodes,
222 const uint16_t *QOpcodes);
Bob Wilson4145e3a2009-10-14 16:19:03 +0000223
Bob Wilson2d790df2010-11-28 06:51:26 +0000224 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
Eli Friedmanf624ec22016-12-16 18:44:08 +0000225 /// should be 1, 2, 3 or 4. The opcode array specifies the instructions used
Bob Wilson2d790df2010-11-28 06:51:26 +0000226 /// for loading D registers. (Q registers are not supported.)
Justin Bogner45571362016-05-12 00:31:09 +0000227 void SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Eli Friedmanf624ec22016-12-16 18:44:08 +0000228 const uint16_t *DOpcodes,
229 const uint16_t *QOpcodes = nullptr);
Bob Wilson2d790df2010-11-28 06:51:26 +0000230
Justin Bogner45571362016-05-12 00:31:09 +0000231 /// Try to select SBFX/UBFX instructions for ARM.
232 bool tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000233
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000234 // Select special operations if node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +0000235 bool tryABSOp(SDNode *N);
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000236
Justin Bogner45571362016-05-12 00:31:09 +0000237 bool tryReadRegister(SDNode *N);
238 bool tryWriteRegister(SDNode *N);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +0000239
Justin Bogner45571362016-05-12 00:31:09 +0000240 bool tryInlineAsm(SDNode *N);
Weiming Zhaoc5987002013-02-14 18:10:21 +0000241
Sjoerd Meijer96e10b52016-12-15 09:38:59 +0000242 void SelectCMPZ(SDNode *N, bool &SwitchEQNEToPLMI);
James Molloye7d97362016-11-03 14:08:01 +0000243
Justin Bogner45571362016-05-12 00:31:09 +0000244 void SelectCMP_SWAP(SDNode *N);
Tim Northoverb629c772016-04-18 21:48:55 +0000245
Evan Chengd9c55362009-07-02 01:23:32 +0000246 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
247 /// inline asm expressions.
Daniel Sanders60f1db02015-03-13 12:45:09 +0000248 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Craig Topper6bc27bf2014-03-10 02:09:33 +0000249 std::vector<SDValue> &OutOps) override;
Bob Wilsone6b778d2009-10-06 22:01:59 +0000250
Weiming Zhao95782222012-11-17 00:23:35 +0000251 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhao8f56f882012-11-16 21:55:34 +0000252 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao95782222012-11-17 00:23:35 +0000253 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
254 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
255 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Chengc2ae5f52010-05-10 17:34:18 +0000256
Bob Wilsond8a9a042010-06-04 00:04:02 +0000257 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +0000258 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
259 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
260 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000261
262 // Get the alignment operand for a NEON VLD or VST instruction.
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000263 SDValue GetVLDSTAlign(SDValue Align, const SDLoc &dl, unsigned NumVecs,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000264 bool is64BitVector);
John Brawn056e6782015-09-14 15:19:41 +0000265
266 /// Returns the number of instructions required to materialize the given
267 /// constant in a register, or 3 if a literal pool load is needed.
268 unsigned ConstantMaterializationCost(unsigned Val) const;
269
270 /// Checks if N is a multiplication by a constant where we can extract out a
271 /// power of two from the constant so that it can be used in a shift, but only
272 /// if it simplifies the materialization of the constant. Returns true if it
273 /// is, and assigns to PowerOfTwo the power of two that should be extracted
274 /// out and to NewMulConst the new constant to be multiplied by.
275 bool canExtractShiftFromMul(const SDValue &N, unsigned MaxShift,
276 unsigned &PowerOfTwo, SDValue &NewMulConst) const;
277
278 /// Replace N with M in CurDAG, in a way that also ensures that M gets
279 /// selected when N would have been selected.
280 void replaceDAGValue(const SDValue &N, SDValue M);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000281};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000282}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000283
Sandeep Patel423e42b2009-10-13 18:59:48 +0000284/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
285/// operand. If so Imm will receive the 32-bit value.
286static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
287 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
288 Imm = cast<ConstantSDNode>(N)->getZExtValue();
289 return true;
290 }
291 return false;
292}
293
294// isInt32Immediate - This method tests to see if a constant operand.
295// If so Imm will receive the 32 bit value.
296static bool isInt32Immediate(SDValue N, unsigned &Imm) {
297 return isInt32Immediate(N.getNode(), Imm);
298}
299
300// isOpcWithIntImmediate - This method tests to see if the node is a specific
301// opcode and that it has a immediate integer right operand.
302// If so Imm will receive the 32 bit value.
303static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
304 return N->getOpcode() == Opc &&
305 isInt32Immediate(N->getOperand(1).getNode(), Imm);
306}
307
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000308/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000309/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000310///
311/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000312static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000313 int RangeMin, int RangeMax,
314 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000315 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000316
317 // Check that this is a constant.
318 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
319 if (!C)
320 return false;
321
322 ScaledConstant = (int) C->getZExtValue();
323 if ((ScaledConstant % Scale) != 0)
324 return false;
325
326 ScaledConstant /= Scale;
327 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
328}
329
Evan Chengeae6d2c2012-12-19 20:16:09 +0000330void ARMDAGToDAGISel::PreprocessISelDAG() {
331 if (!Subtarget->hasV6T2Ops())
332 return;
333
334 bool isThumb2 = Subtarget->isThumb();
335 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
336 E = CurDAG->allnodes_end(); I != E; ) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000337 SDNode *N = &*I++; // Preincrement iterator to avoid invalidation issues.
Evan Chengeae6d2c2012-12-19 20:16:09 +0000338
339 if (N->getOpcode() != ISD::ADD)
340 continue;
341
342 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
343 // leading zeros, followed by consecutive set bits, followed by 1 or 2
344 // trailing zeros, e.g. 1020.
345 // Transform the expression to
346 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
347 // of trailing zeros of c2. The left shift would be folded as an shifter
348 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
349 // node (UBFX).
350
351 SDValue N0 = N->getOperand(0);
352 SDValue N1 = N->getOperand(1);
353 unsigned And_imm = 0;
354 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
355 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
356 std::swap(N0, N1);
357 }
358 if (!And_imm)
359 continue;
360
361 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000362 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000363 if (TZ != 1 && TZ != 2)
364 // Be conservative here. Shifter operands aren't always free. e.g. On
365 // Swift, left shifter operand of 1 / 2 for free but others are not.
366 // e.g.
367 // ubfx r3, r1, #16, #8
368 // ldr.w r3, [r0, r3, lsl #2]
369 // vs.
370 // mov.w r9, #1020
371 // and.w r2, r9, r1, lsr #14
372 // ldr r2, [r0, r2]
373 continue;
374 And_imm >>= TZ;
375 if (And_imm & (And_imm + 1))
376 continue;
377
378 // Look for (and (srl X, c1), c2).
379 SDValue Srl = N1.getOperand(0);
380 unsigned Srl_imm = 0;
381 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
382 (Srl_imm <= 2))
383 continue;
384
385 // Make sure first operand is not a shifter operand which would prevent
386 // folding of the left shift.
387 SDValue CPTmp0;
388 SDValue CPTmp1;
389 SDValue CPTmp2;
390 if (isThumb2) {
John Brawnd8b405a2015-09-07 11:45:18 +0000391 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
Evan Chengeae6d2c2012-12-19 20:16:09 +0000392 continue;
393 } else {
394 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
395 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
396 continue;
397 }
398
399 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000400 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000401 Srl.getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000402 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl),
403 MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000404 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000405 Srl,
406 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000407 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000408 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32));
Evan Chengeae6d2c2012-12-19 20:16:09 +0000409 CurDAG->UpdateNodeOperands(N, N0, N1);
Jim Grosbach1a597112014-04-03 23:43:18 +0000410 }
Evan Chengeae6d2c2012-12-19 20:16:09 +0000411}
412
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000413/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
414/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
415/// least on current ARM implementations) which should be avoidded.
416bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
417 if (OptLevel == CodeGenOpt::None)
418 return true;
419
Diana Picus575f2bb2016-07-07 09:11:39 +0000420 if (!Subtarget->hasVMLxHazards())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000421 return true;
422
423 if (!N->hasOneUse())
424 return false;
425
426 SDNode *Use = *N->use_begin();
427 if (Use->getOpcode() == ISD::CopyToReg)
428 return true;
429 if (Use->isMachineOpcode()) {
Eric Christopher2f991c92014-07-03 22:24:49 +0000430 const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>(
Eric Christopherfc6de422014-08-05 02:39:49 +0000431 CurDAG->getSubtarget().getInstrInfo());
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000432
Evan Cheng6cc775f2011-06-28 19:10:37 +0000433 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
434 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000435 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000436 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000437 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
438 return true;
439 // vmlx feeding into another vmlx. We actually want to unfold
440 // the use later in the MLxExpansion pass. e.g.
441 // vmla
442 // vmla (stall 8 cycles)
443 //
444 // vmul (5 cycles)
445 // vadd (5 cycles)
446 // vmla
447 // This adds up to about 18 - 19 cycles.
448 //
449 // vmla
450 // vmul (stall 4 cycles)
451 // vadd adds up to about 14 cycles.
452 return TII->isFpMLxInstruction(Opcode);
453 }
454
455 return false;
456}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000457
Evan Cheng59bbc542010-10-27 23:41:30 +0000458bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
459 ARM_AM::ShiftOpc ShOpcVal,
460 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000461 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000462 return true;
463 if (Shift.hasOneUse())
464 return true;
465 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000466 return ShOpcVal == ARM_AM::lsl &&
467 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000468}
469
John Brawn056e6782015-09-14 15:19:41 +0000470unsigned ARMDAGToDAGISel::ConstantMaterializationCost(unsigned Val) const {
471 if (Subtarget->isThumb()) {
472 if (Val <= 255) return 1; // MOV
Weiming Zhaof68a6a72016-08-05 20:58:29 +0000473 if (Subtarget->hasV6T2Ops() &&
474 (Val <= 0xffff || ARM_AM::getT2SOImmValSplatVal(Val) != -1))
475 return 1; // MOVW
James Molloy65b6be12016-06-14 13:33:07 +0000476 if (Val <= 510) return 2; // MOV + ADDi8
John Brawn056e6782015-09-14 15:19:41 +0000477 if (~Val <= 255) return 2; // MOV + MVN
478 if (ARM_AM::isThumbImmShiftedVal(Val)) return 2; // MOV + LSL
479 } else {
480 if (ARM_AM::getSOImmVal(Val) != -1) return 1; // MOV
481 if (ARM_AM::getSOImmVal(~Val) != -1) return 1; // MVN
482 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
483 if (ARM_AM::isSOImmTwoPartVal(Val)) return 2; // two instrs
484 }
485 if (Subtarget->useMovt(*MF)) return 2; // MOVW + MOVT
486 return 3; // Literal pool load
487}
488
489bool ARMDAGToDAGISel::canExtractShiftFromMul(const SDValue &N,
490 unsigned MaxShift,
491 unsigned &PowerOfTwo,
492 SDValue &NewMulConst) const {
493 assert(N.getOpcode() == ISD::MUL);
494 assert(MaxShift > 0);
495
496 // If the multiply is used in more than one place then changing the constant
497 // will make other uses incorrect, so don't.
498 if (!N.hasOneUse()) return false;
499 // Check if the multiply is by a constant
500 ConstantSDNode *MulConst = dyn_cast<ConstantSDNode>(N.getOperand(1));
501 if (!MulConst) return false;
502 // If the constant is used in more than one place then modifying it will mean
503 // we need to materialize two constants instead of one, which is a bad idea.
504 if (!MulConst->hasOneUse()) return false;
505 unsigned MulConstVal = MulConst->getZExtValue();
506 if (MulConstVal == 0) return false;
507
508 // Find the largest power of 2 that MulConstVal is a multiple of
509 PowerOfTwo = MaxShift;
510 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
511 --PowerOfTwo;
512 if (PowerOfTwo == 0) return false;
513 }
514
515 // Only optimise if the new cost is better
516 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
517 NewMulConst = CurDAG->getConstant(NewMulConstVal, SDLoc(N), MVT::i32);
518 unsigned OldCost = ConstantMaterializationCost(MulConstVal);
519 unsigned NewCost = ConstantMaterializationCost(NewMulConstVal);
520 return NewCost < OldCost;
521}
522
523void ARMDAGToDAGISel::replaceDAGValue(const SDValue &N, SDValue M) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000524 CurDAG->RepositionNode(N.getNode()->getIterator(), M.getNode());
John Brawn056e6782015-09-14 15:19:41 +0000525 CurDAG->ReplaceAllUsesWith(N, M);
526}
527
Owen Andersonb595ed02011-07-21 18:54:16 +0000528bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000529 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000530 SDValue &Opc,
531 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000532 if (DisableShifterOp)
533 return false;
534
John Brawn056e6782015-09-14 15:19:41 +0000535 // If N is a multiply-by-constant and it's profitable to extract a shift and
536 // use it in a shifted operand do so.
537 if (N.getOpcode() == ISD::MUL) {
538 unsigned PowerOfTwo = 0;
539 SDValue NewMulConst;
540 if (canExtractShiftFromMul(N, 31, PowerOfTwo, NewMulConst)) {
Justin Bogner8752be72016-05-05 01:43:49 +0000541 HandleSDNode Handle(N);
Benjamin Kramer58dadd52017-04-20 18:29:14 +0000542 SDLoc Loc(N);
John Brawn056e6782015-09-14 15:19:41 +0000543 replaceDAGValue(N.getOperand(1), NewMulConst);
Justin Bogner8752be72016-05-05 01:43:49 +0000544 BaseReg = Handle.getValue();
Benjamin Kramer58dadd52017-04-20 18:29:14 +0000545 Opc = CurDAG->getTargetConstant(
546 ARM_AM::getSORegOpc(ARM_AM::lsl, PowerOfTwo), Loc, MVT::i32);
John Brawn056e6782015-09-14 15:19:41 +0000547 return true;
548 }
549 }
550
Evan Chenga20cde32011-07-20 23:34:39 +0000551 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000552
553 // Don't match base register only case. That is matched to a separate
554 // lower complexity pattern with explicit register operand.
555 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000556
Evan Chengb23b50d2009-06-29 07:51:04 +0000557 BaseReg = N.getOperand(0);
558 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000559 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
560 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000561 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000562 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000563 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000564 return true;
565}
566
Owen Andersonb595ed02011-07-21 18:54:16 +0000567bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
568 SDValue &BaseReg,
569 SDValue &ShReg,
570 SDValue &Opc,
571 bool CheckProfitability) {
572 if (DisableShifterOp)
573 return false;
574
575 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
576
577 // Don't match base register only case. That is matched to a separate
578 // lower complexity pattern with explicit register operand.
579 if (ShOpcVal == ARM_AM::no_shift) return false;
580
581 BaseReg = N.getOperand(0);
582 unsigned ShImmVal = 0;
583 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
584 if (RHS) return false;
585
586 ShReg = N.getOperand(1);
587 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
588 return false;
589 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000590 SDLoc(N), MVT::i32);
Owen Andersonb595ed02011-07-21 18:54:16 +0000591 return true;
592}
593
594
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000595bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
596 SDValue &Base,
597 SDValue &OffImm) {
598 // Match simple R + imm12 operands.
599
600 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000601 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
602 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000603 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000604 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000605 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000606 Base = CurDAG->getTargetFrameIndex(
607 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000608 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000609 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000610 }
Owen Anderson6d557452011-03-18 19:46:58 +0000611
Chris Lattner46c01a32011-02-13 22:25:43 +0000612 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000613 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000614 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000615 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000616 Base = N.getOperand(0);
617 } else
618 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000619 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000620 return true;
621 }
622
623 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Renato Golin63e27982014-09-09 09:57:59 +0000624 int RHSC = (int)RHS->getSExtValue();
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000625 if (N.getOpcode() == ISD::SUB)
626 RHSC = -RHSC;
627
Renato Golin63e27982014-09-09 09:57:59 +0000628 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000629 Base = N.getOperand(0);
630 if (Base.getOpcode() == ISD::FrameIndex) {
631 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000632 Base = CurDAG->getTargetFrameIndex(
633 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000634 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000635 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000636 return true;
637 }
638 }
639
640 // Base only.
641 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000642 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000643 return true;
644}
645
646
647
648bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
649 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000650 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000651 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000652 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
653 // X * [3,5,9] -> X + X * [2,4,8] etc.
654 int RHSC = (int)RHS->getZExtValue();
655 if (RHSC & 1) {
656 RHSC = RHSC & ~1;
657 ARM_AM::AddrOpc AddSub = ARM_AM::add;
658 if (RHSC < 0) {
659 AddSub = ARM_AM::sub;
660 RHSC = - RHSC;
661 }
662 if (isPowerOf2_32(RHSC)) {
663 unsigned ShAmt = Log2_32(RHSC);
664 Base = Offset = N.getOperand(0);
665 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
666 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000667 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000668 return true;
669 }
670 }
671 }
672 }
673
Chris Lattner46c01a32011-02-13 22:25:43 +0000674 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
675 // ISD::OR that is equivalent to an ISD::ADD.
676 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000677 return false;
678
679 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000680 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000681 int RHSC;
682 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
683 -0x1000+1, 0x1000, RHSC)) // 12 bits.
684 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000685 }
686
687 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000688 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000689 ARM_AM::ShiftOpc ShOpcVal =
690 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000691 unsigned ShAmt = 0;
692
693 Base = N.getOperand(0);
694 Offset = N.getOperand(1);
695
696 if (ShOpcVal != ARM_AM::no_shift) {
697 // Check to see if the RHS of the shift is a constant, if not, we can't fold
698 // it.
699 if (ConstantSDNode *Sh =
700 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
701 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000702 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
703 Offset = N.getOperand(1).getOperand(0);
704 else {
705 ShAmt = 0;
706 ShOpcVal = ARM_AM::no_shift;
707 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000708 } else {
709 ShOpcVal = ARM_AM::no_shift;
710 }
711 }
712
713 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000714 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000715 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
716 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000717 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000718 if (ShOpcVal != ARM_AM::no_shift) {
719 // Check to see if the RHS of the shift is a constant, if not, we can't
720 // fold it.
721 if (ConstantSDNode *Sh =
722 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
723 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000724 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000725 Offset = N.getOperand(0).getOperand(0);
726 Base = N.getOperand(1);
727 } else {
728 ShAmt = 0;
729 ShOpcVal = ARM_AM::no_shift;
730 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000731 } else {
732 ShOpcVal = ARM_AM::no_shift;
733 }
734 }
735 }
736
John Brawn056e6782015-09-14 15:19:41 +0000737 // If Offset is a multiply-by-constant and it's profitable to extract a shift
738 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +0000739 if (Offset.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +0000740 unsigned PowerOfTwo = 0;
741 SDValue NewMulConst;
742 if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) {
Tim Northover4a01ffb2017-05-02 22:45:19 +0000743 HandleSDNode Handle(Offset);
John Brawn056e6782015-09-14 15:19:41 +0000744 replaceDAGValue(Offset.getOperand(1), NewMulConst);
Tim Northover4a01ffb2017-05-02 22:45:19 +0000745 Offset = Handle.getValue();
John Brawn056e6782015-09-14 15:19:41 +0000746 ShAmt = PowerOfTwo;
747 ShOpcVal = ARM_AM::lsl;
748 }
749 }
750
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000751 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000752 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000753 return true;
754}
755
756
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000757//-----
758
Jim Grosbach08605202010-09-29 19:03:54 +0000759AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
760 SDValue &Base,
761 SDValue &Offset,
762 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000763 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000764 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000765 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
766 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmaneffb8942008-09-12 16:56:44 +0000767 int RHSC = (int)RHS->getZExtValue();
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000768 if (RHSC & 1) {
769 RHSC = RHSC & ~1;
770 ARM_AM::AddrOpc AddSub = ARM_AM::add;
771 if (RHSC < 0) {
772 AddSub = ARM_AM::sub;
773 RHSC = - RHSC;
774 }
775 if (isPowerOf2_32(RHSC)) {
776 unsigned ShAmt = Log2_32(RHSC);
777 Base = Offset = N.getOperand(0);
778 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
779 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000780 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000781 return AM2_SHOP;
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000782 }
783 }
784 }
785 }
786
Chris Lattner46c01a32011-02-13 22:25:43 +0000787 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
788 // ISD::OR that is equivalent to an ADD.
789 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000790 Base = N;
791 if (N.getOpcode() == ISD::FrameIndex) {
792 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000793 Base = CurDAG->getTargetFrameIndex(
794 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +0000795 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000796 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000797 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000798 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000799 Base = N.getOperand(0);
800 }
Owen Anderson9f944592009-08-11 20:47:22 +0000801 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000802 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
803 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000804 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000805 return AM2_BASE;
Rafael Espindola708cb602006-11-08 17:07:32 +0000806 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000807
Evan Cheng10043e22007-01-19 07:51:42 +0000808 // Match simple R +/- imm12 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +0000809 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000810 int RHSC;
811 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
812 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
813 Base = N.getOperand(0);
814 if (Base.getOpcode() == ISD::FrameIndex) {
815 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000816 Base = CurDAG->getTargetFrameIndex(
817 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Rafael Espindola708cb602006-11-08 17:07:32 +0000818 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000819 Offset = CurDAG->getRegister(0, MVT::i32);
820
821 ARM_AM::AddrOpc AddSub = ARM_AM::add;
822 if (RHSC < 0) {
823 AddSub = ARM_AM::sub;
824 RHSC = - RHSC;
825 }
826 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
827 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000828 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000829 return AM2_BASE;
Evan Cheng10043e22007-01-19 07:51:42 +0000830 }
Jim Grosbachc7b10f32010-09-29 17:32:29 +0000831 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000832
Bob Wilsone8a549c2012-09-29 21:43:49 +0000833 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000834 // Compute R +/- (R << N) and reuse it.
835 Base = N;
836 Offset = CurDAG->getRegister(0, MVT::i32);
837 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
838 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000839 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000840 return AM2_BASE;
841 }
842
Johnny Chenb678a562009-10-27 17:25:15 +0000843 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000844 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chenga20cde32011-07-20 23:34:39 +0000845 ARM_AM::ShiftOpc ShOpcVal =
846 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000847 unsigned ShAmt = 0;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000848
Evan Cheng10043e22007-01-19 07:51:42 +0000849 Base = N.getOperand(0);
850 Offset = N.getOperand(1);
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000851
Evan Cheng10043e22007-01-19 07:51:42 +0000852 if (ShOpcVal != ARM_AM::no_shift) {
853 // Check to see if the RHS of the shift is a constant, if not, we can't fold
854 // it.
855 if (ConstantSDNode *Sh =
856 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000857 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000858 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
859 Offset = N.getOperand(1).getOperand(0);
860 else {
861 ShAmt = 0;
862 ShOpcVal = ARM_AM::no_shift;
863 }
Evan Cheng10043e22007-01-19 07:51:42 +0000864 } else {
865 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola708cb602006-11-08 17:07:32 +0000866 }
867 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000868
Evan Cheng10043e22007-01-19 07:51:42 +0000869 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000870 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000871 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
872 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000873 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000874 if (ShOpcVal != ARM_AM::no_shift) {
875 // Check to see if the RHS of the shift is a constant, if not, we can't
876 // fold it.
877 if (ConstantSDNode *Sh =
878 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000879 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000880 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000881 Offset = N.getOperand(0).getOperand(0);
882 Base = N.getOperand(1);
883 } else {
884 ShAmt = 0;
885 ShOpcVal = ARM_AM::no_shift;
886 }
Evan Cheng10043e22007-01-19 07:51:42 +0000887 } else {
888 ShOpcVal = ARM_AM::no_shift;
889 }
890 }
891 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000892
Evan Cheng10043e22007-01-19 07:51:42 +0000893 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000894 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000895 return AM2_SHOP;
Rafael Espindola708cb602006-11-08 17:07:32 +0000896}
897
Owen Anderson2aedba62011-07-26 20:54:26 +0000898bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000899 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000900 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000901 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
902 ? cast<LoadSDNode>(Op)->getAddressingMode()
903 : cast<StoreSDNode>(Op)->getAddressingMode();
904 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
905 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000906 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000907 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
908 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000909
910 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000911 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000912 unsigned ShAmt = 0;
913 if (ShOpcVal != ARM_AM::no_shift) {
914 // Check to see if the RHS of the shift is a constant, if not, we can't fold
915 // it.
916 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000917 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000918 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
919 Offset = N.getOperand(0);
920 else {
921 ShAmt = 0;
922 ShOpcVal = ARM_AM::no_shift;
923 }
Evan Cheng10043e22007-01-19 07:51:42 +0000924 } else {
925 ShOpcVal = ARM_AM::no_shift;
926 }
927 }
928
929 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000930 SDLoc(N), MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000931 return true;
932}
933
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000934bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
935 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000936 unsigned Opcode = Op->getOpcode();
937 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
938 ? cast<LoadSDNode>(Op)->getAddressingMode()
939 : cast<StoreSDNode>(Op)->getAddressingMode();
940 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
941 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000942 int Val;
943 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000944 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000945 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000946 Opc = CurDAG->getTargetConstant(Val, SDLoc(Op), MVT::i32);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000947 return true;
948 }
949
950 return false;
951}
952
953
Owen Anderson2aedba62011-07-26 20:54:26 +0000954bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
955 SDValue &Offset, SDValue &Opc) {
956 unsigned Opcode = Op->getOpcode();
957 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
958 ? cast<LoadSDNode>(Op)->getAddressingMode()
959 : cast<StoreSDNode>(Op)->getAddressingMode();
960 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
961 ? ARM_AM::add : ARM_AM::sub;
962 int Val;
963 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
964 Offset = CurDAG->getRegister(0, MVT::i32);
965 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
966 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000967 SDLoc(Op), MVT::i32);
Owen Anderson2aedba62011-07-26 20:54:26 +0000968 return true;
969 }
970
971 return false;
972}
973
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000974bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
975 Base = N;
976 return true;
977}
Evan Cheng10043e22007-01-19 07:51:42 +0000978
Chris Lattner0e023ea2010-09-21 20:31:19 +0000979bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000980 SDValue &Base, SDValue &Offset,
981 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000982 if (N.getOpcode() == ISD::SUB) {
983 // X - C is canonicalize to X + -C, no need to handle it here.
984 Base = N.getOperand(0);
985 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000986 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0), SDLoc(N),
987 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000988 return true;
989 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000990
Chris Lattner46c01a32011-02-13 22:25:43 +0000991 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000992 Base = N;
993 if (N.getOpcode() == ISD::FrameIndex) {
994 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000995 Base = CurDAG->getTargetFrameIndex(
996 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +0000997 }
Owen Anderson9f944592009-08-11 20:47:22 +0000998 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000999 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1000 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001001 return true;
1002 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001003
Evan Cheng10043e22007-01-19 07:51:42 +00001004 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001005 int RHSC;
1006 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
1007 -256 + 1, 256, RHSC)) { // 8 bits.
1008 Base = N.getOperand(0);
1009 if (Base.getOpcode() == ISD::FrameIndex) {
1010 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001011 Base = CurDAG->getTargetFrameIndex(
1012 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001013 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001014 Offset = CurDAG->getRegister(0, MVT::i32);
1015
1016 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1017 if (RHSC < 0) {
1018 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001019 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001020 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001021 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC), SDLoc(N),
1022 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001023 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001024 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001025
Evan Cheng10043e22007-01-19 07:51:42 +00001026 Base = N.getOperand(0);
1027 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001028 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1029 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001030 return true;
1031}
1032
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001033bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001034 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001035 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +00001036 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1037 ? cast<LoadSDNode>(Op)->getAddressingMode()
1038 : cast<StoreSDNode>(Op)->getAddressingMode();
1039 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
1040 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001041 int Val;
1042 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
1043 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001044 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), SDLoc(Op),
1045 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001046 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001047 }
1048
1049 Offset = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001050 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), SDLoc(Op),
1051 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001052 return true;
1053}
1054
Jim Grosbachd37f0712010-10-21 19:38:40 +00001055bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001056 SDValue &Base, SDValue &Offset) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001057 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +00001058 Base = N;
1059 if (N.getOpcode() == ISD::FrameIndex) {
1060 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001061 Base = CurDAG->getTargetFrameIndex(
1062 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +00001063 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001064 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001065 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001066 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +00001067 Base = N.getOperand(0);
1068 }
1069 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001070 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001071 return true;
1072 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001073
Evan Cheng10043e22007-01-19 07:51:42 +00001074 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001075 int RHSC;
1076 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
1077 -256 + 1, 256, RHSC)) {
1078 Base = N.getOperand(0);
1079 if (Base.getOpcode() == ISD::FrameIndex) {
1080 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001081 Base = CurDAG->getTargetFrameIndex(
1082 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001083 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001084
1085 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1086 if (RHSC < 0) {
1087 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001088 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001089 }
1090 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001091 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001092 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001093 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001094
Evan Cheng10043e22007-01-19 07:51:42 +00001095 Base = N;
1096 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001097 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001098 return true;
1099}
1100
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001101bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
1102 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +00001103 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001104
1105 unsigned Alignment = 0;
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001106
1107 MemSDNode *MemN = cast<MemSDNode>(Parent);
1108
1109 if (isa<LSBaseSDNode>(MemN) ||
1110 ((MemN->getOpcode() == ARMISD::VST1_UPD ||
1111 MemN->getOpcode() == ARMISD::VLD1_UPD) &&
1112 MemN->getConstantOperandVal(MemN->getNumOperands() - 1) == 1)) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001113 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
1114 // The maximum alignment is equal to the memory size being referenced.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001115 unsigned MMOAlign = MemN->getAlignment();
1116 unsigned MemSize = MemN->getMemoryVT().getSizeInBits() / 8;
1117 if (MMOAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001118 Alignment = MemSize;
1119 } else {
1120 // All other uses of addrmode6 are for intrinsics. For now just record
1121 // the raw alignment value; it will be refined later based on the legal
1122 // alignment operands for the intrinsic.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001123 Alignment = MemN->getAlignment();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001124 }
1125
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001126 Align = CurDAG->getTargetConstant(Alignment, SDLoc(N), MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001127 return true;
1128}
1129
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001130bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1131 SDValue &Offset) {
1132 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1133 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1134 if (AM != ISD::POST_INC)
1135 return false;
1136 Offset = N;
1137 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1138 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1139 Offset = CurDAG->getRegister(0, MVT::i32);
1140 }
1141 return true;
1142}
1143
Chris Lattner0e023ea2010-09-21 20:31:19 +00001144bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001145 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001146 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1147 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001148 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001149 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001150 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001151 return true;
1152 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001153
Evan Cheng10043e22007-01-19 07:51:42 +00001154 return false;
1155}
1156
Bill Wendling092a7bd2010-12-14 03:36:38 +00001157
1158//===----------------------------------------------------------------------===//
1159// Thumb Addressing Modes
1160//===----------------------------------------------------------------------===//
1161
Chris Lattner0e023ea2010-09-21 20:31:19 +00001162bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001163 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001164 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001165 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001166 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001167 return false;
1168
1169 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001170 return true;
1171 }
1172
Evan Cheng10043e22007-01-19 07:51:42 +00001173 Base = N.getOperand(0);
1174 Offset = N.getOperand(1);
1175 return true;
1176}
1177
Evan Cheng139edae2007-01-24 02:21:22 +00001178bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001179ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1180 SDValue &Base, SDValue &OffImm) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001181 if (!CurDAG->isBaseWithConstantOffset(N)) {
John Brawn68acdcb2015-08-13 10:48:22 +00001182 if (N.getOpcode() == ISD::ADD) {
1183 return false; // We want to select register offset instead
1184 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001185 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001186 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
James Molloyb7de4972016-10-05 14:52:13 +00001187 N.getOperand(0).getOpcode() != ISD::TargetConstantPool &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001188 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001189 Base = N.getOperand(0);
1190 } else {
1191 Base = N;
1192 }
1193
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001194 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001195 return true;
1196 }
1197
Evan Cheng10043e22007-01-19 07:51:42 +00001198 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001199 int RHSC;
1200 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1201 Base = N.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001202 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001203 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001204 }
1205
John Brawn68acdcb2015-08-13 10:48:22 +00001206 // Offset is too large, so use register offset instead.
1207 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001208}
1209
Bill Wendling092a7bd2010-12-14 03:36:38 +00001210bool
1211ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1212 SDValue &OffImm) {
1213 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001214}
1215
Bill Wendling092a7bd2010-12-14 03:36:38 +00001216bool
1217ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1218 SDValue &OffImm) {
1219 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001220}
1221
Bill Wendling092a7bd2010-12-14 03:36:38 +00001222bool
1223ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1224 SDValue &OffImm) {
1225 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001226}
1227
Chris Lattner0e023ea2010-09-21 20:31:19 +00001228bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1229 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001230 if (N.getOpcode() == ISD::FrameIndex) {
1231 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001232 // Only multiples of 4 are allowed for the offset, so the frame object
1233 // alignment must be at least 4.
Matthias Braun941a7052016-07-28 18:40:00 +00001234 MachineFrameInfo &MFI = MF->getFrameInfo();
1235 if (MFI.getObjectAlignment(FI) < 4)
1236 MFI.setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001237 Base = CurDAG->getTargetFrameIndex(
1238 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001239 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001240 return true;
1241 }
Evan Cheng139edae2007-01-24 02:21:22 +00001242
Chris Lattner46c01a32011-02-13 22:25:43 +00001243 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001244 return false;
1245
1246 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001247 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1248 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001249 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001250 int RHSC;
1251 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1252 Base = N.getOperand(0);
1253 if (Base.getOpcode() == ISD::FrameIndex) {
1254 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001255 // For LHS+RHS to result in an offset that's a multiple of 4 the object
1256 // indexed by the LHS must be 4-byte aligned.
Matthias Braun941a7052016-07-28 18:40:00 +00001257 MachineFrameInfo &MFI = MF->getFrameInfo();
1258 if (MFI.getObjectAlignment(FI) < 4)
1259 MFI.setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001260 Base = CurDAG->getTargetFrameIndex(
1261 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng139edae2007-01-24 02:21:22 +00001262 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001263 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001264 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001265 }
1266 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001267
Evan Cheng10043e22007-01-19 07:51:42 +00001268 return false;
1269}
1270
Bill Wendling092a7bd2010-12-14 03:36:38 +00001271
1272//===----------------------------------------------------------------------===//
1273// Thumb 2 Addressing Modes
1274//===----------------------------------------------------------------------===//
1275
1276
Chris Lattner0e023ea2010-09-21 20:31:19 +00001277bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001278 SDValue &Base, SDValue &OffImm) {
1279 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001280
Evan Cheng36064672009-08-11 08:52:18 +00001281 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001282 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1283 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001284 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001285 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001286 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001287 Base = CurDAG->getTargetFrameIndex(
1288 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001289 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001290 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001291 }
Owen Anderson6d557452011-03-18 19:46:58 +00001292
Chris Lattner46c01a32011-02-13 22:25:43 +00001293 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001294 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001295 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001296 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng36064672009-08-11 08:52:18 +00001297 Base = N.getOperand(0);
1298 if (Base.getOpcode() == ISD::TargetConstantPool)
1299 return false; // We want to select t2LDRpci instead.
1300 } else
1301 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001302 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001303 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001304 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001305
1306 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001307 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001308 // Let t2LDRi8 handle (R - imm8).
1309 return false;
1310
Evan Chengb23b50d2009-06-29 07:51:04 +00001311 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001312 if (N.getOpcode() == ISD::SUB)
1313 RHSC = -RHSC;
1314
1315 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001316 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001317 if (Base.getOpcode() == ISD::FrameIndex) {
1318 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001319 Base = CurDAG->getTargetFrameIndex(
1320 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin79c079b2009-07-30 18:56:48 +00001321 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001322 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001323 return true;
1324 }
1325 }
1326
Evan Cheng36064672009-08-11 08:52:18 +00001327 // Base only.
1328 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001329 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001330 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001331}
1332
Chris Lattner0e023ea2010-09-21 20:31:19 +00001333bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001334 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001335 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001336 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1337 !CurDAG->isBaseWithConstantOffset(N))
1338 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001339
Chris Lattner46c01a32011-02-13 22:25:43 +00001340 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1341 int RHSC = (int)RHS->getSExtValue();
1342 if (N.getOpcode() == ISD::SUB)
1343 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001344
Chris Lattner46c01a32011-02-13 22:25:43 +00001345 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1346 Base = N.getOperand(0);
1347 if (Base.getOpcode() == ISD::FrameIndex) {
1348 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001349 Base = CurDAG->getTargetFrameIndex(
1350 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Chengb23b50d2009-06-29 07:51:04 +00001351 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001352 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Chris Lattner46c01a32011-02-13 22:25:43 +00001353 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001354 }
1355 }
1356
1357 return false;
1358}
1359
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001360bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001361 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001362 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001363 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1364 ? cast<LoadSDNode>(Op)->getAddressingMode()
1365 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001366 int RHSC;
1367 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1368 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001369 ? CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32)
1370 : CurDAG->getTargetConstant(-RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001371 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001372 }
1373
1374 return false;
1375}
1376
Chris Lattner0e023ea2010-09-21 20:31:19 +00001377bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001378 SDValue &Base,
1379 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001380 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001381 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001382 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001383
Evan Cheng36064672009-08-11 08:52:18 +00001384 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1385 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1386 int RHSC = (int)RHS->getZExtValue();
1387 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1388 return false;
1389 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001390 return false;
1391 }
1392
Evan Chengb23b50d2009-06-29 07:51:04 +00001393 // Look for (R + R) or (R + (R << [1,2,3])).
1394 unsigned ShAmt = 0;
1395 Base = N.getOperand(0);
1396 OffReg = N.getOperand(1);
1397
1398 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001399 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001400 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001401 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001402 if (ShOpcVal == ARM_AM::lsl)
1403 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001404 }
1405
Evan Chengb23b50d2009-06-29 07:51:04 +00001406 if (ShOpcVal == ARM_AM::lsl) {
1407 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1408 // it.
1409 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1410 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001411 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1412 OffReg = OffReg.getOperand(0);
1413 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001414 ShAmt = 0;
Evan Cheng59bbc542010-10-27 23:41:30 +00001415 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001416 }
David Goodwinf3912052009-07-15 15:50:19 +00001417 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001418
John Brawn056e6782015-09-14 15:19:41 +00001419 // If OffReg is a multiply-by-constant and it's profitable to extract a shift
1420 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +00001421 if (OffReg.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +00001422 unsigned PowerOfTwo = 0;
1423 SDValue NewMulConst;
1424 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
Tim Northover4a01ffb2017-05-02 22:45:19 +00001425 HandleSDNode Handle(OffReg);
John Brawn056e6782015-09-14 15:19:41 +00001426 replaceDAGValue(OffReg.getOperand(1), NewMulConst);
Tim Northover4a01ffb2017-05-02 22:45:19 +00001427 OffReg = Handle.getValue();
John Brawn056e6782015-09-14 15:19:41 +00001428 ShAmt = PowerOfTwo;
1429 }
1430 }
1431
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001432 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001433
1434 return true;
1435}
1436
Tim Northovera7ecd242013-07-16 09:46:55 +00001437bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1438 SDValue &OffImm) {
Alp Tokercb402912014-01-24 17:20:08 +00001439 // This *must* succeed since it's used for the irreplaceable ldrex and strex
Tim Northovera7ecd242013-07-16 09:46:55 +00001440 // instructions.
1441 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001442 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001443
1444 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1445 return true;
1446
1447 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1448 if (!RHS)
1449 return true;
1450
1451 uint32_t RHSC = (int)RHS->getZExtValue();
1452 if (RHSC > 1020 || RHSC % 4 != 0)
1453 return true;
1454
1455 Base = N.getOperand(0);
1456 if (Base.getOpcode() == ISD::FrameIndex) {
1457 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001458 Base = CurDAG->getTargetFrameIndex(
1459 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Tim Northovera7ecd242013-07-16 09:46:55 +00001460 }
1461
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001462 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001463 return true;
1464}
1465
Evan Chengb23b50d2009-06-29 07:51:04 +00001466//===--------------------------------------------------------------------===//
1467
Evan Cheng7e90b112007-07-05 07:15:27 +00001468/// getAL - Returns a ARMCC::AL immediate node.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001469static inline SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001470 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001471}
1472
Tim Northovereaee28b2016-09-19 09:11:09 +00001473void ARMDAGToDAGISel::transferMemOperands(SDNode *N, SDNode *Result) {
1474 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1475 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
1476 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
1477}
1478
Justin Bogner45571362016-05-12 00:31:09 +00001479bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001480 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001481 ISD::MemIndexedMode AM = LD->getAddressingMode();
1482 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001483 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001484
Owen Anderson53aa7a92009-08-10 22:56:29 +00001485 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001486 SDValue Offset, AMOpc;
1487 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1488 unsigned Opcode = 0;
1489 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001490 if (LoadedVT == MVT::i32 && isPre &&
1491 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1492 Opcode = ARM::LDR_PRE_IMM;
1493 Match = true;
1494 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001495 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001496 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001497 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001498 } else if (LoadedVT == MVT::i32 &&
1499 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001500 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001501 Match = true;
1502
Owen Anderson9f944592009-08-11 20:47:22 +00001503 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001504 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001505 Match = true;
1506 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1507 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1508 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001509 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001510 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001511 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001512 Match = true;
1513 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1514 }
1515 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001516 if (isPre &&
1517 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001518 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001519 Opcode = ARM::LDRB_PRE_IMM;
1520 } else if (!isPre &&
1521 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1522 Match = true;
1523 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001524 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1525 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001526 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001527 }
1528 }
1529 }
1530
1531 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001532 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1533 SDValue Chain = LD->getChain();
1534 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001535 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001536 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001537 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1538 MVT::Other, Ops);
1539 transferMemOperands(N, New);
1540 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001541 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001542 } else {
1543 SDValue Chain = LD->getChain();
1544 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001545 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001546 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001547 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1548 MVT::Other, Ops);
1549 transferMemOperands(N, New);
1550 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001551 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001552 }
Evan Chengd9c55362009-07-02 01:23:32 +00001553 }
1554
Justin Bogner45571362016-05-12 00:31:09 +00001555 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001556}
1557
James Molloyb3326df2016-07-15 08:03:56 +00001558bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *N) {
1559 LoadSDNode *LD = cast<LoadSDNode>(N);
1560 EVT LoadedVT = LD->getMemoryVT();
1561 ISD::MemIndexedMode AM = LD->getAddressingMode();
Chandler Carruth5589aa62016-11-03 17:42:02 +00001562 if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD ||
1563 LoadedVT.getSimpleVT().SimpleTy != MVT::i32)
James Molloyb3326df2016-07-15 08:03:56 +00001564 return false;
1565
1566 auto *COffs = dyn_cast<ConstantSDNode>(LD->getOffset());
1567 if (!COffs || COffs->getZExtValue() != 4)
1568 return false;
1569
1570 // A T1 post-indexed load is just a single register LDM: LDM r0!, {r1}.
1571 // The encoding of LDM is not how the rest of ISel expects a post-inc load to
1572 // look however, so we use a pseudo here and switch it for a tLDMIA_UPD after
1573 // ISel.
1574 SDValue Chain = LD->getChain();
1575 SDValue Base = LD->getBasePtr();
1576 SDValue Ops[]= { Base, getAL(CurDAG, SDLoc(N)),
1577 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001578 SDNode *New = CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(N), MVT::i32,
1579 MVT::i32, MVT::Other, Ops);
1580 transferMemOperands(N, New);
1581 ReplaceNode(N, New);
James Molloyb3326df2016-07-15 08:03:56 +00001582 return true;
1583}
1584
Justin Bogner45571362016-05-12 00:31:09 +00001585bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001586 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001587 ISD::MemIndexedMode AM = LD->getAddressingMode();
1588 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001589 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001590
Owen Anderson53aa7a92009-08-10 22:56:29 +00001591 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001592 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001593 SDValue Offset;
1594 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1595 unsigned Opcode = 0;
1596 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001597 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001598 switch (LoadedVT.getSimpleVT().SimpleTy) {
1599 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001600 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1601 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001602 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001603 if (isSExtLd)
1604 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1605 else
1606 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001607 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001608 case MVT::i8:
1609 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001610 if (isSExtLd)
1611 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1612 else
1613 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001614 break;
1615 default:
Justin Bogner45571362016-05-12 00:31:09 +00001616 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001617 }
1618 Match = true;
1619 }
1620
1621 if (Match) {
1622 SDValue Chain = LD->getChain();
1623 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001624 SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)),
Owen Anderson9f944592009-08-11 20:47:22 +00001625 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001626 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1627 MVT::Other, Ops);
1628 transferMemOperands(N, New);
1629 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001630 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001631 }
1632
Justin Bogner45571362016-05-12 00:31:09 +00001633 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001634}
1635
Weiming Zhao8f56f882012-11-16 21:55:34 +00001636/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1637SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001638 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001639 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001640 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1641 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1642 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001643 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001644 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001645}
1646
Weiming Zhao95782222012-11-17 00:23:35 +00001647/// \brief Form a D register from a pair of S registers.
1648SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001649 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001650 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001651 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1652 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1653 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001654 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001655 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001656}
1657
Weiming Zhao95782222012-11-17 00:23:35 +00001658/// \brief Form a quad register from a pair of D registers.
1659SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001660 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001661 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1662 MVT::i32);
1663 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1664 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001665 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001666 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001667}
1668
Weiming Zhao95782222012-11-17 00:23:35 +00001669/// \brief Form 4 consecutive D registers from a pair of Q registers.
1670SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001671 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001672 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1673 MVT::i32);
1674 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1675 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001676 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001677 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001678}
1679
Weiming Zhao95782222012-11-17 00:23:35 +00001680/// \brief Form 4 consecutive S registers.
1681SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001682 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001683 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001684 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001685 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1686 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1687 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1688 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1689 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001690 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1691 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001692 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001693}
1694
Weiming Zhao95782222012-11-17 00:23:35 +00001695/// \brief Form 4 consecutive D registers.
1696SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001697 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001698 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001699 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1700 MVT::i32);
1701 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1702 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1703 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1704 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001705 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1706 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001707 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001708}
1709
Weiming Zhao95782222012-11-17 00:23:35 +00001710/// \brief Form 4 consecutive Q registers.
1711SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001712 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001713 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001714 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1715 MVT::i32);
1716 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1717 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1718 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1719 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001720 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1721 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001722 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001723}
1724
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001725/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1726/// of a NEON VLD or VST instruction. The supported values depend on the
1727/// number of registers being loaded.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001728SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, const SDLoc &dl,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001729 unsigned NumVecs, bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001730 unsigned NumRegs = NumVecs;
1731 if (!is64BitVector && NumVecs < 3)
1732 NumRegs *= 2;
1733
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001734 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001735 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001736 Alignment = 32;
1737 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1738 Alignment = 16;
1739 else if (Alignment >= 8)
1740 Alignment = 8;
1741 else
1742 Alignment = 0;
1743
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001744 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001745}
1746
Jiangning Liu4df23632014-01-16 09:16:13 +00001747static bool isVLDfixed(unsigned Opc)
1748{
1749 switch (Opc) {
1750 default: return false;
1751 case ARM::VLD1d8wb_fixed : return true;
1752 case ARM::VLD1d16wb_fixed : return true;
1753 case ARM::VLD1d64Qwb_fixed : return true;
1754 case ARM::VLD1d32wb_fixed : return true;
1755 case ARM::VLD1d64wb_fixed : return true;
1756 case ARM::VLD1d64TPseudoWB_fixed : return true;
1757 case ARM::VLD1d64QPseudoWB_fixed : return true;
1758 case ARM::VLD1q8wb_fixed : return true;
1759 case ARM::VLD1q16wb_fixed : return true;
1760 case ARM::VLD1q32wb_fixed : return true;
1761 case ARM::VLD1q64wb_fixed : return true;
Eli Friedmanf624ec22016-12-16 18:44:08 +00001762 case ARM::VLD1DUPd8wb_fixed : return true;
1763 case ARM::VLD1DUPd16wb_fixed : return true;
1764 case ARM::VLD1DUPd32wb_fixed : return true;
1765 case ARM::VLD1DUPq8wb_fixed : return true;
1766 case ARM::VLD1DUPq16wb_fixed : return true;
1767 case ARM::VLD1DUPq32wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001768 case ARM::VLD2d8wb_fixed : return true;
1769 case ARM::VLD2d16wb_fixed : return true;
1770 case ARM::VLD2d32wb_fixed : return true;
1771 case ARM::VLD2q8PseudoWB_fixed : return true;
1772 case ARM::VLD2q16PseudoWB_fixed : return true;
1773 case ARM::VLD2q32PseudoWB_fixed : return true;
1774 case ARM::VLD2DUPd8wb_fixed : return true;
1775 case ARM::VLD2DUPd16wb_fixed : return true;
1776 case ARM::VLD2DUPd32wb_fixed : return true;
1777 }
1778}
1779
1780static bool isVSTfixed(unsigned Opc)
1781{
1782 switch (Opc) {
1783 default: return false;
1784 case ARM::VST1d8wb_fixed : return true;
1785 case ARM::VST1d16wb_fixed : return true;
1786 case ARM::VST1d32wb_fixed : return true;
1787 case ARM::VST1d64wb_fixed : return true;
Jim Grosbach1a597112014-04-03 23:43:18 +00001788 case ARM::VST1q8wb_fixed : return true;
1789 case ARM::VST1q16wb_fixed : return true;
1790 case ARM::VST1q32wb_fixed : return true;
1791 case ARM::VST1q64wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001792 case ARM::VST1d64TPseudoWB_fixed : return true;
1793 case ARM::VST1d64QPseudoWB_fixed : return true;
1794 case ARM::VST2d8wb_fixed : return true;
1795 case ARM::VST2d16wb_fixed : return true;
1796 case ARM::VST2d32wb_fixed : return true;
1797 case ARM::VST2q8PseudoWB_fixed : return true;
1798 case ARM::VST2q16PseudoWB_fixed : return true;
1799 case ARM::VST2q32PseudoWB_fixed : return true;
1800 }
1801}
1802
Jim Grosbach2098cb12011-10-24 21:45:13 +00001803// Get the register stride update opcode of a VLD/VST instruction that
1804// is otherwise equivalent to the given fixed stride updating instruction.
1805static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
Jiangning Liu4df23632014-01-16 09:16:13 +00001806 assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1807 && "Incorrect fixed stride updating instruction.");
Jim Grosbach2098cb12011-10-24 21:45:13 +00001808 switch (Opc) {
1809 default: break;
1810 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1811 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1812 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1813 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1814 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1815 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1816 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1817 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jiangning Liu4df23632014-01-16 09:16:13 +00001818 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1819 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1820 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1821 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
Eli Friedmanf624ec22016-12-16 18:44:08 +00001822 case ARM::VLD1DUPd8wb_fixed : return ARM::VLD1DUPd8wb_register;
1823 case ARM::VLD1DUPd16wb_fixed : return ARM::VLD1DUPd16wb_register;
1824 case ARM::VLD1DUPd32wb_fixed : return ARM::VLD1DUPd32wb_register;
1825 case ARM::VLD1DUPq8wb_fixed : return ARM::VLD1DUPq8wb_register;
1826 case ARM::VLD1DUPq16wb_fixed : return ARM::VLD1DUPq16wb_register;
1827 case ARM::VLD1DUPq32wb_fixed : return ARM::VLD1DUPq32wb_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001828
1829 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1830 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1831 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1832 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1833 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1834 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1835 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1836 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001837 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001838 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001839
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001840 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1841 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1842 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001843 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1844 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1845 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1846
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001847 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1848 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1849 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001850 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1851 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1852 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001853
Jim Grosbach13a292c2012-03-06 22:01:44 +00001854 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1855 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1856 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001857 }
1858 return Opc; // If not one we handle, return it unchanged.
1859}
1860
Tim Northover8b1240b2017-04-20 19:54:02 +00001861/// Returns true if the given increment is a Constant known to be equal to the
1862/// access size performed by a NEON load/store. This means the "[rN]!" form can
1863/// be used.
1864static bool isPerfectIncrement(SDValue Inc, EVT VecTy, unsigned NumVecs) {
1865 auto C = dyn_cast<ConstantSDNode>(Inc);
1866 return C && C->getZExtValue() == VecTy.getSizeInBits() / 8 * NumVecs;
1867}
1868
Justin Bogner45571362016-05-12 00:31:09 +00001869void ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
1870 const uint16_t *DOpcodes,
1871 const uint16_t *QOpcodes0,
1872 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001873 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001874 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001875
Bob Wilsonae08a732010-03-20 22:13:40 +00001876 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001877 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1878 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001879 return;
Bob Wilson12b47992009-10-14 17:28:52 +00001880
1881 SDValue Chain = N->getOperand(0);
1882 EVT VT = N->getValueType(0);
1883 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001884 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001885
Bob Wilson12b47992009-10-14 17:28:52 +00001886 unsigned OpcodeIndex;
1887 switch (VT.getSimpleVT().SimpleTy) {
1888 default: llvm_unreachable("unhandled vld type");
1889 // Double-register operations:
1890 case MVT::v8i8: OpcodeIndex = 0; break;
1891 case MVT::v4i16: OpcodeIndex = 1; break;
1892 case MVT::v2f32:
1893 case MVT::v2i32: OpcodeIndex = 2; break;
1894 case MVT::v1i64: OpcodeIndex = 3; break;
1895 // Quad-register operations:
1896 case MVT::v16i8: OpcodeIndex = 0; break;
1897 case MVT::v8i16: OpcodeIndex = 1; break;
1898 case MVT::v4f32:
1899 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001900 case MVT::v2f64:
Bob Wilson340861d2010-03-23 05:25:43 +00001901 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001902 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson340861d2010-03-23 05:25:43 +00001903 break;
Bob Wilson12b47992009-10-14 17:28:52 +00001904 }
1905
Bob Wilson35fafca2010-09-03 18:16:02 +00001906 EVT ResTy;
1907 if (NumVecs == 1)
1908 ResTy = VT;
1909 else {
1910 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1911 if (!is64BitVector)
1912 ResTyElts *= 2;
1913 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1914 }
Bob Wilson06fce872011-02-07 17:43:21 +00001915 std::vector<EVT> ResTys;
1916 ResTys.push_back(ResTy);
1917 if (isUpdating)
1918 ResTys.push_back(MVT::i32);
1919 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001920
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001921 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001922 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001923 SDNode *VLd;
1924 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001925
Bob Wilson06fce872011-02-07 17:43:21 +00001926 // Double registers and VLD1/VLD2 quad registers are directly supported.
1927 if (is64BitVector || NumVecs <= 2) {
1928 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1929 QOpcodes0[OpcodeIndex]);
1930 Ops.push_back(MemAddr);
1931 Ops.push_back(Align);
1932 if (isUpdating) {
1933 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachd146a022011-12-09 21:28:25 +00001934 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach2098cb12011-10-24 21:45:13 +00001935 // case entirely when the rest are updated to that form, too.
Tim Northover8b1240b2017-04-20 19:54:02 +00001936 bool IsImmUpdate = isPerfectIncrement(Inc, VT, NumVecs);
1937 if ((NumVecs <= 2) && !IsImmUpdate)
Jim Grosbach2098cb12011-10-24 21:45:13 +00001938 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001939 // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001940 // check for that explicitly too. Horribly hacky, but temporary.
Tim Northover8b1240b2017-04-20 19:54:02 +00001941 if ((NumVecs > 2 && !isVLDfixed(Opc)) || !IsImmUpdate)
1942 Ops.push_back(IsImmUpdate ? Reg0 : Inc);
Evan Cheng630063a2010-05-10 21:26:24 +00001943 }
Bob Wilson06fce872011-02-07 17:43:21 +00001944 Ops.push_back(Pred);
1945 Ops.push_back(Reg0);
1946 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001947 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001948
Bob Wilson12b47992009-10-14 17:28:52 +00001949 } else {
1950 // Otherwise, quad registers are loaded with two separate instructions,
1951 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001952 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001953
Bob Wilson06fce872011-02-07 17:43:21 +00001954 // Load the even subregs. This is always an updating load, so that it
1955 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001956 SDValue ImplDef =
1957 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1958 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001959 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001960 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001961 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001962
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001963 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001964 Ops.push_back(SDValue(VLdA, 1));
1965 Ops.push_back(Align);
1966 if (isUpdating) {
1967 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1968 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1969 "only constant post-increment update allowed for VLD3/4");
1970 (void)Inc;
1971 Ops.push_back(Reg0);
1972 }
1973 Ops.push_back(SDValue(VLdA, 0));
1974 Ops.push_back(Pred);
1975 Ops.push_back(Reg0);
1976 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001977 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001978 }
Bob Wilson12b47992009-10-14 17:28:52 +00001979
Evan Cheng40791332011-04-19 00:04:03 +00001980 // Transfer memoperands.
1981 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1982 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1983 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1984
Justin Bogner45571362016-05-12 00:31:09 +00001985 if (NumVecs == 1) {
1986 ReplaceNode(N, VLd);
1987 return;
1988 }
Bob Wilson06fce872011-02-07 17:43:21 +00001989
1990 // Extract out the subregisters.
1991 SDValue SuperReg = SDValue(VLd, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00001992 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
1993 ARM::qsub_3 == ARM::qsub_0 + 3,
1994 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00001995 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1996 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1997 ReplaceUses(SDValue(N, Vec),
1998 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1999 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
2000 if (isUpdating)
2001 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002002 CurDAG->RemoveDeadNode(N);
Bob Wilson12b47992009-10-14 17:28:52 +00002003}
2004
Justin Bogner45571362016-05-12 00:31:09 +00002005void ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
2006 const uint16_t *DOpcodes,
2007 const uint16_t *QOpcodes0,
2008 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00002009 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002010 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002011
Bob Wilsonae08a732010-03-20 22:13:40 +00002012 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00002013 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2014 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2015 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002016 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002017
Evan Cheng40791332011-04-19 00:04:03 +00002018 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2019 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2020
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002021 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00002022 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002023 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002024 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00002025
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002026 unsigned OpcodeIndex;
2027 switch (VT.getSimpleVT().SimpleTy) {
2028 default: llvm_unreachable("unhandled vst type");
2029 // Double-register operations:
2030 case MVT::v8i8: OpcodeIndex = 0; break;
2031 case MVT::v4i16: OpcodeIndex = 1; break;
2032 case MVT::v2f32:
2033 case MVT::v2i32: OpcodeIndex = 2; break;
2034 case MVT::v1i64: OpcodeIndex = 3; break;
2035 // Quad-register operations:
2036 case MVT::v16i8: OpcodeIndex = 0; break;
2037 case MVT::v8i16: OpcodeIndex = 1; break;
2038 case MVT::v4f32:
2039 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00002040 case MVT::v2f64:
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00002041 case MVT::v2i64: OpcodeIndex = 3;
2042 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
2043 break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002044 }
2045
Bob Wilson06fce872011-02-07 17:43:21 +00002046 std::vector<EVT> ResTys;
2047 if (isUpdating)
2048 ResTys.push_back(MVT::i32);
2049 ResTys.push_back(MVT::Other);
2050
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002051 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002052 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00002053 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00002054
Bob Wilson06fce872011-02-07 17:43:21 +00002055 // Double registers and VST1/VST2 quad registers are directly supported.
2056 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00002057 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00002058 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00002059 SrcReg = N->getOperand(Vec0Idx);
2060 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00002061 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00002062 SDValue V0 = N->getOperand(Vec0Idx + 0);
2063 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00002064 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002065 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002066 else {
Bob Wilson06fce872011-02-07 17:43:21 +00002067 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00002068 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00002069 // an undef.
2070 SDValue V3 = (NumVecs == 3)
2071 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002072 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002073 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002074 }
Bob Wilson950882b2010-08-28 05:12:57 +00002075 } else {
2076 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00002077 SDValue Q0 = N->getOperand(Vec0Idx);
2078 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00002079 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002080 }
Bob Wilson06fce872011-02-07 17:43:21 +00002081
2082 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2083 QOpcodes0[OpcodeIndex]);
2084 Ops.push_back(MemAddr);
2085 Ops.push_back(Align);
2086 if (isUpdating) {
2087 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbach88ac7612011-12-14 21:32:11 +00002088 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach05df4602011-10-31 21:50:31 +00002089 // case entirely when the rest are updated to that form, too.
Tim Northover8b1240b2017-04-20 19:54:02 +00002090 bool IsImmUpdate = isPerfectIncrement(Inc, VT, NumVecs);
2091 if (NumVecs <= 2 && !IsImmUpdate)
Jim Grosbach05df4602011-10-31 21:50:31 +00002092 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00002093 // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00002094 // check for that explicitly too. Horribly hacky, but temporary.
Tim Northover8b1240b2017-04-20 19:54:02 +00002095 if (!IsImmUpdate)
Jiangning Liu4df23632014-01-16 09:16:13 +00002096 Ops.push_back(Inc);
2097 else if (NumVecs > 2 && !isVSTfixed(Opc))
2098 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002099 }
2100 Ops.push_back(SrcReg);
2101 Ops.push_back(Pred);
2102 Ops.push_back(Reg0);
2103 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00002104 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002105
2106 // Transfer memoperands.
2107 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
2108
Justin Bogner45571362016-05-12 00:31:09 +00002109 ReplaceNode(N, VSt);
2110 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002111 }
2112
2113 // Otherwise, quad registers are stored with two separate instructions,
2114 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00002115
Bob Wilson01ac8f92010-06-16 21:34:01 +00002116 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00002117 SDValue V0 = N->getOperand(Vec0Idx + 0);
2118 SDValue V1 = N->getOperand(Vec0Idx + 1);
2119 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00002120 SDValue V3 = (NumVecs == 3)
2121 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002122 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002123 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002124
Bob Wilson06fce872011-02-07 17:43:21 +00002125 // Store the even D registers. This is always an updating store, so that it
2126 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00002127 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2128 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2129 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00002130 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00002131 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002132 Chain = SDValue(VStA, 1);
2133
2134 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00002135 Ops.push_back(SDValue(VStA, 0));
2136 Ops.push_back(Align);
2137 if (isUpdating) {
2138 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2139 assert(isa<ConstantSDNode>(Inc.getNode()) &&
2140 "only constant post-increment update allowed for VST3/4");
2141 (void)Inc;
2142 Ops.push_back(Reg0);
2143 }
2144 Ops.push_back(RegSeq);
2145 Ops.push_back(Pred);
2146 Ops.push_back(Reg0);
2147 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00002148 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00002149 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002150 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002151 ReplaceNode(N, VStB);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002152}
2153
Justin Bogner45571362016-05-12 00:31:09 +00002154void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
2155 unsigned NumVecs,
2156 const uint16_t *DOpcodes,
2157 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002158 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002159 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002160
Bob Wilsonae08a732010-03-20 22:13:40 +00002161 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00002162 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2163 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2164 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002165 return;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002166
Evan Cheng40791332011-04-19 00:04:03 +00002167 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2168 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2169
Bob Wilson4145e3a2009-10-14 16:19:03 +00002170 SDValue Chain = N->getOperand(0);
2171 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002172 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2173 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002174 bool is64BitVector = VT.is64BitVector();
2175
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002176 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002177 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002178 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Sanjay Patel1ed771f2016-09-14 16:37:15 +00002179 unsigned NumBytes = NumVecs * VT.getScalarSizeInBits() / 8;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002180 if (Alignment > NumBytes)
2181 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002182 if (Alignment < 8 && Alignment < NumBytes)
2183 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002184 // Alignment must be a power of two; make sure of that.
2185 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002186 if (Alignment == 1)
2187 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002188 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002189 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002190
Bob Wilson4145e3a2009-10-14 16:19:03 +00002191 unsigned OpcodeIndex;
2192 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002193 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002194 // Double-register operations:
2195 case MVT::v8i8: OpcodeIndex = 0; break;
2196 case MVT::v4i16: OpcodeIndex = 1; break;
2197 case MVT::v2f32:
2198 case MVT::v2i32: OpcodeIndex = 2; break;
2199 // Quad-register operations:
2200 case MVT::v8i16: OpcodeIndex = 0; break;
2201 case MVT::v4f32:
2202 case MVT::v4i32: OpcodeIndex = 1; break;
2203 }
2204
Bob Wilson06fce872011-02-07 17:43:21 +00002205 std::vector<EVT> ResTys;
2206 if (IsLoad) {
2207 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2208 if (!is64BitVector)
2209 ResTyElts *= 2;
2210 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2211 MVT::i64, ResTyElts));
2212 }
2213 if (isUpdating)
2214 ResTys.push_back(MVT::i32);
2215 ResTys.push_back(MVT::Other);
2216
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002217 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002218 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002219
Bob Wilson06fce872011-02-07 17:43:21 +00002220 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002221 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002222 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002223 if (isUpdating) {
2224 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Tim Northover8b1240b2017-04-20 19:54:02 +00002225 bool IsImmUpdate =
2226 isPerfectIncrement(Inc, VT.getVectorElementType(), NumVecs);
2227 Ops.push_back(IsImmUpdate ? Reg0 : Inc);
Bob Wilson06fce872011-02-07 17:43:21 +00002228 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002229
Bob Wilsond5c57a52010-09-13 23:01:35 +00002230 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002231 SDValue V0 = N->getOperand(Vec0Idx + 0);
2232 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002233 if (NumVecs == 2) {
2234 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002235 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002236 else
Weiming Zhao95782222012-11-17 00:23:35 +00002237 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002238 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002239 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002240 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002241 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2242 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002243 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002244 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002245 else
Weiming Zhao95782222012-11-17 00:23:35 +00002246 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002247 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002248 Ops.push_back(SuperReg);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002249 Ops.push_back(getI32Imm(Lane, dl));
Evan Chenga33fc862009-11-21 06:21:52 +00002250 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002251 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002252 Ops.push_back(Chain);
2253
Bob Wilson06fce872011-02-07 17:43:21 +00002254 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2255 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002256 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002257 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002258 if (!IsLoad) {
2259 ReplaceNode(N, VLdLn);
2260 return;
2261 }
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002262
Bob Wilsond5c57a52010-09-13 23:01:35 +00002263 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002264 SuperReg = SDValue(VLdLn, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00002265 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2266 ARM::qsub_3 == ARM::qsub_0 + 3,
2267 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00002268 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002269 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2270 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002271 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2272 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2273 if (isUpdating)
2274 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002275 CurDAG->RemoveDeadNode(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002276}
2277
Justin Bogner45571362016-05-12 00:31:09 +00002278void ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Eli Friedmanf624ec22016-12-16 18:44:08 +00002279 const uint16_t *DOpcodes,
2280 const uint16_t *QOpcodes) {
2281 assert(NumVecs >= 1 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002282 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002283
2284 SDValue MemAddr, Align;
2285 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002286 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00002287
Evan Cheng40791332011-04-19 00:04:03 +00002288 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2289 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2290
Bob Wilson2d790df2010-11-28 06:51:26 +00002291 SDValue Chain = N->getOperand(0);
2292 EVT VT = N->getValueType(0);
2293
2294 unsigned Alignment = 0;
2295 if (NumVecs != 3) {
2296 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Sanjay Patel1ed771f2016-09-14 16:37:15 +00002297 unsigned NumBytes = NumVecs * VT.getScalarSizeInBits() / 8;
Bob Wilson2d790df2010-11-28 06:51:26 +00002298 if (Alignment > NumBytes)
2299 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002300 if (Alignment < 8 && Alignment < NumBytes)
2301 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002302 // Alignment must be a power of two; make sure of that.
2303 Alignment = (Alignment & -Alignment);
2304 if (Alignment == 1)
2305 Alignment = 0;
2306 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002307 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson2d790df2010-11-28 06:51:26 +00002308
Eli Friedmanf624ec22016-12-16 18:44:08 +00002309 unsigned Opc;
Bob Wilson2d790df2010-11-28 06:51:26 +00002310 switch (VT.getSimpleVT().SimpleTy) {
2311 default: llvm_unreachable("unhandled vld-dup type");
Eli Friedmanf624ec22016-12-16 18:44:08 +00002312 case MVT::v8i8: Opc = DOpcodes[0]; break;
2313 case MVT::v16i8: Opc = QOpcodes[0]; break;
2314 case MVT::v4i16: Opc = DOpcodes[1]; break;
2315 case MVT::v8i16: Opc = QOpcodes[1]; break;
Bob Wilson2d790df2010-11-28 06:51:26 +00002316 case MVT::v2f32:
Eli Friedmanf624ec22016-12-16 18:44:08 +00002317 case MVT::v2i32: Opc = DOpcodes[2]; break;
2318 case MVT::v4f32:
2319 case MVT::v4i32: Opc = QOpcodes[2]; break;
Bob Wilson2d790df2010-11-28 06:51:26 +00002320 }
2321
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002322 SDValue Pred = getAL(CurDAG, dl);
Bob Wilson2d790df2010-11-28 06:51:26 +00002323 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00002324 SmallVector<SDValue, 6> Ops;
2325 Ops.push_back(MemAddr);
2326 Ops.push_back(Align);
2327 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002328 // fixed-stride update instructions don't have an explicit writeback
2329 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002330 SDValue Inc = N->getOperand(2);
Tim Northover8b1240b2017-04-20 19:54:02 +00002331 bool IsImmUpdate =
2332 isPerfectIncrement(Inc, VT.getVectorElementType(), NumVecs);
2333 if (NumVecs <= 2 && !IsImmUpdate)
Eli Friedmanf624ec22016-12-16 18:44:08 +00002334 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Tim Northover8b1240b2017-04-20 19:54:02 +00002335 if (!IsImmUpdate)
Jim Grosbachc80a2642011-12-21 19:40:55 +00002336 Ops.push_back(Inc);
2337 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2338 else if (NumVecs > 2)
2339 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002340 }
2341 Ops.push_back(Pred);
2342 Ops.push_back(Reg0);
2343 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002344
2345 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002346 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002347 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002348 if (isUpdating)
2349 ResTys.push_back(MVT::i32);
2350 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002351 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002352 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002353
2354 // Extract the subregisters.
Eli Friedmanf624ec22016-12-16 18:44:08 +00002355 if (NumVecs == 1) {
2356 ReplaceUses(SDValue(N, 0), SDValue(VLdDup, 0));
2357 } else {
2358 SDValue SuperReg = SDValue(VLdDup, 0);
2359 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7, "Unexpected subreg numbering");
2360 unsigned SubIdx = ARM::dsub_0;
2361 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2362 ReplaceUses(SDValue(N, Vec),
2363 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
2364 }
Bob Wilson06fce872011-02-07 17:43:21 +00002365 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2366 if (isUpdating)
2367 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002368 CurDAG->RemoveDeadNode(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002369}
2370
Justin Bogner45571362016-05-12 00:31:09 +00002371bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002372 if (!Subtarget->hasV6T2Ops())
Justin Bogner45571362016-05-12 00:31:09 +00002373 return false;
Bob Wilson93117bc2009-10-14 16:46:45 +00002374
Evan Chengeae6d2c2012-12-19 20:16:09 +00002375 unsigned Opc = isSigned
2376 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002377 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002378 SDLoc dl(N);
Jim Grosbach825cb292010-04-22 23:24:18 +00002379
Jim Grosbach825cb292010-04-22 23:24:18 +00002380 // For unsigned extracts, check for a shift right and mask
2381 unsigned And_imm = 0;
2382 if (N->getOpcode() == ISD::AND) {
2383 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2384
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002385 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002386 if (And_imm & (And_imm + 1))
Justin Bogner45571362016-05-12 00:31:09 +00002387 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002388
2389 unsigned Srl_imm = 0;
2390 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2391 Srl_imm)) {
2392 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2393
Jim Grosbach03f56d92011-07-27 21:09:25 +00002394 // Note: The width operand is encoded as width-1.
Benjamin Kramer5f6a9072015-02-12 15:35:40 +00002395 unsigned Width = countTrailingOnes(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002396 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002397
Jim Grosbach825cb292010-04-22 23:24:18 +00002398 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002399
2400 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2401 // It's cheaper to use a right shift to extract the top bits.
2402 if (Subtarget->isThumb()) {
2403 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2404 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002405 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2406 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002407 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2408 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002409 }
2410
2411 // ARM models shift instructions as MOVsi with shifter operand.
2412 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2413 SDValue ShOpc =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002414 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), dl,
Evan Chengeae6d2c2012-12-19 20:16:09 +00002415 MVT::i32);
2416 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002417 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002418 CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops);
2419 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002420 }
2421
Jim Grosbach825cb292010-04-22 23:24:18 +00002422 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002423 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2424 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2425 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002426 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2427 return true;
Jim Grosbach825cb292010-04-22 23:24:18 +00002428 }
2429 }
Justin Bogner45571362016-05-12 00:31:09 +00002430 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002431 }
2432
2433 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002434 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002435 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002436 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2437 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002438 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002439 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002440 // Note: The width operand is encoded as width-1.
2441 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002442 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002443 if (LSB < 0)
Justin Bogner45571362016-05-12 00:31:09 +00002444 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002445 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002446 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002447 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2448 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2449 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002450 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2451 return true;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002452 }
2453 }
Tim Northover14ff2df2014-07-23 13:59:12 +00002454
Oliver Stannard92ca83c2016-06-01 12:01:01 +00002455 // Or we are looking for a shift of an and, with a mask operand
2456 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, And_imm) &&
2457 isShiftedMask_32(And_imm)) {
2458 unsigned Srl_imm = 0;
2459 unsigned LSB = countTrailingZeros(And_imm);
2460 // Shift must be the same as the ands lsb
2461 if (isInt32Immediate(N->getOperand(1), Srl_imm) && Srl_imm == LSB) {
2462 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2463 unsigned MSB = 31 - countLeadingZeros(And_imm);
2464 // Note: The width operand is encoded as width-1.
2465 unsigned Width = MSB - LSB;
2466 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2467 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2468 CurDAG->getTargetConstant(Srl_imm, dl, MVT::i32),
2469 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2470 getAL(CurDAG, dl), Reg0 };
2471 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2472 return true;
2473 }
2474 }
2475
Tim Northover14ff2df2014-07-23 13:59:12 +00002476 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
2477 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2478 unsigned LSB = 0;
2479 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) &&
2480 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB))
Justin Bogner45571362016-05-12 00:31:09 +00002481 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002482
2483 if (LSB + Width > 32)
Justin Bogner45571362016-05-12 00:31:09 +00002484 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002485
2486 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2487 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002488 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2489 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
2490 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002491 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2492 return true;
Tim Northover14ff2df2014-07-23 13:59:12 +00002493 }
2494
Justin Bogner45571362016-05-12 00:31:09 +00002495 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002496}
2497
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002498/// Target-specific DAG combining for ISD::XOR.
2499/// Target-independent combining lowers SELECT_CC nodes of the form
2500/// select_cc setg[ge] X, 0, X, -X
2501/// select_cc setgt X, -1, X, -X
2502/// select_cc setl[te] X, 0, -X, X
2503/// select_cc setlt X, 1, -X, X
2504/// which represent Integer ABS into:
2505/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2506/// ARM instruction selection detects the latter and matches it to
2507/// ARM::ABS or ARM::t2ABS machine node.
Justin Bogner45571362016-05-12 00:31:09 +00002508bool ARMDAGToDAGISel::tryABSOp(SDNode *N){
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002509 SDValue XORSrc0 = N->getOperand(0);
2510 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002511 EVT VT = N->getValueType(0);
2512
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002513 if (Subtarget->isThumb1Only())
Justin Bogner45571362016-05-12 00:31:09 +00002514 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002515
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002516 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Justin Bogner45571362016-05-12 00:31:09 +00002517 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002518
2519 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2520 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2521 SDValue SRASrc0 = XORSrc1.getOperand(0);
2522 SDValue SRASrc1 = XORSrc1.getOperand(1);
2523 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2524 EVT XType = SRASrc0.getValueType();
2525 unsigned Size = XType.getSizeInBits() - 1;
2526
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002527 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
Craig Topper062a2ba2014-04-25 05:30:21 +00002528 XType.isInteger() && SRAConstant != nullptr &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002529 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002530 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Justin Bogner45571362016-05-12 00:31:09 +00002531 CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2532 return true;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002533 }
2534
Justin Bogner45571362016-05-12 00:31:09 +00002535 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002536}
2537
Tim Northoverb629c772016-04-18 21:48:55 +00002538/// We've got special pseudo-instructions for these
Justin Bogner45571362016-05-12 00:31:09 +00002539void ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *N) {
Tim Northoverb629c772016-04-18 21:48:55 +00002540 unsigned Opcode;
2541 EVT MemTy = cast<MemSDNode>(N)->getMemoryVT();
2542 if (MemTy == MVT::i8)
2543 Opcode = ARM::CMP_SWAP_8;
2544 else if (MemTy == MVT::i16)
2545 Opcode = ARM::CMP_SWAP_16;
2546 else if (MemTy == MVT::i32)
2547 Opcode = ARM::CMP_SWAP_32;
2548 else
2549 llvm_unreachable("Unknown AtomicCmpSwap type");
2550
2551 SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3),
2552 N->getOperand(0)};
2553 SDNode *CmpSwap = CurDAG->getMachineNode(
2554 Opcode, SDLoc(N),
2555 CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other), Ops);
2556
2557 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2558 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
2559 cast<MachineSDNode>(CmpSwap)->setMemRefs(MemOp, MemOp + 1);
2560
2561 ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0));
2562 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002563 CurDAG->RemoveDeadNode(N);
Tim Northoverb629c772016-04-18 21:48:55 +00002564}
2565
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002566static Optional<std::pair<unsigned, unsigned>>
2567getContiguousRangeOfSetBits(const APInt &A) {
2568 unsigned FirstOne = A.getBitWidth() - A.countLeadingZeros() - 1;
2569 unsigned LastOne = A.countTrailingZeros();
2570 if (A.countPopulation() != (FirstOne - LastOne + 1))
2571 return Optional<std::pair<unsigned,unsigned>>();
2572 return std::make_pair(FirstOne, LastOne);
2573}
2574
2575void ARMDAGToDAGISel::SelectCMPZ(SDNode *N, bool &SwitchEQNEToPLMI) {
2576 assert(N->getOpcode() == ARMISD::CMPZ);
2577 SwitchEQNEToPLMI = false;
2578
2579 if (!Subtarget->isThumb())
2580 // FIXME: Work out whether it is profitable to do this in A32 mode - LSL and
2581 // LSR don't exist as standalone instructions - they need the barrel shifter.
2582 return;
2583
2584 // select (cmpz (and X, C), #0) -> (LSLS X) or (LSRS X) or (LSRS (LSLS X))
2585 SDValue And = N->getOperand(0);
2586 if (!And->hasOneUse())
2587 return;
2588
2589 SDValue Zero = N->getOperand(1);
2590 if (!isa<ConstantSDNode>(Zero) || !cast<ConstantSDNode>(Zero)->isNullValue() ||
2591 And->getOpcode() != ISD::AND)
2592 return;
2593 SDValue X = And.getOperand(0);
2594 auto C = dyn_cast<ConstantSDNode>(And.getOperand(1));
2595
2596 if (!C || !X->hasOneUse())
2597 return;
2598 auto Range = getContiguousRangeOfSetBits(C->getAPIntValue());
2599 if (!Range)
2600 return;
2601
2602 // There are several ways to lower this:
2603 SDNode *NewN;
2604 SDLoc dl(N);
2605
2606 auto EmitShift = [&](unsigned Opc, SDValue Src, unsigned Imm) -> SDNode* {
2607 if (Subtarget->isThumb2()) {
2608 Opc = (Opc == ARM::tLSLri) ? ARM::t2LSLri : ARM::t2LSRri;
2609 SDValue Ops[] = { Src, CurDAG->getTargetConstant(Imm, dl, MVT::i32),
2610 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
2611 CurDAG->getRegister(0, MVT::i32) };
2612 return CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
2613 } else {
2614 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), Src,
2615 CurDAG->getTargetConstant(Imm, dl, MVT::i32),
2616 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
2617 return CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
2618 }
2619 };
2620
2621 if (Range->second == 0) {
2622 // 1. Mask includes the LSB -> Simply shift the top N bits off
2623 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2624 ReplaceNode(And.getNode(), NewN);
2625 } else if (Range->first == 31) {
2626 // 2. Mask includes the MSB -> Simply shift the bottom N bits off
2627 NewN = EmitShift(ARM::tLSRri, X, Range->second);
2628 ReplaceNode(And.getNode(), NewN);
2629 } else if (Range->first == Range->second) {
2630 // 3. Only one bit is set. We can shift this into the sign bit and use a
2631 // PL/MI comparison.
2632 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2633 ReplaceNode(And.getNode(), NewN);
2634
2635 SwitchEQNEToPLMI = true;
2636 } else if (!Subtarget->hasV6T2Ops()) {
2637 // 4. Do a double shift to clear bottom and top bits, but only in
2638 // thumb-1 mode as in thumb-2 we can use UBFX.
2639 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2640 NewN = EmitShift(ARM::tLSRri, SDValue(NewN, 0),
2641 Range->second + (31 - Range->first));
2642 ReplaceNode(And.getNode(), NewN);
2643 }
2644
2645}
2646
Justin Bogner45571362016-05-12 00:31:09 +00002647void ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002648 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002649
Tim Northover31d093c2013-09-22 08:21:56 +00002650 if (N->isMachineOpcode()) {
2651 N->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00002652 return; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00002653 }
Rafael Espindola4e760152006-06-12 12:28:08 +00002654
2655 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002656 default: break;
Justin Bogner45571362016-05-12 00:31:09 +00002657 case ISD::WRITE_REGISTER:
2658 if (tryWriteRegister(N))
2659 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002660 break;
Justin Bogner45571362016-05-12 00:31:09 +00002661 case ISD::READ_REGISTER:
2662 if (tryReadRegister(N))
2663 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002664 break;
Justin Bogner45571362016-05-12 00:31:09 +00002665 case ISD::INLINEASM:
2666 if (tryInlineAsm(N))
2667 return;
Weiming Zhaoc5987002013-02-14 18:10:21 +00002668 break;
Justin Bogner45571362016-05-12 00:31:09 +00002669 case ISD::XOR:
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002670 // Select special operations if XOR node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +00002671 if (tryABSOp(N))
2672 return;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002673 // Other cases are autogenerated.
2674 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002675 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002676 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
John Brawn056e6782015-09-14 15:19:41 +00002677 // If we can't materialize the constant we need to use a literal pool
2678 if (ConstantMaterializationCost(Val) > 2) {
Eric Christopherb17140d2014-10-08 07:32:17 +00002679 SDValue CPIdx = CurDAG->getTargetConstantPool(
2680 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
Mehdi Amini44ede332015-07-09 02:09:04 +00002681 TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng1526ba52007-01-24 08:53:17 +00002682
2683 SDNode *ResNode;
Tim Northover55c625f2014-01-23 13:43:47 +00002684 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002685 SDValue Pred = getAL(CurDAG, dl);
Owen Anderson9f944592009-08-11 20:47:22 +00002686 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002687 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002688 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002689 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002690 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002691 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002692 CPIdx,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002693 CurDAG->getTargetConstant(0, dl, MVT::i32),
2694 getAL(CurDAG, dl),
Owen Anderson9f944592009-08-11 20:47:22 +00002695 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002696 CurDAG->getEntryNode()
2697 };
Justin Bogner45571362016-05-12 00:31:09 +00002698 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
2699 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002700 }
Justin Bognered4f3782016-05-12 00:20:19 +00002701 ReplaceNode(N, ResNode);
Justin Bogner45571362016-05-12 00:31:09 +00002702 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002703 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002704
Evan Cheng10043e22007-01-19 07:51:42 +00002705 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002706 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002707 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002708 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002709 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002710 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00002711 SDValue TFI = CurDAG->getTargetFrameIndex(
2712 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin22c2fba2009-07-08 23:10:31 +00002713 if (Subtarget->isThumb1Only()) {
Renato Golinb9887ef2015-02-25 14:41:06 +00002714 // Set the alignment of the frame object to 4, to avoid having to generate
2715 // more than one ADD
Matthias Braun941a7052016-07-28 18:40:00 +00002716 MachineFrameInfo &MFI = MF->getFrameInfo();
2717 if (MFI.getObjectAlignment(FI) < 4)
2718 MFI.setObjectAlignment(FI, 4);
Justin Bogner45571362016-05-12 00:31:09 +00002719 CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
2720 CurDAG->getTargetConstant(0, dl, MVT::i32));
2721 return;
Jim Grosbachfde21102009-04-07 20:34:09 +00002722 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002723 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2724 ARM::t2ADDri : ARM::ADDri);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002725 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
2726 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002727 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002728 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2729 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00002730 }
Evan Cheng10043e22007-01-19 07:51:42 +00002731 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002732 case ISD::SRL:
Justin Bogner45571362016-05-12 00:31:09 +00002733 if (tryV6T2BitfieldExtractOp(N, false))
2734 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002735 break;
Tim Northover14ff2df2014-07-23 13:59:12 +00002736 case ISD::SIGN_EXTEND_INREG:
Sandeep Patel423e42b2009-10-13 18:59:48 +00002737 case ISD::SRA:
Justin Bogner45571362016-05-12 00:31:09 +00002738 if (tryV6T2BitfieldExtractOp(N, true))
2739 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002740 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002741 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002742 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002743 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002744 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002745 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002746 if (!RHSV) break;
2747 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002748 unsigned ShImm = Log2_32(RHSV-1);
2749 if (ShImm >= 32)
2750 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002751 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002752 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002753 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002754 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002755 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002756 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002757 CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
2758 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002759 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002760 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2761 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002762 CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
2763 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002764 }
Evan Cheng10043e22007-01-19 07:51:42 +00002765 }
2766 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002767 unsigned ShImm = Log2_32(RHSV+1);
2768 if (ShImm >= 32)
2769 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002770 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002771 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002772 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002773 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002774 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002775 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002776 CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
2777 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002778 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002779 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2780 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002781 CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
2782 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002783 }
Evan Cheng10043e22007-01-19 07:51:42 +00002784 }
2785 }
2786 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002787 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002788 // Check for unsigned bitfield extract
Justin Bogner45571362016-05-12 00:31:09 +00002789 if (tryV6T2BitfieldExtractOp(N, false))
2790 return;
Jim Grosbach825cb292010-04-22 23:24:18 +00002791
James Molloyae5ff992016-07-05 12:37:13 +00002792 // If an immediate is used in an AND node, it is possible that the immediate
2793 // can be more optimally materialized when negated. If this is the case we
2794 // can negate the immediate and use a BIC instead.
2795 auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1));
2796 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
2797 uint32_t Imm = (uint32_t) N1C->getZExtValue();
2798
2799 // In Thumb2 mode, an AND can take a 12-bit immediate. If this
2800 // immediate can be negated and fit in the immediate operand of
2801 // a t2BIC, don't do any manual transform here as this can be
2802 // handled by the generic ISel machinery.
2803 bool PreferImmediateEncoding =
2804 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm));
2805 if (!PreferImmediateEncoding &&
2806 ConstantMaterializationCost(Imm) >
2807 ConstantMaterializationCost(~Imm)) {
2808 // The current immediate costs more to materialize than a negated
2809 // immediate, so negate the immediate and use a BIC.
2810 SDValue NewImm =
2811 CurDAG->getConstant(~N1C->getZExtValue(), dl, MVT::i32);
2812 // If the new constant didn't exist before, reposition it in the topological
2813 // ordering so it is just before N. Otherwise, don't touch its location.
2814 if (NewImm->getNodeId() == -1)
2815 CurDAG->RepositionNode(N->getIterator(), NewImm.getNode());
2816
2817 if (!Subtarget->hasThumb2()) {
2818 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
2819 N->getOperand(0), NewImm, getAL(CurDAG, dl),
2820 CurDAG->getRegister(0, MVT::i32)};
2821 ReplaceNode(N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32, Ops));
2822 return;
2823 } else {
2824 SDValue Ops[] = {N->getOperand(0), NewImm, getAL(CurDAG, dl),
2825 CurDAG->getRegister(0, MVT::i32),
2826 CurDAG->getRegister(0, MVT::i32)};
2827 ReplaceNode(N,
2828 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32, Ops));
2829 return;
2830 }
2831 }
2832 }
2833
Evan Cheng786b15f2009-10-21 08:15:52 +00002834 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2835 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2836 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2837 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2838 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002839 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002840 if (VT != MVT::i32)
2841 break;
2842 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2843 ? ARM::t2MOVTi16
2844 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2845 if (!Opc)
2846 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002847 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
James Molloyae5ff992016-07-05 12:37:13 +00002848 N1C = dyn_cast<ConstantSDNode>(N1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002849 if (!N1C)
2850 break;
2851 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2852 SDValue N2 = N0.getOperand(1);
2853 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2854 if (!N2C)
2855 break;
2856 unsigned N1CVal = N1C->getZExtValue();
2857 unsigned N2CVal = N2C->getZExtValue();
2858 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2859 (N1CVal & 0xffffU) == 0xffffU &&
2860 (N2CVal & 0xffffU) == 0x0U) {
2861 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002862 dl, MVT::i32);
Evan Cheng786b15f2009-10-21 08:15:52 +00002863 SDValue Ops[] = { N0.getOperand(0), Imm16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002864 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002865 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
2866 return;
Evan Cheng786b15f2009-10-21 08:15:52 +00002867 }
2868 }
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002869
Evan Cheng786b15f2009-10-21 08:15:52 +00002870 break;
2871 }
Sam Parkerd616cf02016-06-20 16:47:09 +00002872 case ARMISD::UMAAL: {
2873 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
2874 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2875 N->getOperand(2), N->getOperand(3),
2876 getAL(CurDAG, dl),
2877 CurDAG->getRegister(0, MVT::i32) };
2878 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::i32, Ops));
2879 return;
2880 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002881 case ARMISD::UMLAL:{
2882 if (Subtarget->isThumb()) {
2883 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002884 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002885 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002886 ReplaceNode(
2887 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops));
2888 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002889 }else{
2890 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002891 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002892 CurDAG->getRegister(0, MVT::i32),
2893 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002894 ReplaceNode(N, CurDAG->getMachineNode(
2895 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl,
2896 MVT::i32, MVT::i32, Ops));
2897 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002898 }
2899 }
2900 case ARMISD::SMLAL:{
2901 if (Subtarget->isThumb()) {
2902 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002903 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002904 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002905 ReplaceNode(
2906 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops));
2907 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002908 }else{
2909 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002910 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002911 CurDAG->getRegister(0, MVT::i32),
2912 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002913 ReplaceNode(N, CurDAG->getMachineNode(
2914 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl,
2915 MVT::i32, MVT::i32, Ops));
2916 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002917 }
2918 }
Sam Parker68c71cd2016-07-25 09:20:20 +00002919 case ARMISD::SUBE: {
2920 if (!Subtarget->hasV6Ops())
2921 break;
2922 // Look for a pattern to match SMMLS
2923 // (sube a, (smul_loHi a, b), (subc 0, (smul_LOhi(a, b))))
2924 if (N->getOperand(1).getOpcode() != ISD::SMUL_LOHI ||
Tim Northover765777c2016-08-02 23:12:36 +00002925 N->getOperand(2).getOpcode() != ARMISD::SUBC ||
2926 !SDValue(N, 1).use_empty())
Sam Parker68c71cd2016-07-25 09:20:20 +00002927 break;
2928
2929 if (Subtarget->isThumb())
2930 assert(Subtarget->hasThumb2() &&
2931 "This pattern should not be generated for Thumb");
2932
2933 SDValue SmulLoHi = N->getOperand(1);
2934 SDValue Subc = N->getOperand(2);
2935 auto *Zero = dyn_cast<ConstantSDNode>(Subc.getOperand(0));
2936
2937 if (!Zero || Zero->getZExtValue() != 0 ||
2938 Subc.getOperand(1) != SmulLoHi.getValue(0) ||
2939 N->getOperand(1) != SmulLoHi.getValue(1) ||
2940 N->getOperand(2) != Subc.getValue(1))
2941 break;
2942
2943 unsigned Opc = Subtarget->isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
2944 SDValue Ops[] = { SmulLoHi.getOperand(0), SmulLoHi.getOperand(1),
2945 N->getOperand(0), getAL(CurDAG, dl),
2946 CurDAG->getRegister(0, MVT::i32) };
2947 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops));
2948 return;
2949 }
Evan Cheng10043e22007-01-19 07:51:42 +00002950 case ISD::LOAD: {
Justin Bogner45571362016-05-12 00:31:09 +00002951 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
2952 if (tryT2IndexedLoad(N))
2953 return;
James Molloyb3326df2016-07-15 08:03:56 +00002954 } else if (Subtarget->isThumb()) {
2955 if (tryT1IndexedLoad(N))
2956 return;
Justin Bogner45571362016-05-12 00:31:09 +00002957 } else if (tryARMIndexedLoad(N))
2958 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002959 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002960 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00002961 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002962 case ARMISD::BRCOND: {
2963 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2964 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2965 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00002966
Evan Cheng7e90b112007-07-05 07:15:27 +00002967 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2968 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2969 // Pattern complexity = 6 cost = 1 size = 0
2970
David Goodwin27303cd2009-06-30 18:04:13 +00002971 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2972 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2973 // Pattern complexity = 6 cost = 1 size = 0
2974
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002975 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00002976 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002977 SDValue Chain = N->getOperand(0);
2978 SDValue N1 = N->getOperand(1);
2979 SDValue N2 = N->getOperand(2);
2980 SDValue N3 = N->getOperand(3);
2981 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00002982 assert(N1.getOpcode() == ISD::BasicBlock);
2983 assert(N2.getOpcode() == ISD::Constant);
2984 assert(N3.getOpcode() == ISD::Register);
2985
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002986 unsigned CC = (unsigned) cast<ConstantSDNode>(N2)->getZExtValue();
2987
2988 if (InFlag.getOpcode() == ARMISD::CMPZ) {
2989 bool SwitchEQNEToPLMI;
2990 SelectCMPZ(InFlag.getNode(), SwitchEQNEToPLMI);
2991 InFlag = N->getOperand(4);
2992
2993 if (SwitchEQNEToPLMI) {
2994 switch ((ARMCC::CondCodes)CC) {
2995 default: llvm_unreachable("CMPZ must be either NE or EQ!");
2996 case ARMCC::NE:
2997 CC = (unsigned)ARMCC::MI;
2998 break;
2999 case ARMCC::EQ:
3000 CC = (unsigned)ARMCC::PL;
3001 break;
3002 }
3003 }
3004 }
3005
3006 SDValue Tmp2 = CurDAG->getTargetConstant(CC, dl, MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003007 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00003008 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00003009 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003010 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003011 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003012 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003013 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00003014 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003015 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00003016 SDValue(Chain.getNode(), Chain.getResNo()));
Justin Bognered4f3782016-05-12 00:20:19 +00003017 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003018 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00003019 }
James Molloy4d86bed2016-09-09 12:52:24 +00003020
3021 case ARMISD::CMPZ: {
3022 // select (CMPZ X, #-C) -> (CMPZ (ADDS X, #C), #0)
3023 // This allows us to avoid materializing the expensive negative constant.
3024 // The CMPZ #0 is useless and will be peepholed away but we need to keep it
3025 // for its glue output.
3026 SDValue X = N->getOperand(0);
3027 auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1).getNode());
3028 if (C && C->getSExtValue() < 0 && Subtarget->isThumb()) {
3029 int64_t Addend = -C->getSExtValue();
3030
3031 SDNode *Add = nullptr;
Artyom Skrobov4592f622017-02-17 18:59:16 +00003032 // ADDS can be better than CMN if the immediate fits in a
James Molloy4d86bed2016-09-09 12:52:24 +00003033 // 16-bit ADDS, which means either [0,256) for tADDi8 or [0,8) for tADDi3.
3034 // Outside that range we can just use a CMN which is 32-bit but has a
3035 // 12-bit immediate range.
Artyom Skrobov4592f622017-02-17 18:59:16 +00003036 if (Addend < 1<<8) {
3037 if (Subtarget->isThumb2()) {
3038 SDValue Ops[] = { X, CurDAG->getTargetConstant(Addend, dl, MVT::i32),
3039 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
3040 CurDAG->getRegister(0, MVT::i32) };
3041 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl, MVT::i32, Ops);
3042 } else {
3043 unsigned Opc = (Addend < 1<<3) ? ARM::tADDi3 : ARM::tADDi8;
3044 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), X,
3045 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
3046 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
3047 Add = CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
3048 }
James Molloy4d86bed2016-09-09 12:52:24 +00003049 }
3050 if (Add) {
3051 SDValue Ops2[] = {SDValue(Add, 0), CurDAG->getConstant(0, dl, MVT::i32)};
3052 CurDAG->MorphNodeTo(N, ARMISD::CMPZ, CurDAG->getVTList(MVT::Glue), Ops2);
3053 }
3054 }
3055 // Other cases are autogenerated.
3056 break;
3057 }
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00003058
3059 case ARMISD::CMOV: {
3060 SDValue InFlag = N->getOperand(4);
3061
3062 if (InFlag.getOpcode() == ARMISD::CMPZ) {
3063 bool SwitchEQNEToPLMI;
3064 SelectCMPZ(InFlag.getNode(), SwitchEQNEToPLMI);
3065
3066 if (SwitchEQNEToPLMI) {
3067 SDValue ARMcc = N->getOperand(2);
3068 ARMCC::CondCodes CC =
3069 (ARMCC::CondCodes)cast<ConstantSDNode>(ARMcc)->getZExtValue();
3070
3071 switch (CC) {
3072 default: llvm_unreachable("CMPZ must be either NE or EQ!");
3073 case ARMCC::NE:
3074 CC = ARMCC::MI;
3075 break;
3076 case ARMCC::EQ:
3077 CC = ARMCC::PL;
3078 break;
3079 }
3080 SDValue NewARMcc = CurDAG->getConstant((unsigned)CC, dl, MVT::i32);
3081 SDValue Ops[] = {N->getOperand(0), N->getOperand(1), NewARMcc,
3082 N->getOperand(3), N->getOperand(4)};
3083 CurDAG->MorphNodeTo(N, ARMISD::CMOV, N->getVTList(), Ops);
3084 }
3085
3086 }
3087 // Other cases are autogenerated.
3088 break;
3089 }
James Molloy4d86bed2016-09-09 12:52:24 +00003090
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003091 case ARMISD::VZIP: {
3092 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003093 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003094 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003095 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003096 case MVT::v8i8: Opc = ARM::VZIPd8; break;
3097 case MVT::v4i16: Opc = ARM::VZIPd16; break;
3098 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00003099 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3100 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003101 case MVT::v16i8: Opc = ARM::VZIPq8; break;
3102 case MVT::v8i16: Opc = ARM::VZIPq16; break;
3103 case MVT::v4f32:
3104 case MVT::v4i32: Opc = ARM::VZIPq32; break;
3105 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003106 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003107 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3108 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003109 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3110 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003111 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003112 case ARMISD::VUZP: {
3113 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003114 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003115 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003116 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003117 case MVT::v8i8: Opc = ARM::VUZPd8; break;
3118 case MVT::v4i16: Opc = ARM::VUZPd16; break;
3119 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00003120 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3121 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003122 case MVT::v16i8: Opc = ARM::VUZPq8; break;
3123 case MVT::v8i16: Opc = ARM::VUZPq16; break;
3124 case MVT::v4f32:
3125 case MVT::v4i32: Opc = ARM::VUZPq32; break;
3126 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003127 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003128 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3129 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003130 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3131 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003132 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003133 case ARMISD::VTRN: {
3134 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003135 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003136 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003137 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003138 case MVT::v8i8: Opc = ARM::VTRNd8; break;
3139 case MVT::v4i16: Opc = ARM::VTRNd16; break;
3140 case MVT::v2f32:
3141 case MVT::v2i32: Opc = ARM::VTRNd32; break;
3142 case MVT::v16i8: Opc = ARM::VTRNq8; break;
3143 case MVT::v8i16: Opc = ARM::VTRNq16; break;
3144 case MVT::v4f32:
3145 case MVT::v4i32: Opc = ARM::VTRNq32; break;
3146 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003147 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003148 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3149 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003150 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3151 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003152 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003153 case ARMISD::BUILD_VECTOR: {
3154 EVT VecVT = N->getValueType(0);
3155 EVT EltVT = VecVT.getVectorElementType();
3156 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00003157 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00003158 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003159 ReplaceNode(
3160 N, createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3161 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003162 }
Duncan Sands14627772010-11-03 12:17:33 +00003163 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003164 if (NumElts == 2) {
3165 ReplaceNode(
3166 N, createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3167 return;
3168 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003169 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003170 ReplaceNode(N,
3171 createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
3172 N->getOperand(2), N->getOperand(3)));
3173 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003174 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003175
Eli Friedmanf624ec22016-12-16 18:44:08 +00003176 case ARMISD::VLD1DUP: {
3177 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8, ARM::VLD1DUPd16,
3178 ARM::VLD1DUPd32 };
3179 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8, ARM::VLD1DUPq16,
3180 ARM::VLD1DUPq32 };
3181 SelectVLDDup(N, false, 1, DOpcodes, QOpcodes);
3182 return;
3183 }
3184
Bob Wilson2d790df2010-11-28 06:51:26 +00003185 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003186 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
3187 ARM::VLD2DUPd32 };
Justin Bogner45571362016-05-12 00:31:09 +00003188 SelectVLDDup(N, false, 2, Opcodes);
3189 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00003190 }
3191
Bob Wilson77ab1652010-11-29 19:35:29 +00003192 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003193 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
3194 ARM::VLD3DUPd16Pseudo,
3195 ARM::VLD3DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003196 SelectVLDDup(N, false, 3, Opcodes);
3197 return;
Bob Wilson77ab1652010-11-29 19:35:29 +00003198 }
3199
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003200 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003201 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
3202 ARM::VLD4DUPd16Pseudo,
3203 ARM::VLD4DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003204 SelectVLDDup(N, false, 4, Opcodes);
3205 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003206 }
3207
Eli Friedmanf624ec22016-12-16 18:44:08 +00003208 case ARMISD::VLD1DUP_UPD: {
3209 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8wb_fixed,
3210 ARM::VLD1DUPd16wb_fixed,
3211 ARM::VLD1DUPd32wb_fixed };
3212 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8wb_fixed,
3213 ARM::VLD1DUPq16wb_fixed,
3214 ARM::VLD1DUPq32wb_fixed };
3215 SelectVLDDup(N, true, 1, DOpcodes, QOpcodes);
3216 return;
3217 }
3218
Bob Wilson06fce872011-02-07 17:43:21 +00003219 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003220 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
3221 ARM::VLD2DUPd16wb_fixed,
3222 ARM::VLD2DUPd32wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003223 SelectVLDDup(N, true, 2, Opcodes);
3224 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003225 }
3226
3227 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003228 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
3229 ARM::VLD3DUPd16Pseudo_UPD,
3230 ARM::VLD3DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003231 SelectVLDDup(N, true, 3, Opcodes);
3232 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003233 }
3234
3235 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003236 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
3237 ARM::VLD4DUPd16Pseudo_UPD,
3238 ARM::VLD4DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003239 SelectVLDDup(N, true, 4, Opcodes);
3240 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003241 }
3242
3243 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003244 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
3245 ARM::VLD1d16wb_fixed,
3246 ARM::VLD1d32wb_fixed,
3247 ARM::VLD1d64wb_fixed };
3248 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
3249 ARM::VLD1q16wb_fixed,
3250 ARM::VLD1q32wb_fixed,
3251 ARM::VLD1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003252 SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
3253 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003254 }
3255
3256 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003257 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
3258 ARM::VLD2d16wb_fixed,
3259 ARM::VLD2d32wb_fixed,
3260 ARM::VLD1q64wb_fixed};
3261 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
3262 ARM::VLD2q16PseudoWB_fixed,
3263 ARM::VLD2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003264 SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
3265 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003266 }
3267
3268 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003269 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
3270 ARM::VLD3d16Pseudo_UPD,
3271 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003272 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003273 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3274 ARM::VLD3q16Pseudo_UPD,
3275 ARM::VLD3q32Pseudo_UPD };
3276 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3277 ARM::VLD3q16oddPseudo_UPD,
3278 ARM::VLD3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003279 SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3280 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003281 }
3282
3283 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003284 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3285 ARM::VLD4d16Pseudo_UPD,
3286 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003287 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003288 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3289 ARM::VLD4q16Pseudo_UPD,
3290 ARM::VLD4q32Pseudo_UPD };
3291 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3292 ARM::VLD4q16oddPseudo_UPD,
3293 ARM::VLD4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003294 SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3295 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003296 }
3297
3298 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003299 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3300 ARM::VLD2LNd16Pseudo_UPD,
3301 ARM::VLD2LNd32Pseudo_UPD };
3302 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3303 ARM::VLD2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003304 SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3305 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003306 }
3307
3308 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003309 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3310 ARM::VLD3LNd16Pseudo_UPD,
3311 ARM::VLD3LNd32Pseudo_UPD };
3312 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3313 ARM::VLD3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003314 SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3315 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003316 }
3317
3318 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003319 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3320 ARM::VLD4LNd16Pseudo_UPD,
3321 ARM::VLD4LNd32Pseudo_UPD };
3322 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3323 ARM::VLD4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003324 SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3325 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003326 }
3327
3328 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003329 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3330 ARM::VST1d16wb_fixed,
3331 ARM::VST1d32wb_fixed,
3332 ARM::VST1d64wb_fixed };
3333 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3334 ARM::VST1q16wb_fixed,
3335 ARM::VST1q32wb_fixed,
3336 ARM::VST1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003337 SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
3338 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003339 }
3340
3341 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003342 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3343 ARM::VST2d16wb_fixed,
3344 ARM::VST2d32wb_fixed,
3345 ARM::VST1q64wb_fixed};
3346 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3347 ARM::VST2q16PseudoWB_fixed,
3348 ARM::VST2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003349 SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
3350 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003351 }
3352
3353 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003354 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3355 ARM::VST3d16Pseudo_UPD,
3356 ARM::VST3d32Pseudo_UPD,
3357 ARM::VST1d64TPseudoWB_fixed};
3358 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3359 ARM::VST3q16Pseudo_UPD,
3360 ARM::VST3q32Pseudo_UPD };
3361 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3362 ARM::VST3q16oddPseudo_UPD,
3363 ARM::VST3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003364 SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3365 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003366 }
3367
3368 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003369 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3370 ARM::VST4d16Pseudo_UPD,
3371 ARM::VST4d32Pseudo_UPD,
3372 ARM::VST1d64QPseudoWB_fixed};
3373 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3374 ARM::VST4q16Pseudo_UPD,
3375 ARM::VST4q32Pseudo_UPD };
3376 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3377 ARM::VST4q16oddPseudo_UPD,
3378 ARM::VST4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003379 SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3380 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003381 }
3382
3383 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003384 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3385 ARM::VST2LNd16Pseudo_UPD,
3386 ARM::VST2LNd32Pseudo_UPD };
3387 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3388 ARM::VST2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003389 SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3390 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003391 }
3392
3393 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003394 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3395 ARM::VST3LNd16Pseudo_UPD,
3396 ARM::VST3LNd32Pseudo_UPD };
3397 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3398 ARM::VST3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003399 SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3400 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003401 }
3402
3403 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003404 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3405 ARM::VST4LNd16Pseudo_UPD,
3406 ARM::VST4LNd32Pseudo_UPD };
3407 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3408 ARM::VST4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003409 SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
3410 return;
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003411 }
3412
Bob Wilsone0636a72009-08-26 17:39:53 +00003413 case ISD::INTRINSIC_VOID:
3414 case ISD::INTRINSIC_W_CHAIN: {
3415 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003416 switch (IntNo) {
3417 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003418 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003419
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003420 case Intrinsic::arm_mrrc:
3421 case Intrinsic::arm_mrrc2: {
3422 SDLoc dl(N);
3423 SDValue Chain = N->getOperand(0);
3424 unsigned Opc;
3425
3426 if (Subtarget->isThumb())
3427 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
3428 else
3429 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
3430
3431 SmallVector<SDValue, 5> Ops;
3432 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(), dl)); /* coproc */
3433 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(), dl)); /* opc */
3434 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(4))->getZExtValue(), dl)); /* CRm */
3435
3436 // The mrrc2 instruction in ARM doesn't allow predicates, the top 4 bits of the encoded
3437 // instruction will always be '1111' but it is possible in assembly language to specify
3438 // AL as a predicate to mrrc2 but it doesn't make any difference to the encoded instruction.
3439 if (Opc != ARM::MRRC2) {
3440 Ops.push_back(getAL(CurDAG, dl));
3441 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3442 }
3443
3444 Ops.push_back(Chain);
3445
3446 // Writes to two registers.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003447 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003448
3449 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, RetType, Ops));
3450 return;
3451 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003452 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003453 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003454 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003455 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003456 SDValue MemAddr = N->getOperand(2);
Bradley Smith433c22e2016-01-15 10:26:51 +00003457 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
Tim Northover1ff5f292014-03-26 14:39:31 +00003458
3459 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3460 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3461 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003462
3463 // arm_ldrexd returns a i64 value in {i32, i32}
3464 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003465 if (isThumb) {
3466 ResTys.push_back(MVT::i32);
3467 ResTys.push_back(MVT::i32);
3468 } else
3469 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003470 ResTys.push_back(MVT::Other);
3471
Weiming Zhao8f56f882012-11-16 21:55:34 +00003472 // Place arguments in the right order.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003473 SDValue Ops[] = {MemAddr, getAL(CurDAG, dl),
3474 CurDAG->getRegister(0, MVT::i32), Chain};
Michael Liaob53d8962013-04-19 22:22:57 +00003475 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003476 // Transfer memoperands.
3477 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3478 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3479 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3480
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003481 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003482 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003483 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003484 SDValue Result;
3485 if (isThumb)
3486 Result = SDValue(Ld, 0);
3487 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003488 SDValue SubRegIdx =
3489 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003490 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003491 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003492 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003493 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003494 ReplaceUses(SDValue(N, 0), Result);
3495 }
3496 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003497 SDValue Result;
3498 if (isThumb)
3499 Result = SDValue(Ld, 1);
3500 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003501 SDValue SubRegIdx =
3502 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003503 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003504 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003505 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003506 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003507 ReplaceUses(SDValue(N, 1), Result);
3508 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003509 ReplaceUses(SDValue(N, 2), OutChain);
Justin Bognered4f3782016-05-12 00:20:19 +00003510 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003511 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003512 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003513 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003514 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003515 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003516 SDValue Chain = N->getOperand(0);
3517 SDValue Val0 = N->getOperand(2);
3518 SDValue Val1 = N->getOperand(3);
3519 SDValue MemAddr = N->getOperand(4);
3520
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003521 // Store exclusive double return a i32 value which is the return status
3522 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003523 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003524
Weiming Zhao8f56f882012-11-16 21:55:34 +00003525 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3526 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003527 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003528 if (isThumb) {
3529 Ops.push_back(Val0);
3530 Ops.push_back(Val1);
3531 } else
3532 // arm_strexd uses GPRPair.
3533 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003534 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003535 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003536 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3537 Ops.push_back(Chain);
3538
Tim Northover1ff5f292014-03-26 14:39:31 +00003539 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3540 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3541 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003542
Michael Liaob53d8962013-04-19 22:22:57 +00003543 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003544 // Transfer memoperands.
3545 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3546 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3547 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3548
Justin Bogner45571362016-05-12 00:31:09 +00003549 ReplaceNode(N, St);
3550 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003551 }
3552
Bob Wilson340861d2010-03-23 05:25:43 +00003553 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003554 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3555 ARM::VLD1d32, ARM::VLD1d64 };
3556 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3557 ARM::VLD1q32, ARM::VLD1q64};
Justin Bogner45571362016-05-12 00:31:09 +00003558 SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
3559 return;
Bob Wilson340861d2010-03-23 05:25:43 +00003560 }
3561
Bob Wilsone0636a72009-08-26 17:39:53 +00003562 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003563 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3564 ARM::VLD2d32, ARM::VLD1q64 };
3565 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3566 ARM::VLD2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003567 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3568 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003569 }
3570
3571 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003572 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3573 ARM::VLD3d16Pseudo,
3574 ARM::VLD3d32Pseudo,
3575 ARM::VLD1d64TPseudo };
3576 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3577 ARM::VLD3q16Pseudo_UPD,
3578 ARM::VLD3q32Pseudo_UPD };
3579 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3580 ARM::VLD3q16oddPseudo,
3581 ARM::VLD3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003582 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3583 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003584 }
3585
3586 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003587 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3588 ARM::VLD4d16Pseudo,
3589 ARM::VLD4d32Pseudo,
3590 ARM::VLD1d64QPseudo };
3591 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3592 ARM::VLD4q16Pseudo_UPD,
3593 ARM::VLD4q32Pseudo_UPD };
3594 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3595 ARM::VLD4q16oddPseudo,
3596 ARM::VLD4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003597 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3598 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003599 }
3600
Bob Wilsonda9817c2009-09-01 04:26:28 +00003601 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003602 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3603 ARM::VLD2LNd16Pseudo,
3604 ARM::VLD2LNd32Pseudo };
3605 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3606 ARM::VLD2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003607 SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
3608 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003609 }
3610
3611 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003612 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3613 ARM::VLD3LNd16Pseudo,
3614 ARM::VLD3LNd32Pseudo };
3615 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3616 ARM::VLD3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003617 SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
3618 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003619 }
3620
3621 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003622 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3623 ARM::VLD4LNd16Pseudo,
3624 ARM::VLD4LNd32Pseudo };
3625 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3626 ARM::VLD4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003627 SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
3628 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003629 }
3630
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003631 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003632 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3633 ARM::VST1d32, ARM::VST1d64 };
3634 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3635 ARM::VST1q32, ARM::VST1q64 };
Justin Bogner45571362016-05-12 00:31:09 +00003636 SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
3637 return;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003638 }
3639
Bob Wilsone0636a72009-08-26 17:39:53 +00003640 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003641 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3642 ARM::VST2d32, ARM::VST1q64 };
Benjamin Kramerf690da42016-06-17 14:14:29 +00003643 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3644 ARM::VST2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003645 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3646 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003647 }
3648
3649 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003650 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3651 ARM::VST3d16Pseudo,
3652 ARM::VST3d32Pseudo,
3653 ARM::VST1d64TPseudo };
3654 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3655 ARM::VST3q16Pseudo_UPD,
3656 ARM::VST3q32Pseudo_UPD };
3657 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3658 ARM::VST3q16oddPseudo,
3659 ARM::VST3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003660 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3661 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003662 }
3663
3664 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003665 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3666 ARM::VST4d16Pseudo,
3667 ARM::VST4d32Pseudo,
3668 ARM::VST1d64QPseudo };
3669 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3670 ARM::VST4q16Pseudo_UPD,
3671 ARM::VST4q32Pseudo_UPD };
3672 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3673 ARM::VST4q16oddPseudo,
3674 ARM::VST4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003675 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3676 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003677 }
Bob Wilsond7797752009-09-01 18:51:56 +00003678
3679 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003680 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3681 ARM::VST2LNd16Pseudo,
3682 ARM::VST2LNd32Pseudo };
3683 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3684 ARM::VST2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003685 SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
3686 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003687 }
3688
3689 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003690 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3691 ARM::VST3LNd16Pseudo,
3692 ARM::VST3LNd32Pseudo };
3693 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3694 ARM::VST3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003695 SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
3696 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003697 }
3698
3699 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003700 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3701 ARM::VST4LNd16Pseudo,
3702 ARM::VST4LNd32Pseudo };
3703 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3704 ARM::VST4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003705 SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
3706 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003707 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003708 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003709 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003710 }
Evan Chengd85631e2010-05-05 18:28:36 +00003711
Tim Northoverb629c772016-04-18 21:48:55 +00003712 case ISD::ATOMIC_CMP_SWAP:
Justin Bogner45571362016-05-12 00:31:09 +00003713 SelectCMP_SWAP(N);
3714 return;
Evan Chengd85631e2010-05-05 18:28:36 +00003715 }
Evan Chengd5021732008-12-10 21:54:21 +00003716
Justin Bogner45571362016-05-12 00:31:09 +00003717 SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003718}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003719
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003720// Inspect a register string of the form
3721// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3722// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3723// and obtain the integer operands from them, adding these operands to the
3724// provided vector.
3725static void getIntOperandsFromRegisterString(StringRef RegString,
Benjamin Kramerbdc49562016-06-12 15:39:02 +00003726 SelectionDAG *CurDAG,
3727 const SDLoc &DL,
3728 std::vector<SDValue> &Ops) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003729 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003730 RegString.split(Fields, ':');
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003731
3732 if (Fields.size() > 1) {
3733 bool AllIntFields = true;
3734
3735 for (StringRef Field : Fields) {
3736 // Need to trim out leading 'cp' characters and get the integer field.
3737 unsigned IntField;
3738 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3739 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3740 }
3741
3742 assert(AllIntFields &&
3743 "Unexpected non-integer value in special register string.");
3744 }
3745}
3746
3747// Maps a Banked Register string to its mask value. The mask value returned is
3748// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3749// mask operand, which expresses which register is to be used, e.g. r8, and in
3750// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3751// was invalid.
3752static inline int getBankedRegisterMask(StringRef RegString) {
3753 return StringSwitch<int>(RegString.lower())
3754 .Case("r8_usr", 0x00)
3755 .Case("r9_usr", 0x01)
3756 .Case("r10_usr", 0x02)
3757 .Case("r11_usr", 0x03)
3758 .Case("r12_usr", 0x04)
3759 .Case("sp_usr", 0x05)
3760 .Case("lr_usr", 0x06)
3761 .Case("r8_fiq", 0x08)
3762 .Case("r9_fiq", 0x09)
3763 .Case("r10_fiq", 0x0a)
3764 .Case("r11_fiq", 0x0b)
3765 .Case("r12_fiq", 0x0c)
3766 .Case("sp_fiq", 0x0d)
3767 .Case("lr_fiq", 0x0e)
3768 .Case("lr_irq", 0x10)
3769 .Case("sp_irq", 0x11)
3770 .Case("lr_svc", 0x12)
3771 .Case("sp_svc", 0x13)
3772 .Case("lr_abt", 0x14)
3773 .Case("sp_abt", 0x15)
3774 .Case("lr_und", 0x16)
3775 .Case("sp_und", 0x17)
3776 .Case("lr_mon", 0x1c)
3777 .Case("sp_mon", 0x1d)
3778 .Case("elr_hyp", 0x1e)
3779 .Case("sp_hyp", 0x1f)
3780 .Case("spsr_fiq", 0x2e)
3781 .Case("spsr_irq", 0x30)
3782 .Case("spsr_svc", 0x32)
3783 .Case("spsr_abt", 0x34)
3784 .Case("spsr_und", 0x36)
3785 .Case("spsr_mon", 0x3c)
3786 .Case("spsr_hyp", 0x3e)
3787 .Default(-1);
3788}
3789
3790// Maps a MClass special register string to its value for use in the
3791// t2MRS_M / t2MSR_M instruction nodes as the SYSm value operand.
3792// Returns -1 to signify that the string was invalid.
3793static inline int getMClassRegisterSYSmValueMask(StringRef RegString) {
3794 return StringSwitch<int>(RegString.lower())
3795 .Case("apsr", 0x0)
3796 .Case("iapsr", 0x1)
3797 .Case("eapsr", 0x2)
3798 .Case("xpsr", 0x3)
3799 .Case("ipsr", 0x5)
3800 .Case("epsr", 0x6)
3801 .Case("iepsr", 0x7)
3802 .Case("msp", 0x8)
3803 .Case("psp", 0x9)
3804 .Case("primask", 0x10)
3805 .Case("basepri", 0x11)
3806 .Case("basepri_max", 0x12)
3807 .Case("faultmask", 0x13)
3808 .Case("control", 0x14)
Bradley Smithf277c8a2016-01-25 11:25:36 +00003809 .Case("msplim", 0x0a)
3810 .Case("psplim", 0x0b)
3811 .Case("sp", 0x18)
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003812 .Default(-1);
3813}
3814
3815// The flags here are common to those allowed for apsr in the A class cores and
3816// those allowed for the special registers in the M class cores. Returns a
3817// value representing which flags were present, -1 if invalid.
John Brawne60f4e42017-02-10 17:41:08 +00003818static inline int getMClassFlagsMask(StringRef Flags) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003819 return StringSwitch<int>(Flags)
John Brawne60f4e42017-02-10 17:41:08 +00003820 .Case("", 0x2) // no flags means nzcvq for psr registers, and 0x2 is
3821 // correct when flags are not permitted
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003822 .Case("g", 0x1)
3823 .Case("nzcvq", 0x2)
3824 .Case("nzcvqg", 0x3)
3825 .Default(-1);
3826}
3827
3828static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead,
3829 const ARMSubtarget *Subtarget) {
3830 // Ensure that the register (without flags) was a valid M Class special
3831 // register.
3832 int SYSmvalue = getMClassRegisterSYSmValueMask(Reg);
3833 if (SYSmvalue == -1)
3834 return -1;
3835
3836 // basepri, basepri_max and faultmask are only valid for V7m.
3837 if (!Subtarget->hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
3838 return -1;
3839
Bradley Smithf277c8a2016-01-25 11:25:36 +00003840 if (Subtarget->has8MSecExt() && Flags.lower() == "ns") {
3841 Flags = "";
3842 SYSmvalue |= 0x80;
3843 }
3844
3845 if (!Subtarget->has8MSecExt() &&
3846 (SYSmvalue == 0xa || SYSmvalue == 0xb || SYSmvalue > 0x14))
3847 return -1;
3848
3849 if (!Subtarget->hasV8MMainlineOps() &&
3850 (SYSmvalue == 0x8a || SYSmvalue == 0x8b || SYSmvalue == 0x91 ||
3851 SYSmvalue == 0x93))
3852 return -1;
3853
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003854 // If it was a read then we won't be expecting flags and so at this point
3855 // we can return the mask.
3856 if (IsRead) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00003857 if (Flags.empty())
3858 return SYSmvalue;
3859 else
3860 return -1;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003861 }
3862
3863 // We know we are now handling a write so need to get the mask for the flags.
John Brawne60f4e42017-02-10 17:41:08 +00003864 int Mask = getMClassFlagsMask(Flags);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003865
3866 // Only apsr, iapsr, eapsr, xpsr can have flags. The other register values
3867 // shouldn't have flags present.
3868 if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.empty()))
3869 return -1;
3870
3871 // The _g and _nzcvqg versions are only valid if the DSP extension is
3872 // available.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003873 if (!Subtarget->hasDSP() && (Mask & 0x1))
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003874 return -1;
3875
3876 // The register was valid so need to put the mask in the correct place
3877 // (the flags need to be in bits 11-10) and combine with the SYSmvalue to
3878 // construct the operand for the instruction node.
John Brawne60f4e42017-02-10 17:41:08 +00003879 return SYSmvalue | Mask << 10;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003880}
3881
3882static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
3883 // The mask operand contains the special register (R Bit) in bit 4, whether
3884 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
3885 // bits 3-0 contains the fields to be accessed in the special register, set by
3886 // the flags provided with the register.
3887 int Mask = 0;
3888 if (Reg == "apsr") {
3889 // The flags permitted for apsr are the same flags that are allowed in
3890 // M class registers. We get the flag value and then shift the flags into
3891 // the correct place to combine with the mask.
John Brawne60f4e42017-02-10 17:41:08 +00003892 Mask = getMClassFlagsMask(Flags);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003893 if (Mask == -1)
3894 return -1;
3895 return Mask << 2;
3896 }
3897
3898 if (Reg != "cpsr" && Reg != "spsr") {
3899 return -1;
3900 }
3901
3902 // This is the same as if the flags were "fc"
3903 if (Flags.empty() || Flags == "all")
3904 return Mask | 0x9;
3905
3906 // Inspect the supplied flags string and set the bits in the mask for
3907 // the relevant and valid flags allowed for cpsr and spsr.
3908 for (char Flag : Flags) {
3909 int FlagVal;
3910 switch (Flag) {
3911 case 'c':
3912 FlagVal = 0x1;
3913 break;
3914 case 'x':
3915 FlagVal = 0x2;
3916 break;
3917 case 's':
3918 FlagVal = 0x4;
3919 break;
3920 case 'f':
3921 FlagVal = 0x8;
3922 break;
3923 default:
3924 FlagVal = 0;
3925 }
3926
3927 // This avoids allowing strings where the same flag bit appears twice.
3928 if (!FlagVal || (Mask & FlagVal))
3929 return -1;
3930 Mask |= FlagVal;
3931 }
3932
3933 // If the register is spsr then we need to set the R bit.
3934 if (Reg == "spsr")
3935 Mask |= 0x10;
3936
3937 return Mask;
3938}
3939
3940// Lower the read_register intrinsic to ARM specific DAG nodes
3941// using the supplied metadata string to select the instruction node to use
3942// and the registers/masks to construct as operands for the node.
Justin Bogner45571362016-05-12 00:31:09 +00003943bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003944 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3945 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3946 bool IsThumb2 = Subtarget->isThumb2();
3947 SDLoc DL(N);
3948
3949 std::vector<SDValue> Ops;
3950 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3951
3952 if (!Ops.empty()) {
3953 // If the special register string was constructed of fields (as defined
3954 // in the ACLE) then need to lower to MRC node (32 bit) or
3955 // MRRC node(64 bit), we can make the distinction based on the number of
3956 // operands we have.
3957 unsigned Opcode;
3958 SmallVector<EVT, 3> ResTypes;
3959 if (Ops.size() == 5){
3960 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
3961 ResTypes.append({ MVT::i32, MVT::Other });
3962 } else {
3963 assert(Ops.size() == 3 &&
3964 "Invalid number of fields in special register string.");
3965 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
3966 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
3967 }
3968
3969 Ops.push_back(getAL(CurDAG, DL));
3970 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3971 Ops.push_back(N->getOperand(0));
Justin Bogner45571362016-05-12 00:31:09 +00003972 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops));
3973 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003974 }
3975
3976 std::string SpecialReg = RegString->getString().lower();
3977
3978 int BankedReg = getBankedRegisterMask(SpecialReg);
3979 if (BankedReg != -1) {
3980 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
3981 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3982 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003983 ReplaceNode(
3984 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
3985 DL, MVT::i32, MVT::Other, Ops));
3986 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003987 }
3988
3989 // The VFP registers are read by creating SelectionDAG nodes with opcodes
3990 // corresponding to the register that is being read from. So we switch on the
3991 // string to find which opcode we need to use.
3992 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3993 .Case("fpscr", ARM::VMRS)
3994 .Case("fpexc", ARM::VMRS_FPEXC)
3995 .Case("fpsid", ARM::VMRS_FPSID)
3996 .Case("mvfr0", ARM::VMRS_MVFR0)
3997 .Case("mvfr1", ARM::VMRS_MVFR1)
3998 .Case("mvfr2", ARM::VMRS_MVFR2)
3999 .Case("fpinst", ARM::VMRS_FPINST)
4000 .Case("fpinst2", ARM::VMRS_FPINST2)
4001 .Default(0);
4002
4003 // If an opcode was found then we can lower the read to a VFP instruction.
4004 if (Opcode) {
4005 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004006 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004007 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
Justin Bogner45571362016-05-12 00:31:09 +00004008 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004009
4010 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4011 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004012 ReplaceNode(N,
4013 CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops));
4014 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004015 }
4016
4017 // If the target is M Class then need to validate that the register string
4018 // is an acceptable value, so check that a mask can be constructed from the
4019 // string.
4020 if (Subtarget->isMClass()) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00004021 StringRef Flags = "", Reg = SpecialReg;
4022 if (Reg.endswith("_ns")) {
4023 Flags = "ns";
4024 Reg = Reg.drop_back(3);
4025 }
4026
4027 int SYSmValue = getMClassRegisterMask(Reg, Flags, true, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004028 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004029 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004030
4031 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4032 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4033 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004034 ReplaceNode(
4035 N, CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops));
4036 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004037 }
4038
4039 // Here we know the target is not M Class so we need to check if it is one
4040 // of the remaining possible values which are apsr, cpsr or spsr.
4041 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
4042 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4043 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004044 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
4045 DL, MVT::i32, MVT::Other, Ops));
4046 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004047 }
4048
4049 if (SpecialReg == "spsr") {
4050 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4051 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004052 ReplaceNode(
4053 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys, DL,
4054 MVT::i32, MVT::Other, Ops));
4055 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004056 }
4057
Justin Bogner45571362016-05-12 00:31:09 +00004058 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004059}
4060
4061// Lower the write_register intrinsic to ARM specific DAG nodes
4062// using the supplied metadata string to select the instruction node to use
4063// and the registers/masks to use in the nodes
Justin Bogner45571362016-05-12 00:31:09 +00004064bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004065 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
4066 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
4067 bool IsThumb2 = Subtarget->isThumb2();
4068 SDLoc DL(N);
4069
4070 std::vector<SDValue> Ops;
4071 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
4072
4073 if (!Ops.empty()) {
4074 // If the special register string was constructed of fields (as defined
4075 // in the ACLE) then need to lower to MCR node (32 bit) or
4076 // MCRR node(64 bit), we can make the distinction based on the number of
4077 // operands we have.
4078 unsigned Opcode;
4079 if (Ops.size() == 5) {
4080 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
4081 Ops.insert(Ops.begin()+2, N->getOperand(2));
4082 } else {
4083 assert(Ops.size() == 3 &&
4084 "Invalid number of fields in special register string.");
4085 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
4086 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
4087 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
4088 }
4089
4090 Ops.push_back(getAL(CurDAG, DL));
4091 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4092 Ops.push_back(N->getOperand(0));
4093
Justin Bogner45571362016-05-12 00:31:09 +00004094 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4095 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004096 }
4097
4098 std::string SpecialReg = RegString->getString().lower();
4099 int BankedReg = getBankedRegisterMask(SpecialReg);
4100 if (BankedReg != -1) {
4101 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
4102 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4103 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004104 ReplaceNode(
4105 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
4106 DL, MVT::Other, Ops));
4107 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004108 }
4109
4110 // The VFP registers are written to by creating SelectionDAG nodes with
4111 // opcodes corresponding to the register that is being written. So we switch
4112 // on the string to find which opcode we need to use.
4113 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
4114 .Case("fpscr", ARM::VMSR)
4115 .Case("fpexc", ARM::VMSR_FPEXC)
4116 .Case("fpsid", ARM::VMSR_FPSID)
4117 .Case("fpinst", ARM::VMSR_FPINST)
4118 .Case("fpinst2", ARM::VMSR_FPINST2)
4119 .Default(0);
4120
4121 if (Opcode) {
4122 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004123 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004124 Ops = { N->getOperand(2), getAL(CurDAG, DL),
4125 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004126 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4127 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004128 }
4129
Bradley Smithf277c8a2016-01-25 11:25:36 +00004130 std::pair<StringRef, StringRef> Fields;
4131 Fields = StringRef(SpecialReg).rsplit('_');
4132 std::string Reg = Fields.first.str();
4133 StringRef Flags = Fields.second;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004134
4135 // If the target was M Class then need to validate the special register value
4136 // and retrieve the mask for use in the instruction node.
4137 if (Subtarget->isMClass()) {
4138 // basepri_max gets split so need to correct Reg and Flags.
4139 if (SpecialReg == "basepri_max") {
4140 Reg = SpecialReg;
4141 Flags = "";
4142 }
4143 int SYSmValue = getMClassRegisterMask(Reg, Flags, false, Subtarget);
4144 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004145 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004146
4147 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4148 N->getOperand(2), getAL(CurDAG, DL),
4149 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004150 ReplaceNode(N, CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops));
4151 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004152 }
4153
4154 // We then check to see if a valid mask can be constructed for one of the
4155 // register string values permitted for the A and R class cores. These values
4156 // are apsr, spsr and cpsr; these are also valid on older cores.
4157 int Mask = getARClassRegisterMask(Reg, Flags);
4158 if (Mask != -1) {
4159 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
4160 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4161 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004162 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
4163 DL, MVT::Other, Ops));
4164 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004165 }
4166
Justin Bogner45571362016-05-12 00:31:09 +00004167 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004168}
4169
Justin Bogner45571362016-05-12 00:31:09 +00004170bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){
Weiming Zhaoc5987002013-02-14 18:10:21 +00004171 std::vector<SDValue> AsmNodeOperands;
4172 unsigned Flag, Kind;
4173 bool Changed = false;
4174 unsigned NumOps = N->getNumOperands();
4175
Weiming Zhaoc5987002013-02-14 18:10:21 +00004176 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
4177 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
4178 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
4179 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004180 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
4181 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
4182 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00004183
Andrew Trickef9de2a2013-05-25 02:42:55 +00004184 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00004185 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
4186 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004187
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004188 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004189 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004190 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00004191 SDValue op = N->getOperand(i);
4192 AsmNodeOperands.push_back(op);
4193
4194 if (i < InlineAsm::Op_FirstOperand)
4195 continue;
4196
4197 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
4198 Flag = C->getZExtValue();
4199 Kind = InlineAsm::getKind(Flag);
4200 }
4201 else
4202 continue;
4203
Joey Gouly392cdad2013-07-08 19:52:51 +00004204 // Immediate operands to inline asm in the SelectionDAG are modeled with
4205 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
4206 // the second is a constant with the value of the immediate. If we get here
4207 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00004208 if (Kind == InlineAsm::Kind_Imm) {
4209 SDValue op = N->getOperand(++i);
4210 AsmNodeOperands.push_back(op);
4211 continue;
4212 }
4213
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004214 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
4215 if (NumRegs)
4216 OpChanged.push_back(false);
4217
4218 unsigned DefIdx = 0;
4219 bool IsTiedToChangedOp = false;
4220 // If it's a use that is tied with a previous def, it has no
4221 // reg class constraint.
4222 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
4223 IsTiedToChangedOp = OpChanged[DefIdx];
4224
Diana Picusf345d402016-07-20 09:48:24 +00004225 // Memory operands to inline asm in the SelectionDAG are modeled with two
4226 // operands: a constant of value InlineAsm::Kind_Mem followed by the input
4227 // operand. If we get here and we have a Kind_Mem, skip the next operand (so
4228 // it doesn't get misinterpreted), and continue. We do this here because
4229 // it's important to update the OpChanged array correctly before moving on.
4230 if (Kind == InlineAsm::Kind_Mem) {
4231 SDValue op = N->getOperand(++i);
4232 AsmNodeOperands.push_back(op);
4233 continue;
4234 }
4235
Weiming Zhaoc5987002013-02-14 18:10:21 +00004236 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
4237 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
4238 continue;
4239
Weiming Zhaoc5987002013-02-14 18:10:21 +00004240 unsigned RC;
4241 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004242 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
4243 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00004244 continue;
4245
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004246 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00004247 SDValue V0 = N->getOperand(i+1);
4248 SDValue V1 = N->getOperand(i+2);
4249 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
4250 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
4251 SDValue PairedReg;
4252 MachineRegisterInfo &MRI = MF->getRegInfo();
4253
4254 if (Kind == InlineAsm::Kind_RegDef ||
4255 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
4256 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
4257 // the original GPRs.
4258
4259 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4260 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4261 SDValue Chain = SDValue(N,0);
4262
4263 SDNode *GU = N->getGluedUser();
4264 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
4265 Chain.getValue(1));
4266
4267 // Extract values from a GPRPair reg and copy to the original GPR reg.
4268 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4269 RegCopy);
4270 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4271 RegCopy);
4272 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
4273 RegCopy.getValue(1));
4274 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
4275
4276 // Update the original glue user.
4277 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
4278 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00004279 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004280 }
4281 else {
4282 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
4283 // GPRPair and then pass the GPRPair to the inline asm.
4284 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
4285
4286 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
4287 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
4288 Chain.getValue(1));
4289 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
4290 T0.getValue(1));
4291 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
4292
4293 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
4294 // i32 VRs of inline asm with it.
4295 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4296 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4297 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
4298
4299 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
4300 Glue = Chain.getValue(1);
4301 }
4302
4303 Changed = true;
4304
4305 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004306 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004307 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00004308 if (IsTiedToChangedOp)
4309 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
4310 else
4311 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004312 // Replace the current flag.
4313 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00004314 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004315 // Add the new register node and skip the original two GPRs.
4316 AsmNodeOperands.push_back(PairedReg);
4317 // Skip the next two GPRs.
4318 i += 2;
4319 }
4320 }
4321
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004322 if (Glue.getNode())
4323 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004324 if (!Changed)
Justin Bogner45571362016-05-12 00:31:09 +00004325 return false;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004326
Andrew Trickef9de2a2013-05-25 02:42:55 +00004327 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00004328 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004329 New->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00004330 ReplaceNode(N, New.getNode());
4331 return true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004332}
4333
4334
Bob Wilsona2c462b2009-05-19 05:53:42 +00004335bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00004336SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00004337 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004338 switch(ConstraintID) {
4339 default:
4340 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00004341 case InlineAsm::Constraint_i:
4342 // FIXME: It seems strange that 'i' is needed here since it's supposed to
4343 // be an immediate and not a memory constraint.
Justin Bognerb03fd122016-08-17 05:10:15 +00004344 LLVM_FALLTHROUGH;
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004345 case InlineAsm::Constraint_m:
James Molloy72222f52015-10-26 10:04:52 +00004346 case InlineAsm::Constraint_o:
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004347 case InlineAsm::Constraint_Q:
4348 case InlineAsm::Constraint_Um:
4349 case InlineAsm::Constraint_Un:
4350 case InlineAsm::Constraint_Uq:
4351 case InlineAsm::Constraint_Us:
4352 case InlineAsm::Constraint_Ut:
4353 case InlineAsm::Constraint_Uv:
4354 case InlineAsm::Constraint_Uy:
4355 // Require the address to be in a register. That is safe for all ARM
4356 // variants and it is hard to do anything much smarter without knowing
4357 // how the operand is used.
4358 OutOps.push_back(Op);
4359 return false;
4360 }
4361 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00004362}
4363
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004364/// createARMISelDag - This pass converts a legalized DAG into a
4365/// ARM-specific DAG, ready for instruction scheduling.
4366///
Bob Wilson2dd957f2009-09-28 14:30:20 +00004367FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
4368 CodeGenOpt::Level OptLevel) {
4369 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004370}