blob: c3c44d71092790b786107a0da031cd8bbc15ee62 [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"
David Blaikieb3bde2e2017-11-17 01:07:10 +000018#include "Utils/ARMBaseInfo.h"
Luke Cheeseman85fd06d2015-06-01 12:02:47 +000019#include "llvm/ADT/StringSwitch.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000020#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
Weiming Zhaoc5987002013-02-14 18:10:21 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000024#include "llvm/CodeGen/SelectionDAG.h"
25#include "llvm/CodeGen/SelectionDAGISel.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000026#include "llvm/CodeGen/TargetLowering.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000027#include "llvm/IR/CallingConv.h"
28#include "llvm/IR/Constants.h"
29#include "llvm/IR/DerivedTypes.h"
30#include "llvm/IR/Function.h"
31#include "llvm/IR/Intrinsics.h"
32#include "llvm/IR/LLVMContext.h"
Evan Cheng8e6b40a2010-05-04 20:39:49 +000033#include "llvm/Support/CommandLine.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000034#include "llvm/Support/Debug.h"
Torok Edwinfb8d6d52009-07-08 20:53:28 +000035#include "llvm/Support/ErrorHandling.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000036#include "llvm/Target/TargetOptions.h"
Torok Edwinfb8d6d52009-07-08 20:53:28 +000037
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000038using namespace llvm;
39
Chandler Carruth84e68b22014-04-22 02:41:26 +000040#define DEBUG_TYPE "arm-isel"
41
Evan Cheng59069ec2010-07-30 23:33:54 +000042static cl::opt<bool>
43DisableShifterOp("disable-shifter-op", cl::Hidden,
44 cl::desc("Disable isel of shifter-op"),
45 cl::init(false));
46
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000047//===--------------------------------------------------------------------===//
48/// ARMDAGToDAGISel - ARM specific code to select ARM machine
49/// instructions for SelectionDAG operations.
50///
51namespace {
Jim Grosbach08605202010-09-29 19:03:54 +000052
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000053class ARMDAGToDAGISel : public SelectionDAGISel {
Evan Cheng10043e22007-01-19 07:51:42 +000054 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
55 /// make the right decision when generating code for different targets.
56 const ARMSubtarget *Subtarget;
57
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000058public:
Eric Christopher2f991c92014-07-03 22:24:49 +000059 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, CodeGenOpt::Level OptLevel)
60 : SelectionDAGISel(tm, OptLevel) {}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000061
Eric Christopher0e6e7cf2014-05-22 02:00:27 +000062 bool runOnMachineFunction(MachineFunction &MF) override {
63 // Reset the subtarget each time through.
Eric Christopher22b2ad22015-02-20 08:24:37 +000064 Subtarget = &MF.getSubtarget<ARMSubtarget>();
Eric Christopher0e6e7cf2014-05-22 02:00:27 +000065 SelectionDAGISel::runOnMachineFunction(MF);
66 return true;
67 }
68
Mehdi Amini117296c2016-10-01 02:56:57 +000069 StringRef getPassName() const override { return "ARM Instruction Selection"; }
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000070
Craig Topper6bc27bf2014-03-10 02:09:33 +000071 void PreprocessISelDAG() override;
Evan Chengeae6d2c2012-12-19 20:16:09 +000072
Bob Wilson4facd962009-10-08 18:51:31 +000073 /// getI32Imm - Return a target constant of type i32 with the specified
74 /// value.
Benjamin Kramerbdc49562016-06-12 15:39:02 +000075 inline SDValue getI32Imm(unsigned Imm, const SDLoc &dl) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +000076 return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000077 }
78
Justin Bogner45571362016-05-12 00:31:09 +000079 void Select(SDNode *N) override;
Evan Cheng62c7b5b2010-12-05 22:04:16 +000080
81 bool hasNoVMLxHazardUse(SDNode *N) const;
Evan Cheng59bbc542010-10-27 23:41:30 +000082 bool isShifterOpProfitable(const SDValue &Shift,
83 ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt);
Owen Andersonb595ed02011-07-21 18:54:16 +000084 bool SelectRegShifterOperand(SDValue N, SDValue &A,
85 SDValue &B, SDValue &C,
86 bool CheckProfitability = true);
87 bool SelectImmShifterOperand(SDValue N, SDValue &A,
Owen Anderson04912702011-07-21 23:38:37 +000088 SDValue &B, bool CheckProfitability = true);
89 bool SelectShiftRegShifterOperand(SDValue N, SDValue &A,
Owen Anderson6d557452011-03-18 19:46:58 +000090 SDValue &B, SDValue &C) {
91 // Don't apply the profitability check
Owen Anderson04912702011-07-21 23:38:37 +000092 return SelectRegShifterOperand(N, A, B, C, false);
93 }
94 bool SelectShiftImmShifterOperand(SDValue N, SDValue &A,
95 SDValue &B) {
96 // Don't apply the profitability check
97 return SelectImmShifterOperand(N, A, B, false);
Owen Anderson6d557452011-03-18 19:46:58 +000098 }
99
Tim Northover644a8192018-06-20 12:09:44 +0000100 bool SelectAddLikeOr(SDNode *Parent, SDValue N, SDValue &Out);
101
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000102 bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
103 bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);
104
Tim Northover42180442013-08-22 09:57:11 +0000105 bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) {
106 const ConstantSDNode *CN = cast<ConstantSDNode>(N);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000107 Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32);
Tim Northover42180442013-08-22 09:57:11 +0000108 Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32);
109 return true;
110 }
111
Owen Anderson2aedba62011-07-26 20:54:26 +0000112 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
113 SDValue &Offset, SDValue &Opc);
114 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000115 SDValue &Offset, SDValue &Opc);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000116 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
117 SDValue &Offset, SDValue &Opc);
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000118 bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000119 bool SelectAddrMode3(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000120 SDValue &Offset, SDValue &Opc);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000121 bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000122 SDValue &Offset, SDValue &Opc);
Sjoerd Meijer011de9c2018-01-26 09:26:40 +0000123 bool IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offset,
124 int Lwb, int Upb, bool FP16);
125 bool SelectAddrMode5(SDValue N, SDValue &Base, SDValue &Offset);
126 bool SelectAddrMode5FP16(SDValue N, SDValue &Base, SDValue &Offset);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000127 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
Bob Wilsone3ecd5f2011-02-25 06:42:42 +0000128 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000129
Evan Chengdfce83c2011-01-17 08:03:18 +0000130 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
Evan Cheng10043e22007-01-19 07:51:42 +0000131
Bill Wendling092a7bd2010-12-14 03:36:38 +0000132 // Thumb Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000133 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
Bill Wendling092a7bd2010-12-14 03:36:38 +0000134 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
135 SDValue &OffImm);
136 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
137 SDValue &OffImm);
138 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
139 SDValue &OffImm);
140 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
141 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000142 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +0000143
Bill Wendling092a7bd2010-12-14 03:36:38 +0000144 // Thumb 2 Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000145 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
146 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000147 SDValue &OffImm);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000148 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +0000149 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000150 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000151 SDValue &OffReg, SDValue &ShImm);
Tim Northovera7ecd242013-07-16 09:46:55 +0000152 bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Chengb23b50d2009-06-29 07:51:04 +0000153
Evan Cheng0fc80842010-11-12 22:42:47 +0000154 inline bool is_so_imm(unsigned Imm) const {
155 return ARM_AM::getSOImmVal(Imm) != -1;
156 }
157
158 inline bool is_so_imm_not(unsigned Imm) const {
159 return ARM_AM::getSOImmVal(~Imm) != -1;
160 }
161
162 inline bool is_t2_so_imm(unsigned Imm) const {
163 return ARM_AM::getT2SOImmVal(Imm) != -1;
164 }
165
166 inline bool is_t2_so_imm_not(unsigned Imm) const {
167 return ARM_AM::getT2SOImmVal(~Imm) != -1;
168 }
169
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000170 // Include the pieces autogenerated from the target description.
171#include "ARMGenDAGISel.inc"
Bob Wilsona2c462b2009-05-19 05:53:42 +0000172
173private:
Tim Northovereaee28b2016-09-19 09:11:09 +0000174 void transferMemOperands(SDNode *Src, SDNode *Dst);
175
Justin Bogner45571362016-05-12 00:31:09 +0000176 /// Indexed (pre/post inc/dec) load matching code for ARM.
177 bool tryARMIndexedLoad(SDNode *N);
James Molloyb3326df2016-07-15 08:03:56 +0000178 bool tryT1IndexedLoad(SDNode *N);
Justin Bogner45571362016-05-12 00:31:09 +0000179 bool tryT2IndexedLoad(SDNode *N);
Evan Cheng84c6cda2009-07-02 07:28:31 +0000180
Bob Wilson340861d2010-03-23 05:25:43 +0000181 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
182 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson12b47992009-10-14 17:28:52 +0000183 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson340861d2010-03-23 05:25:43 +0000184 /// For NumVecs <= 2, QOpcodes1 is not used.
Justin Bogner45571362016-05-12 00:31:09 +0000185 void SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
186 const uint16_t *DOpcodes, const uint16_t *QOpcodes0,
187 const uint16_t *QOpcodes1);
Bob Wilson12b47992009-10-14 17:28:52 +0000188
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000189 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000190 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000191 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000192 /// For NumVecs <= 2, QOpcodes1 is not used.
Justin Bogner45571362016-05-12 00:31:09 +0000193 void SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
194 const uint16_t *DOpcodes, const uint16_t *QOpcodes0,
195 const uint16_t *QOpcodes1);
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000196
Bob Wilson93117bc2009-10-14 16:46:45 +0000197 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilson4145e3a2009-10-14 16:19:03 +0000198 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsond5c57a52010-09-13 23:01:35 +0000199 /// load/store of D registers and Q registers.
Justin Bogner45571362016-05-12 00:31:09 +0000200 void SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
201 unsigned NumVecs, const uint16_t *DOpcodes,
202 const uint16_t *QOpcodes);
Bob Wilson4145e3a2009-10-14 16:19:03 +0000203
Bob Wilson2d790df2010-11-28 06:51:26 +0000204 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
Eli Friedmanf624ec22016-12-16 18:44:08 +0000205 /// should be 1, 2, 3 or 4. The opcode array specifies the instructions used
Bob Wilson2d790df2010-11-28 06:51:26 +0000206 /// for loading D registers. (Q registers are not supported.)
Justin Bogner45571362016-05-12 00:31:09 +0000207 void SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Eli Friedmanf624ec22016-12-16 18:44:08 +0000208 const uint16_t *DOpcodes,
209 const uint16_t *QOpcodes = nullptr);
Bob Wilson2d790df2010-11-28 06:51:26 +0000210
Justin Bogner45571362016-05-12 00:31:09 +0000211 /// Try to select SBFX/UBFX instructions for ARM.
212 bool tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000213
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000214 // Select special operations if node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +0000215 bool tryABSOp(SDNode *N);
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000216
Justin Bogner45571362016-05-12 00:31:09 +0000217 bool tryReadRegister(SDNode *N);
218 bool tryWriteRegister(SDNode *N);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +0000219
Justin Bogner45571362016-05-12 00:31:09 +0000220 bool tryInlineAsm(SDNode *N);
Weiming Zhaoc5987002013-02-14 18:10:21 +0000221
Sjoerd Meijer96e10b52016-12-15 09:38:59 +0000222 void SelectCMPZ(SDNode *N, bool &SwitchEQNEToPLMI);
James Molloye7d97362016-11-03 14:08:01 +0000223
Justin Bogner45571362016-05-12 00:31:09 +0000224 void SelectCMP_SWAP(SDNode *N);
Tim Northoverb629c772016-04-18 21:48:55 +0000225
Evan Chengd9c55362009-07-02 01:23:32 +0000226 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
227 /// inline asm expressions.
Daniel Sanders60f1db02015-03-13 12:45:09 +0000228 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Craig Topper6bc27bf2014-03-10 02:09:33 +0000229 std::vector<SDValue> &OutOps) override;
Bob Wilsone6b778d2009-10-06 22:01:59 +0000230
Weiming Zhao95782222012-11-17 00:23:35 +0000231 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhao8f56f882012-11-16 21:55:34 +0000232 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao95782222012-11-17 00:23:35 +0000233 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
234 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
235 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Chengc2ae5f52010-05-10 17:34:18 +0000236
Bob Wilsond8a9a042010-06-04 00:04:02 +0000237 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +0000238 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
239 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
240 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000241
242 // Get the alignment operand for a NEON VLD or VST instruction.
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000243 SDValue GetVLDSTAlign(SDValue Align, const SDLoc &dl, unsigned NumVecs,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000244 bool is64BitVector);
John Brawn056e6782015-09-14 15:19:41 +0000245
246 /// Returns the number of instructions required to materialize the given
247 /// constant in a register, or 3 if a literal pool load is needed.
248 unsigned ConstantMaterializationCost(unsigned Val) const;
249
250 /// Checks if N is a multiplication by a constant where we can extract out a
251 /// power of two from the constant so that it can be used in a shift, but only
252 /// if it simplifies the materialization of the constant. Returns true if it
253 /// is, and assigns to PowerOfTwo the power of two that should be extracted
254 /// out and to NewMulConst the new constant to be multiplied by.
255 bool canExtractShiftFromMul(const SDValue &N, unsigned MaxShift,
256 unsigned &PowerOfTwo, SDValue &NewMulConst) const;
257
258 /// Replace N with M in CurDAG, in a way that also ensures that M gets
259 /// selected when N would have been selected.
260 void replaceDAGValue(const SDValue &N, SDValue M);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000261};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000262}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000263
Sandeep Patel423e42b2009-10-13 18:59:48 +0000264/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
265/// operand. If so Imm will receive the 32-bit value.
266static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
267 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
268 Imm = cast<ConstantSDNode>(N)->getZExtValue();
269 return true;
270 }
271 return false;
272}
273
274// isInt32Immediate - This method tests to see if a constant operand.
275// If so Imm will receive the 32 bit value.
276static bool isInt32Immediate(SDValue N, unsigned &Imm) {
277 return isInt32Immediate(N.getNode(), Imm);
278}
279
280// isOpcWithIntImmediate - This method tests to see if the node is a specific
281// opcode and that it has a immediate integer right operand.
282// If so Imm will receive the 32 bit value.
283static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
284 return N->getOpcode() == Opc &&
285 isInt32Immediate(N->getOperand(1).getNode(), Imm);
286}
287
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000288/// Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000289/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000290///
291/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000292static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000293 int RangeMin, int RangeMax,
294 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000295 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000296
297 // Check that this is a constant.
298 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
299 if (!C)
300 return false;
301
302 ScaledConstant = (int) C->getZExtValue();
303 if ((ScaledConstant % Scale) != 0)
304 return false;
305
306 ScaledConstant /= Scale;
307 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
308}
309
Evan Chengeae6d2c2012-12-19 20:16:09 +0000310void ARMDAGToDAGISel::PreprocessISelDAG() {
311 if (!Subtarget->hasV6T2Ops())
312 return;
313
314 bool isThumb2 = Subtarget->isThumb();
315 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
316 E = CurDAG->allnodes_end(); I != E; ) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000317 SDNode *N = &*I++; // Preincrement iterator to avoid invalidation issues.
Evan Chengeae6d2c2012-12-19 20:16:09 +0000318
319 if (N->getOpcode() != ISD::ADD)
320 continue;
321
322 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
323 // leading zeros, followed by consecutive set bits, followed by 1 or 2
324 // trailing zeros, e.g. 1020.
325 // Transform the expression to
326 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
327 // of trailing zeros of c2. The left shift would be folded as an shifter
328 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
329 // node (UBFX).
330
331 SDValue N0 = N->getOperand(0);
332 SDValue N1 = N->getOperand(1);
333 unsigned And_imm = 0;
334 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
335 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
336 std::swap(N0, N1);
337 }
338 if (!And_imm)
339 continue;
340
341 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000342 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000343 if (TZ != 1 && TZ != 2)
344 // Be conservative here. Shifter operands aren't always free. e.g. On
345 // Swift, left shifter operand of 1 / 2 for free but others are not.
346 // e.g.
347 // ubfx r3, r1, #16, #8
348 // ldr.w r3, [r0, r3, lsl #2]
349 // vs.
350 // mov.w r9, #1020
351 // and.w r2, r9, r1, lsr #14
352 // ldr r2, [r0, r2]
353 continue;
354 And_imm >>= TZ;
355 if (And_imm & (And_imm + 1))
356 continue;
357
358 // Look for (and (srl X, c1), c2).
359 SDValue Srl = N1.getOperand(0);
360 unsigned Srl_imm = 0;
361 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
362 (Srl_imm <= 2))
363 continue;
364
365 // Make sure first operand is not a shifter operand which would prevent
366 // folding of the left shift.
367 SDValue CPTmp0;
368 SDValue CPTmp1;
369 SDValue CPTmp2;
370 if (isThumb2) {
John Brawnd8b405a2015-09-07 11:45:18 +0000371 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
Evan Chengeae6d2c2012-12-19 20:16:09 +0000372 continue;
373 } else {
374 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
375 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
376 continue;
377 }
378
379 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000380 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000381 Srl.getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000382 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl),
383 MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000384 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000385 Srl,
386 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000387 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000388 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32));
Evan Chengeae6d2c2012-12-19 20:16:09 +0000389 CurDAG->UpdateNodeOperands(N, N0, N1);
Jim Grosbach1a597112014-04-03 23:43:18 +0000390 }
Evan Chengeae6d2c2012-12-19 20:16:09 +0000391}
392
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000393/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
394/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
395/// least on current ARM implementations) which should be avoidded.
396bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
397 if (OptLevel == CodeGenOpt::None)
398 return true;
399
Diana Picus575f2bb2016-07-07 09:11:39 +0000400 if (!Subtarget->hasVMLxHazards())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000401 return true;
402
403 if (!N->hasOneUse())
404 return false;
405
406 SDNode *Use = *N->use_begin();
407 if (Use->getOpcode() == ISD::CopyToReg)
408 return true;
409 if (Use->isMachineOpcode()) {
Eric Christopher2f991c92014-07-03 22:24:49 +0000410 const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>(
Eric Christopherfc6de422014-08-05 02:39:49 +0000411 CurDAG->getSubtarget().getInstrInfo());
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000412
Evan Cheng6cc775f2011-06-28 19:10:37 +0000413 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
414 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000415 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000416 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000417 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
418 return true;
419 // vmlx feeding into another vmlx. We actually want to unfold
420 // the use later in the MLxExpansion pass. e.g.
421 // vmla
422 // vmla (stall 8 cycles)
423 //
424 // vmul (5 cycles)
425 // vadd (5 cycles)
426 // vmla
427 // This adds up to about 18 - 19 cycles.
428 //
429 // vmla
430 // vmul (stall 4 cycles)
431 // vadd adds up to about 14 cycles.
432 return TII->isFpMLxInstruction(Opcode);
433 }
434
435 return false;
436}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000437
Evan Cheng59bbc542010-10-27 23:41:30 +0000438bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
439 ARM_AM::ShiftOpc ShOpcVal,
440 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000441 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000442 return true;
443 if (Shift.hasOneUse())
444 return true;
445 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000446 return ShOpcVal == ARM_AM::lsl &&
447 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000448}
449
John Brawn056e6782015-09-14 15:19:41 +0000450unsigned ARMDAGToDAGISel::ConstantMaterializationCost(unsigned Val) const {
451 if (Subtarget->isThumb()) {
452 if (Val <= 255) return 1; // MOV
Weiming Zhaof68a6a72016-08-05 20:58:29 +0000453 if (Subtarget->hasV6T2Ops() &&
454 (Val <= 0xffff || ARM_AM::getT2SOImmValSplatVal(Val) != -1))
455 return 1; // MOVW
James Molloy65b6be12016-06-14 13:33:07 +0000456 if (Val <= 510) return 2; // MOV + ADDi8
John Brawn056e6782015-09-14 15:19:41 +0000457 if (~Val <= 255) return 2; // MOV + MVN
458 if (ARM_AM::isThumbImmShiftedVal(Val)) return 2; // MOV + LSL
459 } else {
460 if (ARM_AM::getSOImmVal(Val) != -1) return 1; // MOV
461 if (ARM_AM::getSOImmVal(~Val) != -1) return 1; // MVN
462 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
463 if (ARM_AM::isSOImmTwoPartVal(Val)) return 2; // two instrs
464 }
465 if (Subtarget->useMovt(*MF)) return 2; // MOVW + MOVT
466 return 3; // Literal pool load
467}
468
469bool ARMDAGToDAGISel::canExtractShiftFromMul(const SDValue &N,
470 unsigned MaxShift,
471 unsigned &PowerOfTwo,
472 SDValue &NewMulConst) const {
473 assert(N.getOpcode() == ISD::MUL);
474 assert(MaxShift > 0);
475
476 // If the multiply is used in more than one place then changing the constant
477 // will make other uses incorrect, so don't.
478 if (!N.hasOneUse()) return false;
479 // Check if the multiply is by a constant
480 ConstantSDNode *MulConst = dyn_cast<ConstantSDNode>(N.getOperand(1));
481 if (!MulConst) return false;
482 // If the constant is used in more than one place then modifying it will mean
483 // we need to materialize two constants instead of one, which is a bad idea.
484 if (!MulConst->hasOneUse()) return false;
485 unsigned MulConstVal = MulConst->getZExtValue();
486 if (MulConstVal == 0) return false;
487
488 // Find the largest power of 2 that MulConstVal is a multiple of
489 PowerOfTwo = MaxShift;
490 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
491 --PowerOfTwo;
492 if (PowerOfTwo == 0) return false;
493 }
494
495 // Only optimise if the new cost is better
496 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
497 NewMulConst = CurDAG->getConstant(NewMulConstVal, SDLoc(N), MVT::i32);
498 unsigned OldCost = ConstantMaterializationCost(MulConstVal);
499 unsigned NewCost = ConstantMaterializationCost(NewMulConstVal);
500 return NewCost < OldCost;
501}
502
503void ARMDAGToDAGISel::replaceDAGValue(const SDValue &N, SDValue M) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000504 CurDAG->RepositionNode(N.getNode()->getIterator(), M.getNode());
Nirav Dave3264c1b2018-03-19 20:19:46 +0000505 ReplaceUses(N, M);
John Brawn056e6782015-09-14 15:19:41 +0000506}
507
Owen Andersonb595ed02011-07-21 18:54:16 +0000508bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000509 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000510 SDValue &Opc,
511 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000512 if (DisableShifterOp)
513 return false;
514
John Brawn056e6782015-09-14 15:19:41 +0000515 // If N is a multiply-by-constant and it's profitable to extract a shift and
516 // use it in a shifted operand do so.
517 if (N.getOpcode() == ISD::MUL) {
518 unsigned PowerOfTwo = 0;
519 SDValue NewMulConst;
520 if (canExtractShiftFromMul(N, 31, PowerOfTwo, NewMulConst)) {
Justin Bogner8752be72016-05-05 01:43:49 +0000521 HandleSDNode Handle(N);
Benjamin Kramer58dadd52017-04-20 18:29:14 +0000522 SDLoc Loc(N);
John Brawn056e6782015-09-14 15:19:41 +0000523 replaceDAGValue(N.getOperand(1), NewMulConst);
Justin Bogner8752be72016-05-05 01:43:49 +0000524 BaseReg = Handle.getValue();
Benjamin Kramer58dadd52017-04-20 18:29:14 +0000525 Opc = CurDAG->getTargetConstant(
526 ARM_AM::getSORegOpc(ARM_AM::lsl, PowerOfTwo), Loc, MVT::i32);
John Brawn056e6782015-09-14 15:19:41 +0000527 return true;
528 }
529 }
530
Evan Chenga20cde32011-07-20 23:34:39 +0000531 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000532
533 // Don't match base register only case. That is matched to a separate
534 // lower complexity pattern with explicit register operand.
535 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000536
Evan Chengb23b50d2009-06-29 07:51:04 +0000537 BaseReg = N.getOperand(0);
538 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000539 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
540 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000541 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000542 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000543 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000544 return true;
545}
546
Owen Andersonb595ed02011-07-21 18:54:16 +0000547bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
548 SDValue &BaseReg,
549 SDValue &ShReg,
550 SDValue &Opc,
551 bool CheckProfitability) {
552 if (DisableShifterOp)
553 return false;
554
555 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
556
557 // Don't match base register only case. That is matched to a separate
558 // lower complexity pattern with explicit register operand.
559 if (ShOpcVal == ARM_AM::no_shift) return false;
560
561 BaseReg = N.getOperand(0);
562 unsigned ShImmVal = 0;
563 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
564 if (RHS) return false;
565
566 ShReg = N.getOperand(1);
567 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
568 return false;
569 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000570 SDLoc(N), MVT::i32);
Owen Andersonb595ed02011-07-21 18:54:16 +0000571 return true;
572}
573
Tim Northover644a8192018-06-20 12:09:44 +0000574// Determine whether an ISD::OR's operands are suitable to turn the operation
575// into an addition, which often has more compact encodings.
576bool ARMDAGToDAGISel::SelectAddLikeOr(SDNode *Parent, SDValue N, SDValue &Out) {
577 assert(Parent->getOpcode() == ISD::OR && "unexpected parent");
578 Out = N;
579 return CurDAG->haveNoCommonBitsSet(N, Parent->getOperand(1));
580}
581
Owen Andersonb595ed02011-07-21 18:54:16 +0000582
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000583bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
584 SDValue &Base,
585 SDValue &OffImm) {
586 // Match simple R + imm12 operands.
587
588 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000589 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
590 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000591 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000592 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000593 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000594 Base = CurDAG->getTargetFrameIndex(
595 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000596 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000597 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000598 }
Owen Anderson6d557452011-03-18 19:46:58 +0000599
Chris Lattner46c01a32011-02-13 22:25:43 +0000600 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000601 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000602 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000603 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000604 Base = N.getOperand(0);
605 } else
606 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000607 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000608 return true;
609 }
610
611 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Renato Golin63e27982014-09-09 09:57:59 +0000612 int RHSC = (int)RHS->getSExtValue();
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000613 if (N.getOpcode() == ISD::SUB)
614 RHSC = -RHSC;
615
Renato Golin63e27982014-09-09 09:57:59 +0000616 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000617 Base = N.getOperand(0);
618 if (Base.getOpcode() == ISD::FrameIndex) {
619 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000620 Base = CurDAG->getTargetFrameIndex(
621 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000622 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000623 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000624 return true;
625 }
626 }
627
628 // Base only.
629 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000630 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000631 return true;
632}
633
634
635
636bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
637 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000638 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000639 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000640 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
641 // X * [3,5,9] -> X + X * [2,4,8] etc.
642 int RHSC = (int)RHS->getZExtValue();
643 if (RHSC & 1) {
644 RHSC = RHSC & ~1;
645 ARM_AM::AddrOpc AddSub = ARM_AM::add;
646 if (RHSC < 0) {
647 AddSub = ARM_AM::sub;
648 RHSC = - RHSC;
649 }
650 if (isPowerOf2_32(RHSC)) {
651 unsigned ShAmt = Log2_32(RHSC);
652 Base = Offset = N.getOperand(0);
653 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
654 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000655 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000656 return true;
657 }
658 }
659 }
660 }
661
Chris Lattner46c01a32011-02-13 22:25:43 +0000662 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
663 // ISD::OR that is equivalent to an ISD::ADD.
664 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000665 return false;
666
667 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000668 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000669 int RHSC;
670 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
671 -0x1000+1, 0x1000, RHSC)) // 12 bits.
672 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000673 }
674
675 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000676 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000677 ARM_AM::ShiftOpc ShOpcVal =
678 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000679 unsigned ShAmt = 0;
680
681 Base = N.getOperand(0);
682 Offset = N.getOperand(1);
683
684 if (ShOpcVal != ARM_AM::no_shift) {
685 // Check to see if the RHS of the shift is a constant, if not, we can't fold
686 // it.
687 if (ConstantSDNode *Sh =
688 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
689 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000690 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
691 Offset = N.getOperand(1).getOperand(0);
692 else {
693 ShAmt = 0;
694 ShOpcVal = ARM_AM::no_shift;
695 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000696 } else {
697 ShOpcVal = ARM_AM::no_shift;
698 }
699 }
700
701 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000702 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000703 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
704 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000705 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000706 if (ShOpcVal != ARM_AM::no_shift) {
707 // Check to see if the RHS of the shift is a constant, if not, we can't
708 // fold it.
709 if (ConstantSDNode *Sh =
710 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
711 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000712 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000713 Offset = N.getOperand(0).getOperand(0);
714 Base = N.getOperand(1);
715 } else {
716 ShAmt = 0;
717 ShOpcVal = ARM_AM::no_shift;
718 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000719 } else {
720 ShOpcVal = ARM_AM::no_shift;
721 }
722 }
723 }
724
John Brawn056e6782015-09-14 15:19:41 +0000725 // If Offset is a multiply-by-constant and it's profitable to extract a shift
726 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +0000727 if (Offset.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +0000728 unsigned PowerOfTwo = 0;
729 SDValue NewMulConst;
730 if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) {
Tim Northover4a01ffb2017-05-02 22:45:19 +0000731 HandleSDNode Handle(Offset);
John Brawn056e6782015-09-14 15:19:41 +0000732 replaceDAGValue(Offset.getOperand(1), NewMulConst);
Tim Northover4a01ffb2017-05-02 22:45:19 +0000733 Offset = Handle.getValue();
John Brawn056e6782015-09-14 15:19:41 +0000734 ShAmt = PowerOfTwo;
735 ShOpcVal = ARM_AM::lsl;
736 }
737 }
738
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000739 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000740 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000741 return true;
742}
743
Owen Anderson2aedba62011-07-26 20:54:26 +0000744bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000745 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000746 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000747 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
748 ? cast<LoadSDNode>(Op)->getAddressingMode()
749 : cast<StoreSDNode>(Op)->getAddressingMode();
750 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
751 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000752 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000753 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
754 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000755
756 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000757 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000758 unsigned ShAmt = 0;
759 if (ShOpcVal != ARM_AM::no_shift) {
760 // Check to see if the RHS of the shift is a constant, if not, we can't fold
761 // it.
762 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000763 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000764 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
765 Offset = N.getOperand(0);
766 else {
767 ShAmt = 0;
768 ShOpcVal = ARM_AM::no_shift;
769 }
Evan Cheng10043e22007-01-19 07:51:42 +0000770 } else {
771 ShOpcVal = ARM_AM::no_shift;
772 }
773 }
774
775 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000776 SDLoc(N), MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000777 return true;
778}
779
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000780bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
781 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000782 unsigned Opcode = Op->getOpcode();
783 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
784 ? cast<LoadSDNode>(Op)->getAddressingMode()
785 : cast<StoreSDNode>(Op)->getAddressingMode();
786 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
787 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000788 int Val;
789 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000790 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000791 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000792 Opc = CurDAG->getTargetConstant(Val, SDLoc(Op), MVT::i32);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000793 return true;
794 }
795
796 return false;
797}
798
799
Owen Anderson2aedba62011-07-26 20:54:26 +0000800bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
801 SDValue &Offset, SDValue &Opc) {
802 unsigned Opcode = Op->getOpcode();
803 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
804 ? cast<LoadSDNode>(Op)->getAddressingMode()
805 : cast<StoreSDNode>(Op)->getAddressingMode();
806 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
807 ? ARM_AM::add : ARM_AM::sub;
808 int Val;
809 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
810 Offset = CurDAG->getRegister(0, MVT::i32);
811 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
812 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000813 SDLoc(Op), MVT::i32);
Owen Anderson2aedba62011-07-26 20:54:26 +0000814 return true;
815 }
816
817 return false;
818}
819
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000820bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
821 Base = N;
822 return true;
823}
Evan Cheng10043e22007-01-19 07:51:42 +0000824
Chris Lattner0e023ea2010-09-21 20:31:19 +0000825bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000826 SDValue &Base, SDValue &Offset,
827 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000828 if (N.getOpcode() == ISD::SUB) {
829 // X - C is canonicalize to X + -C, no need to handle it here.
830 Base = N.getOperand(0);
831 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000832 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0), SDLoc(N),
833 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000834 return true;
835 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000836
Chris Lattner46c01a32011-02-13 22:25:43 +0000837 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000838 Base = N;
839 if (N.getOpcode() == ISD::FrameIndex) {
840 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000841 Base = CurDAG->getTargetFrameIndex(
842 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +0000843 }
Owen Anderson9f944592009-08-11 20:47:22 +0000844 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000845 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
846 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000847 return true;
848 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000849
Evan Cheng10043e22007-01-19 07:51:42 +0000850 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000851 int RHSC;
852 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
853 -256 + 1, 256, RHSC)) { // 8 bits.
854 Base = N.getOperand(0);
855 if (Base.getOpcode() == ISD::FrameIndex) {
856 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000857 Base = CurDAG->getTargetFrameIndex(
858 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +0000859 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000860 Offset = CurDAG->getRegister(0, MVT::i32);
861
862 ARM_AM::AddrOpc AddSub = ARM_AM::add;
863 if (RHSC < 0) {
864 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000865 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000866 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000867 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC), SDLoc(N),
868 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000869 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000870 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000871
Evan Cheng10043e22007-01-19 07:51:42 +0000872 Base = N.getOperand(0);
873 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000874 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
875 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000876 return true;
877}
878
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000879bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000880 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000881 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000882 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
883 ? cast<LoadSDNode>(Op)->getAddressingMode()
884 : cast<StoreSDNode>(Op)->getAddressingMode();
885 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
886 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000887 int Val;
888 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
889 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000890 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), SDLoc(Op),
891 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000892 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000893 }
894
895 Offset = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000896 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), SDLoc(Op),
897 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000898 return true;
899}
900
Sjoerd Meijer011de9c2018-01-26 09:26:40 +0000901bool ARMDAGToDAGISel::IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offset,
902 int Lwb, int Upb, bool FP16) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000903 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000904 Base = N;
905 if (N.getOpcode() == ISD::FrameIndex) {
906 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000907 Base = CurDAG->getTargetFrameIndex(
908 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +0000909 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000910 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000911 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000912 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000913 Base = N.getOperand(0);
914 }
915 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000916 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000917 return true;
918 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000919
Evan Cheng10043e22007-01-19 07:51:42 +0000920 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000921 int RHSC;
Sjoerd Meijer011de9c2018-01-26 09:26:40 +0000922 const int Scale = FP16 ? 2 : 4;
923
924 if (isScaledConstantInRange(N.getOperand(1), Scale, Lwb, Upb, RHSC)) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000925 Base = N.getOperand(0);
926 if (Base.getOpcode() == ISD::FrameIndex) {
927 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000928 Base = CurDAG->getTargetFrameIndex(
929 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +0000930 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000931
932 ARM_AM::AddrOpc AddSub = ARM_AM::add;
933 if (RHSC < 0) {
934 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000935 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000936 }
Sjoerd Meijer011de9c2018-01-26 09:26:40 +0000937
938 if (FP16)
939 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5FP16Opc(AddSub, RHSC),
940 SDLoc(N), MVT::i32);
941 else
942 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
943 SDLoc(N), MVT::i32);
944
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000945 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000946 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000947
Evan Cheng10043e22007-01-19 07:51:42 +0000948 Base = N;
Sjoerd Meijer011de9c2018-01-26 09:26:40 +0000949
950 if (FP16)
951 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5FP16Opc(ARM_AM::add, 0),
952 SDLoc(N), MVT::i32);
953 else
954 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
955 SDLoc(N), MVT::i32);
956
Evan Cheng10043e22007-01-19 07:51:42 +0000957 return true;
958}
959
Sjoerd Meijer011de9c2018-01-26 09:26:40 +0000960bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
961 SDValue &Base, SDValue &Offset) {
962 int Lwb = -256 + 1;
963 int Upb = 256;
964 return IsAddressingMode5(N, Base, Offset, Lwb, Upb, /*FP16=*/ false);
965}
966
967bool ARMDAGToDAGISel::SelectAddrMode5FP16(SDValue N,
968 SDValue &Base, SDValue &Offset) {
969 int Lwb = -512 + 1;
970 int Upb = 512;
971 return IsAddressingMode5(N, Base, Offset, Lwb, Upb, /*FP16=*/ true);
972}
973
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000974bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
975 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +0000976 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000977
978 unsigned Alignment = 0;
Ahmed Bougachadb141ac2015-02-19 23:52:41 +0000979
980 MemSDNode *MemN = cast<MemSDNode>(Parent);
981
982 if (isa<LSBaseSDNode>(MemN) ||
983 ((MemN->getOpcode() == ARMISD::VST1_UPD ||
984 MemN->getOpcode() == ARMISD::VLD1_UPD) &&
985 MemN->getConstantOperandVal(MemN->getNumOperands() - 1) == 1)) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000986 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
987 // The maximum alignment is equal to the memory size being referenced.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +0000988 unsigned MMOAlign = MemN->getAlignment();
989 unsigned MemSize = MemN->getMemoryVT().getSizeInBits() / 8;
990 if (MMOAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000991 Alignment = MemSize;
992 } else {
993 // All other uses of addrmode6 are for intrinsics. For now just record
994 // the raw alignment value; it will be refined later based on the legal
995 // alignment operands for the intrinsic.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +0000996 Alignment = MemN->getAlignment();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000997 }
998
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000999 Align = CurDAG->getTargetConstant(Alignment, SDLoc(N), MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001000 return true;
1001}
1002
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001003bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1004 SDValue &Offset) {
1005 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1006 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1007 if (AM != ISD::POST_INC)
1008 return false;
1009 Offset = N;
1010 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1011 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1012 Offset = CurDAG->getRegister(0, MVT::i32);
1013 }
1014 return true;
1015}
1016
Chris Lattner0e023ea2010-09-21 20:31:19 +00001017bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001018 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001019 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1020 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001021 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001022 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001023 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001024 return true;
1025 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001026
Evan Cheng10043e22007-01-19 07:51:42 +00001027 return false;
1028}
1029
Bill Wendling092a7bd2010-12-14 03:36:38 +00001030
1031//===----------------------------------------------------------------------===//
1032// Thumb Addressing Modes
1033//===----------------------------------------------------------------------===//
1034
Chris Lattner0e023ea2010-09-21 20:31:19 +00001035bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001036 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001037 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001038 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001039 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001040 return false;
1041
1042 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001043 return true;
1044 }
1045
Evan Cheng10043e22007-01-19 07:51:42 +00001046 Base = N.getOperand(0);
1047 Offset = N.getOperand(1);
1048 return true;
1049}
1050
Evan Cheng139edae2007-01-24 02:21:22 +00001051bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001052ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1053 SDValue &Base, SDValue &OffImm) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001054 if (!CurDAG->isBaseWithConstantOffset(N)) {
John Brawn68acdcb2015-08-13 10:48:22 +00001055 if (N.getOpcode() == ISD::ADD) {
1056 return false; // We want to select register offset instead
1057 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001058 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001059 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
James Molloyb7de4972016-10-05 14:52:13 +00001060 N.getOperand(0).getOpcode() != ISD::TargetConstantPool &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001061 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001062 Base = N.getOperand(0);
1063 } else {
1064 Base = N;
1065 }
1066
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001067 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001068 return true;
1069 }
1070
Evan Cheng10043e22007-01-19 07:51:42 +00001071 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001072 int RHSC;
1073 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1074 Base = N.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001075 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001076 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001077 }
1078
John Brawn68acdcb2015-08-13 10:48:22 +00001079 // Offset is too large, so use register offset instead.
1080 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001081}
1082
Bill Wendling092a7bd2010-12-14 03:36:38 +00001083bool
1084ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1085 SDValue &OffImm) {
1086 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001087}
1088
Bill Wendling092a7bd2010-12-14 03:36:38 +00001089bool
1090ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1091 SDValue &OffImm) {
1092 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001093}
1094
Bill Wendling092a7bd2010-12-14 03:36:38 +00001095bool
1096ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1097 SDValue &OffImm) {
1098 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001099}
1100
Chris Lattner0e023ea2010-09-21 20:31:19 +00001101bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1102 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001103 if (N.getOpcode() == ISD::FrameIndex) {
1104 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001105 // Only multiples of 4 are allowed for the offset, so the frame object
1106 // alignment must be at least 4.
Matthias Braun941a7052016-07-28 18:40:00 +00001107 MachineFrameInfo &MFI = MF->getFrameInfo();
1108 if (MFI.getObjectAlignment(FI) < 4)
1109 MFI.setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001110 Base = CurDAG->getTargetFrameIndex(
1111 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001112 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001113 return true;
1114 }
Evan Cheng139edae2007-01-24 02:21:22 +00001115
Chris Lattner46c01a32011-02-13 22:25:43 +00001116 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001117 return false;
1118
1119 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001120 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1121 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001122 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001123 int RHSC;
1124 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1125 Base = N.getOperand(0);
1126 if (Base.getOpcode() == ISD::FrameIndex) {
1127 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001128 // For LHS+RHS to result in an offset that's a multiple of 4 the object
1129 // indexed by the LHS must be 4-byte aligned.
Matthias Braun941a7052016-07-28 18:40:00 +00001130 MachineFrameInfo &MFI = MF->getFrameInfo();
1131 if (MFI.getObjectAlignment(FI) < 4)
1132 MFI.setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001133 Base = CurDAG->getTargetFrameIndex(
1134 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng139edae2007-01-24 02:21:22 +00001135 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001136 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001137 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001138 }
1139 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001140
Evan Cheng10043e22007-01-19 07:51:42 +00001141 return false;
1142}
1143
Bill Wendling092a7bd2010-12-14 03:36:38 +00001144
1145//===----------------------------------------------------------------------===//
1146// Thumb 2 Addressing Modes
1147//===----------------------------------------------------------------------===//
1148
1149
Chris Lattner0e023ea2010-09-21 20:31:19 +00001150bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001151 SDValue &Base, SDValue &OffImm) {
1152 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001153
Evan Cheng36064672009-08-11 08:52:18 +00001154 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001155 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1156 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001157 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001158 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001159 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001160 Base = CurDAG->getTargetFrameIndex(
1161 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001162 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001163 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001164 }
Owen Anderson6d557452011-03-18 19:46:58 +00001165
Chris Lattner46c01a32011-02-13 22:25:43 +00001166 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001167 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001168 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001169 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng36064672009-08-11 08:52:18 +00001170 Base = N.getOperand(0);
1171 if (Base.getOpcode() == ISD::TargetConstantPool)
1172 return false; // We want to select t2LDRpci instead.
1173 } else
1174 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001175 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001176 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001177 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001178
1179 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001180 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001181 // Let t2LDRi8 handle (R - imm8).
1182 return false;
1183
Evan Chengb23b50d2009-06-29 07:51:04 +00001184 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001185 if (N.getOpcode() == ISD::SUB)
1186 RHSC = -RHSC;
1187
1188 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001189 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001190 if (Base.getOpcode() == ISD::FrameIndex) {
1191 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001192 Base = CurDAG->getTargetFrameIndex(
1193 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin79c079b2009-07-30 18:56:48 +00001194 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001195 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001196 return true;
1197 }
1198 }
1199
Evan Cheng36064672009-08-11 08:52:18 +00001200 // Base only.
1201 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001202 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001203 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001204}
1205
Chris Lattner0e023ea2010-09-21 20:31:19 +00001206bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001207 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001208 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001209 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1210 !CurDAG->isBaseWithConstantOffset(N))
1211 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001212
Chris Lattner46c01a32011-02-13 22:25:43 +00001213 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1214 int RHSC = (int)RHS->getSExtValue();
1215 if (N.getOpcode() == ISD::SUB)
1216 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001217
Chris Lattner46c01a32011-02-13 22:25:43 +00001218 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1219 Base = N.getOperand(0);
1220 if (Base.getOpcode() == ISD::FrameIndex) {
1221 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001222 Base = CurDAG->getTargetFrameIndex(
1223 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Chengb23b50d2009-06-29 07:51:04 +00001224 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001225 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Chris Lattner46c01a32011-02-13 22:25:43 +00001226 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001227 }
1228 }
1229
1230 return false;
1231}
1232
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001233bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001234 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001235 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001236 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1237 ? cast<LoadSDNode>(Op)->getAddressingMode()
1238 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001239 int RHSC;
1240 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1241 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001242 ? CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32)
1243 : CurDAG->getTargetConstant(-RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001244 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001245 }
1246
1247 return false;
1248}
1249
Chris Lattner0e023ea2010-09-21 20:31:19 +00001250bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001251 SDValue &Base,
1252 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001253 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001254 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001255 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001256
Evan Cheng36064672009-08-11 08:52:18 +00001257 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1258 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1259 int RHSC = (int)RHS->getZExtValue();
1260 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1261 return false;
1262 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001263 return false;
1264 }
1265
Evan Chengb23b50d2009-06-29 07:51:04 +00001266 // Look for (R + R) or (R + (R << [1,2,3])).
1267 unsigned ShAmt = 0;
1268 Base = N.getOperand(0);
1269 OffReg = N.getOperand(1);
1270
1271 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001272 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001273 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001274 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001275 if (ShOpcVal == ARM_AM::lsl)
1276 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001277 }
1278
Evan Chengb23b50d2009-06-29 07:51:04 +00001279 if (ShOpcVal == ARM_AM::lsl) {
1280 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1281 // it.
1282 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1283 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001284 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1285 OffReg = OffReg.getOperand(0);
1286 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001287 ShAmt = 0;
Evan Cheng59bbc542010-10-27 23:41:30 +00001288 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001289 }
David Goodwinf3912052009-07-15 15:50:19 +00001290 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001291
John Brawn056e6782015-09-14 15:19:41 +00001292 // If OffReg is a multiply-by-constant and it's profitable to extract a shift
1293 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +00001294 if (OffReg.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +00001295 unsigned PowerOfTwo = 0;
1296 SDValue NewMulConst;
1297 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
Tim Northover4a01ffb2017-05-02 22:45:19 +00001298 HandleSDNode Handle(OffReg);
John Brawn056e6782015-09-14 15:19:41 +00001299 replaceDAGValue(OffReg.getOperand(1), NewMulConst);
Tim Northover4a01ffb2017-05-02 22:45:19 +00001300 OffReg = Handle.getValue();
John Brawn056e6782015-09-14 15:19:41 +00001301 ShAmt = PowerOfTwo;
1302 }
1303 }
1304
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001305 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001306
1307 return true;
1308}
1309
Tim Northovera7ecd242013-07-16 09:46:55 +00001310bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1311 SDValue &OffImm) {
Alp Tokercb402912014-01-24 17:20:08 +00001312 // This *must* succeed since it's used for the irreplaceable ldrex and strex
Tim Northovera7ecd242013-07-16 09:46:55 +00001313 // instructions.
1314 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001315 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001316
1317 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1318 return true;
1319
1320 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1321 if (!RHS)
1322 return true;
1323
1324 uint32_t RHSC = (int)RHS->getZExtValue();
1325 if (RHSC > 1020 || RHSC % 4 != 0)
1326 return true;
1327
1328 Base = N.getOperand(0);
1329 if (Base.getOpcode() == ISD::FrameIndex) {
1330 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001331 Base = CurDAG->getTargetFrameIndex(
1332 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Tim Northovera7ecd242013-07-16 09:46:55 +00001333 }
1334
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001335 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001336 return true;
1337}
1338
Evan Chengb23b50d2009-06-29 07:51:04 +00001339//===--------------------------------------------------------------------===//
1340
Evan Cheng7e90b112007-07-05 07:15:27 +00001341/// getAL - Returns a ARMCC::AL immediate node.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001342static inline SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001343 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001344}
1345
Tim Northovereaee28b2016-09-19 09:11:09 +00001346void ARMDAGToDAGISel::transferMemOperands(SDNode *N, SDNode *Result) {
1347 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1348 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
1349 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
1350}
1351
Justin Bogner45571362016-05-12 00:31:09 +00001352bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001353 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001354 ISD::MemIndexedMode AM = LD->getAddressingMode();
1355 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001356 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001357
Owen Anderson53aa7a92009-08-10 22:56:29 +00001358 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001359 SDValue Offset, AMOpc;
1360 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1361 unsigned Opcode = 0;
1362 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001363 if (LoadedVT == MVT::i32 && isPre &&
1364 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1365 Opcode = ARM::LDR_PRE_IMM;
1366 Match = true;
1367 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001368 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001369 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001370 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001371 } else if (LoadedVT == MVT::i32 &&
1372 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001373 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001374 Match = true;
1375
Owen Anderson9f944592009-08-11 20:47:22 +00001376 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001377 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001378 Match = true;
1379 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1380 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1381 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001382 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001383 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001384 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001385 Match = true;
1386 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1387 }
1388 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001389 if (isPre &&
1390 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001391 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001392 Opcode = ARM::LDRB_PRE_IMM;
1393 } else if (!isPre &&
1394 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1395 Match = true;
1396 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001397 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1398 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001399 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001400 }
1401 }
1402 }
1403
1404 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001405 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1406 SDValue Chain = LD->getChain();
1407 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001408 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001409 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001410 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1411 MVT::Other, Ops);
1412 transferMemOperands(N, New);
1413 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001414 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001415 } else {
1416 SDValue Chain = LD->getChain();
1417 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001418 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001419 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001420 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1421 MVT::Other, Ops);
1422 transferMemOperands(N, New);
1423 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001424 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001425 }
Evan Chengd9c55362009-07-02 01:23:32 +00001426 }
1427
Justin Bogner45571362016-05-12 00:31:09 +00001428 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001429}
1430
James Molloyb3326df2016-07-15 08:03:56 +00001431bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *N) {
1432 LoadSDNode *LD = cast<LoadSDNode>(N);
1433 EVT LoadedVT = LD->getMemoryVT();
1434 ISD::MemIndexedMode AM = LD->getAddressingMode();
Chandler Carruth5589aa62016-11-03 17:42:02 +00001435 if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD ||
1436 LoadedVT.getSimpleVT().SimpleTy != MVT::i32)
James Molloyb3326df2016-07-15 08:03:56 +00001437 return false;
1438
1439 auto *COffs = dyn_cast<ConstantSDNode>(LD->getOffset());
1440 if (!COffs || COffs->getZExtValue() != 4)
1441 return false;
1442
1443 // A T1 post-indexed load is just a single register LDM: LDM r0!, {r1}.
1444 // The encoding of LDM is not how the rest of ISel expects a post-inc load to
1445 // look however, so we use a pseudo here and switch it for a tLDMIA_UPD after
1446 // ISel.
1447 SDValue Chain = LD->getChain();
1448 SDValue Base = LD->getBasePtr();
1449 SDValue Ops[]= { Base, getAL(CurDAG, SDLoc(N)),
1450 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001451 SDNode *New = CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(N), MVT::i32,
1452 MVT::i32, MVT::Other, Ops);
1453 transferMemOperands(N, New);
1454 ReplaceNode(N, New);
James Molloyb3326df2016-07-15 08:03:56 +00001455 return true;
1456}
1457
Justin Bogner45571362016-05-12 00:31:09 +00001458bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001459 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001460 ISD::MemIndexedMode AM = LD->getAddressingMode();
1461 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001462 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001463
Owen Anderson53aa7a92009-08-10 22:56:29 +00001464 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001465 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001466 SDValue Offset;
1467 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1468 unsigned Opcode = 0;
1469 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001470 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001471 switch (LoadedVT.getSimpleVT().SimpleTy) {
1472 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001473 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1474 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001475 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001476 if (isSExtLd)
1477 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1478 else
1479 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001480 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001481 case MVT::i8:
1482 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001483 if (isSExtLd)
1484 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1485 else
1486 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001487 break;
1488 default:
Justin Bogner45571362016-05-12 00:31:09 +00001489 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001490 }
1491 Match = true;
1492 }
1493
1494 if (Match) {
1495 SDValue Chain = LD->getChain();
1496 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001497 SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)),
Owen Anderson9f944592009-08-11 20:47:22 +00001498 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001499 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1500 MVT::Other, Ops);
1501 transferMemOperands(N, New);
1502 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001503 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001504 }
1505
Justin Bogner45571362016-05-12 00:31:09 +00001506 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001507}
1508
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001509/// Form a GPRPair pseudo register from a pair of GPR regs.
Weiming Zhao8f56f882012-11-16 21:55:34 +00001510SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001511 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001512 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001513 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1514 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1515 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001516 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001517 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001518}
1519
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001520/// Form a D register from a pair of S registers.
Weiming Zhao95782222012-11-17 00:23:35 +00001521SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001522 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001523 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001524 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1525 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1526 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001527 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001528 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001529}
1530
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001531/// Form a quad register from a pair of D registers.
Weiming Zhao95782222012-11-17 00:23:35 +00001532SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001533 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001534 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1535 MVT::i32);
1536 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1537 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001538 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001539 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001540}
1541
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001542/// Form 4 consecutive D registers from a pair of Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +00001543SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001544 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001545 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1546 MVT::i32);
1547 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1548 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001549 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001550 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001551}
1552
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001553/// Form 4 consecutive S registers.
Weiming Zhao95782222012-11-17 00:23:35 +00001554SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001555 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001556 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001557 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001558 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1559 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1560 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1561 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1562 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001563 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1564 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001565 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001566}
1567
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001568/// Form 4 consecutive D registers.
Weiming Zhao95782222012-11-17 00:23:35 +00001569SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001570 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001571 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001572 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1573 MVT::i32);
1574 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1575 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1576 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1577 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001578 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1579 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001580 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001581}
1582
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001583/// Form 4 consecutive Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +00001584SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001585 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001586 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001587 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1588 MVT::i32);
1589 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1590 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1591 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1592 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001593 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1594 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001595 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001596}
1597
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001598/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1599/// of a NEON VLD or VST instruction. The supported values depend on the
1600/// number of registers being loaded.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001601SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, const SDLoc &dl,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001602 unsigned NumVecs, bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001603 unsigned NumRegs = NumVecs;
1604 if (!is64BitVector && NumVecs < 3)
1605 NumRegs *= 2;
1606
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001607 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001608 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001609 Alignment = 32;
1610 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1611 Alignment = 16;
1612 else if (Alignment >= 8)
1613 Alignment = 8;
1614 else
1615 Alignment = 0;
1616
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001617 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001618}
1619
Jiangning Liu4df23632014-01-16 09:16:13 +00001620static bool isVLDfixed(unsigned Opc)
1621{
1622 switch (Opc) {
1623 default: return false;
1624 case ARM::VLD1d8wb_fixed : return true;
1625 case ARM::VLD1d16wb_fixed : return true;
1626 case ARM::VLD1d64Qwb_fixed : return true;
1627 case ARM::VLD1d32wb_fixed : return true;
1628 case ARM::VLD1d64wb_fixed : return true;
1629 case ARM::VLD1d64TPseudoWB_fixed : return true;
1630 case ARM::VLD1d64QPseudoWB_fixed : return true;
1631 case ARM::VLD1q8wb_fixed : return true;
1632 case ARM::VLD1q16wb_fixed : return true;
1633 case ARM::VLD1q32wb_fixed : return true;
1634 case ARM::VLD1q64wb_fixed : return true;
Eli Friedmanf624ec22016-12-16 18:44:08 +00001635 case ARM::VLD1DUPd8wb_fixed : return true;
1636 case ARM::VLD1DUPd16wb_fixed : return true;
1637 case ARM::VLD1DUPd32wb_fixed : return true;
1638 case ARM::VLD1DUPq8wb_fixed : return true;
1639 case ARM::VLD1DUPq16wb_fixed : return true;
1640 case ARM::VLD1DUPq32wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001641 case ARM::VLD2d8wb_fixed : return true;
1642 case ARM::VLD2d16wb_fixed : return true;
1643 case ARM::VLD2d32wb_fixed : return true;
1644 case ARM::VLD2q8PseudoWB_fixed : return true;
1645 case ARM::VLD2q16PseudoWB_fixed : return true;
1646 case ARM::VLD2q32PseudoWB_fixed : return true;
1647 case ARM::VLD2DUPd8wb_fixed : return true;
1648 case ARM::VLD2DUPd16wb_fixed : return true;
1649 case ARM::VLD2DUPd32wb_fixed : return true;
1650 }
1651}
1652
1653static bool isVSTfixed(unsigned Opc)
1654{
1655 switch (Opc) {
1656 default: return false;
1657 case ARM::VST1d8wb_fixed : return true;
1658 case ARM::VST1d16wb_fixed : return true;
1659 case ARM::VST1d32wb_fixed : return true;
1660 case ARM::VST1d64wb_fixed : return true;
Jim Grosbach1a597112014-04-03 23:43:18 +00001661 case ARM::VST1q8wb_fixed : return true;
1662 case ARM::VST1q16wb_fixed : return true;
1663 case ARM::VST1q32wb_fixed : return true;
1664 case ARM::VST1q64wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001665 case ARM::VST1d64TPseudoWB_fixed : return true;
1666 case ARM::VST1d64QPseudoWB_fixed : return true;
1667 case ARM::VST2d8wb_fixed : return true;
1668 case ARM::VST2d16wb_fixed : return true;
1669 case ARM::VST2d32wb_fixed : return true;
1670 case ARM::VST2q8PseudoWB_fixed : return true;
1671 case ARM::VST2q16PseudoWB_fixed : return true;
1672 case ARM::VST2q32PseudoWB_fixed : return true;
1673 }
1674}
1675
Jim Grosbach2098cb12011-10-24 21:45:13 +00001676// Get the register stride update opcode of a VLD/VST instruction that
1677// is otherwise equivalent to the given fixed stride updating instruction.
1678static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
Jiangning Liu4df23632014-01-16 09:16:13 +00001679 assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1680 && "Incorrect fixed stride updating instruction.");
Jim Grosbach2098cb12011-10-24 21:45:13 +00001681 switch (Opc) {
1682 default: break;
1683 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1684 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1685 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1686 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1687 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1688 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1689 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1690 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jiangning Liu4df23632014-01-16 09:16:13 +00001691 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1692 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1693 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1694 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
Eli Friedmanf624ec22016-12-16 18:44:08 +00001695 case ARM::VLD1DUPd8wb_fixed : return ARM::VLD1DUPd8wb_register;
1696 case ARM::VLD1DUPd16wb_fixed : return ARM::VLD1DUPd16wb_register;
1697 case ARM::VLD1DUPd32wb_fixed : return ARM::VLD1DUPd32wb_register;
1698 case ARM::VLD1DUPq8wb_fixed : return ARM::VLD1DUPq8wb_register;
1699 case ARM::VLD1DUPq16wb_fixed : return ARM::VLD1DUPq16wb_register;
1700 case ARM::VLD1DUPq32wb_fixed : return ARM::VLD1DUPq32wb_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001701
1702 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1703 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1704 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1705 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1706 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1707 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1708 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1709 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001710 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001711 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001712
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001713 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1714 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1715 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001716 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1717 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1718 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1719
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001720 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1721 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1722 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001723 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1724 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1725 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001726
Jim Grosbach13a292c2012-03-06 22:01:44 +00001727 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1728 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1729 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001730 }
1731 return Opc; // If not one we handle, return it unchanged.
1732}
1733
Tim Northover8b1240b2017-04-20 19:54:02 +00001734/// Returns true if the given increment is a Constant known to be equal to the
1735/// access size performed by a NEON load/store. This means the "[rN]!" form can
1736/// be used.
1737static bool isPerfectIncrement(SDValue Inc, EVT VecTy, unsigned NumVecs) {
1738 auto C = dyn_cast<ConstantSDNode>(Inc);
1739 return C && C->getZExtValue() == VecTy.getSizeInBits() / 8 * NumVecs;
1740}
1741
Justin Bogner45571362016-05-12 00:31:09 +00001742void ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
1743 const uint16_t *DOpcodes,
1744 const uint16_t *QOpcodes0,
1745 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001746 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001747 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001748
Bob Wilsonae08a732010-03-20 22:13:40 +00001749 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001750 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1751 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001752 return;
Bob Wilson12b47992009-10-14 17:28:52 +00001753
1754 SDValue Chain = N->getOperand(0);
1755 EVT VT = N->getValueType(0);
1756 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001757 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001758
Bob Wilson12b47992009-10-14 17:28:52 +00001759 unsigned OpcodeIndex;
1760 switch (VT.getSimpleVT().SimpleTy) {
1761 default: llvm_unreachable("unhandled vld type");
1762 // Double-register operations:
1763 case MVT::v8i8: OpcodeIndex = 0; break;
1764 case MVT::v4i16: OpcodeIndex = 1; break;
1765 case MVT::v2f32:
1766 case MVT::v2i32: OpcodeIndex = 2; break;
1767 case MVT::v1i64: OpcodeIndex = 3; break;
1768 // Quad-register operations:
1769 case MVT::v16i8: OpcodeIndex = 0; break;
1770 case MVT::v8i16: OpcodeIndex = 1; break;
1771 case MVT::v4f32:
1772 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001773 case MVT::v2f64:
Ivan A. Kosarev60a991e2018-06-02 16:40:03 +00001774 case MVT::v2i64: OpcodeIndex = 3; break;
Bob Wilson12b47992009-10-14 17:28:52 +00001775 }
1776
Bob Wilson35fafca2010-09-03 18:16:02 +00001777 EVT ResTy;
1778 if (NumVecs == 1)
1779 ResTy = VT;
1780 else {
1781 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1782 if (!is64BitVector)
1783 ResTyElts *= 2;
1784 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1785 }
Bob Wilson06fce872011-02-07 17:43:21 +00001786 std::vector<EVT> ResTys;
1787 ResTys.push_back(ResTy);
1788 if (isUpdating)
1789 ResTys.push_back(MVT::i32);
1790 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001791
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001792 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001793 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001794 SDNode *VLd;
1795 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001796
Bob Wilson06fce872011-02-07 17:43:21 +00001797 // Double registers and VLD1/VLD2 quad registers are directly supported.
1798 if (is64BitVector || NumVecs <= 2) {
1799 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1800 QOpcodes0[OpcodeIndex]);
1801 Ops.push_back(MemAddr);
1802 Ops.push_back(Align);
1803 if (isUpdating) {
1804 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Tim Northover8b1240b2017-04-20 19:54:02 +00001805 bool IsImmUpdate = isPerfectIncrement(Inc, VT, NumVecs);
Florian Hahn9deef202018-03-02 13:02:55 +00001806 if (!IsImmUpdate) {
1807 // We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
1808 // check for the opcode rather than the number of vector elements.
1809 if (isVLDfixed(Opc))
1810 Opc = getVLDSTRegisterUpdateOpcode(Opc);
1811 Ops.push_back(Inc);
1812 // VLD1/VLD2 fixed increment does not need Reg0 so only include it in
1813 // the operands if not such an opcode.
1814 } else if (!isVLDfixed(Opc))
1815 Ops.push_back(Reg0);
Evan Cheng630063a2010-05-10 21:26:24 +00001816 }
Bob Wilson06fce872011-02-07 17:43:21 +00001817 Ops.push_back(Pred);
1818 Ops.push_back(Reg0);
1819 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001820 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001821
Bob Wilson12b47992009-10-14 17:28:52 +00001822 } else {
1823 // Otherwise, quad registers are loaded with two separate instructions,
1824 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001825 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001826
Bob Wilson06fce872011-02-07 17:43:21 +00001827 // Load the even subregs. This is always an updating load, so that it
1828 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001829 SDValue ImplDef =
1830 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1831 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001832 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001833 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001834 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001835
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001836 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001837 Ops.push_back(SDValue(VLdA, 1));
1838 Ops.push_back(Align);
1839 if (isUpdating) {
1840 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1841 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1842 "only constant post-increment update allowed for VLD3/4");
1843 (void)Inc;
1844 Ops.push_back(Reg0);
1845 }
1846 Ops.push_back(SDValue(VLdA, 0));
1847 Ops.push_back(Pred);
1848 Ops.push_back(Reg0);
1849 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001850 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001851 }
Bob Wilson12b47992009-10-14 17:28:52 +00001852
Evan Cheng40791332011-04-19 00:04:03 +00001853 // Transfer memoperands.
1854 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1855 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1856 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1857
Justin Bogner45571362016-05-12 00:31:09 +00001858 if (NumVecs == 1) {
1859 ReplaceNode(N, VLd);
1860 return;
1861 }
Bob Wilson06fce872011-02-07 17:43:21 +00001862
1863 // Extract out the subregisters.
1864 SDValue SuperReg = SDValue(VLd, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00001865 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
1866 ARM::qsub_3 == ARM::qsub_0 + 3,
1867 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00001868 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1869 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1870 ReplaceUses(SDValue(N, Vec),
1871 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1872 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1873 if (isUpdating)
1874 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00001875 CurDAG->RemoveDeadNode(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001876}
1877
Justin Bogner45571362016-05-12 00:31:09 +00001878void ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
1879 const uint16_t *DOpcodes,
1880 const uint16_t *QOpcodes0,
1881 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001882 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001883 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001884
Bob Wilsonae08a732010-03-20 22:13:40 +00001885 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001886 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1887 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1888 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001889 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001890
Evan Cheng40791332011-04-19 00:04:03 +00001891 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1892 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1893
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001894 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00001895 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001896 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001897 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001898
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001899 unsigned OpcodeIndex;
1900 switch (VT.getSimpleVT().SimpleTy) {
1901 default: llvm_unreachable("unhandled vst type");
1902 // Double-register operations:
1903 case MVT::v8i8: OpcodeIndex = 0; break;
Sjoerd Meijerd16037d2018-03-19 13:35:25 +00001904 case MVT::v4f16:
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001905 case MVT::v4i16: OpcodeIndex = 1; break;
1906 case MVT::v2f32:
1907 case MVT::v2i32: OpcodeIndex = 2; break;
1908 case MVT::v1i64: OpcodeIndex = 3; break;
1909 // Quad-register operations:
1910 case MVT::v16i8: OpcodeIndex = 0; break;
Sjoerd Meijerd16037d2018-03-19 13:35:25 +00001911 case MVT::v8f16:
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001912 case MVT::v8i16: OpcodeIndex = 1; break;
1913 case MVT::v4f32:
1914 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001915 case MVT::v2f64:
Ivan A. Kosarev847daa12018-06-10 09:27:27 +00001916 case MVT::v2i64: OpcodeIndex = 3; break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001917 }
1918
Bob Wilson06fce872011-02-07 17:43:21 +00001919 std::vector<EVT> ResTys;
1920 if (isUpdating)
1921 ResTys.push_back(MVT::i32);
1922 ResTys.push_back(MVT::Other);
1923
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001924 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001925 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001926 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00001927
Bob Wilson06fce872011-02-07 17:43:21 +00001928 // Double registers and VST1/VST2 quad registers are directly supported.
1929 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00001930 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00001931 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00001932 SrcReg = N->getOperand(Vec0Idx);
1933 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00001934 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00001935 SDValue V0 = N->getOperand(Vec0Idx + 0);
1936 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00001937 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00001938 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001939 else {
Bob Wilson06fce872011-02-07 17:43:21 +00001940 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00001941 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00001942 // an undef.
1943 SDValue V3 = (NumVecs == 3)
1944 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00001945 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00001946 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001947 }
Bob Wilson950882b2010-08-28 05:12:57 +00001948 } else {
1949 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00001950 SDValue Q0 = N->getOperand(Vec0Idx);
1951 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00001952 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001953 }
Bob Wilson06fce872011-02-07 17:43:21 +00001954
1955 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1956 QOpcodes0[OpcodeIndex]);
1957 Ops.push_back(MemAddr);
1958 Ops.push_back(Align);
1959 if (isUpdating) {
1960 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Tim Northover8b1240b2017-04-20 19:54:02 +00001961 bool IsImmUpdate = isPerfectIncrement(Inc, VT, NumVecs);
Florian Hahn9deef202018-03-02 13:02:55 +00001962 if (!IsImmUpdate) {
1963 // We use a VST1 for v1i64 even if the pseudo says VST2/3/4, so
1964 // check for the opcode rather than the number of vector elements.
1965 if (isVSTfixed(Opc))
1966 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001967 Ops.push_back(Inc);
Florian Hahn9deef202018-03-02 13:02:55 +00001968 }
1969 // VST1/VST2 fixed increment does not need Reg0 so only include it in
1970 // the operands if not such an opcode.
1971 else if (!isVSTfixed(Opc))
Jiangning Liu4df23632014-01-16 09:16:13 +00001972 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00001973 }
1974 Ops.push_back(SrcReg);
1975 Ops.push_back(Pred);
1976 Ops.push_back(Reg0);
1977 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001978 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00001979
1980 // Transfer memoperands.
1981 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
1982
Justin Bogner45571362016-05-12 00:31:09 +00001983 ReplaceNode(N, VSt);
1984 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001985 }
1986
1987 // Otherwise, quad registers are stored with two separate instructions,
1988 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00001989
Bob Wilson01ac8f92010-06-16 21:34:01 +00001990 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00001991 SDValue V0 = N->getOperand(Vec0Idx + 0);
1992 SDValue V1 = N->getOperand(Vec0Idx + 1);
1993 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00001994 SDValue V3 = (NumVecs == 3)
1995 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00001996 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00001997 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00001998
Bob Wilson06fce872011-02-07 17:43:21 +00001999 // Store the even D registers. This is always an updating store, so that it
2000 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00002001 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2002 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2003 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00002004 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00002005 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002006 Chain = SDValue(VStA, 1);
2007
2008 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00002009 Ops.push_back(SDValue(VStA, 0));
2010 Ops.push_back(Align);
2011 if (isUpdating) {
2012 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2013 assert(isa<ConstantSDNode>(Inc.getNode()) &&
2014 "only constant post-increment update allowed for VST3/4");
2015 (void)Inc;
2016 Ops.push_back(Reg0);
2017 }
2018 Ops.push_back(RegSeq);
2019 Ops.push_back(Pred);
2020 Ops.push_back(Reg0);
2021 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00002022 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00002023 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002024 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002025 ReplaceNode(N, VStB);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002026}
2027
Justin Bogner45571362016-05-12 00:31:09 +00002028void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
2029 unsigned NumVecs,
2030 const uint16_t *DOpcodes,
2031 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002032 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002033 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002034
Bob Wilsonae08a732010-03-20 22:13:40 +00002035 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00002036 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2037 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2038 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002039 return;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002040
Evan Cheng40791332011-04-19 00:04:03 +00002041 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2042 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2043
Bob Wilson4145e3a2009-10-14 16:19:03 +00002044 SDValue Chain = N->getOperand(0);
2045 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002046 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2047 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002048 bool is64BitVector = VT.is64BitVector();
2049
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002050 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002051 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002052 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Sanjay Patel1ed771f2016-09-14 16:37:15 +00002053 unsigned NumBytes = NumVecs * VT.getScalarSizeInBits() / 8;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002054 if (Alignment > NumBytes)
2055 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002056 if (Alignment < 8 && Alignment < NumBytes)
2057 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002058 // Alignment must be a power of two; make sure of that.
2059 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002060 if (Alignment == 1)
2061 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002062 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002063 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002064
Bob Wilson4145e3a2009-10-14 16:19:03 +00002065 unsigned OpcodeIndex;
2066 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002067 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002068 // Double-register operations:
2069 case MVT::v8i8: OpcodeIndex = 0; break;
2070 case MVT::v4i16: OpcodeIndex = 1; break;
2071 case MVT::v2f32:
2072 case MVT::v2i32: OpcodeIndex = 2; break;
2073 // Quad-register operations:
2074 case MVT::v8i16: OpcodeIndex = 0; break;
2075 case MVT::v4f32:
2076 case MVT::v4i32: OpcodeIndex = 1; break;
2077 }
2078
Bob Wilson06fce872011-02-07 17:43:21 +00002079 std::vector<EVT> ResTys;
2080 if (IsLoad) {
2081 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2082 if (!is64BitVector)
2083 ResTyElts *= 2;
2084 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2085 MVT::i64, ResTyElts));
2086 }
2087 if (isUpdating)
2088 ResTys.push_back(MVT::i32);
2089 ResTys.push_back(MVT::Other);
2090
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002091 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002092 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002093
Bob Wilson06fce872011-02-07 17:43:21 +00002094 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002095 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002096 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002097 if (isUpdating) {
2098 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Tim Northover8b1240b2017-04-20 19:54:02 +00002099 bool IsImmUpdate =
2100 isPerfectIncrement(Inc, VT.getVectorElementType(), NumVecs);
2101 Ops.push_back(IsImmUpdate ? Reg0 : Inc);
Bob Wilson06fce872011-02-07 17:43:21 +00002102 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002103
Bob Wilsond5c57a52010-09-13 23:01:35 +00002104 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002105 SDValue V0 = N->getOperand(Vec0Idx + 0);
2106 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002107 if (NumVecs == 2) {
2108 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002109 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002110 else
Weiming Zhao95782222012-11-17 00:23:35 +00002111 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002112 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002113 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002114 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002115 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2116 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002117 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002118 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002119 else
Weiming Zhao95782222012-11-17 00:23:35 +00002120 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002121 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002122 Ops.push_back(SuperReg);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002123 Ops.push_back(getI32Imm(Lane, dl));
Evan Chenga33fc862009-11-21 06:21:52 +00002124 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002125 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002126 Ops.push_back(Chain);
2127
Bob Wilson06fce872011-02-07 17:43:21 +00002128 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2129 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002130 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002131 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002132 if (!IsLoad) {
2133 ReplaceNode(N, VLdLn);
2134 return;
2135 }
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002136
Bob Wilsond5c57a52010-09-13 23:01:35 +00002137 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002138 SuperReg = SDValue(VLdLn, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00002139 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2140 ARM::qsub_3 == ARM::qsub_0 + 3,
2141 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00002142 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002143 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2144 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002145 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2146 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2147 if (isUpdating)
2148 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002149 CurDAG->RemoveDeadNode(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002150}
2151
Justin Bogner45571362016-05-12 00:31:09 +00002152void ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Eli Friedmanf624ec22016-12-16 18:44:08 +00002153 const uint16_t *DOpcodes,
2154 const uint16_t *QOpcodes) {
2155 assert(NumVecs >= 1 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002156 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002157
2158 SDValue MemAddr, Align;
2159 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002160 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00002161
Evan Cheng40791332011-04-19 00:04:03 +00002162 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2163 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2164
Bob Wilson2d790df2010-11-28 06:51:26 +00002165 SDValue Chain = N->getOperand(0);
2166 EVT VT = N->getValueType(0);
2167
2168 unsigned Alignment = 0;
2169 if (NumVecs != 3) {
2170 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Sanjay Patel1ed771f2016-09-14 16:37:15 +00002171 unsigned NumBytes = NumVecs * VT.getScalarSizeInBits() / 8;
Bob Wilson2d790df2010-11-28 06:51:26 +00002172 if (Alignment > NumBytes)
2173 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002174 if (Alignment < 8 && Alignment < NumBytes)
2175 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002176 // Alignment must be a power of two; make sure of that.
2177 Alignment = (Alignment & -Alignment);
2178 if (Alignment == 1)
2179 Alignment = 0;
2180 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002181 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson2d790df2010-11-28 06:51:26 +00002182
Eli Friedmanf624ec22016-12-16 18:44:08 +00002183 unsigned Opc;
Bob Wilson2d790df2010-11-28 06:51:26 +00002184 switch (VT.getSimpleVT().SimpleTy) {
2185 default: llvm_unreachable("unhandled vld-dup type");
Eli Friedmanf624ec22016-12-16 18:44:08 +00002186 case MVT::v8i8: Opc = DOpcodes[0]; break;
2187 case MVT::v16i8: Opc = QOpcodes[0]; break;
2188 case MVT::v4i16: Opc = DOpcodes[1]; break;
2189 case MVT::v8i16: Opc = QOpcodes[1]; break;
Bob Wilson2d790df2010-11-28 06:51:26 +00002190 case MVT::v2f32:
Eli Friedmanf624ec22016-12-16 18:44:08 +00002191 case MVT::v2i32: Opc = DOpcodes[2]; break;
2192 case MVT::v4f32:
2193 case MVT::v4i32: Opc = QOpcodes[2]; break;
Bob Wilson2d790df2010-11-28 06:51:26 +00002194 }
2195
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002196 SDValue Pred = getAL(CurDAG, dl);
Bob Wilson2d790df2010-11-28 06:51:26 +00002197 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00002198 SmallVector<SDValue, 6> Ops;
2199 Ops.push_back(MemAddr);
2200 Ops.push_back(Align);
2201 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002202 // fixed-stride update instructions don't have an explicit writeback
2203 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002204 SDValue Inc = N->getOperand(2);
Tim Northover8b1240b2017-04-20 19:54:02 +00002205 bool IsImmUpdate =
2206 isPerfectIncrement(Inc, VT.getVectorElementType(), NumVecs);
2207 if (NumVecs <= 2 && !IsImmUpdate)
Eli Friedmanf624ec22016-12-16 18:44:08 +00002208 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Tim Northover8b1240b2017-04-20 19:54:02 +00002209 if (!IsImmUpdate)
Jim Grosbachc80a2642011-12-21 19:40:55 +00002210 Ops.push_back(Inc);
2211 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2212 else if (NumVecs > 2)
2213 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002214 }
2215 Ops.push_back(Pred);
2216 Ops.push_back(Reg0);
2217 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002218
2219 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002220 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002221 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002222 if (isUpdating)
2223 ResTys.push_back(MVT::i32);
2224 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002225 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002226 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002227
2228 // Extract the subregisters.
Eli Friedmanf624ec22016-12-16 18:44:08 +00002229 if (NumVecs == 1) {
2230 ReplaceUses(SDValue(N, 0), SDValue(VLdDup, 0));
2231 } else {
2232 SDValue SuperReg = SDValue(VLdDup, 0);
2233 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7, "Unexpected subreg numbering");
2234 unsigned SubIdx = ARM::dsub_0;
2235 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2236 ReplaceUses(SDValue(N, Vec),
2237 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
2238 }
Bob Wilson06fce872011-02-07 17:43:21 +00002239 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2240 if (isUpdating)
2241 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002242 CurDAG->RemoveDeadNode(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002243}
2244
Justin Bogner45571362016-05-12 00:31:09 +00002245bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002246 if (!Subtarget->hasV6T2Ops())
Justin Bogner45571362016-05-12 00:31:09 +00002247 return false;
Bob Wilson93117bc2009-10-14 16:46:45 +00002248
Evan Chengeae6d2c2012-12-19 20:16:09 +00002249 unsigned Opc = isSigned
2250 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002251 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002252 SDLoc dl(N);
Jim Grosbach825cb292010-04-22 23:24:18 +00002253
Jim Grosbach825cb292010-04-22 23:24:18 +00002254 // For unsigned extracts, check for a shift right and mask
2255 unsigned And_imm = 0;
2256 if (N->getOpcode() == ISD::AND) {
2257 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2258
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002259 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002260 if (And_imm & (And_imm + 1))
Justin Bogner45571362016-05-12 00:31:09 +00002261 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002262
2263 unsigned Srl_imm = 0;
2264 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2265 Srl_imm)) {
2266 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2267
Jim Grosbach03f56d92011-07-27 21:09:25 +00002268 // Note: The width operand is encoded as width-1.
Benjamin Kramer5f6a9072015-02-12 15:35:40 +00002269 unsigned Width = countTrailingOnes(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002270 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002271
Jim Grosbach825cb292010-04-22 23:24:18 +00002272 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002273
2274 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2275 // It's cheaper to use a right shift to extract the top bits.
2276 if (Subtarget->isThumb()) {
2277 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2278 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002279 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2280 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002281 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2282 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002283 }
2284
2285 // ARM models shift instructions as MOVsi with shifter operand.
2286 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2287 SDValue ShOpc =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002288 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), dl,
Evan Chengeae6d2c2012-12-19 20:16:09 +00002289 MVT::i32);
2290 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002291 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002292 CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops);
2293 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002294 }
2295
Jim Grosbach825cb292010-04-22 23:24:18 +00002296 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002297 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2298 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2299 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002300 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2301 return true;
Jim Grosbach825cb292010-04-22 23:24:18 +00002302 }
2303 }
Justin Bogner45571362016-05-12 00:31:09 +00002304 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002305 }
2306
2307 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002308 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002309 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002310 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2311 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002312 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002313 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002314 // Note: The width operand is encoded as width-1.
2315 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002316 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002317 if (LSB < 0)
Justin Bogner45571362016-05-12 00:31:09 +00002318 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002319 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002320 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002321 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2322 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2323 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002324 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2325 return true;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002326 }
2327 }
Tim Northover14ff2df2014-07-23 13:59:12 +00002328
Oliver Stannard92ca83c2016-06-01 12:01:01 +00002329 // Or we are looking for a shift of an and, with a mask operand
2330 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, And_imm) &&
2331 isShiftedMask_32(And_imm)) {
2332 unsigned Srl_imm = 0;
2333 unsigned LSB = countTrailingZeros(And_imm);
2334 // Shift must be the same as the ands lsb
2335 if (isInt32Immediate(N->getOperand(1), Srl_imm) && Srl_imm == LSB) {
2336 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2337 unsigned MSB = 31 - countLeadingZeros(And_imm);
2338 // Note: The width operand is encoded as width-1.
2339 unsigned Width = MSB - LSB;
2340 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2341 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2342 CurDAG->getTargetConstant(Srl_imm, dl, MVT::i32),
2343 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2344 getAL(CurDAG, dl), Reg0 };
2345 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2346 return true;
2347 }
2348 }
2349
Tim Northover14ff2df2014-07-23 13:59:12 +00002350 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
2351 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2352 unsigned LSB = 0;
2353 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) &&
2354 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB))
Justin Bogner45571362016-05-12 00:31:09 +00002355 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002356
2357 if (LSB + Width > 32)
Justin Bogner45571362016-05-12 00:31:09 +00002358 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002359
2360 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2361 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002362 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2363 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
2364 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002365 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2366 return true;
Tim Northover14ff2df2014-07-23 13:59:12 +00002367 }
2368
Justin Bogner45571362016-05-12 00:31:09 +00002369 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002370}
2371
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002372/// Target-specific DAG combining for ISD::XOR.
2373/// Target-independent combining lowers SELECT_CC nodes of the form
2374/// select_cc setg[ge] X, 0, X, -X
2375/// select_cc setgt X, -1, X, -X
2376/// select_cc setl[te] X, 0, -X, X
2377/// select_cc setlt X, 1, -X, X
2378/// which represent Integer ABS into:
2379/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2380/// ARM instruction selection detects the latter and matches it to
2381/// ARM::ABS or ARM::t2ABS machine node.
Justin Bogner45571362016-05-12 00:31:09 +00002382bool ARMDAGToDAGISel::tryABSOp(SDNode *N){
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002383 SDValue XORSrc0 = N->getOperand(0);
2384 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002385 EVT VT = N->getValueType(0);
2386
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002387 if (Subtarget->isThumb1Only())
Justin Bogner45571362016-05-12 00:31:09 +00002388 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002389
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002390 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Justin Bogner45571362016-05-12 00:31:09 +00002391 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002392
2393 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2394 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2395 SDValue SRASrc0 = XORSrc1.getOperand(0);
2396 SDValue SRASrc1 = XORSrc1.getOperand(1);
2397 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2398 EVT XType = SRASrc0.getValueType();
2399 unsigned Size = XType.getSizeInBits() - 1;
2400
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002401 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
Craig Topper062a2ba2014-04-25 05:30:21 +00002402 XType.isInteger() && SRAConstant != nullptr &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002403 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002404 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Justin Bogner45571362016-05-12 00:31:09 +00002405 CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2406 return true;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002407 }
2408
Justin Bogner45571362016-05-12 00:31:09 +00002409 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002410}
2411
Tim Northoverb629c772016-04-18 21:48:55 +00002412/// We've got special pseudo-instructions for these
Justin Bogner45571362016-05-12 00:31:09 +00002413void ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *N) {
Tim Northoverb629c772016-04-18 21:48:55 +00002414 unsigned Opcode;
2415 EVT MemTy = cast<MemSDNode>(N)->getMemoryVT();
2416 if (MemTy == MVT::i8)
2417 Opcode = ARM::CMP_SWAP_8;
2418 else if (MemTy == MVT::i16)
2419 Opcode = ARM::CMP_SWAP_16;
2420 else if (MemTy == MVT::i32)
2421 Opcode = ARM::CMP_SWAP_32;
2422 else
2423 llvm_unreachable("Unknown AtomicCmpSwap type");
2424
2425 SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3),
2426 N->getOperand(0)};
2427 SDNode *CmpSwap = CurDAG->getMachineNode(
2428 Opcode, SDLoc(N),
2429 CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other), Ops);
2430
2431 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2432 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
2433 cast<MachineSDNode>(CmpSwap)->setMemRefs(MemOp, MemOp + 1);
2434
2435 ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0));
2436 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002437 CurDAG->RemoveDeadNode(N);
Tim Northoverb629c772016-04-18 21:48:55 +00002438}
2439
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002440static Optional<std::pair<unsigned, unsigned>>
2441getContiguousRangeOfSetBits(const APInt &A) {
2442 unsigned FirstOne = A.getBitWidth() - A.countLeadingZeros() - 1;
2443 unsigned LastOne = A.countTrailingZeros();
2444 if (A.countPopulation() != (FirstOne - LastOne + 1))
2445 return Optional<std::pair<unsigned,unsigned>>();
2446 return std::make_pair(FirstOne, LastOne);
2447}
2448
2449void ARMDAGToDAGISel::SelectCMPZ(SDNode *N, bool &SwitchEQNEToPLMI) {
2450 assert(N->getOpcode() == ARMISD::CMPZ);
2451 SwitchEQNEToPLMI = false;
2452
2453 if (!Subtarget->isThumb())
2454 // FIXME: Work out whether it is profitable to do this in A32 mode - LSL and
2455 // LSR don't exist as standalone instructions - they need the barrel shifter.
2456 return;
2457
2458 // select (cmpz (and X, C), #0) -> (LSLS X) or (LSRS X) or (LSRS (LSLS X))
2459 SDValue And = N->getOperand(0);
2460 if (!And->hasOneUse())
2461 return;
2462
2463 SDValue Zero = N->getOperand(1);
2464 if (!isa<ConstantSDNode>(Zero) || !cast<ConstantSDNode>(Zero)->isNullValue() ||
2465 And->getOpcode() != ISD::AND)
2466 return;
2467 SDValue X = And.getOperand(0);
2468 auto C = dyn_cast<ConstantSDNode>(And.getOperand(1));
2469
Eli Friedman864df222018-06-08 21:16:56 +00002470 if (!C)
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002471 return;
2472 auto Range = getContiguousRangeOfSetBits(C->getAPIntValue());
2473 if (!Range)
2474 return;
2475
2476 // There are several ways to lower this:
2477 SDNode *NewN;
2478 SDLoc dl(N);
2479
2480 auto EmitShift = [&](unsigned Opc, SDValue Src, unsigned Imm) -> SDNode* {
2481 if (Subtarget->isThumb2()) {
2482 Opc = (Opc == ARM::tLSLri) ? ARM::t2LSLri : ARM::t2LSRri;
2483 SDValue Ops[] = { Src, CurDAG->getTargetConstant(Imm, dl, MVT::i32),
2484 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
2485 CurDAG->getRegister(0, MVT::i32) };
2486 return CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
2487 } else {
2488 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), Src,
2489 CurDAG->getTargetConstant(Imm, dl, MVT::i32),
2490 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
2491 return CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
2492 }
2493 };
2494
2495 if (Range->second == 0) {
2496 // 1. Mask includes the LSB -> Simply shift the top N bits off
2497 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2498 ReplaceNode(And.getNode(), NewN);
2499 } else if (Range->first == 31) {
2500 // 2. Mask includes the MSB -> Simply shift the bottom N bits off
2501 NewN = EmitShift(ARM::tLSRri, X, Range->second);
2502 ReplaceNode(And.getNode(), NewN);
2503 } else if (Range->first == Range->second) {
2504 // 3. Only one bit is set. We can shift this into the sign bit and use a
2505 // PL/MI comparison.
2506 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2507 ReplaceNode(And.getNode(), NewN);
2508
2509 SwitchEQNEToPLMI = true;
2510 } else if (!Subtarget->hasV6T2Ops()) {
2511 // 4. Do a double shift to clear bottom and top bits, but only in
2512 // thumb-1 mode as in thumb-2 we can use UBFX.
2513 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2514 NewN = EmitShift(ARM::tLSRri, SDValue(NewN, 0),
2515 Range->second + (31 - Range->first));
2516 ReplaceNode(And.getNode(), NewN);
2517 }
2518
2519}
2520
Justin Bogner45571362016-05-12 00:31:09 +00002521void ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002522 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002523
Tim Northover31d093c2013-09-22 08:21:56 +00002524 if (N->isMachineOpcode()) {
2525 N->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00002526 return; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00002527 }
Rafael Espindola4e760152006-06-12 12:28:08 +00002528
2529 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002530 default: break;
Justin Bogner45571362016-05-12 00:31:09 +00002531 case ISD::WRITE_REGISTER:
2532 if (tryWriteRegister(N))
2533 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002534 break;
Justin Bogner45571362016-05-12 00:31:09 +00002535 case ISD::READ_REGISTER:
2536 if (tryReadRegister(N))
2537 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002538 break;
Justin Bogner45571362016-05-12 00:31:09 +00002539 case ISD::INLINEASM:
2540 if (tryInlineAsm(N))
2541 return;
Weiming Zhaoc5987002013-02-14 18:10:21 +00002542 break;
Justin Bogner45571362016-05-12 00:31:09 +00002543 case ISD::XOR:
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002544 // Select special operations if XOR node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +00002545 if (tryABSOp(N))
2546 return;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002547 // Other cases are autogenerated.
2548 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002549 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002550 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
John Brawn056e6782015-09-14 15:19:41 +00002551 // If we can't materialize the constant we need to use a literal pool
2552 if (ConstantMaterializationCost(Val) > 2) {
Eric Christopherb17140d2014-10-08 07:32:17 +00002553 SDValue CPIdx = CurDAG->getTargetConstantPool(
2554 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
Mehdi Amini44ede332015-07-09 02:09:04 +00002555 TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng1526ba52007-01-24 08:53:17 +00002556
2557 SDNode *ResNode;
Tim Northover55c625f2014-01-23 13:43:47 +00002558 if (Subtarget->isThumb()) {
Sam Parker28934482017-07-14 08:23:56 +00002559 SDValue Ops[] = {
2560 CPIdx,
2561 getAL(CurDAG, dl),
2562 CurDAG->getRegister(0, MVT::i32),
2563 CurDAG->getEntryNode()
2564 };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002565 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002566 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002567 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002568 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002569 CPIdx,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002570 CurDAG->getTargetConstant(0, dl, MVT::i32),
2571 getAL(CurDAG, dl),
Owen Anderson9f944592009-08-11 20:47:22 +00002572 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002573 CurDAG->getEntryNode()
2574 };
Justin Bogner45571362016-05-12 00:31:09 +00002575 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
2576 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002577 }
Sam Parker28934482017-07-14 08:23:56 +00002578 // Annotate the Node with memory operand information so that MachineInstr
2579 // queries work properly. This e.g. gives the register allocation the
2580 // required information for rematerialization.
2581 MachineFunction& MF = CurDAG->getMachineFunction();
2582 MachineSDNode::mmo_iterator MemOp = MF.allocateMemRefsArray(1);
2583 MemOp[0] = MF.getMachineMemOperand(
2584 MachinePointerInfo::getConstantPool(MF),
2585 MachineMemOperand::MOLoad, 4, 4);
2586
2587 cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp+1);
2588
Justin Bognered4f3782016-05-12 00:20:19 +00002589 ReplaceNode(N, ResNode);
Justin Bogner45571362016-05-12 00:31:09 +00002590 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002591 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002592
Evan Cheng10043e22007-01-19 07:51:42 +00002593 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002594 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002595 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002596 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002597 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002598 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00002599 SDValue TFI = CurDAG->getTargetFrameIndex(
2600 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin22c2fba2009-07-08 23:10:31 +00002601 if (Subtarget->isThumb1Only()) {
Renato Golinb9887ef2015-02-25 14:41:06 +00002602 // Set the alignment of the frame object to 4, to avoid having to generate
2603 // more than one ADD
Matthias Braun941a7052016-07-28 18:40:00 +00002604 MachineFrameInfo &MFI = MF->getFrameInfo();
2605 if (MFI.getObjectAlignment(FI) < 4)
2606 MFI.setObjectAlignment(FI, 4);
Justin Bogner45571362016-05-12 00:31:09 +00002607 CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
2608 CurDAG->getTargetConstant(0, dl, MVT::i32));
2609 return;
Jim Grosbachfde21102009-04-07 20:34:09 +00002610 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002611 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2612 ARM::t2ADDri : ARM::ADDri);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002613 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
2614 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002615 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002616 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2617 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00002618 }
Evan Cheng10043e22007-01-19 07:51:42 +00002619 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002620 case ISD::SRL:
Justin Bogner45571362016-05-12 00:31:09 +00002621 if (tryV6T2BitfieldExtractOp(N, false))
2622 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002623 break;
Tim Northover14ff2df2014-07-23 13:59:12 +00002624 case ISD::SIGN_EXTEND_INREG:
Sandeep Patel423e42b2009-10-13 18:59:48 +00002625 case ISD::SRA:
Justin Bogner45571362016-05-12 00:31:09 +00002626 if (tryV6T2BitfieldExtractOp(N, true))
2627 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002628 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002629 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002630 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002631 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002632 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002633 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002634 if (!RHSV) break;
2635 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002636 unsigned ShImm = Log2_32(RHSV-1);
2637 if (ShImm >= 32)
2638 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002639 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002640 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002641 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002642 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002643 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002644 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002645 CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
2646 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002647 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002648 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2649 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002650 CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
2651 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002652 }
Evan Cheng10043e22007-01-19 07:51:42 +00002653 }
2654 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002655 unsigned ShImm = Log2_32(RHSV+1);
2656 if (ShImm >= 32)
2657 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002658 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002659 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002660 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002661 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002662 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002663 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002664 CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
2665 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002666 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002667 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2668 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002669 CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
2670 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002671 }
Evan Cheng10043e22007-01-19 07:51:42 +00002672 }
2673 }
2674 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002675 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002676 // Check for unsigned bitfield extract
Justin Bogner45571362016-05-12 00:31:09 +00002677 if (tryV6T2BitfieldExtractOp(N, false))
2678 return;
Jim Grosbach825cb292010-04-22 23:24:18 +00002679
James Molloyae5ff992016-07-05 12:37:13 +00002680 // If an immediate is used in an AND node, it is possible that the immediate
2681 // can be more optimally materialized when negated. If this is the case we
2682 // can negate the immediate and use a BIC instead.
2683 auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1));
2684 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
2685 uint32_t Imm = (uint32_t) N1C->getZExtValue();
2686
2687 // In Thumb2 mode, an AND can take a 12-bit immediate. If this
2688 // immediate can be negated and fit in the immediate operand of
2689 // a t2BIC, don't do any manual transform here as this can be
2690 // handled by the generic ISel machinery.
2691 bool PreferImmediateEncoding =
2692 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm));
2693 if (!PreferImmediateEncoding &&
2694 ConstantMaterializationCost(Imm) >
2695 ConstantMaterializationCost(~Imm)) {
2696 // The current immediate costs more to materialize than a negated
2697 // immediate, so negate the immediate and use a BIC.
2698 SDValue NewImm =
2699 CurDAG->getConstant(~N1C->getZExtValue(), dl, MVT::i32);
2700 // If the new constant didn't exist before, reposition it in the topological
2701 // ordering so it is just before N. Otherwise, don't touch its location.
2702 if (NewImm->getNodeId() == -1)
2703 CurDAG->RepositionNode(N->getIterator(), NewImm.getNode());
2704
2705 if (!Subtarget->hasThumb2()) {
2706 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
2707 N->getOperand(0), NewImm, getAL(CurDAG, dl),
2708 CurDAG->getRegister(0, MVT::i32)};
2709 ReplaceNode(N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32, Ops));
2710 return;
2711 } else {
2712 SDValue Ops[] = {N->getOperand(0), NewImm, getAL(CurDAG, dl),
2713 CurDAG->getRegister(0, MVT::i32),
2714 CurDAG->getRegister(0, MVT::i32)};
2715 ReplaceNode(N,
2716 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32, Ops));
2717 return;
2718 }
2719 }
2720 }
2721
Evan Cheng786b15f2009-10-21 08:15:52 +00002722 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2723 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2724 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2725 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2726 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002727 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002728 if (VT != MVT::i32)
2729 break;
2730 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2731 ? ARM::t2MOVTi16
2732 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2733 if (!Opc)
2734 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002735 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
James Molloyae5ff992016-07-05 12:37:13 +00002736 N1C = dyn_cast<ConstantSDNode>(N1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002737 if (!N1C)
2738 break;
2739 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2740 SDValue N2 = N0.getOperand(1);
2741 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2742 if (!N2C)
2743 break;
2744 unsigned N1CVal = N1C->getZExtValue();
2745 unsigned N2CVal = N2C->getZExtValue();
2746 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2747 (N1CVal & 0xffffU) == 0xffffU &&
2748 (N2CVal & 0xffffU) == 0x0U) {
2749 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002750 dl, MVT::i32);
Evan Cheng786b15f2009-10-21 08:15:52 +00002751 SDValue Ops[] = { N0.getOperand(0), Imm16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002752 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002753 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
2754 return;
Evan Cheng786b15f2009-10-21 08:15:52 +00002755 }
2756 }
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002757
Evan Cheng786b15f2009-10-21 08:15:52 +00002758 break;
2759 }
Sam Parkerd616cf02016-06-20 16:47:09 +00002760 case ARMISD::UMAAL: {
2761 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
2762 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2763 N->getOperand(2), N->getOperand(3),
2764 getAL(CurDAG, dl),
2765 CurDAG->getRegister(0, MVT::i32) };
2766 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::i32, Ops));
2767 return;
2768 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002769 case ARMISD::UMLAL:{
2770 if (Subtarget->isThumb()) {
2771 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002772 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002773 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002774 ReplaceNode(
2775 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops));
2776 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002777 }else{
2778 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002779 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002780 CurDAG->getRegister(0, MVT::i32),
2781 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002782 ReplaceNode(N, CurDAG->getMachineNode(
2783 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl,
2784 MVT::i32, MVT::i32, Ops));
2785 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002786 }
2787 }
2788 case ARMISD::SMLAL:{
2789 if (Subtarget->isThumb()) {
2790 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002791 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002792 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002793 ReplaceNode(
2794 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops));
2795 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002796 }else{
2797 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002798 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002799 CurDAG->getRegister(0, MVT::i32),
2800 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002801 ReplaceNode(N, CurDAG->getMachineNode(
2802 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl,
2803 MVT::i32, MVT::i32, Ops));
2804 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002805 }
2806 }
Sam Parker68c71cd2016-07-25 09:20:20 +00002807 case ARMISD::SUBE: {
Andre Vieira26b9de92018-01-12 09:21:09 +00002808 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
Sam Parker68c71cd2016-07-25 09:20:20 +00002809 break;
2810 // Look for a pattern to match SMMLS
2811 // (sube a, (smul_loHi a, b), (subc 0, (smul_LOhi(a, b))))
2812 if (N->getOperand(1).getOpcode() != ISD::SMUL_LOHI ||
Tim Northover765777c2016-08-02 23:12:36 +00002813 N->getOperand(2).getOpcode() != ARMISD::SUBC ||
2814 !SDValue(N, 1).use_empty())
Sam Parker68c71cd2016-07-25 09:20:20 +00002815 break;
2816
2817 if (Subtarget->isThumb())
2818 assert(Subtarget->hasThumb2() &&
2819 "This pattern should not be generated for Thumb");
2820
2821 SDValue SmulLoHi = N->getOperand(1);
2822 SDValue Subc = N->getOperand(2);
2823 auto *Zero = dyn_cast<ConstantSDNode>(Subc.getOperand(0));
2824
2825 if (!Zero || Zero->getZExtValue() != 0 ||
2826 Subc.getOperand(1) != SmulLoHi.getValue(0) ||
2827 N->getOperand(1) != SmulLoHi.getValue(1) ||
2828 N->getOperand(2) != Subc.getValue(1))
2829 break;
2830
2831 unsigned Opc = Subtarget->isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
2832 SDValue Ops[] = { SmulLoHi.getOperand(0), SmulLoHi.getOperand(1),
2833 N->getOperand(0), getAL(CurDAG, dl),
2834 CurDAG->getRegister(0, MVT::i32) };
2835 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops));
2836 return;
2837 }
Evan Cheng10043e22007-01-19 07:51:42 +00002838 case ISD::LOAD: {
Justin Bogner45571362016-05-12 00:31:09 +00002839 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
2840 if (tryT2IndexedLoad(N))
2841 return;
James Molloyb3326df2016-07-15 08:03:56 +00002842 } else if (Subtarget->isThumb()) {
2843 if (tryT1IndexedLoad(N))
2844 return;
Justin Bogner45571362016-05-12 00:31:09 +00002845 } else if (tryARMIndexedLoad(N))
2846 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002847 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002848 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00002849 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002850 case ARMISD::BRCOND: {
2851 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2852 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2853 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00002854
Evan Cheng7e90b112007-07-05 07:15:27 +00002855 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2856 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2857 // Pattern complexity = 6 cost = 1 size = 0
2858
David Goodwin27303cd2009-06-30 18:04:13 +00002859 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2860 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2861 // Pattern complexity = 6 cost = 1 size = 0
2862
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002863 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00002864 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002865 SDValue Chain = N->getOperand(0);
2866 SDValue N1 = N->getOperand(1);
2867 SDValue N2 = N->getOperand(2);
2868 SDValue N3 = N->getOperand(3);
2869 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00002870 assert(N1.getOpcode() == ISD::BasicBlock);
2871 assert(N2.getOpcode() == ISD::Constant);
2872 assert(N3.getOpcode() == ISD::Register);
2873
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002874 unsigned CC = (unsigned) cast<ConstantSDNode>(N2)->getZExtValue();
2875
2876 if (InFlag.getOpcode() == ARMISD::CMPZ) {
2877 bool SwitchEQNEToPLMI;
2878 SelectCMPZ(InFlag.getNode(), SwitchEQNEToPLMI);
2879 InFlag = N->getOperand(4);
2880
2881 if (SwitchEQNEToPLMI) {
2882 switch ((ARMCC::CondCodes)CC) {
2883 default: llvm_unreachable("CMPZ must be either NE or EQ!");
2884 case ARMCC::NE:
2885 CC = (unsigned)ARMCC::MI;
2886 break;
2887 case ARMCC::EQ:
2888 CC = (unsigned)ARMCC::PL;
2889 break;
2890 }
2891 }
2892 }
2893
2894 SDValue Tmp2 = CurDAG->getTargetConstant(CC, dl, MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002895 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00002896 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002897 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002898 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002899 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002900 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002901 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00002902 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002903 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00002904 SDValue(Chain.getNode(), Chain.getResNo()));
Justin Bognered4f3782016-05-12 00:20:19 +00002905 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00002906 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00002907 }
James Molloy4d86bed2016-09-09 12:52:24 +00002908
2909 case ARMISD::CMPZ: {
2910 // select (CMPZ X, #-C) -> (CMPZ (ADDS X, #C), #0)
2911 // This allows us to avoid materializing the expensive negative constant.
2912 // The CMPZ #0 is useless and will be peepholed away but we need to keep it
2913 // for its glue output.
2914 SDValue X = N->getOperand(0);
2915 auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1).getNode());
2916 if (C && C->getSExtValue() < 0 && Subtarget->isThumb()) {
2917 int64_t Addend = -C->getSExtValue();
2918
2919 SDNode *Add = nullptr;
Artyom Skrobov4592f622017-02-17 18:59:16 +00002920 // ADDS can be better than CMN if the immediate fits in a
James Molloy4d86bed2016-09-09 12:52:24 +00002921 // 16-bit ADDS, which means either [0,256) for tADDi8 or [0,8) for tADDi3.
2922 // Outside that range we can just use a CMN which is 32-bit but has a
2923 // 12-bit immediate range.
Artyom Skrobov4592f622017-02-17 18:59:16 +00002924 if (Addend < 1<<8) {
2925 if (Subtarget->isThumb2()) {
2926 SDValue Ops[] = { X, CurDAG->getTargetConstant(Addend, dl, MVT::i32),
2927 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
2928 CurDAG->getRegister(0, MVT::i32) };
2929 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl, MVT::i32, Ops);
2930 } else {
2931 unsigned Opc = (Addend < 1<<3) ? ARM::tADDi3 : ARM::tADDi8;
2932 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), X,
2933 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
2934 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
2935 Add = CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
2936 }
James Molloy4d86bed2016-09-09 12:52:24 +00002937 }
2938 if (Add) {
2939 SDValue Ops2[] = {SDValue(Add, 0), CurDAG->getConstant(0, dl, MVT::i32)};
2940 CurDAG->MorphNodeTo(N, ARMISD::CMPZ, CurDAG->getVTList(MVT::Glue), Ops2);
2941 }
2942 }
2943 // Other cases are autogenerated.
2944 break;
2945 }
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002946
2947 case ARMISD::CMOV: {
2948 SDValue InFlag = N->getOperand(4);
2949
2950 if (InFlag.getOpcode() == ARMISD::CMPZ) {
2951 bool SwitchEQNEToPLMI;
2952 SelectCMPZ(InFlag.getNode(), SwitchEQNEToPLMI);
2953
2954 if (SwitchEQNEToPLMI) {
2955 SDValue ARMcc = N->getOperand(2);
2956 ARMCC::CondCodes CC =
2957 (ARMCC::CondCodes)cast<ConstantSDNode>(ARMcc)->getZExtValue();
2958
2959 switch (CC) {
2960 default: llvm_unreachable("CMPZ must be either NE or EQ!");
2961 case ARMCC::NE:
2962 CC = ARMCC::MI;
2963 break;
2964 case ARMCC::EQ:
2965 CC = ARMCC::PL;
2966 break;
2967 }
2968 SDValue NewARMcc = CurDAG->getConstant((unsigned)CC, dl, MVT::i32);
2969 SDValue Ops[] = {N->getOperand(0), N->getOperand(1), NewARMcc,
2970 N->getOperand(3), N->getOperand(4)};
2971 CurDAG->MorphNodeTo(N, ARMISD::CMOV, N->getVTList(), Ops);
2972 }
2973
2974 }
2975 // Other cases are autogenerated.
2976 break;
2977 }
James Molloy4d86bed2016-09-09 12:52:24 +00002978
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002979 case ARMISD::VZIP: {
2980 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002981 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002982 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00002983 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002984 case MVT::v8i8: Opc = ARM::VZIPd8; break;
2985 case MVT::v4i16: Opc = ARM::VZIPd16; break;
2986 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00002987 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2988 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002989 case MVT::v16i8: Opc = ARM::VZIPq8; break;
2990 case MVT::v8i16: Opc = ARM::VZIPq16; break;
2991 case MVT::v4f32:
2992 case MVT::v4i32: Opc = ARM::VZIPq32; break;
2993 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002994 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002995 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2996 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00002997 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
2998 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002999 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003000 case ARMISD::VUZP: {
3001 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003002 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003003 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003004 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003005 case MVT::v8i8: Opc = ARM::VUZPd8; break;
3006 case MVT::v4i16: Opc = ARM::VUZPd16; break;
3007 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00003008 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3009 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003010 case MVT::v16i8: Opc = ARM::VUZPq8; break;
3011 case MVT::v8i16: Opc = ARM::VUZPq16; break;
3012 case MVT::v4f32:
3013 case MVT::v4i32: Opc = ARM::VUZPq32; break;
3014 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003015 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003016 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3017 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003018 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3019 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003020 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003021 case ARMISD::VTRN: {
3022 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003023 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003024 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003025 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003026 case MVT::v8i8: Opc = ARM::VTRNd8; break;
3027 case MVT::v4i16: Opc = ARM::VTRNd16; break;
3028 case MVT::v2f32:
3029 case MVT::v2i32: Opc = ARM::VTRNd32; break;
3030 case MVT::v16i8: Opc = ARM::VTRNq8; break;
3031 case MVT::v8i16: Opc = ARM::VTRNq16; break;
3032 case MVT::v4f32:
3033 case MVT::v4i32: Opc = ARM::VTRNq32; break;
3034 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003035 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003036 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3037 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003038 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3039 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003040 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003041 case ARMISD::BUILD_VECTOR: {
3042 EVT VecVT = N->getValueType(0);
3043 EVT EltVT = VecVT.getVectorElementType();
3044 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00003045 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00003046 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003047 ReplaceNode(
3048 N, createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3049 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003050 }
Duncan Sands14627772010-11-03 12:17:33 +00003051 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003052 if (NumElts == 2) {
3053 ReplaceNode(
3054 N, createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3055 return;
3056 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003057 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003058 ReplaceNode(N,
3059 createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
3060 N->getOperand(2), N->getOperand(3)));
3061 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003062 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003063
Eli Friedmanf624ec22016-12-16 18:44:08 +00003064 case ARMISD::VLD1DUP: {
3065 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8, ARM::VLD1DUPd16,
3066 ARM::VLD1DUPd32 };
3067 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8, ARM::VLD1DUPq16,
3068 ARM::VLD1DUPq32 };
3069 SelectVLDDup(N, false, 1, DOpcodes, QOpcodes);
3070 return;
3071 }
3072
Bob Wilson2d790df2010-11-28 06:51:26 +00003073 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003074 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
3075 ARM::VLD2DUPd32 };
Justin Bogner45571362016-05-12 00:31:09 +00003076 SelectVLDDup(N, false, 2, Opcodes);
3077 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00003078 }
3079
Bob Wilson77ab1652010-11-29 19:35:29 +00003080 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003081 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
3082 ARM::VLD3DUPd16Pseudo,
3083 ARM::VLD3DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003084 SelectVLDDup(N, false, 3, Opcodes);
3085 return;
Bob Wilson77ab1652010-11-29 19:35:29 +00003086 }
3087
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003088 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003089 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
3090 ARM::VLD4DUPd16Pseudo,
3091 ARM::VLD4DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003092 SelectVLDDup(N, false, 4, Opcodes);
3093 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003094 }
3095
Eli Friedmanf624ec22016-12-16 18:44:08 +00003096 case ARMISD::VLD1DUP_UPD: {
3097 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8wb_fixed,
3098 ARM::VLD1DUPd16wb_fixed,
3099 ARM::VLD1DUPd32wb_fixed };
3100 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8wb_fixed,
3101 ARM::VLD1DUPq16wb_fixed,
3102 ARM::VLD1DUPq32wb_fixed };
3103 SelectVLDDup(N, true, 1, DOpcodes, QOpcodes);
3104 return;
3105 }
3106
Bob Wilson06fce872011-02-07 17:43:21 +00003107 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003108 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
3109 ARM::VLD2DUPd16wb_fixed,
3110 ARM::VLD2DUPd32wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003111 SelectVLDDup(N, true, 2, Opcodes);
3112 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003113 }
3114
3115 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003116 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
3117 ARM::VLD3DUPd16Pseudo_UPD,
3118 ARM::VLD3DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003119 SelectVLDDup(N, true, 3, Opcodes);
3120 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003121 }
3122
3123 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003124 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
3125 ARM::VLD4DUPd16Pseudo_UPD,
3126 ARM::VLD4DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003127 SelectVLDDup(N, true, 4, Opcodes);
3128 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003129 }
3130
3131 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003132 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
3133 ARM::VLD1d16wb_fixed,
3134 ARM::VLD1d32wb_fixed,
3135 ARM::VLD1d64wb_fixed };
3136 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
3137 ARM::VLD1q16wb_fixed,
3138 ARM::VLD1q32wb_fixed,
3139 ARM::VLD1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003140 SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
3141 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003142 }
3143
3144 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003145 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
3146 ARM::VLD2d16wb_fixed,
3147 ARM::VLD2d32wb_fixed,
3148 ARM::VLD1q64wb_fixed};
3149 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
3150 ARM::VLD2q16PseudoWB_fixed,
3151 ARM::VLD2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003152 SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
3153 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003154 }
3155
3156 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003157 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
3158 ARM::VLD3d16Pseudo_UPD,
3159 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003160 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003161 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3162 ARM::VLD3q16Pseudo_UPD,
3163 ARM::VLD3q32Pseudo_UPD };
3164 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3165 ARM::VLD3q16oddPseudo_UPD,
3166 ARM::VLD3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003167 SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3168 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003169 }
3170
3171 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003172 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3173 ARM::VLD4d16Pseudo_UPD,
3174 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003175 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003176 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3177 ARM::VLD4q16Pseudo_UPD,
3178 ARM::VLD4q32Pseudo_UPD };
3179 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3180 ARM::VLD4q16oddPseudo_UPD,
3181 ARM::VLD4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003182 SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3183 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003184 }
3185
3186 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003187 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3188 ARM::VLD2LNd16Pseudo_UPD,
3189 ARM::VLD2LNd32Pseudo_UPD };
3190 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3191 ARM::VLD2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003192 SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3193 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003194 }
3195
3196 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003197 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3198 ARM::VLD3LNd16Pseudo_UPD,
3199 ARM::VLD3LNd32Pseudo_UPD };
3200 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3201 ARM::VLD3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003202 SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3203 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003204 }
3205
3206 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003207 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3208 ARM::VLD4LNd16Pseudo_UPD,
3209 ARM::VLD4LNd32Pseudo_UPD };
3210 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3211 ARM::VLD4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003212 SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3213 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003214 }
3215
3216 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003217 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3218 ARM::VST1d16wb_fixed,
3219 ARM::VST1d32wb_fixed,
3220 ARM::VST1d64wb_fixed };
3221 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3222 ARM::VST1q16wb_fixed,
3223 ARM::VST1q32wb_fixed,
3224 ARM::VST1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003225 SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
3226 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003227 }
3228
3229 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003230 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3231 ARM::VST2d16wb_fixed,
3232 ARM::VST2d32wb_fixed,
3233 ARM::VST1q64wb_fixed};
3234 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3235 ARM::VST2q16PseudoWB_fixed,
3236 ARM::VST2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003237 SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
3238 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003239 }
3240
3241 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003242 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3243 ARM::VST3d16Pseudo_UPD,
3244 ARM::VST3d32Pseudo_UPD,
3245 ARM::VST1d64TPseudoWB_fixed};
3246 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3247 ARM::VST3q16Pseudo_UPD,
3248 ARM::VST3q32Pseudo_UPD };
3249 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3250 ARM::VST3q16oddPseudo_UPD,
3251 ARM::VST3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003252 SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3253 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003254 }
3255
3256 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003257 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3258 ARM::VST4d16Pseudo_UPD,
3259 ARM::VST4d32Pseudo_UPD,
3260 ARM::VST1d64QPseudoWB_fixed};
3261 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3262 ARM::VST4q16Pseudo_UPD,
3263 ARM::VST4q32Pseudo_UPD };
3264 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3265 ARM::VST4q16oddPseudo_UPD,
3266 ARM::VST4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003267 SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3268 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003269 }
3270
3271 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003272 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3273 ARM::VST2LNd16Pseudo_UPD,
3274 ARM::VST2LNd32Pseudo_UPD };
3275 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3276 ARM::VST2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003277 SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3278 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003279 }
3280
3281 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003282 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3283 ARM::VST3LNd16Pseudo_UPD,
3284 ARM::VST3LNd32Pseudo_UPD };
3285 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3286 ARM::VST3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003287 SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3288 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003289 }
3290
3291 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003292 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3293 ARM::VST4LNd16Pseudo_UPD,
3294 ARM::VST4LNd32Pseudo_UPD };
3295 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3296 ARM::VST4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003297 SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
3298 return;
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003299 }
3300
Bob Wilsone0636a72009-08-26 17:39:53 +00003301 case ISD::INTRINSIC_VOID:
3302 case ISD::INTRINSIC_W_CHAIN: {
3303 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003304 switch (IntNo) {
3305 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003306 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003307
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003308 case Intrinsic::arm_mrrc:
3309 case Intrinsic::arm_mrrc2: {
3310 SDLoc dl(N);
3311 SDValue Chain = N->getOperand(0);
3312 unsigned Opc;
3313
3314 if (Subtarget->isThumb())
3315 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
3316 else
3317 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
3318
3319 SmallVector<SDValue, 5> Ops;
3320 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(), dl)); /* coproc */
3321 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(), dl)); /* opc */
3322 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(4))->getZExtValue(), dl)); /* CRm */
3323
3324 // The mrrc2 instruction in ARM doesn't allow predicates, the top 4 bits of the encoded
3325 // instruction will always be '1111' but it is possible in assembly language to specify
3326 // AL as a predicate to mrrc2 but it doesn't make any difference to the encoded instruction.
3327 if (Opc != ARM::MRRC2) {
3328 Ops.push_back(getAL(CurDAG, dl));
3329 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3330 }
3331
3332 Ops.push_back(Chain);
3333
3334 // Writes to two registers.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003335 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003336
3337 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, RetType, Ops));
3338 return;
3339 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003340 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003341 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003342 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003343 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003344 SDValue MemAddr = N->getOperand(2);
Bradley Smith433c22e2016-01-15 10:26:51 +00003345 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
Tim Northover1ff5f292014-03-26 14:39:31 +00003346
3347 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3348 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3349 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003350
3351 // arm_ldrexd returns a i64 value in {i32, i32}
3352 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003353 if (isThumb) {
3354 ResTys.push_back(MVT::i32);
3355 ResTys.push_back(MVT::i32);
3356 } else
3357 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003358 ResTys.push_back(MVT::Other);
3359
Weiming Zhao8f56f882012-11-16 21:55:34 +00003360 // Place arguments in the right order.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003361 SDValue Ops[] = {MemAddr, getAL(CurDAG, dl),
3362 CurDAG->getRegister(0, MVT::i32), Chain};
Michael Liaob53d8962013-04-19 22:22:57 +00003363 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003364 // Transfer memoperands.
3365 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3366 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3367 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3368
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003369 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003370 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003371 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003372 SDValue Result;
3373 if (isThumb)
3374 Result = SDValue(Ld, 0);
3375 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003376 SDValue SubRegIdx =
3377 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003378 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003379 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003380 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003381 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003382 ReplaceUses(SDValue(N, 0), Result);
3383 }
3384 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003385 SDValue Result;
3386 if (isThumb)
3387 Result = SDValue(Ld, 1);
3388 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003389 SDValue SubRegIdx =
3390 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003391 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003392 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003393 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003394 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003395 ReplaceUses(SDValue(N, 1), Result);
3396 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003397 ReplaceUses(SDValue(N, 2), OutChain);
Justin Bognered4f3782016-05-12 00:20:19 +00003398 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003399 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003400 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003401 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003402 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003403 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003404 SDValue Chain = N->getOperand(0);
3405 SDValue Val0 = N->getOperand(2);
3406 SDValue Val1 = N->getOperand(3);
3407 SDValue MemAddr = N->getOperand(4);
3408
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003409 // Store exclusive double return a i32 value which is the return status
3410 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003411 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003412
Weiming Zhao8f56f882012-11-16 21:55:34 +00003413 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3414 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003415 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003416 if (isThumb) {
3417 Ops.push_back(Val0);
3418 Ops.push_back(Val1);
3419 } else
3420 // arm_strexd uses GPRPair.
3421 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003422 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003423 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003424 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3425 Ops.push_back(Chain);
3426
Tim Northover1ff5f292014-03-26 14:39:31 +00003427 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3428 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3429 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003430
Michael Liaob53d8962013-04-19 22:22:57 +00003431 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003432 // Transfer memoperands.
3433 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3434 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3435 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3436
Justin Bogner45571362016-05-12 00:31:09 +00003437 ReplaceNode(N, St);
3438 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003439 }
3440
Bob Wilson340861d2010-03-23 05:25:43 +00003441 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003442 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3443 ARM::VLD1d32, ARM::VLD1d64 };
3444 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3445 ARM::VLD1q32, ARM::VLD1q64};
Justin Bogner45571362016-05-12 00:31:09 +00003446 SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
3447 return;
Bob Wilson340861d2010-03-23 05:25:43 +00003448 }
3449
Ivan A. Kosarev60a991e2018-06-02 16:40:03 +00003450 case Intrinsic::arm_neon_vld1x2: {
3451 static const uint16_t DOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3452 ARM::VLD1q32, ARM::VLD1q64 };
3453 static const uint16_t QOpcodes[] = { ARM::VLD1d8QPseudo,
3454 ARM::VLD1d16QPseudo,
3455 ARM::VLD1d32QPseudo,
3456 ARM::VLD1d64QPseudo };
3457 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3458 return;
3459 }
3460
3461 case Intrinsic::arm_neon_vld1x3: {
3462 static const uint16_t DOpcodes[] = { ARM::VLD1d8TPseudo,
3463 ARM::VLD1d16TPseudo,
3464 ARM::VLD1d32TPseudo,
3465 ARM::VLD1d64TPseudo };
3466 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowTPseudo_UPD,
3467 ARM::VLD1q16LowTPseudo_UPD,
3468 ARM::VLD1q32LowTPseudo_UPD,
3469 ARM::VLD1q64LowTPseudo_UPD };
3470 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighTPseudo,
3471 ARM::VLD1q16HighTPseudo,
3472 ARM::VLD1q32HighTPseudo,
3473 ARM::VLD1q64HighTPseudo };
3474 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3475 return;
3476 }
3477
3478 case Intrinsic::arm_neon_vld1x4: {
3479 static const uint16_t DOpcodes[] = { ARM::VLD1d8QPseudo,
3480 ARM::VLD1d16QPseudo,
3481 ARM::VLD1d32QPseudo,
3482 ARM::VLD1d64QPseudo };
3483 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowQPseudo_UPD,
3484 ARM::VLD1q16LowQPseudo_UPD,
3485 ARM::VLD1q32LowQPseudo_UPD,
3486 ARM::VLD1q64LowQPseudo_UPD };
3487 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighQPseudo,
3488 ARM::VLD1q16HighQPseudo,
3489 ARM::VLD1q32HighQPseudo,
3490 ARM::VLD1q64HighQPseudo };
3491 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3492 return;
3493 }
3494
Bob Wilsone0636a72009-08-26 17:39:53 +00003495 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003496 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3497 ARM::VLD2d32, ARM::VLD1q64 };
3498 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3499 ARM::VLD2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003500 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3501 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003502 }
3503
3504 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003505 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3506 ARM::VLD3d16Pseudo,
3507 ARM::VLD3d32Pseudo,
3508 ARM::VLD1d64TPseudo };
3509 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3510 ARM::VLD3q16Pseudo_UPD,
3511 ARM::VLD3q32Pseudo_UPD };
3512 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3513 ARM::VLD3q16oddPseudo,
3514 ARM::VLD3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003515 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3516 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003517 }
3518
3519 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003520 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3521 ARM::VLD4d16Pseudo,
3522 ARM::VLD4d32Pseudo,
3523 ARM::VLD1d64QPseudo };
3524 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3525 ARM::VLD4q16Pseudo_UPD,
3526 ARM::VLD4q32Pseudo_UPD };
3527 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3528 ARM::VLD4q16oddPseudo,
3529 ARM::VLD4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003530 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3531 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003532 }
3533
Bob Wilsonda9817c2009-09-01 04:26:28 +00003534 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003535 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3536 ARM::VLD2LNd16Pseudo,
3537 ARM::VLD2LNd32Pseudo };
3538 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3539 ARM::VLD2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003540 SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
3541 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003542 }
3543
3544 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003545 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3546 ARM::VLD3LNd16Pseudo,
3547 ARM::VLD3LNd32Pseudo };
3548 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3549 ARM::VLD3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003550 SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
3551 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003552 }
3553
3554 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003555 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3556 ARM::VLD4LNd16Pseudo,
3557 ARM::VLD4LNd32Pseudo };
3558 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3559 ARM::VLD4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003560 SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
3561 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003562 }
3563
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003564 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003565 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3566 ARM::VST1d32, ARM::VST1d64 };
3567 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3568 ARM::VST1q32, ARM::VST1q64 };
Justin Bogner45571362016-05-12 00:31:09 +00003569 SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
3570 return;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003571 }
3572
Ivan A. Kosarev847daa12018-06-10 09:27:27 +00003573 case Intrinsic::arm_neon_vst1x2: {
3574 static const uint16_t DOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3575 ARM::VST1q32, ARM::VST1q64 };
3576 static const uint16_t QOpcodes[] = { ARM::VST1d8QPseudo,
3577 ARM::VST1d16QPseudo,
3578 ARM::VST1d32QPseudo,
3579 ARM::VST1d64QPseudo };
3580 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3581 return;
3582 }
3583
3584 case Intrinsic::arm_neon_vst1x3: {
3585 static const uint16_t DOpcodes[] = { ARM::VST1d8TPseudo,
3586 ARM::VST1d16TPseudo,
3587 ARM::VST1d32TPseudo,
3588 ARM::VST1d64TPseudo };
3589 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowTPseudo_UPD,
3590 ARM::VST1q16LowTPseudo_UPD,
3591 ARM::VST1q32LowTPseudo_UPD,
3592 ARM::VST1q64LowTPseudo_UPD };
3593 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighTPseudo,
3594 ARM::VST1q16HighTPseudo,
3595 ARM::VST1q32HighTPseudo,
3596 ARM::VST1q64HighTPseudo };
3597 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3598 return;
3599 }
3600
3601 case Intrinsic::arm_neon_vst1x4: {
3602 static const uint16_t DOpcodes[] = { ARM::VST1d8QPseudo,
3603 ARM::VST1d16QPseudo,
3604 ARM::VST1d32QPseudo,
3605 ARM::VST1d64QPseudo };
3606 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowQPseudo_UPD,
3607 ARM::VST1q16LowQPseudo_UPD,
3608 ARM::VST1q32LowQPseudo_UPD,
3609 ARM::VST1q64LowQPseudo_UPD };
3610 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighQPseudo,
3611 ARM::VST1q16HighQPseudo,
3612 ARM::VST1q32HighQPseudo,
3613 ARM::VST1q64HighQPseudo };
3614 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3615 return;
3616 }
3617
Bob Wilsone0636a72009-08-26 17:39:53 +00003618 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003619 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3620 ARM::VST2d32, ARM::VST1q64 };
Benjamin Kramerf690da42016-06-17 14:14:29 +00003621 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3622 ARM::VST2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003623 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3624 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003625 }
3626
3627 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003628 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3629 ARM::VST3d16Pseudo,
3630 ARM::VST3d32Pseudo,
3631 ARM::VST1d64TPseudo };
3632 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3633 ARM::VST3q16Pseudo_UPD,
3634 ARM::VST3q32Pseudo_UPD };
3635 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3636 ARM::VST3q16oddPseudo,
3637 ARM::VST3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003638 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3639 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003640 }
3641
3642 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003643 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3644 ARM::VST4d16Pseudo,
3645 ARM::VST4d32Pseudo,
3646 ARM::VST1d64QPseudo };
3647 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3648 ARM::VST4q16Pseudo_UPD,
3649 ARM::VST4q32Pseudo_UPD };
3650 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3651 ARM::VST4q16oddPseudo,
3652 ARM::VST4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003653 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3654 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003655 }
Bob Wilsond7797752009-09-01 18:51:56 +00003656
3657 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003658 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3659 ARM::VST2LNd16Pseudo,
3660 ARM::VST2LNd32Pseudo };
3661 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3662 ARM::VST2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003663 SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
3664 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003665 }
3666
3667 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003668 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3669 ARM::VST3LNd16Pseudo,
3670 ARM::VST3LNd32Pseudo };
3671 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3672 ARM::VST3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003673 SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
3674 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003675 }
3676
3677 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003678 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3679 ARM::VST4LNd16Pseudo,
3680 ARM::VST4LNd32Pseudo };
3681 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3682 ARM::VST4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003683 SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
3684 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003685 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003686 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003687 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003688 }
Evan Chengd85631e2010-05-05 18:28:36 +00003689
Tim Northoverb629c772016-04-18 21:48:55 +00003690 case ISD::ATOMIC_CMP_SWAP:
Justin Bogner45571362016-05-12 00:31:09 +00003691 SelectCMP_SWAP(N);
3692 return;
Evan Chengd85631e2010-05-05 18:28:36 +00003693 }
Evan Chengd5021732008-12-10 21:54:21 +00003694
Justin Bogner45571362016-05-12 00:31:09 +00003695 SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003696}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003697
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003698// Inspect a register string of the form
3699// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3700// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3701// and obtain the integer operands from them, adding these operands to the
3702// provided vector.
3703static void getIntOperandsFromRegisterString(StringRef RegString,
Benjamin Kramerbdc49562016-06-12 15:39:02 +00003704 SelectionDAG *CurDAG,
3705 const SDLoc &DL,
3706 std::vector<SDValue> &Ops) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003707 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003708 RegString.split(Fields, ':');
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003709
3710 if (Fields.size() > 1) {
3711 bool AllIntFields = true;
3712
3713 for (StringRef Field : Fields) {
3714 // Need to trim out leading 'cp' characters and get the integer field.
3715 unsigned IntField;
3716 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3717 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3718 }
3719
3720 assert(AllIntFields &&
3721 "Unexpected non-integer value in special register string.");
3722 }
3723}
3724
3725// Maps a Banked Register string to its mask value. The mask value returned is
3726// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3727// mask operand, which expresses which register is to be used, e.g. r8, and in
3728// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3729// was invalid.
3730static inline int getBankedRegisterMask(StringRef RegString) {
Javed Absar054d1ae2017-08-03 01:24:12 +00003731 auto TheReg = ARMBankedReg::lookupBankedRegByName(RegString.lower());
3732 if (!TheReg)
3733 return -1;
3734 return TheReg->Encoding;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003735}
3736
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003737// The flags here are common to those allowed for apsr in the A class cores and
3738// those allowed for the special registers in the M class cores. Returns a
3739// value representing which flags were present, -1 if invalid.
John Brawne60f4e42017-02-10 17:41:08 +00003740static inline int getMClassFlagsMask(StringRef Flags) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003741 return StringSwitch<int>(Flags)
John Brawne60f4e42017-02-10 17:41:08 +00003742 .Case("", 0x2) // no flags means nzcvq for psr registers, and 0x2 is
3743 // correct when flags are not permitted
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003744 .Case("g", 0x1)
3745 .Case("nzcvq", 0x2)
3746 .Case("nzcvqg", 0x3)
3747 .Default(-1);
3748}
3749
Javed Absar2cb0c952017-07-19 12:57:16 +00003750// Maps MClass special registers string to its value for use in the
3751// t2MRS_M/t2MSR_M instruction nodes as the SYSm value operand.
3752// Returns -1 to signify that the string was invalid.
3753static int getMClassRegisterMask(StringRef Reg, const ARMSubtarget *Subtarget) {
3754 auto TheReg = ARMSysReg::lookupMClassSysRegByName(Reg);
3755 const FeatureBitset &FeatureBits = Subtarget->getFeatureBits();
3756 if (!TheReg || !TheReg->hasRequiredFeatures(FeatureBits))
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003757 return -1;
Javed Absar2cb0c952017-07-19 12:57:16 +00003758 return (int)(TheReg->Encoding & 0xFFF); // SYSm value
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003759}
3760
3761static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
3762 // The mask operand contains the special register (R Bit) in bit 4, whether
3763 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
3764 // bits 3-0 contains the fields to be accessed in the special register, set by
3765 // the flags provided with the register.
3766 int Mask = 0;
3767 if (Reg == "apsr") {
3768 // The flags permitted for apsr are the same flags that are allowed in
3769 // M class registers. We get the flag value and then shift the flags into
3770 // the correct place to combine with the mask.
John Brawne60f4e42017-02-10 17:41:08 +00003771 Mask = getMClassFlagsMask(Flags);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003772 if (Mask == -1)
3773 return -1;
3774 return Mask << 2;
3775 }
3776
3777 if (Reg != "cpsr" && Reg != "spsr") {
3778 return -1;
3779 }
3780
3781 // This is the same as if the flags were "fc"
3782 if (Flags.empty() || Flags == "all")
3783 return Mask | 0x9;
3784
3785 // Inspect the supplied flags string and set the bits in the mask for
3786 // the relevant and valid flags allowed for cpsr and spsr.
3787 for (char Flag : Flags) {
3788 int FlagVal;
3789 switch (Flag) {
3790 case 'c':
3791 FlagVal = 0x1;
3792 break;
3793 case 'x':
3794 FlagVal = 0x2;
3795 break;
3796 case 's':
3797 FlagVal = 0x4;
3798 break;
3799 case 'f':
3800 FlagVal = 0x8;
3801 break;
3802 default:
3803 FlagVal = 0;
3804 }
3805
3806 // This avoids allowing strings where the same flag bit appears twice.
3807 if (!FlagVal || (Mask & FlagVal))
3808 return -1;
3809 Mask |= FlagVal;
3810 }
3811
3812 // If the register is spsr then we need to set the R bit.
3813 if (Reg == "spsr")
3814 Mask |= 0x10;
3815
3816 return Mask;
3817}
3818
3819// Lower the read_register intrinsic to ARM specific DAG nodes
3820// using the supplied metadata string to select the instruction node to use
3821// and the registers/masks to construct as operands for the node.
Justin Bogner45571362016-05-12 00:31:09 +00003822bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003823 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3824 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3825 bool IsThumb2 = Subtarget->isThumb2();
3826 SDLoc DL(N);
3827
3828 std::vector<SDValue> Ops;
3829 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3830
3831 if (!Ops.empty()) {
3832 // If the special register string was constructed of fields (as defined
3833 // in the ACLE) then need to lower to MRC node (32 bit) or
3834 // MRRC node(64 bit), we can make the distinction based on the number of
3835 // operands we have.
3836 unsigned Opcode;
3837 SmallVector<EVT, 3> ResTypes;
3838 if (Ops.size() == 5){
3839 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
3840 ResTypes.append({ MVT::i32, MVT::Other });
3841 } else {
3842 assert(Ops.size() == 3 &&
3843 "Invalid number of fields in special register string.");
3844 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
3845 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
3846 }
3847
3848 Ops.push_back(getAL(CurDAG, DL));
3849 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3850 Ops.push_back(N->getOperand(0));
Justin Bogner45571362016-05-12 00:31:09 +00003851 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops));
3852 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003853 }
3854
3855 std::string SpecialReg = RegString->getString().lower();
3856
3857 int BankedReg = getBankedRegisterMask(SpecialReg);
3858 if (BankedReg != -1) {
3859 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
3860 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3861 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003862 ReplaceNode(
3863 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
3864 DL, MVT::i32, MVT::Other, Ops));
3865 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003866 }
3867
3868 // The VFP registers are read by creating SelectionDAG nodes with opcodes
3869 // corresponding to the register that is being read from. So we switch on the
3870 // string to find which opcode we need to use.
3871 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3872 .Case("fpscr", ARM::VMRS)
3873 .Case("fpexc", ARM::VMRS_FPEXC)
3874 .Case("fpsid", ARM::VMRS_FPSID)
3875 .Case("mvfr0", ARM::VMRS_MVFR0)
3876 .Case("mvfr1", ARM::VMRS_MVFR1)
3877 .Case("mvfr2", ARM::VMRS_MVFR2)
3878 .Case("fpinst", ARM::VMRS_FPINST)
3879 .Case("fpinst2", ARM::VMRS_FPINST2)
3880 .Default(0);
3881
3882 // If an opcode was found then we can lower the read to a VFP instruction.
3883 if (Opcode) {
3884 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00003885 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003886 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
Justin Bogner45571362016-05-12 00:31:09 +00003887 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003888
3889 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3890 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003891 ReplaceNode(N,
3892 CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops));
3893 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003894 }
3895
3896 // If the target is M Class then need to validate that the register string
3897 // is an acceptable value, so check that a mask can be constructed from the
3898 // string.
3899 if (Subtarget->isMClass()) {
Javed Absar2cb0c952017-07-19 12:57:16 +00003900 int SYSmValue = getMClassRegisterMask(SpecialReg, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003901 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00003902 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003903
3904 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
3905 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3906 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003907 ReplaceNode(
3908 N, CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops));
3909 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003910 }
3911
3912 // Here we know the target is not M Class so we need to check if it is one
3913 // of the remaining possible values which are apsr, cpsr or spsr.
3914 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
3915 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3916 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003917 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
3918 DL, MVT::i32, MVT::Other, Ops));
3919 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003920 }
3921
3922 if (SpecialReg == "spsr") {
3923 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3924 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003925 ReplaceNode(
3926 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys, DL,
3927 MVT::i32, MVT::Other, Ops));
3928 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003929 }
3930
Justin Bogner45571362016-05-12 00:31:09 +00003931 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003932}
3933
3934// Lower the write_register intrinsic to ARM specific DAG nodes
3935// using the supplied metadata string to select the instruction node to use
3936// and the registers/masks to use in the nodes
Justin Bogner45571362016-05-12 00:31:09 +00003937bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003938 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3939 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3940 bool IsThumb2 = Subtarget->isThumb2();
3941 SDLoc DL(N);
3942
3943 std::vector<SDValue> Ops;
3944 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3945
3946 if (!Ops.empty()) {
3947 // If the special register string was constructed of fields (as defined
3948 // in the ACLE) then need to lower to MCR node (32 bit) or
3949 // MCRR node(64 bit), we can make the distinction based on the number of
3950 // operands we have.
3951 unsigned Opcode;
3952 if (Ops.size() == 5) {
3953 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
3954 Ops.insert(Ops.begin()+2, N->getOperand(2));
3955 } else {
3956 assert(Ops.size() == 3 &&
3957 "Invalid number of fields in special register string.");
3958 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
3959 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
3960 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
3961 }
3962
3963 Ops.push_back(getAL(CurDAG, DL));
3964 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3965 Ops.push_back(N->getOperand(0));
3966
Justin Bogner45571362016-05-12 00:31:09 +00003967 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
3968 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003969 }
3970
3971 std::string SpecialReg = RegString->getString().lower();
3972 int BankedReg = getBankedRegisterMask(SpecialReg);
3973 if (BankedReg != -1) {
3974 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
3975 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3976 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003977 ReplaceNode(
3978 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
3979 DL, MVT::Other, Ops));
3980 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003981 }
3982
3983 // The VFP registers are written to by creating SelectionDAG nodes with
3984 // opcodes corresponding to the register that is being written. So we switch
3985 // on the string to find which opcode we need to use.
3986 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3987 .Case("fpscr", ARM::VMSR)
3988 .Case("fpexc", ARM::VMSR_FPEXC)
3989 .Case("fpsid", ARM::VMSR_FPSID)
3990 .Case("fpinst", ARM::VMSR_FPINST)
3991 .Case("fpinst2", ARM::VMSR_FPINST2)
3992 .Default(0);
3993
3994 if (Opcode) {
3995 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00003996 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003997 Ops = { N->getOperand(2), getAL(CurDAG, DL),
3998 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003999 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4000 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004001 }
4002
Bradley Smithf277c8a2016-01-25 11:25:36 +00004003 std::pair<StringRef, StringRef> Fields;
4004 Fields = StringRef(SpecialReg).rsplit('_');
4005 std::string Reg = Fields.first.str();
4006 StringRef Flags = Fields.second;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004007
4008 // If the target was M Class then need to validate the special register value
4009 // and retrieve the mask for use in the instruction node.
4010 if (Subtarget->isMClass()) {
Javed Absar2cb0c952017-07-19 12:57:16 +00004011 int SYSmValue = getMClassRegisterMask(SpecialReg, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004012 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004013 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004014
4015 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4016 N->getOperand(2), getAL(CurDAG, DL),
4017 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004018 ReplaceNode(N, CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops));
4019 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004020 }
4021
4022 // We then check to see if a valid mask can be constructed for one of the
4023 // register string values permitted for the A and R class cores. These values
4024 // are apsr, spsr and cpsr; these are also valid on older cores.
4025 int Mask = getARClassRegisterMask(Reg, Flags);
4026 if (Mask != -1) {
4027 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
4028 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4029 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004030 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
4031 DL, MVT::Other, Ops));
4032 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004033 }
4034
Justin Bogner45571362016-05-12 00:31:09 +00004035 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004036}
4037
Justin Bogner45571362016-05-12 00:31:09 +00004038bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){
Weiming Zhaoc5987002013-02-14 18:10:21 +00004039 std::vector<SDValue> AsmNodeOperands;
4040 unsigned Flag, Kind;
4041 bool Changed = false;
4042 unsigned NumOps = N->getNumOperands();
4043
Weiming Zhaoc5987002013-02-14 18:10:21 +00004044 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
4045 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
4046 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
4047 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004048 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
4049 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
4050 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00004051
Andrew Trickef9de2a2013-05-25 02:42:55 +00004052 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00004053 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
4054 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004055
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004056 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004057 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004058 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00004059 SDValue op = N->getOperand(i);
4060 AsmNodeOperands.push_back(op);
4061
4062 if (i < InlineAsm::Op_FirstOperand)
4063 continue;
4064
4065 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
4066 Flag = C->getZExtValue();
4067 Kind = InlineAsm::getKind(Flag);
4068 }
4069 else
4070 continue;
4071
Joey Gouly392cdad2013-07-08 19:52:51 +00004072 // Immediate operands to inline asm in the SelectionDAG are modeled with
4073 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
4074 // the second is a constant with the value of the immediate. If we get here
4075 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00004076 if (Kind == InlineAsm::Kind_Imm) {
4077 SDValue op = N->getOperand(++i);
4078 AsmNodeOperands.push_back(op);
4079 continue;
4080 }
4081
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004082 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
4083 if (NumRegs)
4084 OpChanged.push_back(false);
4085
4086 unsigned DefIdx = 0;
4087 bool IsTiedToChangedOp = false;
4088 // If it's a use that is tied with a previous def, it has no
4089 // reg class constraint.
4090 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
4091 IsTiedToChangedOp = OpChanged[DefIdx];
4092
Diana Picusf345d402016-07-20 09:48:24 +00004093 // Memory operands to inline asm in the SelectionDAG are modeled with two
4094 // operands: a constant of value InlineAsm::Kind_Mem followed by the input
4095 // operand. If we get here and we have a Kind_Mem, skip the next operand (so
4096 // it doesn't get misinterpreted), and continue. We do this here because
4097 // it's important to update the OpChanged array correctly before moving on.
4098 if (Kind == InlineAsm::Kind_Mem) {
4099 SDValue op = N->getOperand(++i);
4100 AsmNodeOperands.push_back(op);
4101 continue;
4102 }
4103
Weiming Zhaoc5987002013-02-14 18:10:21 +00004104 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
4105 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
4106 continue;
4107
Weiming Zhaoc5987002013-02-14 18:10:21 +00004108 unsigned RC;
4109 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004110 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
4111 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00004112 continue;
4113
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004114 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00004115 SDValue V0 = N->getOperand(i+1);
4116 SDValue V1 = N->getOperand(i+2);
4117 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
4118 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
4119 SDValue PairedReg;
4120 MachineRegisterInfo &MRI = MF->getRegInfo();
4121
4122 if (Kind == InlineAsm::Kind_RegDef ||
4123 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
4124 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
4125 // the original GPRs.
4126
4127 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4128 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4129 SDValue Chain = SDValue(N,0);
4130
4131 SDNode *GU = N->getGluedUser();
4132 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
4133 Chain.getValue(1));
4134
4135 // Extract values from a GPRPair reg and copy to the original GPR reg.
4136 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4137 RegCopy);
4138 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4139 RegCopy);
4140 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
4141 RegCopy.getValue(1));
4142 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
4143
4144 // Update the original glue user.
4145 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
4146 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00004147 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004148 }
4149 else {
4150 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
4151 // GPRPair and then pass the GPRPair to the inline asm.
4152 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
4153
4154 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
4155 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
4156 Chain.getValue(1));
4157 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
4158 T0.getValue(1));
4159 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
4160
4161 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
4162 // i32 VRs of inline asm with it.
4163 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4164 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4165 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
4166
4167 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
4168 Glue = Chain.getValue(1);
4169 }
4170
4171 Changed = true;
4172
4173 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004174 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004175 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00004176 if (IsTiedToChangedOp)
4177 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
4178 else
4179 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004180 // Replace the current flag.
4181 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00004182 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004183 // Add the new register node and skip the original two GPRs.
4184 AsmNodeOperands.push_back(PairedReg);
4185 // Skip the next two GPRs.
4186 i += 2;
4187 }
4188 }
4189
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004190 if (Glue.getNode())
4191 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004192 if (!Changed)
Justin Bogner45571362016-05-12 00:31:09 +00004193 return false;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004194
Andrew Trickef9de2a2013-05-25 02:42:55 +00004195 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00004196 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004197 New->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00004198 ReplaceNode(N, New.getNode());
4199 return true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004200}
4201
4202
Bob Wilsona2c462b2009-05-19 05:53:42 +00004203bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00004204SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00004205 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004206 switch(ConstraintID) {
4207 default:
4208 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00004209 case InlineAsm::Constraint_i:
4210 // FIXME: It seems strange that 'i' is needed here since it's supposed to
4211 // be an immediate and not a memory constraint.
Justin Bognerb03fd122016-08-17 05:10:15 +00004212 LLVM_FALLTHROUGH;
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004213 case InlineAsm::Constraint_m:
James Molloy72222f52015-10-26 10:04:52 +00004214 case InlineAsm::Constraint_o:
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004215 case InlineAsm::Constraint_Q:
4216 case InlineAsm::Constraint_Um:
4217 case InlineAsm::Constraint_Un:
4218 case InlineAsm::Constraint_Uq:
4219 case InlineAsm::Constraint_Us:
4220 case InlineAsm::Constraint_Ut:
4221 case InlineAsm::Constraint_Uv:
4222 case InlineAsm::Constraint_Uy:
4223 // Require the address to be in a register. That is safe for all ARM
4224 // variants and it is hard to do anything much smarter without knowing
4225 // how the operand is used.
4226 OutOps.push_back(Op);
4227 return false;
4228 }
4229 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00004230}
4231
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004232/// createARMISelDag - This pass converts a legalized DAG into a
4233/// ARM-specific DAG, ready for instruction scheduling.
4234///
Bob Wilson2dd957f2009-09-28 14:30:20 +00004235FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
4236 CodeGenOpt::Level OptLevel) {
4237 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004238}