blob: f75dd4de3f96ca24b1bdcd11cef7192de47003d7 [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()) {
Sam Parker28934482017-07-14 08:23:56 +00002685 SDValue Ops[] = {
2686 CPIdx,
2687 getAL(CurDAG, dl),
2688 CurDAG->getRegister(0, MVT::i32),
2689 CurDAG->getEntryNode()
2690 };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002691 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002692 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002693 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002694 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002695 CPIdx,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002696 CurDAG->getTargetConstant(0, dl, MVT::i32),
2697 getAL(CurDAG, dl),
Owen Anderson9f944592009-08-11 20:47:22 +00002698 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002699 CurDAG->getEntryNode()
2700 };
Justin Bogner45571362016-05-12 00:31:09 +00002701 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
2702 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002703 }
Sam Parker28934482017-07-14 08:23:56 +00002704 // Annotate the Node with memory operand information so that MachineInstr
2705 // queries work properly. This e.g. gives the register allocation the
2706 // required information for rematerialization.
2707 MachineFunction& MF = CurDAG->getMachineFunction();
2708 MachineSDNode::mmo_iterator MemOp = MF.allocateMemRefsArray(1);
2709 MemOp[0] = MF.getMachineMemOperand(
2710 MachinePointerInfo::getConstantPool(MF),
2711 MachineMemOperand::MOLoad, 4, 4);
2712
2713 cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp+1);
2714
Justin Bognered4f3782016-05-12 00:20:19 +00002715 ReplaceNode(N, ResNode);
Justin Bogner45571362016-05-12 00:31:09 +00002716 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002717 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002718
Evan Cheng10043e22007-01-19 07:51:42 +00002719 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002720 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002721 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002722 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002723 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002724 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00002725 SDValue TFI = CurDAG->getTargetFrameIndex(
2726 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin22c2fba2009-07-08 23:10:31 +00002727 if (Subtarget->isThumb1Only()) {
Renato Golinb9887ef2015-02-25 14:41:06 +00002728 // Set the alignment of the frame object to 4, to avoid having to generate
2729 // more than one ADD
Matthias Braun941a7052016-07-28 18:40:00 +00002730 MachineFrameInfo &MFI = MF->getFrameInfo();
2731 if (MFI.getObjectAlignment(FI) < 4)
2732 MFI.setObjectAlignment(FI, 4);
Justin Bogner45571362016-05-12 00:31:09 +00002733 CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
2734 CurDAG->getTargetConstant(0, dl, MVT::i32));
2735 return;
Jim Grosbachfde21102009-04-07 20:34:09 +00002736 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002737 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2738 ARM::t2ADDri : ARM::ADDri);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002739 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
2740 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002741 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002742 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2743 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00002744 }
Evan Cheng10043e22007-01-19 07:51:42 +00002745 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002746 case ISD::SRL:
Justin Bogner45571362016-05-12 00:31:09 +00002747 if (tryV6T2BitfieldExtractOp(N, false))
2748 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002749 break;
Tim Northover14ff2df2014-07-23 13:59:12 +00002750 case ISD::SIGN_EXTEND_INREG:
Sandeep Patel423e42b2009-10-13 18:59:48 +00002751 case ISD::SRA:
Justin Bogner45571362016-05-12 00:31:09 +00002752 if (tryV6T2BitfieldExtractOp(N, true))
2753 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002754 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002755 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002756 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002757 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002758 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002759 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002760 if (!RHSV) break;
2761 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002762 unsigned ShImm = Log2_32(RHSV-1);
2763 if (ShImm >= 32)
2764 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002765 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002766 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002767 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002768 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002769 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002770 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002771 CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
2772 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002773 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002774 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2775 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002776 CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
2777 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002778 }
Evan Cheng10043e22007-01-19 07:51:42 +00002779 }
2780 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002781 unsigned ShImm = Log2_32(RHSV+1);
2782 if (ShImm >= 32)
2783 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002784 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002785 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002786 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002787 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002788 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002789 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002790 CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
2791 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002792 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002793 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2794 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002795 CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
2796 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002797 }
Evan Cheng10043e22007-01-19 07:51:42 +00002798 }
2799 }
2800 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002801 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002802 // Check for unsigned bitfield extract
Justin Bogner45571362016-05-12 00:31:09 +00002803 if (tryV6T2BitfieldExtractOp(N, false))
2804 return;
Jim Grosbach825cb292010-04-22 23:24:18 +00002805
James Molloyae5ff992016-07-05 12:37:13 +00002806 // If an immediate is used in an AND node, it is possible that the immediate
2807 // can be more optimally materialized when negated. If this is the case we
2808 // can negate the immediate and use a BIC instead.
2809 auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1));
2810 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
2811 uint32_t Imm = (uint32_t) N1C->getZExtValue();
2812
2813 // In Thumb2 mode, an AND can take a 12-bit immediate. If this
2814 // immediate can be negated and fit in the immediate operand of
2815 // a t2BIC, don't do any manual transform here as this can be
2816 // handled by the generic ISel machinery.
2817 bool PreferImmediateEncoding =
2818 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm));
2819 if (!PreferImmediateEncoding &&
2820 ConstantMaterializationCost(Imm) >
2821 ConstantMaterializationCost(~Imm)) {
2822 // The current immediate costs more to materialize than a negated
2823 // immediate, so negate the immediate and use a BIC.
2824 SDValue NewImm =
2825 CurDAG->getConstant(~N1C->getZExtValue(), dl, MVT::i32);
2826 // If the new constant didn't exist before, reposition it in the topological
2827 // ordering so it is just before N. Otherwise, don't touch its location.
2828 if (NewImm->getNodeId() == -1)
2829 CurDAG->RepositionNode(N->getIterator(), NewImm.getNode());
2830
2831 if (!Subtarget->hasThumb2()) {
2832 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
2833 N->getOperand(0), NewImm, getAL(CurDAG, dl),
2834 CurDAG->getRegister(0, MVT::i32)};
2835 ReplaceNode(N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32, Ops));
2836 return;
2837 } else {
2838 SDValue Ops[] = {N->getOperand(0), NewImm, getAL(CurDAG, dl),
2839 CurDAG->getRegister(0, MVT::i32),
2840 CurDAG->getRegister(0, MVT::i32)};
2841 ReplaceNode(N,
2842 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32, Ops));
2843 return;
2844 }
2845 }
2846 }
2847
Evan Cheng786b15f2009-10-21 08:15:52 +00002848 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2849 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2850 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2851 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2852 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002853 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002854 if (VT != MVT::i32)
2855 break;
2856 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2857 ? ARM::t2MOVTi16
2858 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2859 if (!Opc)
2860 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002861 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
James Molloyae5ff992016-07-05 12:37:13 +00002862 N1C = dyn_cast<ConstantSDNode>(N1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002863 if (!N1C)
2864 break;
2865 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2866 SDValue N2 = N0.getOperand(1);
2867 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2868 if (!N2C)
2869 break;
2870 unsigned N1CVal = N1C->getZExtValue();
2871 unsigned N2CVal = N2C->getZExtValue();
2872 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2873 (N1CVal & 0xffffU) == 0xffffU &&
2874 (N2CVal & 0xffffU) == 0x0U) {
2875 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002876 dl, MVT::i32);
Evan Cheng786b15f2009-10-21 08:15:52 +00002877 SDValue Ops[] = { N0.getOperand(0), Imm16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002878 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002879 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
2880 return;
Evan Cheng786b15f2009-10-21 08:15:52 +00002881 }
2882 }
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002883
Evan Cheng786b15f2009-10-21 08:15:52 +00002884 break;
2885 }
Sam Parkerd616cf02016-06-20 16:47:09 +00002886 case ARMISD::UMAAL: {
2887 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
2888 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2889 N->getOperand(2), N->getOperand(3),
2890 getAL(CurDAG, dl),
2891 CurDAG->getRegister(0, MVT::i32) };
2892 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::i32, Ops));
2893 return;
2894 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002895 case ARMISD::UMLAL:{
2896 if (Subtarget->isThumb()) {
2897 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002898 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002899 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002900 ReplaceNode(
2901 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops));
2902 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002903 }else{
2904 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002905 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002906 CurDAG->getRegister(0, MVT::i32),
2907 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002908 ReplaceNode(N, CurDAG->getMachineNode(
2909 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl,
2910 MVT::i32, MVT::i32, Ops));
2911 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002912 }
2913 }
2914 case ARMISD::SMLAL:{
2915 if (Subtarget->isThumb()) {
2916 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002917 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002918 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002919 ReplaceNode(
2920 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops));
2921 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002922 }else{
2923 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002924 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002925 CurDAG->getRegister(0, MVT::i32),
2926 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002927 ReplaceNode(N, CurDAG->getMachineNode(
2928 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl,
2929 MVT::i32, MVT::i32, Ops));
2930 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002931 }
2932 }
Sam Parker68c71cd2016-07-25 09:20:20 +00002933 case ARMISD::SUBE: {
2934 if (!Subtarget->hasV6Ops())
2935 break;
2936 // Look for a pattern to match SMMLS
2937 // (sube a, (smul_loHi a, b), (subc 0, (smul_LOhi(a, b))))
2938 if (N->getOperand(1).getOpcode() != ISD::SMUL_LOHI ||
Tim Northover765777c2016-08-02 23:12:36 +00002939 N->getOperand(2).getOpcode() != ARMISD::SUBC ||
2940 !SDValue(N, 1).use_empty())
Sam Parker68c71cd2016-07-25 09:20:20 +00002941 break;
2942
2943 if (Subtarget->isThumb())
2944 assert(Subtarget->hasThumb2() &&
2945 "This pattern should not be generated for Thumb");
2946
2947 SDValue SmulLoHi = N->getOperand(1);
2948 SDValue Subc = N->getOperand(2);
2949 auto *Zero = dyn_cast<ConstantSDNode>(Subc.getOperand(0));
2950
2951 if (!Zero || Zero->getZExtValue() != 0 ||
2952 Subc.getOperand(1) != SmulLoHi.getValue(0) ||
2953 N->getOperand(1) != SmulLoHi.getValue(1) ||
2954 N->getOperand(2) != Subc.getValue(1))
2955 break;
2956
2957 unsigned Opc = Subtarget->isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
2958 SDValue Ops[] = { SmulLoHi.getOperand(0), SmulLoHi.getOperand(1),
2959 N->getOperand(0), getAL(CurDAG, dl),
2960 CurDAG->getRegister(0, MVT::i32) };
2961 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops));
2962 return;
2963 }
Evan Cheng10043e22007-01-19 07:51:42 +00002964 case ISD::LOAD: {
Justin Bogner45571362016-05-12 00:31:09 +00002965 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
2966 if (tryT2IndexedLoad(N))
2967 return;
James Molloyb3326df2016-07-15 08:03:56 +00002968 } else if (Subtarget->isThumb()) {
2969 if (tryT1IndexedLoad(N))
2970 return;
Justin Bogner45571362016-05-12 00:31:09 +00002971 } else if (tryARMIndexedLoad(N))
2972 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002973 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002974 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00002975 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002976 case ARMISD::BRCOND: {
2977 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2978 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2979 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00002980
Evan Cheng7e90b112007-07-05 07:15:27 +00002981 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2982 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2983 // Pattern complexity = 6 cost = 1 size = 0
2984
David Goodwin27303cd2009-06-30 18:04:13 +00002985 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2986 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2987 // Pattern complexity = 6 cost = 1 size = 0
2988
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002989 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00002990 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002991 SDValue Chain = N->getOperand(0);
2992 SDValue N1 = N->getOperand(1);
2993 SDValue N2 = N->getOperand(2);
2994 SDValue N3 = N->getOperand(3);
2995 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00002996 assert(N1.getOpcode() == ISD::BasicBlock);
2997 assert(N2.getOpcode() == ISD::Constant);
2998 assert(N3.getOpcode() == ISD::Register);
2999
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00003000 unsigned CC = (unsigned) cast<ConstantSDNode>(N2)->getZExtValue();
3001
3002 if (InFlag.getOpcode() == ARMISD::CMPZ) {
3003 bool SwitchEQNEToPLMI;
3004 SelectCMPZ(InFlag.getNode(), SwitchEQNEToPLMI);
3005 InFlag = N->getOperand(4);
3006
3007 if (SwitchEQNEToPLMI) {
3008 switch ((ARMCC::CondCodes)CC) {
3009 default: llvm_unreachable("CMPZ must be either NE or EQ!");
3010 case ARMCC::NE:
3011 CC = (unsigned)ARMCC::MI;
3012 break;
3013 case ARMCC::EQ:
3014 CC = (unsigned)ARMCC::PL;
3015 break;
3016 }
3017 }
3018 }
3019
3020 SDValue Tmp2 = CurDAG->getTargetConstant(CC, dl, MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003021 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00003022 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00003023 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003024 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003025 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00003026 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003027 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00003028 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003029 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00003030 SDValue(Chain.getNode(), Chain.getResNo()));
Justin Bognered4f3782016-05-12 00:20:19 +00003031 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003032 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00003033 }
James Molloy4d86bed2016-09-09 12:52:24 +00003034
3035 case ARMISD::CMPZ: {
3036 // select (CMPZ X, #-C) -> (CMPZ (ADDS X, #C), #0)
3037 // This allows us to avoid materializing the expensive negative constant.
3038 // The CMPZ #0 is useless and will be peepholed away but we need to keep it
3039 // for its glue output.
3040 SDValue X = N->getOperand(0);
3041 auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1).getNode());
3042 if (C && C->getSExtValue() < 0 && Subtarget->isThumb()) {
3043 int64_t Addend = -C->getSExtValue();
3044
3045 SDNode *Add = nullptr;
Artyom Skrobov4592f622017-02-17 18:59:16 +00003046 // ADDS can be better than CMN if the immediate fits in a
James Molloy4d86bed2016-09-09 12:52:24 +00003047 // 16-bit ADDS, which means either [0,256) for tADDi8 or [0,8) for tADDi3.
3048 // Outside that range we can just use a CMN which is 32-bit but has a
3049 // 12-bit immediate range.
Artyom Skrobov4592f622017-02-17 18:59:16 +00003050 if (Addend < 1<<8) {
3051 if (Subtarget->isThumb2()) {
3052 SDValue Ops[] = { X, CurDAG->getTargetConstant(Addend, dl, MVT::i32),
3053 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
3054 CurDAG->getRegister(0, MVT::i32) };
3055 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl, MVT::i32, Ops);
3056 } else {
3057 unsigned Opc = (Addend < 1<<3) ? ARM::tADDi3 : ARM::tADDi8;
3058 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), X,
3059 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
3060 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
3061 Add = CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
3062 }
James Molloy4d86bed2016-09-09 12:52:24 +00003063 }
3064 if (Add) {
3065 SDValue Ops2[] = {SDValue(Add, 0), CurDAG->getConstant(0, dl, MVT::i32)};
3066 CurDAG->MorphNodeTo(N, ARMISD::CMPZ, CurDAG->getVTList(MVT::Glue), Ops2);
3067 }
3068 }
3069 // Other cases are autogenerated.
3070 break;
3071 }
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00003072
3073 case ARMISD::CMOV: {
3074 SDValue InFlag = N->getOperand(4);
3075
3076 if (InFlag.getOpcode() == ARMISD::CMPZ) {
3077 bool SwitchEQNEToPLMI;
3078 SelectCMPZ(InFlag.getNode(), SwitchEQNEToPLMI);
3079
3080 if (SwitchEQNEToPLMI) {
3081 SDValue ARMcc = N->getOperand(2);
3082 ARMCC::CondCodes CC =
3083 (ARMCC::CondCodes)cast<ConstantSDNode>(ARMcc)->getZExtValue();
3084
3085 switch (CC) {
3086 default: llvm_unreachable("CMPZ must be either NE or EQ!");
3087 case ARMCC::NE:
3088 CC = ARMCC::MI;
3089 break;
3090 case ARMCC::EQ:
3091 CC = ARMCC::PL;
3092 break;
3093 }
3094 SDValue NewARMcc = CurDAG->getConstant((unsigned)CC, dl, MVT::i32);
3095 SDValue Ops[] = {N->getOperand(0), N->getOperand(1), NewARMcc,
3096 N->getOperand(3), N->getOperand(4)};
3097 CurDAG->MorphNodeTo(N, ARMISD::CMOV, N->getVTList(), Ops);
3098 }
3099
3100 }
3101 // Other cases are autogenerated.
3102 break;
3103 }
James Molloy4d86bed2016-09-09 12:52:24 +00003104
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003105 case ARMISD::VZIP: {
3106 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003107 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003108 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003109 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003110 case MVT::v8i8: Opc = ARM::VZIPd8; break;
3111 case MVT::v4i16: Opc = ARM::VZIPd16; break;
3112 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00003113 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3114 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003115 case MVT::v16i8: Opc = ARM::VZIPq8; break;
3116 case MVT::v8i16: Opc = ARM::VZIPq16; break;
3117 case MVT::v4f32:
3118 case MVT::v4i32: Opc = ARM::VZIPq32; break;
3119 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003120 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003121 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3122 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003123 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3124 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003125 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003126 case ARMISD::VUZP: {
3127 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003128 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003129 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003130 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003131 case MVT::v8i8: Opc = ARM::VUZPd8; break;
3132 case MVT::v4i16: Opc = ARM::VUZPd16; break;
3133 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00003134 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3135 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003136 case MVT::v16i8: Opc = ARM::VUZPq8; break;
3137 case MVT::v8i16: Opc = ARM::VUZPq16; break;
3138 case MVT::v4f32:
3139 case MVT::v4i32: Opc = ARM::VUZPq32; break;
3140 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003141 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003142 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3143 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003144 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3145 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003146 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003147 case ARMISD::VTRN: {
3148 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003149 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003150 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003151 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003152 case MVT::v8i8: Opc = ARM::VTRNd8; break;
3153 case MVT::v4i16: Opc = ARM::VTRNd16; break;
3154 case MVT::v2f32:
3155 case MVT::v2i32: Opc = ARM::VTRNd32; break;
3156 case MVT::v16i8: Opc = ARM::VTRNq8; break;
3157 case MVT::v8i16: Opc = ARM::VTRNq16; break;
3158 case MVT::v4f32:
3159 case MVT::v4i32: Opc = ARM::VTRNq32; break;
3160 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003161 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003162 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3163 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003164 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3165 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003166 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003167 case ARMISD::BUILD_VECTOR: {
3168 EVT VecVT = N->getValueType(0);
3169 EVT EltVT = VecVT.getVectorElementType();
3170 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00003171 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00003172 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003173 ReplaceNode(
3174 N, createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3175 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003176 }
Duncan Sands14627772010-11-03 12:17:33 +00003177 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003178 if (NumElts == 2) {
3179 ReplaceNode(
3180 N, createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3181 return;
3182 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003183 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003184 ReplaceNode(N,
3185 createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
3186 N->getOperand(2), N->getOperand(3)));
3187 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003188 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003189
Eli Friedmanf624ec22016-12-16 18:44:08 +00003190 case ARMISD::VLD1DUP: {
3191 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8, ARM::VLD1DUPd16,
3192 ARM::VLD1DUPd32 };
3193 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8, ARM::VLD1DUPq16,
3194 ARM::VLD1DUPq32 };
3195 SelectVLDDup(N, false, 1, DOpcodes, QOpcodes);
3196 return;
3197 }
3198
Bob Wilson2d790df2010-11-28 06:51:26 +00003199 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003200 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
3201 ARM::VLD2DUPd32 };
Justin Bogner45571362016-05-12 00:31:09 +00003202 SelectVLDDup(N, false, 2, Opcodes);
3203 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00003204 }
3205
Bob Wilson77ab1652010-11-29 19:35:29 +00003206 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003207 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
3208 ARM::VLD3DUPd16Pseudo,
3209 ARM::VLD3DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003210 SelectVLDDup(N, false, 3, Opcodes);
3211 return;
Bob Wilson77ab1652010-11-29 19:35:29 +00003212 }
3213
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003214 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003215 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
3216 ARM::VLD4DUPd16Pseudo,
3217 ARM::VLD4DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003218 SelectVLDDup(N, false, 4, Opcodes);
3219 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003220 }
3221
Eli Friedmanf624ec22016-12-16 18:44:08 +00003222 case ARMISD::VLD1DUP_UPD: {
3223 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8wb_fixed,
3224 ARM::VLD1DUPd16wb_fixed,
3225 ARM::VLD1DUPd32wb_fixed };
3226 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8wb_fixed,
3227 ARM::VLD1DUPq16wb_fixed,
3228 ARM::VLD1DUPq32wb_fixed };
3229 SelectVLDDup(N, true, 1, DOpcodes, QOpcodes);
3230 return;
3231 }
3232
Bob Wilson06fce872011-02-07 17:43:21 +00003233 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003234 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
3235 ARM::VLD2DUPd16wb_fixed,
3236 ARM::VLD2DUPd32wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003237 SelectVLDDup(N, true, 2, Opcodes);
3238 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003239 }
3240
3241 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003242 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
3243 ARM::VLD3DUPd16Pseudo_UPD,
3244 ARM::VLD3DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003245 SelectVLDDup(N, true, 3, Opcodes);
3246 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003247 }
3248
3249 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003250 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
3251 ARM::VLD4DUPd16Pseudo_UPD,
3252 ARM::VLD4DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003253 SelectVLDDup(N, true, 4, Opcodes);
3254 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003255 }
3256
3257 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003258 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
3259 ARM::VLD1d16wb_fixed,
3260 ARM::VLD1d32wb_fixed,
3261 ARM::VLD1d64wb_fixed };
3262 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
3263 ARM::VLD1q16wb_fixed,
3264 ARM::VLD1q32wb_fixed,
3265 ARM::VLD1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003266 SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
3267 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003268 }
3269
3270 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003271 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
3272 ARM::VLD2d16wb_fixed,
3273 ARM::VLD2d32wb_fixed,
3274 ARM::VLD1q64wb_fixed};
3275 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
3276 ARM::VLD2q16PseudoWB_fixed,
3277 ARM::VLD2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003278 SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
3279 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003280 }
3281
3282 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003283 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
3284 ARM::VLD3d16Pseudo_UPD,
3285 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003286 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003287 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3288 ARM::VLD3q16Pseudo_UPD,
3289 ARM::VLD3q32Pseudo_UPD };
3290 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3291 ARM::VLD3q16oddPseudo_UPD,
3292 ARM::VLD3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003293 SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3294 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003295 }
3296
3297 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003298 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3299 ARM::VLD4d16Pseudo_UPD,
3300 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003301 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003302 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3303 ARM::VLD4q16Pseudo_UPD,
3304 ARM::VLD4q32Pseudo_UPD };
3305 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3306 ARM::VLD4q16oddPseudo_UPD,
3307 ARM::VLD4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003308 SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3309 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003310 }
3311
3312 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003313 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3314 ARM::VLD2LNd16Pseudo_UPD,
3315 ARM::VLD2LNd32Pseudo_UPD };
3316 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3317 ARM::VLD2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003318 SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3319 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003320 }
3321
3322 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003323 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3324 ARM::VLD3LNd16Pseudo_UPD,
3325 ARM::VLD3LNd32Pseudo_UPD };
3326 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3327 ARM::VLD3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003328 SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3329 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003330 }
3331
3332 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003333 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3334 ARM::VLD4LNd16Pseudo_UPD,
3335 ARM::VLD4LNd32Pseudo_UPD };
3336 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3337 ARM::VLD4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003338 SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3339 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003340 }
3341
3342 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003343 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3344 ARM::VST1d16wb_fixed,
3345 ARM::VST1d32wb_fixed,
3346 ARM::VST1d64wb_fixed };
3347 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3348 ARM::VST1q16wb_fixed,
3349 ARM::VST1q32wb_fixed,
3350 ARM::VST1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003351 SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
3352 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003353 }
3354
3355 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003356 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3357 ARM::VST2d16wb_fixed,
3358 ARM::VST2d32wb_fixed,
3359 ARM::VST1q64wb_fixed};
3360 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3361 ARM::VST2q16PseudoWB_fixed,
3362 ARM::VST2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003363 SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
3364 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003365 }
3366
3367 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003368 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3369 ARM::VST3d16Pseudo_UPD,
3370 ARM::VST3d32Pseudo_UPD,
3371 ARM::VST1d64TPseudoWB_fixed};
3372 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3373 ARM::VST3q16Pseudo_UPD,
3374 ARM::VST3q32Pseudo_UPD };
3375 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3376 ARM::VST3q16oddPseudo_UPD,
3377 ARM::VST3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003378 SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3379 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003380 }
3381
3382 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003383 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3384 ARM::VST4d16Pseudo_UPD,
3385 ARM::VST4d32Pseudo_UPD,
3386 ARM::VST1d64QPseudoWB_fixed};
3387 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3388 ARM::VST4q16Pseudo_UPD,
3389 ARM::VST4q32Pseudo_UPD };
3390 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3391 ARM::VST4q16oddPseudo_UPD,
3392 ARM::VST4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003393 SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3394 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003395 }
3396
3397 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003398 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3399 ARM::VST2LNd16Pseudo_UPD,
3400 ARM::VST2LNd32Pseudo_UPD };
3401 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3402 ARM::VST2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003403 SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3404 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003405 }
3406
3407 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003408 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3409 ARM::VST3LNd16Pseudo_UPD,
3410 ARM::VST3LNd32Pseudo_UPD };
3411 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3412 ARM::VST3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003413 SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3414 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003415 }
3416
3417 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003418 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3419 ARM::VST4LNd16Pseudo_UPD,
3420 ARM::VST4LNd32Pseudo_UPD };
3421 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3422 ARM::VST4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003423 SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
3424 return;
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003425 }
3426
Bob Wilsone0636a72009-08-26 17:39:53 +00003427 case ISD::INTRINSIC_VOID:
3428 case ISD::INTRINSIC_W_CHAIN: {
3429 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003430 switch (IntNo) {
3431 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003432 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003433
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003434 case Intrinsic::arm_mrrc:
3435 case Intrinsic::arm_mrrc2: {
3436 SDLoc dl(N);
3437 SDValue Chain = N->getOperand(0);
3438 unsigned Opc;
3439
3440 if (Subtarget->isThumb())
3441 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
3442 else
3443 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
3444
3445 SmallVector<SDValue, 5> Ops;
3446 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(), dl)); /* coproc */
3447 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(), dl)); /* opc */
3448 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(4))->getZExtValue(), dl)); /* CRm */
3449
3450 // The mrrc2 instruction in ARM doesn't allow predicates, the top 4 bits of the encoded
3451 // instruction will always be '1111' but it is possible in assembly language to specify
3452 // AL as a predicate to mrrc2 but it doesn't make any difference to the encoded instruction.
3453 if (Opc != ARM::MRRC2) {
3454 Ops.push_back(getAL(CurDAG, dl));
3455 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3456 }
3457
3458 Ops.push_back(Chain);
3459
3460 // Writes to two registers.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003461 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003462
3463 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, RetType, Ops));
3464 return;
3465 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003466 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003467 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003468 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003469 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003470 SDValue MemAddr = N->getOperand(2);
Bradley Smith433c22e2016-01-15 10:26:51 +00003471 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
Tim Northover1ff5f292014-03-26 14:39:31 +00003472
3473 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3474 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3475 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003476
3477 // arm_ldrexd returns a i64 value in {i32, i32}
3478 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003479 if (isThumb) {
3480 ResTys.push_back(MVT::i32);
3481 ResTys.push_back(MVT::i32);
3482 } else
3483 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003484 ResTys.push_back(MVT::Other);
3485
Weiming Zhao8f56f882012-11-16 21:55:34 +00003486 // Place arguments in the right order.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003487 SDValue Ops[] = {MemAddr, getAL(CurDAG, dl),
3488 CurDAG->getRegister(0, MVT::i32), Chain};
Michael Liaob53d8962013-04-19 22:22:57 +00003489 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003490 // Transfer memoperands.
3491 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3492 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3493 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3494
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003495 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003496 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003497 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003498 SDValue Result;
3499 if (isThumb)
3500 Result = SDValue(Ld, 0);
3501 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003502 SDValue SubRegIdx =
3503 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003504 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003505 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003506 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003507 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003508 ReplaceUses(SDValue(N, 0), Result);
3509 }
3510 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003511 SDValue Result;
3512 if (isThumb)
3513 Result = SDValue(Ld, 1);
3514 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003515 SDValue SubRegIdx =
3516 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003517 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003518 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003519 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003520 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003521 ReplaceUses(SDValue(N, 1), Result);
3522 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003523 ReplaceUses(SDValue(N, 2), OutChain);
Justin Bognered4f3782016-05-12 00:20:19 +00003524 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003525 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003526 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003527 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003528 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003529 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003530 SDValue Chain = N->getOperand(0);
3531 SDValue Val0 = N->getOperand(2);
3532 SDValue Val1 = N->getOperand(3);
3533 SDValue MemAddr = N->getOperand(4);
3534
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003535 // Store exclusive double return a i32 value which is the return status
3536 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003537 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003538
Weiming Zhao8f56f882012-11-16 21:55:34 +00003539 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3540 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003541 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003542 if (isThumb) {
3543 Ops.push_back(Val0);
3544 Ops.push_back(Val1);
3545 } else
3546 // arm_strexd uses GPRPair.
3547 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003548 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003549 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003550 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3551 Ops.push_back(Chain);
3552
Tim Northover1ff5f292014-03-26 14:39:31 +00003553 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3554 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3555 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003556
Michael Liaob53d8962013-04-19 22:22:57 +00003557 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003558 // Transfer memoperands.
3559 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3560 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3561 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3562
Justin Bogner45571362016-05-12 00:31:09 +00003563 ReplaceNode(N, St);
3564 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003565 }
3566
Bob Wilson340861d2010-03-23 05:25:43 +00003567 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003568 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3569 ARM::VLD1d32, ARM::VLD1d64 };
3570 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3571 ARM::VLD1q32, ARM::VLD1q64};
Justin Bogner45571362016-05-12 00:31:09 +00003572 SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
3573 return;
Bob Wilson340861d2010-03-23 05:25:43 +00003574 }
3575
Bob Wilsone0636a72009-08-26 17:39:53 +00003576 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003577 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3578 ARM::VLD2d32, ARM::VLD1q64 };
3579 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3580 ARM::VLD2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003581 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3582 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003583 }
3584
3585 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003586 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3587 ARM::VLD3d16Pseudo,
3588 ARM::VLD3d32Pseudo,
3589 ARM::VLD1d64TPseudo };
3590 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3591 ARM::VLD3q16Pseudo_UPD,
3592 ARM::VLD3q32Pseudo_UPD };
3593 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3594 ARM::VLD3q16oddPseudo,
3595 ARM::VLD3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003596 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3597 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003598 }
3599
3600 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003601 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3602 ARM::VLD4d16Pseudo,
3603 ARM::VLD4d32Pseudo,
3604 ARM::VLD1d64QPseudo };
3605 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3606 ARM::VLD4q16Pseudo_UPD,
3607 ARM::VLD4q32Pseudo_UPD };
3608 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3609 ARM::VLD4q16oddPseudo,
3610 ARM::VLD4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003611 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3612 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003613 }
3614
Bob Wilsonda9817c2009-09-01 04:26:28 +00003615 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003616 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3617 ARM::VLD2LNd16Pseudo,
3618 ARM::VLD2LNd32Pseudo };
3619 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3620 ARM::VLD2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003621 SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
3622 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003623 }
3624
3625 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003626 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3627 ARM::VLD3LNd16Pseudo,
3628 ARM::VLD3LNd32Pseudo };
3629 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3630 ARM::VLD3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003631 SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
3632 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003633 }
3634
3635 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003636 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3637 ARM::VLD4LNd16Pseudo,
3638 ARM::VLD4LNd32Pseudo };
3639 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3640 ARM::VLD4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003641 SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
3642 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003643 }
3644
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003645 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003646 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3647 ARM::VST1d32, ARM::VST1d64 };
3648 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3649 ARM::VST1q32, ARM::VST1q64 };
Justin Bogner45571362016-05-12 00:31:09 +00003650 SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
3651 return;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003652 }
3653
Bob Wilsone0636a72009-08-26 17:39:53 +00003654 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003655 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3656 ARM::VST2d32, ARM::VST1q64 };
Benjamin Kramerf690da42016-06-17 14:14:29 +00003657 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3658 ARM::VST2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003659 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3660 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003661 }
3662
3663 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003664 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3665 ARM::VST3d16Pseudo,
3666 ARM::VST3d32Pseudo,
3667 ARM::VST1d64TPseudo };
3668 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3669 ARM::VST3q16Pseudo_UPD,
3670 ARM::VST3q32Pseudo_UPD };
3671 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3672 ARM::VST3q16oddPseudo,
3673 ARM::VST3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003674 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3675 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003676 }
3677
3678 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003679 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3680 ARM::VST4d16Pseudo,
3681 ARM::VST4d32Pseudo,
3682 ARM::VST1d64QPseudo };
3683 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3684 ARM::VST4q16Pseudo_UPD,
3685 ARM::VST4q32Pseudo_UPD };
3686 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3687 ARM::VST4q16oddPseudo,
3688 ARM::VST4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003689 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3690 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003691 }
Bob Wilsond7797752009-09-01 18:51:56 +00003692
3693 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003694 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3695 ARM::VST2LNd16Pseudo,
3696 ARM::VST2LNd32Pseudo };
3697 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3698 ARM::VST2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003699 SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
3700 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003701 }
3702
3703 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003704 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3705 ARM::VST3LNd16Pseudo,
3706 ARM::VST3LNd32Pseudo };
3707 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3708 ARM::VST3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003709 SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
3710 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003711 }
3712
3713 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003714 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3715 ARM::VST4LNd16Pseudo,
3716 ARM::VST4LNd32Pseudo };
3717 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3718 ARM::VST4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003719 SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
3720 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003721 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003722 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003723 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003724 }
Evan Chengd85631e2010-05-05 18:28:36 +00003725
Tim Northoverb629c772016-04-18 21:48:55 +00003726 case ISD::ATOMIC_CMP_SWAP:
Justin Bogner45571362016-05-12 00:31:09 +00003727 SelectCMP_SWAP(N);
3728 return;
Evan Chengd85631e2010-05-05 18:28:36 +00003729 }
Evan Chengd5021732008-12-10 21:54:21 +00003730
Justin Bogner45571362016-05-12 00:31:09 +00003731 SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003732}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003733
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003734// Inspect a register string of the form
3735// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3736// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3737// and obtain the integer operands from them, adding these operands to the
3738// provided vector.
3739static void getIntOperandsFromRegisterString(StringRef RegString,
Benjamin Kramerbdc49562016-06-12 15:39:02 +00003740 SelectionDAG *CurDAG,
3741 const SDLoc &DL,
3742 std::vector<SDValue> &Ops) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003743 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003744 RegString.split(Fields, ':');
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003745
3746 if (Fields.size() > 1) {
3747 bool AllIntFields = true;
3748
3749 for (StringRef Field : Fields) {
3750 // Need to trim out leading 'cp' characters and get the integer field.
3751 unsigned IntField;
3752 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3753 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3754 }
3755
3756 assert(AllIntFields &&
3757 "Unexpected non-integer value in special register string.");
3758 }
3759}
3760
3761// Maps a Banked Register string to its mask value. The mask value returned is
3762// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3763// mask operand, which expresses which register is to be used, e.g. r8, and in
3764// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3765// was invalid.
3766static inline int getBankedRegisterMask(StringRef RegString) {
3767 return StringSwitch<int>(RegString.lower())
3768 .Case("r8_usr", 0x00)
3769 .Case("r9_usr", 0x01)
3770 .Case("r10_usr", 0x02)
3771 .Case("r11_usr", 0x03)
3772 .Case("r12_usr", 0x04)
3773 .Case("sp_usr", 0x05)
3774 .Case("lr_usr", 0x06)
3775 .Case("r8_fiq", 0x08)
3776 .Case("r9_fiq", 0x09)
3777 .Case("r10_fiq", 0x0a)
3778 .Case("r11_fiq", 0x0b)
3779 .Case("r12_fiq", 0x0c)
3780 .Case("sp_fiq", 0x0d)
3781 .Case("lr_fiq", 0x0e)
3782 .Case("lr_irq", 0x10)
3783 .Case("sp_irq", 0x11)
3784 .Case("lr_svc", 0x12)
3785 .Case("sp_svc", 0x13)
3786 .Case("lr_abt", 0x14)
3787 .Case("sp_abt", 0x15)
3788 .Case("lr_und", 0x16)
3789 .Case("sp_und", 0x17)
3790 .Case("lr_mon", 0x1c)
3791 .Case("sp_mon", 0x1d)
3792 .Case("elr_hyp", 0x1e)
3793 .Case("sp_hyp", 0x1f)
3794 .Case("spsr_fiq", 0x2e)
3795 .Case("spsr_irq", 0x30)
3796 .Case("spsr_svc", 0x32)
3797 .Case("spsr_abt", 0x34)
3798 .Case("spsr_und", 0x36)
3799 .Case("spsr_mon", 0x3c)
3800 .Case("spsr_hyp", 0x3e)
3801 .Default(-1);
3802}
3803
3804// Maps a MClass special register string to its value for use in the
3805// t2MRS_M / t2MSR_M instruction nodes as the SYSm value operand.
3806// Returns -1 to signify that the string was invalid.
3807static inline int getMClassRegisterSYSmValueMask(StringRef RegString) {
3808 return StringSwitch<int>(RegString.lower())
3809 .Case("apsr", 0x0)
3810 .Case("iapsr", 0x1)
3811 .Case("eapsr", 0x2)
3812 .Case("xpsr", 0x3)
3813 .Case("ipsr", 0x5)
3814 .Case("epsr", 0x6)
3815 .Case("iepsr", 0x7)
3816 .Case("msp", 0x8)
3817 .Case("psp", 0x9)
3818 .Case("primask", 0x10)
3819 .Case("basepri", 0x11)
3820 .Case("basepri_max", 0x12)
3821 .Case("faultmask", 0x13)
3822 .Case("control", 0x14)
Bradley Smithf277c8a2016-01-25 11:25:36 +00003823 .Case("msplim", 0x0a)
3824 .Case("psplim", 0x0b)
3825 .Case("sp", 0x18)
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003826 .Default(-1);
3827}
3828
3829// The flags here are common to those allowed for apsr in the A class cores and
3830// those allowed for the special registers in the M class cores. Returns a
3831// value representing which flags were present, -1 if invalid.
John Brawne60f4e42017-02-10 17:41:08 +00003832static inline int getMClassFlagsMask(StringRef Flags) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003833 return StringSwitch<int>(Flags)
John Brawne60f4e42017-02-10 17:41:08 +00003834 .Case("", 0x2) // no flags means nzcvq for psr registers, and 0x2 is
3835 // correct when flags are not permitted
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003836 .Case("g", 0x1)
3837 .Case("nzcvq", 0x2)
3838 .Case("nzcvqg", 0x3)
3839 .Default(-1);
3840}
3841
3842static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead,
3843 const ARMSubtarget *Subtarget) {
3844 // Ensure that the register (without flags) was a valid M Class special
3845 // register.
3846 int SYSmvalue = getMClassRegisterSYSmValueMask(Reg);
3847 if (SYSmvalue == -1)
3848 return -1;
3849
3850 // basepri, basepri_max and faultmask are only valid for V7m.
3851 if (!Subtarget->hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
3852 return -1;
3853
Bradley Smithf277c8a2016-01-25 11:25:36 +00003854 if (Subtarget->has8MSecExt() && Flags.lower() == "ns") {
3855 Flags = "";
3856 SYSmvalue |= 0x80;
3857 }
3858
3859 if (!Subtarget->has8MSecExt() &&
3860 (SYSmvalue == 0xa || SYSmvalue == 0xb || SYSmvalue > 0x14))
3861 return -1;
3862
3863 if (!Subtarget->hasV8MMainlineOps() &&
3864 (SYSmvalue == 0x8a || SYSmvalue == 0x8b || SYSmvalue == 0x91 ||
3865 SYSmvalue == 0x93))
3866 return -1;
3867
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003868 // If it was a read then we won't be expecting flags and so at this point
3869 // we can return the mask.
3870 if (IsRead) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00003871 if (Flags.empty())
3872 return SYSmvalue;
3873 else
3874 return -1;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003875 }
3876
3877 // We know we are now handling a write so need to get the mask for the flags.
John Brawne60f4e42017-02-10 17:41:08 +00003878 int Mask = getMClassFlagsMask(Flags);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003879
3880 // Only apsr, iapsr, eapsr, xpsr can have flags. The other register values
3881 // shouldn't have flags present.
3882 if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.empty()))
3883 return -1;
3884
3885 // The _g and _nzcvqg versions are only valid if the DSP extension is
3886 // available.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003887 if (!Subtarget->hasDSP() && (Mask & 0x1))
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003888 return -1;
3889
3890 // The register was valid so need to put the mask in the correct place
3891 // (the flags need to be in bits 11-10) and combine with the SYSmvalue to
3892 // construct the operand for the instruction node.
John Brawne60f4e42017-02-10 17:41:08 +00003893 return SYSmvalue | Mask << 10;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003894}
3895
3896static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
3897 // The mask operand contains the special register (R Bit) in bit 4, whether
3898 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
3899 // bits 3-0 contains the fields to be accessed in the special register, set by
3900 // the flags provided with the register.
3901 int Mask = 0;
3902 if (Reg == "apsr") {
3903 // The flags permitted for apsr are the same flags that are allowed in
3904 // M class registers. We get the flag value and then shift the flags into
3905 // the correct place to combine with the mask.
John Brawne60f4e42017-02-10 17:41:08 +00003906 Mask = getMClassFlagsMask(Flags);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003907 if (Mask == -1)
3908 return -1;
3909 return Mask << 2;
3910 }
3911
3912 if (Reg != "cpsr" && Reg != "spsr") {
3913 return -1;
3914 }
3915
3916 // This is the same as if the flags were "fc"
3917 if (Flags.empty() || Flags == "all")
3918 return Mask | 0x9;
3919
3920 // Inspect the supplied flags string and set the bits in the mask for
3921 // the relevant and valid flags allowed for cpsr and spsr.
3922 for (char Flag : Flags) {
3923 int FlagVal;
3924 switch (Flag) {
3925 case 'c':
3926 FlagVal = 0x1;
3927 break;
3928 case 'x':
3929 FlagVal = 0x2;
3930 break;
3931 case 's':
3932 FlagVal = 0x4;
3933 break;
3934 case 'f':
3935 FlagVal = 0x8;
3936 break;
3937 default:
3938 FlagVal = 0;
3939 }
3940
3941 // This avoids allowing strings where the same flag bit appears twice.
3942 if (!FlagVal || (Mask & FlagVal))
3943 return -1;
3944 Mask |= FlagVal;
3945 }
3946
3947 // If the register is spsr then we need to set the R bit.
3948 if (Reg == "spsr")
3949 Mask |= 0x10;
3950
3951 return Mask;
3952}
3953
3954// Lower the read_register intrinsic to ARM specific DAG nodes
3955// using the supplied metadata string to select the instruction node to use
3956// and the registers/masks to construct as operands for the node.
Justin Bogner45571362016-05-12 00:31:09 +00003957bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003958 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3959 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3960 bool IsThumb2 = Subtarget->isThumb2();
3961 SDLoc DL(N);
3962
3963 std::vector<SDValue> Ops;
3964 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3965
3966 if (!Ops.empty()) {
3967 // If the special register string was constructed of fields (as defined
3968 // in the ACLE) then need to lower to MRC node (32 bit) or
3969 // MRRC node(64 bit), we can make the distinction based on the number of
3970 // operands we have.
3971 unsigned Opcode;
3972 SmallVector<EVT, 3> ResTypes;
3973 if (Ops.size() == 5){
3974 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
3975 ResTypes.append({ MVT::i32, MVT::Other });
3976 } else {
3977 assert(Ops.size() == 3 &&
3978 "Invalid number of fields in special register string.");
3979 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
3980 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
3981 }
3982
3983 Ops.push_back(getAL(CurDAG, DL));
3984 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3985 Ops.push_back(N->getOperand(0));
Justin Bogner45571362016-05-12 00:31:09 +00003986 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops));
3987 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003988 }
3989
3990 std::string SpecialReg = RegString->getString().lower();
3991
3992 int BankedReg = getBankedRegisterMask(SpecialReg);
3993 if (BankedReg != -1) {
3994 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
3995 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3996 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003997 ReplaceNode(
3998 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
3999 DL, MVT::i32, MVT::Other, Ops));
4000 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004001 }
4002
4003 // The VFP registers are read by creating SelectionDAG nodes with opcodes
4004 // corresponding to the register that is being read from. So we switch on the
4005 // string to find which opcode we need to use.
4006 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
4007 .Case("fpscr", ARM::VMRS)
4008 .Case("fpexc", ARM::VMRS_FPEXC)
4009 .Case("fpsid", ARM::VMRS_FPSID)
4010 .Case("mvfr0", ARM::VMRS_MVFR0)
4011 .Case("mvfr1", ARM::VMRS_MVFR1)
4012 .Case("mvfr2", ARM::VMRS_MVFR2)
4013 .Case("fpinst", ARM::VMRS_FPINST)
4014 .Case("fpinst2", ARM::VMRS_FPINST2)
4015 .Default(0);
4016
4017 // If an opcode was found then we can lower the read to a VFP instruction.
4018 if (Opcode) {
4019 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004020 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004021 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
Justin Bogner45571362016-05-12 00:31:09 +00004022 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004023
4024 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4025 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004026 ReplaceNode(N,
4027 CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops));
4028 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004029 }
4030
4031 // If the target is M Class then need to validate that the register string
4032 // is an acceptable value, so check that a mask can be constructed from the
4033 // string.
4034 if (Subtarget->isMClass()) {
Bradley Smithf277c8a2016-01-25 11:25:36 +00004035 StringRef Flags = "", Reg = SpecialReg;
4036 if (Reg.endswith("_ns")) {
4037 Flags = "ns";
4038 Reg = Reg.drop_back(3);
4039 }
4040
4041 int SYSmValue = getMClassRegisterMask(Reg, Flags, true, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004042 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004043 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004044
4045 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4046 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4047 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004048 ReplaceNode(
4049 N, CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops));
4050 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004051 }
4052
4053 // Here we know the target is not M Class so we need to check if it is one
4054 // of the remaining possible values which are apsr, cpsr or spsr.
4055 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
4056 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4057 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004058 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
4059 DL, MVT::i32, MVT::Other, Ops));
4060 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004061 }
4062
4063 if (SpecialReg == "spsr") {
4064 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4065 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004066 ReplaceNode(
4067 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys, DL,
4068 MVT::i32, MVT::Other, Ops));
4069 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004070 }
4071
Justin Bogner45571362016-05-12 00:31:09 +00004072 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004073}
4074
4075// Lower the write_register intrinsic to ARM specific DAG nodes
4076// using the supplied metadata string to select the instruction node to use
4077// and the registers/masks to use in the nodes
Justin Bogner45571362016-05-12 00:31:09 +00004078bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004079 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
4080 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
4081 bool IsThumb2 = Subtarget->isThumb2();
4082 SDLoc DL(N);
4083
4084 std::vector<SDValue> Ops;
4085 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
4086
4087 if (!Ops.empty()) {
4088 // If the special register string was constructed of fields (as defined
4089 // in the ACLE) then need to lower to MCR node (32 bit) or
4090 // MCRR node(64 bit), we can make the distinction based on the number of
4091 // operands we have.
4092 unsigned Opcode;
4093 if (Ops.size() == 5) {
4094 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
4095 Ops.insert(Ops.begin()+2, N->getOperand(2));
4096 } else {
4097 assert(Ops.size() == 3 &&
4098 "Invalid number of fields in special register string.");
4099 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
4100 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
4101 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
4102 }
4103
4104 Ops.push_back(getAL(CurDAG, DL));
4105 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4106 Ops.push_back(N->getOperand(0));
4107
Justin Bogner45571362016-05-12 00:31:09 +00004108 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4109 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004110 }
4111
4112 std::string SpecialReg = RegString->getString().lower();
4113 int BankedReg = getBankedRegisterMask(SpecialReg);
4114 if (BankedReg != -1) {
4115 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
4116 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4117 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004118 ReplaceNode(
4119 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
4120 DL, MVT::Other, Ops));
4121 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004122 }
4123
4124 // The VFP registers are written to by creating SelectionDAG nodes with
4125 // opcodes corresponding to the register that is being written. So we switch
4126 // on the string to find which opcode we need to use.
4127 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
4128 .Case("fpscr", ARM::VMSR)
4129 .Case("fpexc", ARM::VMSR_FPEXC)
4130 .Case("fpsid", ARM::VMSR_FPSID)
4131 .Case("fpinst", ARM::VMSR_FPINST)
4132 .Case("fpinst2", ARM::VMSR_FPINST2)
4133 .Default(0);
4134
4135 if (Opcode) {
4136 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004137 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004138 Ops = { N->getOperand(2), getAL(CurDAG, DL),
4139 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004140 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4141 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004142 }
4143
Bradley Smithf277c8a2016-01-25 11:25:36 +00004144 std::pair<StringRef, StringRef> Fields;
4145 Fields = StringRef(SpecialReg).rsplit('_');
4146 std::string Reg = Fields.first.str();
4147 StringRef Flags = Fields.second;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004148
4149 // If the target was M Class then need to validate the special register value
4150 // and retrieve the mask for use in the instruction node.
4151 if (Subtarget->isMClass()) {
4152 // basepri_max gets split so need to correct Reg and Flags.
4153 if (SpecialReg == "basepri_max") {
4154 Reg = SpecialReg;
4155 Flags = "";
4156 }
4157 int SYSmValue = getMClassRegisterMask(Reg, Flags, false, Subtarget);
4158 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004159 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004160
4161 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4162 N->getOperand(2), getAL(CurDAG, DL),
4163 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004164 ReplaceNode(N, CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops));
4165 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004166 }
4167
4168 // We then check to see if a valid mask can be constructed for one of the
4169 // register string values permitted for the A and R class cores. These values
4170 // are apsr, spsr and cpsr; these are also valid on older cores.
4171 int Mask = getARClassRegisterMask(Reg, Flags);
4172 if (Mask != -1) {
4173 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
4174 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4175 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004176 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
4177 DL, MVT::Other, Ops));
4178 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004179 }
4180
Justin Bogner45571362016-05-12 00:31:09 +00004181 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004182}
4183
Justin Bogner45571362016-05-12 00:31:09 +00004184bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){
Weiming Zhaoc5987002013-02-14 18:10:21 +00004185 std::vector<SDValue> AsmNodeOperands;
4186 unsigned Flag, Kind;
4187 bool Changed = false;
4188 unsigned NumOps = N->getNumOperands();
4189
Weiming Zhaoc5987002013-02-14 18:10:21 +00004190 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
4191 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
4192 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
4193 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004194 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
4195 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
4196 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00004197
Andrew Trickef9de2a2013-05-25 02:42:55 +00004198 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00004199 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
4200 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004201
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004202 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004203 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004204 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00004205 SDValue op = N->getOperand(i);
4206 AsmNodeOperands.push_back(op);
4207
4208 if (i < InlineAsm::Op_FirstOperand)
4209 continue;
4210
4211 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
4212 Flag = C->getZExtValue();
4213 Kind = InlineAsm::getKind(Flag);
4214 }
4215 else
4216 continue;
4217
Joey Gouly392cdad2013-07-08 19:52:51 +00004218 // Immediate operands to inline asm in the SelectionDAG are modeled with
4219 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
4220 // the second is a constant with the value of the immediate. If we get here
4221 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00004222 if (Kind == InlineAsm::Kind_Imm) {
4223 SDValue op = N->getOperand(++i);
4224 AsmNodeOperands.push_back(op);
4225 continue;
4226 }
4227
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004228 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
4229 if (NumRegs)
4230 OpChanged.push_back(false);
4231
4232 unsigned DefIdx = 0;
4233 bool IsTiedToChangedOp = false;
4234 // If it's a use that is tied with a previous def, it has no
4235 // reg class constraint.
4236 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
4237 IsTiedToChangedOp = OpChanged[DefIdx];
4238
Diana Picusf345d402016-07-20 09:48:24 +00004239 // Memory operands to inline asm in the SelectionDAG are modeled with two
4240 // operands: a constant of value InlineAsm::Kind_Mem followed by the input
4241 // operand. If we get here and we have a Kind_Mem, skip the next operand (so
4242 // it doesn't get misinterpreted), and continue. We do this here because
4243 // it's important to update the OpChanged array correctly before moving on.
4244 if (Kind == InlineAsm::Kind_Mem) {
4245 SDValue op = N->getOperand(++i);
4246 AsmNodeOperands.push_back(op);
4247 continue;
4248 }
4249
Weiming Zhaoc5987002013-02-14 18:10:21 +00004250 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
4251 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
4252 continue;
4253
Weiming Zhaoc5987002013-02-14 18:10:21 +00004254 unsigned RC;
4255 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004256 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
4257 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00004258 continue;
4259
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004260 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00004261 SDValue V0 = N->getOperand(i+1);
4262 SDValue V1 = N->getOperand(i+2);
4263 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
4264 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
4265 SDValue PairedReg;
4266 MachineRegisterInfo &MRI = MF->getRegInfo();
4267
4268 if (Kind == InlineAsm::Kind_RegDef ||
4269 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
4270 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
4271 // the original GPRs.
4272
4273 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4274 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4275 SDValue Chain = SDValue(N,0);
4276
4277 SDNode *GU = N->getGluedUser();
4278 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
4279 Chain.getValue(1));
4280
4281 // Extract values from a GPRPair reg and copy to the original GPR reg.
4282 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4283 RegCopy);
4284 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4285 RegCopy);
4286 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
4287 RegCopy.getValue(1));
4288 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
4289
4290 // Update the original glue user.
4291 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
4292 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00004293 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004294 }
4295 else {
4296 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
4297 // GPRPair and then pass the GPRPair to the inline asm.
4298 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
4299
4300 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
4301 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
4302 Chain.getValue(1));
4303 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
4304 T0.getValue(1));
4305 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
4306
4307 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
4308 // i32 VRs of inline asm with it.
4309 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4310 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4311 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
4312
4313 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
4314 Glue = Chain.getValue(1);
4315 }
4316
4317 Changed = true;
4318
4319 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004320 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004321 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00004322 if (IsTiedToChangedOp)
4323 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
4324 else
4325 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004326 // Replace the current flag.
4327 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00004328 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004329 // Add the new register node and skip the original two GPRs.
4330 AsmNodeOperands.push_back(PairedReg);
4331 // Skip the next two GPRs.
4332 i += 2;
4333 }
4334 }
4335
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004336 if (Glue.getNode())
4337 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004338 if (!Changed)
Justin Bogner45571362016-05-12 00:31:09 +00004339 return false;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004340
Andrew Trickef9de2a2013-05-25 02:42:55 +00004341 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00004342 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004343 New->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00004344 ReplaceNode(N, New.getNode());
4345 return true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004346}
4347
4348
Bob Wilsona2c462b2009-05-19 05:53:42 +00004349bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00004350SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00004351 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004352 switch(ConstraintID) {
4353 default:
4354 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00004355 case InlineAsm::Constraint_i:
4356 // FIXME: It seems strange that 'i' is needed here since it's supposed to
4357 // be an immediate and not a memory constraint.
Justin Bognerb03fd122016-08-17 05:10:15 +00004358 LLVM_FALLTHROUGH;
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004359 case InlineAsm::Constraint_m:
James Molloy72222f52015-10-26 10:04:52 +00004360 case InlineAsm::Constraint_o:
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004361 case InlineAsm::Constraint_Q:
4362 case InlineAsm::Constraint_Um:
4363 case InlineAsm::Constraint_Un:
4364 case InlineAsm::Constraint_Uq:
4365 case InlineAsm::Constraint_Us:
4366 case InlineAsm::Constraint_Ut:
4367 case InlineAsm::Constraint_Uv:
4368 case InlineAsm::Constraint_Uy:
4369 // Require the address to be in a register. That is safe for all ARM
4370 // variants and it is hard to do anything much smarter without knowing
4371 // how the operand is used.
4372 OutOps.push_back(Op);
4373 return false;
4374 }
4375 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00004376}
4377
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004378/// createARMISelDag - This pass converts a legalized DAG into a
4379/// ARM-specific DAG, ready for instruction scheduling.
4380///
Bob Wilson2dd957f2009-09-28 14:30:20 +00004381FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
4382 CodeGenOpt::Level OptLevel) {
4383 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004384}