blob: b5eb57cfb8efc75c6327199f56658b0499388dd8 [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
Ivan A. Kosarev72315982018-06-27 13:57:52 +0000206 /// for loading D registers.
207 void SelectVLDDup(SDNode *N, bool IsIntrinsic, bool isUpdating,
208 unsigned NumVecs, const uint16_t *DOpcodes,
209 const uint16_t *QOpcodes0 = nullptr,
210 const uint16_t *QOpcodes1 = nullptr);
Bob Wilson2d790df2010-11-28 06:51:26 +0000211
Justin Bogner45571362016-05-12 00:31:09 +0000212 /// Try to select SBFX/UBFX instructions for ARM.
213 bool tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000214
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000215 // Select special operations if node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +0000216 bool tryABSOp(SDNode *N);
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000217
Justin Bogner45571362016-05-12 00:31:09 +0000218 bool tryReadRegister(SDNode *N);
219 bool tryWriteRegister(SDNode *N);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +0000220
Justin Bogner45571362016-05-12 00:31:09 +0000221 bool tryInlineAsm(SDNode *N);
Weiming Zhaoc5987002013-02-14 18:10:21 +0000222
Sjoerd Meijer96e10b52016-12-15 09:38:59 +0000223 void SelectCMPZ(SDNode *N, bool &SwitchEQNEToPLMI);
James Molloye7d97362016-11-03 14:08:01 +0000224
Justin Bogner45571362016-05-12 00:31:09 +0000225 void SelectCMP_SWAP(SDNode *N);
Tim Northoverb629c772016-04-18 21:48:55 +0000226
Evan Chengd9c55362009-07-02 01:23:32 +0000227 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
228 /// inline asm expressions.
Daniel Sanders60f1db02015-03-13 12:45:09 +0000229 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Craig Topper6bc27bf2014-03-10 02:09:33 +0000230 std::vector<SDValue> &OutOps) override;
Bob Wilsone6b778d2009-10-06 22:01:59 +0000231
Weiming Zhao95782222012-11-17 00:23:35 +0000232 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhao8f56f882012-11-16 21:55:34 +0000233 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao95782222012-11-17 00:23:35 +0000234 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
235 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
236 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Chengc2ae5f52010-05-10 17:34:18 +0000237
Bob Wilsond8a9a042010-06-04 00:04:02 +0000238 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +0000239 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
240 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
241 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000242
243 // Get the alignment operand for a NEON VLD or VST instruction.
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000244 SDValue GetVLDSTAlign(SDValue Align, const SDLoc &dl, unsigned NumVecs,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000245 bool is64BitVector);
John Brawn056e6782015-09-14 15:19:41 +0000246
247 /// Returns the number of instructions required to materialize the given
248 /// constant in a register, or 3 if a literal pool load is needed.
249 unsigned ConstantMaterializationCost(unsigned Val) const;
250
251 /// Checks if N is a multiplication by a constant where we can extract out a
252 /// power of two from the constant so that it can be used in a shift, but only
253 /// if it simplifies the materialization of the constant. Returns true if it
254 /// is, and assigns to PowerOfTwo the power of two that should be extracted
255 /// out and to NewMulConst the new constant to be multiplied by.
256 bool canExtractShiftFromMul(const SDValue &N, unsigned MaxShift,
257 unsigned &PowerOfTwo, SDValue &NewMulConst) const;
258
259 /// Replace N with M in CurDAG, in a way that also ensures that M gets
260 /// selected when N would have been selected.
261 void replaceDAGValue(const SDValue &N, SDValue M);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000262};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000263}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000264
Sandeep Patel423e42b2009-10-13 18:59:48 +0000265/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
266/// operand. If so Imm will receive the 32-bit value.
267static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
268 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
269 Imm = cast<ConstantSDNode>(N)->getZExtValue();
270 return true;
271 }
272 return false;
273}
274
275// isInt32Immediate - This method tests to see if a constant operand.
276// If so Imm will receive the 32 bit value.
277static bool isInt32Immediate(SDValue N, unsigned &Imm) {
278 return isInt32Immediate(N.getNode(), Imm);
279}
280
281// isOpcWithIntImmediate - This method tests to see if the node is a specific
282// opcode and that it has a immediate integer right operand.
283// If so Imm will receive the 32 bit value.
284static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
285 return N->getOpcode() == Opc &&
286 isInt32Immediate(N->getOperand(1).getNode(), Imm);
287}
288
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000289/// Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000290/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000291///
292/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000293static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000294 int RangeMin, int RangeMax,
295 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000296 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000297
298 // Check that this is a constant.
299 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
300 if (!C)
301 return false;
302
303 ScaledConstant = (int) C->getZExtValue();
304 if ((ScaledConstant % Scale) != 0)
305 return false;
306
307 ScaledConstant /= Scale;
308 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
309}
310
Evan Chengeae6d2c2012-12-19 20:16:09 +0000311void ARMDAGToDAGISel::PreprocessISelDAG() {
312 if (!Subtarget->hasV6T2Ops())
313 return;
314
315 bool isThumb2 = Subtarget->isThumb();
316 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
317 E = CurDAG->allnodes_end(); I != E; ) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000318 SDNode *N = &*I++; // Preincrement iterator to avoid invalidation issues.
Evan Chengeae6d2c2012-12-19 20:16:09 +0000319
320 if (N->getOpcode() != ISD::ADD)
321 continue;
322
323 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
324 // leading zeros, followed by consecutive set bits, followed by 1 or 2
325 // trailing zeros, e.g. 1020.
326 // Transform the expression to
327 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
328 // of trailing zeros of c2. The left shift would be folded as an shifter
329 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
330 // node (UBFX).
331
332 SDValue N0 = N->getOperand(0);
333 SDValue N1 = N->getOperand(1);
334 unsigned And_imm = 0;
335 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
336 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
337 std::swap(N0, N1);
338 }
339 if (!And_imm)
340 continue;
341
342 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000343 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000344 if (TZ != 1 && TZ != 2)
345 // Be conservative here. Shifter operands aren't always free. e.g. On
346 // Swift, left shifter operand of 1 / 2 for free but others are not.
347 // e.g.
348 // ubfx r3, r1, #16, #8
349 // ldr.w r3, [r0, r3, lsl #2]
350 // vs.
351 // mov.w r9, #1020
352 // and.w r2, r9, r1, lsr #14
353 // ldr r2, [r0, r2]
354 continue;
355 And_imm >>= TZ;
356 if (And_imm & (And_imm + 1))
357 continue;
358
359 // Look for (and (srl X, c1), c2).
360 SDValue Srl = N1.getOperand(0);
361 unsigned Srl_imm = 0;
362 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
363 (Srl_imm <= 2))
364 continue;
365
366 // Make sure first operand is not a shifter operand which would prevent
367 // folding of the left shift.
368 SDValue CPTmp0;
369 SDValue CPTmp1;
370 SDValue CPTmp2;
371 if (isThumb2) {
John Brawnd8b405a2015-09-07 11:45:18 +0000372 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
Evan Chengeae6d2c2012-12-19 20:16:09 +0000373 continue;
374 } else {
375 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
376 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
377 continue;
378 }
379
380 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000381 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000382 Srl.getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000383 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl),
384 MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000385 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000386 Srl,
387 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000388 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000389 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32));
Evan Chengeae6d2c2012-12-19 20:16:09 +0000390 CurDAG->UpdateNodeOperands(N, N0, N1);
Jim Grosbach1a597112014-04-03 23:43:18 +0000391 }
Evan Chengeae6d2c2012-12-19 20:16:09 +0000392}
393
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000394/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
395/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
396/// least on current ARM implementations) which should be avoidded.
397bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
398 if (OptLevel == CodeGenOpt::None)
399 return true;
400
Diana Picus575f2bb2016-07-07 09:11:39 +0000401 if (!Subtarget->hasVMLxHazards())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000402 return true;
403
404 if (!N->hasOneUse())
405 return false;
406
407 SDNode *Use = *N->use_begin();
408 if (Use->getOpcode() == ISD::CopyToReg)
409 return true;
410 if (Use->isMachineOpcode()) {
Eric Christopher2f991c92014-07-03 22:24:49 +0000411 const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>(
Eric Christopherfc6de422014-08-05 02:39:49 +0000412 CurDAG->getSubtarget().getInstrInfo());
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000413
Evan Cheng6cc775f2011-06-28 19:10:37 +0000414 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
415 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000416 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000417 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000418 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
419 return true;
420 // vmlx feeding into another vmlx. We actually want to unfold
421 // the use later in the MLxExpansion pass. e.g.
422 // vmla
423 // vmla (stall 8 cycles)
424 //
425 // vmul (5 cycles)
426 // vadd (5 cycles)
427 // vmla
428 // This adds up to about 18 - 19 cycles.
429 //
430 // vmla
431 // vmul (stall 4 cycles)
432 // vadd adds up to about 14 cycles.
433 return TII->isFpMLxInstruction(Opcode);
434 }
435
436 return false;
437}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000438
Evan Cheng59bbc542010-10-27 23:41:30 +0000439bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
440 ARM_AM::ShiftOpc ShOpcVal,
441 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000442 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000443 return true;
444 if (Shift.hasOneUse())
445 return true;
446 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000447 return ShOpcVal == ARM_AM::lsl &&
448 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000449}
450
John Brawn056e6782015-09-14 15:19:41 +0000451unsigned ARMDAGToDAGISel::ConstantMaterializationCost(unsigned Val) const {
452 if (Subtarget->isThumb()) {
453 if (Val <= 255) return 1; // MOV
Weiming Zhaof68a6a72016-08-05 20:58:29 +0000454 if (Subtarget->hasV6T2Ops() &&
455 (Val <= 0xffff || ARM_AM::getT2SOImmValSplatVal(Val) != -1))
456 return 1; // MOVW
James Molloy65b6be12016-06-14 13:33:07 +0000457 if (Val <= 510) return 2; // MOV + ADDi8
John Brawn056e6782015-09-14 15:19:41 +0000458 if (~Val <= 255) return 2; // MOV + MVN
459 if (ARM_AM::isThumbImmShiftedVal(Val)) return 2; // MOV + LSL
460 } else {
461 if (ARM_AM::getSOImmVal(Val) != -1) return 1; // MOV
462 if (ARM_AM::getSOImmVal(~Val) != -1) return 1; // MVN
463 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
464 if (ARM_AM::isSOImmTwoPartVal(Val)) return 2; // two instrs
465 }
466 if (Subtarget->useMovt(*MF)) return 2; // MOVW + MOVT
467 return 3; // Literal pool load
468}
469
470bool ARMDAGToDAGISel::canExtractShiftFromMul(const SDValue &N,
471 unsigned MaxShift,
472 unsigned &PowerOfTwo,
473 SDValue &NewMulConst) const {
474 assert(N.getOpcode() == ISD::MUL);
475 assert(MaxShift > 0);
476
477 // If the multiply is used in more than one place then changing the constant
478 // will make other uses incorrect, so don't.
479 if (!N.hasOneUse()) return false;
480 // Check if the multiply is by a constant
481 ConstantSDNode *MulConst = dyn_cast<ConstantSDNode>(N.getOperand(1));
482 if (!MulConst) return false;
483 // If the constant is used in more than one place then modifying it will mean
484 // we need to materialize two constants instead of one, which is a bad idea.
485 if (!MulConst->hasOneUse()) return false;
486 unsigned MulConstVal = MulConst->getZExtValue();
487 if (MulConstVal == 0) return false;
488
489 // Find the largest power of 2 that MulConstVal is a multiple of
490 PowerOfTwo = MaxShift;
491 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
492 --PowerOfTwo;
493 if (PowerOfTwo == 0) return false;
494 }
495
496 // Only optimise if the new cost is better
497 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
498 NewMulConst = CurDAG->getConstant(NewMulConstVal, SDLoc(N), MVT::i32);
499 unsigned OldCost = ConstantMaterializationCost(MulConstVal);
500 unsigned NewCost = ConstantMaterializationCost(NewMulConstVal);
501 return NewCost < OldCost;
502}
503
504void ARMDAGToDAGISel::replaceDAGValue(const SDValue &N, SDValue M) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000505 CurDAG->RepositionNode(N.getNode()->getIterator(), M.getNode());
Nirav Dave3264c1b2018-03-19 20:19:46 +0000506 ReplaceUses(N, M);
John Brawn056e6782015-09-14 15:19:41 +0000507}
508
Owen Andersonb595ed02011-07-21 18:54:16 +0000509bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000510 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000511 SDValue &Opc,
512 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000513 if (DisableShifterOp)
514 return false;
515
John Brawn056e6782015-09-14 15:19:41 +0000516 // If N is a multiply-by-constant and it's profitable to extract a shift and
517 // use it in a shifted operand do so.
518 if (N.getOpcode() == ISD::MUL) {
519 unsigned PowerOfTwo = 0;
520 SDValue NewMulConst;
521 if (canExtractShiftFromMul(N, 31, PowerOfTwo, NewMulConst)) {
Justin Bogner8752be72016-05-05 01:43:49 +0000522 HandleSDNode Handle(N);
Benjamin Kramer58dadd52017-04-20 18:29:14 +0000523 SDLoc Loc(N);
John Brawn056e6782015-09-14 15:19:41 +0000524 replaceDAGValue(N.getOperand(1), NewMulConst);
Justin Bogner8752be72016-05-05 01:43:49 +0000525 BaseReg = Handle.getValue();
Benjamin Kramer58dadd52017-04-20 18:29:14 +0000526 Opc = CurDAG->getTargetConstant(
527 ARM_AM::getSORegOpc(ARM_AM::lsl, PowerOfTwo), Loc, MVT::i32);
John Brawn056e6782015-09-14 15:19:41 +0000528 return true;
529 }
530 }
531
Evan Chenga20cde32011-07-20 23:34:39 +0000532 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000533
534 // Don't match base register only case. That is matched to a separate
535 // lower complexity pattern with explicit register operand.
536 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000537
Evan Chengb23b50d2009-06-29 07:51:04 +0000538 BaseReg = N.getOperand(0);
539 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000540 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
541 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000542 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000543 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000544 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000545 return true;
546}
547
Owen Andersonb595ed02011-07-21 18:54:16 +0000548bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
549 SDValue &BaseReg,
550 SDValue &ShReg,
551 SDValue &Opc,
552 bool CheckProfitability) {
553 if (DisableShifterOp)
554 return false;
555
556 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
557
558 // Don't match base register only case. That is matched to a separate
559 // lower complexity pattern with explicit register operand.
560 if (ShOpcVal == ARM_AM::no_shift) return false;
561
562 BaseReg = N.getOperand(0);
563 unsigned ShImmVal = 0;
564 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
565 if (RHS) return false;
566
567 ShReg = N.getOperand(1);
568 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
569 return false;
570 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000571 SDLoc(N), MVT::i32);
Owen Andersonb595ed02011-07-21 18:54:16 +0000572 return true;
573}
574
Tim Northover644a8192018-06-20 12:09:44 +0000575// Determine whether an ISD::OR's operands are suitable to turn the operation
576// into an addition, which often has more compact encodings.
577bool ARMDAGToDAGISel::SelectAddLikeOr(SDNode *Parent, SDValue N, SDValue &Out) {
578 assert(Parent->getOpcode() == ISD::OR && "unexpected parent");
579 Out = N;
580 return CurDAG->haveNoCommonBitsSet(N, Parent->getOperand(1));
581}
582
Owen Andersonb595ed02011-07-21 18:54:16 +0000583
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000584bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
585 SDValue &Base,
586 SDValue &OffImm) {
587 // Match simple R + imm12 operands.
588
589 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000590 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
591 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000592 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000593 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000594 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000595 Base = CurDAG->getTargetFrameIndex(
596 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000597 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000598 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000599 }
Owen Anderson6d557452011-03-18 19:46:58 +0000600
Chris Lattner46c01a32011-02-13 22:25:43 +0000601 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000602 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000603 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000604 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000605 Base = N.getOperand(0);
606 } else
607 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000608 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000609 return true;
610 }
611
612 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Renato Golin63e27982014-09-09 09:57:59 +0000613 int RHSC = (int)RHS->getSExtValue();
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000614 if (N.getOpcode() == ISD::SUB)
615 RHSC = -RHSC;
616
Renato Golin63e27982014-09-09 09:57:59 +0000617 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000618 Base = N.getOperand(0);
619 if (Base.getOpcode() == ISD::FrameIndex) {
620 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000621 Base = CurDAG->getTargetFrameIndex(
622 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000623 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000624 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000625 return true;
626 }
627 }
628
629 // Base only.
630 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000631 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000632 return true;
633}
634
635
636
637bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
638 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000639 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000640 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000641 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
642 // X * [3,5,9] -> X + X * [2,4,8] etc.
643 int RHSC = (int)RHS->getZExtValue();
644 if (RHSC & 1) {
645 RHSC = RHSC & ~1;
646 ARM_AM::AddrOpc AddSub = ARM_AM::add;
647 if (RHSC < 0) {
648 AddSub = ARM_AM::sub;
649 RHSC = - RHSC;
650 }
651 if (isPowerOf2_32(RHSC)) {
652 unsigned ShAmt = Log2_32(RHSC);
653 Base = Offset = N.getOperand(0);
654 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
655 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000656 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000657 return true;
658 }
659 }
660 }
661 }
662
Chris Lattner46c01a32011-02-13 22:25:43 +0000663 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
664 // ISD::OR that is equivalent to an ISD::ADD.
665 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000666 return false;
667
668 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000669 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000670 int RHSC;
671 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
672 -0x1000+1, 0x1000, RHSC)) // 12 bits.
673 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000674 }
675
676 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000677 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000678 ARM_AM::ShiftOpc ShOpcVal =
679 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000680 unsigned ShAmt = 0;
681
682 Base = N.getOperand(0);
683 Offset = N.getOperand(1);
684
685 if (ShOpcVal != ARM_AM::no_shift) {
686 // Check to see if the RHS of the shift is a constant, if not, we can't fold
687 // it.
688 if (ConstantSDNode *Sh =
689 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
690 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000691 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
692 Offset = N.getOperand(1).getOperand(0);
693 else {
694 ShAmt = 0;
695 ShOpcVal = ARM_AM::no_shift;
696 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000697 } else {
698 ShOpcVal = ARM_AM::no_shift;
699 }
700 }
701
702 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000703 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000704 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
705 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000706 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000707 if (ShOpcVal != ARM_AM::no_shift) {
708 // Check to see if the RHS of the shift is a constant, if not, we can't
709 // fold it.
710 if (ConstantSDNode *Sh =
711 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
712 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000713 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000714 Offset = N.getOperand(0).getOperand(0);
715 Base = N.getOperand(1);
716 } else {
717 ShAmt = 0;
718 ShOpcVal = ARM_AM::no_shift;
719 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000720 } else {
721 ShOpcVal = ARM_AM::no_shift;
722 }
723 }
724 }
725
John Brawn056e6782015-09-14 15:19:41 +0000726 // If Offset is a multiply-by-constant and it's profitable to extract a shift
727 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +0000728 if (Offset.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +0000729 unsigned PowerOfTwo = 0;
730 SDValue NewMulConst;
731 if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) {
Tim Northover4a01ffb2017-05-02 22:45:19 +0000732 HandleSDNode Handle(Offset);
John Brawn056e6782015-09-14 15:19:41 +0000733 replaceDAGValue(Offset.getOperand(1), NewMulConst);
Tim Northover4a01ffb2017-05-02 22:45:19 +0000734 Offset = Handle.getValue();
John Brawn056e6782015-09-14 15:19:41 +0000735 ShAmt = PowerOfTwo;
736 ShOpcVal = ARM_AM::lsl;
737 }
738 }
739
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000740 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000741 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000742 return true;
743}
744
Owen Anderson2aedba62011-07-26 20:54:26 +0000745bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000746 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000747 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000748 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
749 ? cast<LoadSDNode>(Op)->getAddressingMode()
750 : cast<StoreSDNode>(Op)->getAddressingMode();
751 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
752 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000753 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000754 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
755 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000756
757 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000758 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000759 unsigned ShAmt = 0;
760 if (ShOpcVal != ARM_AM::no_shift) {
761 // Check to see if the RHS of the shift is a constant, if not, we can't fold
762 // it.
763 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000764 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000765 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
766 Offset = N.getOperand(0);
767 else {
768 ShAmt = 0;
769 ShOpcVal = ARM_AM::no_shift;
770 }
Evan Cheng10043e22007-01-19 07:51:42 +0000771 } else {
772 ShOpcVal = ARM_AM::no_shift;
773 }
774 }
775
776 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000777 SDLoc(N), MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000778 return true;
779}
780
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000781bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
782 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000783 unsigned Opcode = Op->getOpcode();
784 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
785 ? cast<LoadSDNode>(Op)->getAddressingMode()
786 : cast<StoreSDNode>(Op)->getAddressingMode();
787 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
788 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000789 int Val;
790 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000791 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000792 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000793 Opc = CurDAG->getTargetConstant(Val, SDLoc(Op), MVT::i32);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000794 return true;
795 }
796
797 return false;
798}
799
800
Owen Anderson2aedba62011-07-26 20:54:26 +0000801bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
802 SDValue &Offset, SDValue &Opc) {
803 unsigned Opcode = Op->getOpcode();
804 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
805 ? cast<LoadSDNode>(Op)->getAddressingMode()
806 : cast<StoreSDNode>(Op)->getAddressingMode();
807 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
808 ? ARM_AM::add : ARM_AM::sub;
809 int Val;
810 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
811 Offset = CurDAG->getRegister(0, MVT::i32);
812 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
813 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000814 SDLoc(Op), MVT::i32);
Owen Anderson2aedba62011-07-26 20:54:26 +0000815 return true;
816 }
817
818 return false;
819}
820
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000821bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
822 Base = N;
823 return true;
824}
Evan Cheng10043e22007-01-19 07:51:42 +0000825
Chris Lattner0e023ea2010-09-21 20:31:19 +0000826bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000827 SDValue &Base, SDValue &Offset,
828 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000829 if (N.getOpcode() == ISD::SUB) {
830 // X - C is canonicalize to X + -C, no need to handle it here.
831 Base = N.getOperand(0);
832 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000833 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0), SDLoc(N),
834 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000835 return true;
836 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000837
Chris Lattner46c01a32011-02-13 22:25:43 +0000838 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000839 Base = N;
840 if (N.getOpcode() == ISD::FrameIndex) {
841 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000842 Base = CurDAG->getTargetFrameIndex(
843 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +0000844 }
Owen Anderson9f944592009-08-11 20:47:22 +0000845 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000846 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
847 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000848 return true;
849 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000850
Evan Cheng10043e22007-01-19 07:51:42 +0000851 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000852 int RHSC;
853 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
854 -256 + 1, 256, RHSC)) { // 8 bits.
855 Base = N.getOperand(0);
856 if (Base.getOpcode() == ISD::FrameIndex) {
857 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000858 Base = CurDAG->getTargetFrameIndex(
859 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +0000860 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000861 Offset = CurDAG->getRegister(0, MVT::i32);
862
863 ARM_AM::AddrOpc AddSub = ARM_AM::add;
864 if (RHSC < 0) {
865 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000866 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000867 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000868 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC), SDLoc(N),
869 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000870 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000871 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000872
Evan Cheng10043e22007-01-19 07:51:42 +0000873 Base = N.getOperand(0);
874 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000875 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
876 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000877 return true;
878}
879
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000880bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000881 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000882 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000883 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
884 ? cast<LoadSDNode>(Op)->getAddressingMode()
885 : cast<StoreSDNode>(Op)->getAddressingMode();
886 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
887 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000888 int Val;
889 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
890 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000891 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), SDLoc(Op),
892 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000893 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000894 }
895
896 Offset = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000897 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), SDLoc(Op),
898 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000899 return true;
900}
901
Sjoerd Meijer011de9c2018-01-26 09:26:40 +0000902bool ARMDAGToDAGISel::IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offset,
903 int Lwb, int Upb, bool FP16) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000904 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000905 Base = N;
906 if (N.getOpcode() == ISD::FrameIndex) {
907 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000908 Base = CurDAG->getTargetFrameIndex(
909 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +0000910 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000911 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000912 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000913 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000914 Base = N.getOperand(0);
915 }
916 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000917 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000918 return true;
919 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000920
Evan Cheng10043e22007-01-19 07:51:42 +0000921 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000922 int RHSC;
Sjoerd Meijer011de9c2018-01-26 09:26:40 +0000923 const int Scale = FP16 ? 2 : 4;
924
925 if (isScaledConstantInRange(N.getOperand(1), Scale, Lwb, Upb, RHSC)) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000926 Base = N.getOperand(0);
927 if (Base.getOpcode() == ISD::FrameIndex) {
928 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000929 Base = CurDAG->getTargetFrameIndex(
930 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +0000931 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000932
933 ARM_AM::AddrOpc AddSub = ARM_AM::add;
934 if (RHSC < 0) {
935 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000936 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000937 }
Sjoerd Meijer011de9c2018-01-26 09:26:40 +0000938
939 if (FP16)
940 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5FP16Opc(AddSub, RHSC),
941 SDLoc(N), MVT::i32);
942 else
943 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
944 SDLoc(N), MVT::i32);
945
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000946 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000947 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000948
Evan Cheng10043e22007-01-19 07:51:42 +0000949 Base = N;
Sjoerd Meijer011de9c2018-01-26 09:26:40 +0000950
951 if (FP16)
952 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5FP16Opc(ARM_AM::add, 0),
953 SDLoc(N), MVT::i32);
954 else
955 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
956 SDLoc(N), MVT::i32);
957
Evan Cheng10043e22007-01-19 07:51:42 +0000958 return true;
959}
960
Sjoerd Meijer011de9c2018-01-26 09:26:40 +0000961bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
962 SDValue &Base, SDValue &Offset) {
963 int Lwb = -256 + 1;
964 int Upb = 256;
965 return IsAddressingMode5(N, Base, Offset, Lwb, Upb, /*FP16=*/ false);
966}
967
968bool ARMDAGToDAGISel::SelectAddrMode5FP16(SDValue N,
969 SDValue &Base, SDValue &Offset) {
970 int Lwb = -512 + 1;
971 int Upb = 512;
972 return IsAddressingMode5(N, Base, Offset, Lwb, Upb, /*FP16=*/ true);
973}
974
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000975bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
976 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +0000977 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000978
979 unsigned Alignment = 0;
Ahmed Bougachadb141ac2015-02-19 23:52:41 +0000980
981 MemSDNode *MemN = cast<MemSDNode>(Parent);
982
983 if (isa<LSBaseSDNode>(MemN) ||
984 ((MemN->getOpcode() == ARMISD::VST1_UPD ||
985 MemN->getOpcode() == ARMISD::VLD1_UPD) &&
986 MemN->getConstantOperandVal(MemN->getNumOperands() - 1) == 1)) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000987 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
988 // The maximum alignment is equal to the memory size being referenced.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +0000989 unsigned MMOAlign = MemN->getAlignment();
990 unsigned MemSize = MemN->getMemoryVT().getSizeInBits() / 8;
991 if (MMOAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000992 Alignment = MemSize;
993 } else {
994 // All other uses of addrmode6 are for intrinsics. For now just record
995 // the raw alignment value; it will be refined later based on the legal
996 // alignment operands for the intrinsic.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +0000997 Alignment = MemN->getAlignment();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000998 }
999
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001000 Align = CurDAG->getTargetConstant(Alignment, SDLoc(N), MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001001 return true;
1002}
1003
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001004bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1005 SDValue &Offset) {
1006 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1007 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1008 if (AM != ISD::POST_INC)
1009 return false;
1010 Offset = N;
1011 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1012 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1013 Offset = CurDAG->getRegister(0, MVT::i32);
1014 }
1015 return true;
1016}
1017
Chris Lattner0e023ea2010-09-21 20:31:19 +00001018bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001019 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001020 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1021 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001022 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001023 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001024 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001025 return true;
1026 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001027
Evan Cheng10043e22007-01-19 07:51:42 +00001028 return false;
1029}
1030
Bill Wendling092a7bd2010-12-14 03:36:38 +00001031
1032//===----------------------------------------------------------------------===//
1033// Thumb Addressing Modes
1034//===----------------------------------------------------------------------===//
1035
Chris Lattner0e023ea2010-09-21 20:31:19 +00001036bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001037 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001038 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001039 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001040 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001041 return false;
1042
1043 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001044 return true;
1045 }
1046
Evan Cheng10043e22007-01-19 07:51:42 +00001047 Base = N.getOperand(0);
1048 Offset = N.getOperand(1);
1049 return true;
1050}
1051
Evan Cheng139edae2007-01-24 02:21:22 +00001052bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001053ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1054 SDValue &Base, SDValue &OffImm) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001055 if (!CurDAG->isBaseWithConstantOffset(N)) {
John Brawn68acdcb2015-08-13 10:48:22 +00001056 if (N.getOpcode() == ISD::ADD) {
1057 return false; // We want to select register offset instead
1058 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001059 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001060 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
James Molloyb7de4972016-10-05 14:52:13 +00001061 N.getOperand(0).getOpcode() != ISD::TargetConstantPool &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001062 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001063 Base = N.getOperand(0);
1064 } else {
1065 Base = N;
1066 }
1067
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001068 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001069 return true;
1070 }
1071
Evan Cheng10043e22007-01-19 07:51:42 +00001072 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001073 int RHSC;
1074 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1075 Base = N.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001076 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001077 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001078 }
1079
John Brawn68acdcb2015-08-13 10:48:22 +00001080 // Offset is too large, so use register offset instead.
1081 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001082}
1083
Bill Wendling092a7bd2010-12-14 03:36:38 +00001084bool
1085ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1086 SDValue &OffImm) {
1087 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001088}
1089
Bill Wendling092a7bd2010-12-14 03:36:38 +00001090bool
1091ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1092 SDValue &OffImm) {
1093 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001094}
1095
Bill Wendling092a7bd2010-12-14 03:36:38 +00001096bool
1097ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1098 SDValue &OffImm) {
1099 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001100}
1101
Chris Lattner0e023ea2010-09-21 20:31:19 +00001102bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1103 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001104 if (N.getOpcode() == ISD::FrameIndex) {
1105 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001106 // Only multiples of 4 are allowed for the offset, so the frame object
1107 // alignment must be at least 4.
Matthias Braun941a7052016-07-28 18:40:00 +00001108 MachineFrameInfo &MFI = MF->getFrameInfo();
1109 if (MFI.getObjectAlignment(FI) < 4)
1110 MFI.setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001111 Base = CurDAG->getTargetFrameIndex(
1112 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001113 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001114 return true;
1115 }
Evan Cheng139edae2007-01-24 02:21:22 +00001116
Chris Lattner46c01a32011-02-13 22:25:43 +00001117 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001118 return false;
1119
1120 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001121 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1122 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001123 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001124 int RHSC;
1125 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1126 Base = N.getOperand(0);
1127 if (Base.getOpcode() == ISD::FrameIndex) {
1128 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001129 // For LHS+RHS to result in an offset that's a multiple of 4 the object
1130 // indexed by the LHS must be 4-byte aligned.
Matthias Braun941a7052016-07-28 18:40:00 +00001131 MachineFrameInfo &MFI = MF->getFrameInfo();
1132 if (MFI.getObjectAlignment(FI) < 4)
1133 MFI.setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001134 Base = CurDAG->getTargetFrameIndex(
1135 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng139edae2007-01-24 02:21:22 +00001136 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001137 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001138 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001139 }
1140 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001141
Evan Cheng10043e22007-01-19 07:51:42 +00001142 return false;
1143}
1144
Bill Wendling092a7bd2010-12-14 03:36:38 +00001145
1146//===----------------------------------------------------------------------===//
1147// Thumb 2 Addressing Modes
1148//===----------------------------------------------------------------------===//
1149
1150
Chris Lattner0e023ea2010-09-21 20:31:19 +00001151bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001152 SDValue &Base, SDValue &OffImm) {
1153 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001154
Evan Cheng36064672009-08-11 08:52:18 +00001155 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001156 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1157 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001158 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001159 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001160 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001161 Base = CurDAG->getTargetFrameIndex(
1162 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001163 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001164 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001165 }
Owen Anderson6d557452011-03-18 19:46:58 +00001166
Chris Lattner46c01a32011-02-13 22:25:43 +00001167 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001168 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001169 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001170 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng36064672009-08-11 08:52:18 +00001171 Base = N.getOperand(0);
1172 if (Base.getOpcode() == ISD::TargetConstantPool)
1173 return false; // We want to select t2LDRpci instead.
1174 } else
1175 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001176 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001177 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001178 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001179
1180 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001181 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001182 // Let t2LDRi8 handle (R - imm8).
1183 return false;
1184
Evan Chengb23b50d2009-06-29 07:51:04 +00001185 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001186 if (N.getOpcode() == ISD::SUB)
1187 RHSC = -RHSC;
1188
1189 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001190 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001191 if (Base.getOpcode() == ISD::FrameIndex) {
1192 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001193 Base = CurDAG->getTargetFrameIndex(
1194 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin79c079b2009-07-30 18:56:48 +00001195 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001196 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001197 return true;
1198 }
1199 }
1200
Evan Cheng36064672009-08-11 08:52:18 +00001201 // Base only.
1202 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001203 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001204 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001205}
1206
Chris Lattner0e023ea2010-09-21 20:31:19 +00001207bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001208 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001209 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001210 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1211 !CurDAG->isBaseWithConstantOffset(N))
1212 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001213
Chris Lattner46c01a32011-02-13 22:25:43 +00001214 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1215 int RHSC = (int)RHS->getSExtValue();
1216 if (N.getOpcode() == ISD::SUB)
1217 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001218
Chris Lattner46c01a32011-02-13 22:25:43 +00001219 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1220 Base = N.getOperand(0);
1221 if (Base.getOpcode() == ISD::FrameIndex) {
1222 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001223 Base = CurDAG->getTargetFrameIndex(
1224 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Chengb23b50d2009-06-29 07:51:04 +00001225 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001226 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Chris Lattner46c01a32011-02-13 22:25:43 +00001227 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001228 }
1229 }
1230
1231 return false;
1232}
1233
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001234bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001235 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001236 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001237 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1238 ? cast<LoadSDNode>(Op)->getAddressingMode()
1239 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001240 int RHSC;
1241 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1242 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001243 ? CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32)
1244 : CurDAG->getTargetConstant(-RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001245 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001246 }
1247
1248 return false;
1249}
1250
Chris Lattner0e023ea2010-09-21 20:31:19 +00001251bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001252 SDValue &Base,
1253 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001254 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001255 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001256 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001257
Evan Cheng36064672009-08-11 08:52:18 +00001258 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1259 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1260 int RHSC = (int)RHS->getZExtValue();
1261 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1262 return false;
1263 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001264 return false;
1265 }
1266
Evan Chengb23b50d2009-06-29 07:51:04 +00001267 // Look for (R + R) or (R + (R << [1,2,3])).
1268 unsigned ShAmt = 0;
1269 Base = N.getOperand(0);
1270 OffReg = N.getOperand(1);
1271
1272 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001273 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001274 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001275 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001276 if (ShOpcVal == ARM_AM::lsl)
1277 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001278 }
1279
Evan Chengb23b50d2009-06-29 07:51:04 +00001280 if (ShOpcVal == ARM_AM::lsl) {
1281 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1282 // it.
1283 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1284 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001285 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1286 OffReg = OffReg.getOperand(0);
1287 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001288 ShAmt = 0;
Evan Cheng59bbc542010-10-27 23:41:30 +00001289 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001290 }
David Goodwinf3912052009-07-15 15:50:19 +00001291 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001292
John Brawn056e6782015-09-14 15:19:41 +00001293 // If OffReg is a multiply-by-constant and it's profitable to extract a shift
1294 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +00001295 if (OffReg.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +00001296 unsigned PowerOfTwo = 0;
1297 SDValue NewMulConst;
1298 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
Tim Northover4a01ffb2017-05-02 22:45:19 +00001299 HandleSDNode Handle(OffReg);
John Brawn056e6782015-09-14 15:19:41 +00001300 replaceDAGValue(OffReg.getOperand(1), NewMulConst);
Tim Northover4a01ffb2017-05-02 22:45:19 +00001301 OffReg = Handle.getValue();
John Brawn056e6782015-09-14 15:19:41 +00001302 ShAmt = PowerOfTwo;
1303 }
1304 }
1305
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001306 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001307
1308 return true;
1309}
1310
Tim Northovera7ecd242013-07-16 09:46:55 +00001311bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1312 SDValue &OffImm) {
Alp Tokercb402912014-01-24 17:20:08 +00001313 // This *must* succeed since it's used for the irreplaceable ldrex and strex
Tim Northovera7ecd242013-07-16 09:46:55 +00001314 // instructions.
1315 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001316 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001317
1318 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1319 return true;
1320
1321 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1322 if (!RHS)
1323 return true;
1324
1325 uint32_t RHSC = (int)RHS->getZExtValue();
1326 if (RHSC > 1020 || RHSC % 4 != 0)
1327 return true;
1328
1329 Base = N.getOperand(0);
1330 if (Base.getOpcode() == ISD::FrameIndex) {
1331 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001332 Base = CurDAG->getTargetFrameIndex(
1333 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Tim Northovera7ecd242013-07-16 09:46:55 +00001334 }
1335
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001336 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001337 return true;
1338}
1339
Evan Chengb23b50d2009-06-29 07:51:04 +00001340//===--------------------------------------------------------------------===//
1341
Evan Cheng7e90b112007-07-05 07:15:27 +00001342/// getAL - Returns a ARMCC::AL immediate node.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001343static inline SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001344 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001345}
1346
Tim Northovereaee28b2016-09-19 09:11:09 +00001347void ARMDAGToDAGISel::transferMemOperands(SDNode *N, SDNode *Result) {
1348 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1349 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
1350 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
1351}
1352
Justin Bogner45571362016-05-12 00:31:09 +00001353bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001354 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001355 ISD::MemIndexedMode AM = LD->getAddressingMode();
1356 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001357 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001358
Owen Anderson53aa7a92009-08-10 22:56:29 +00001359 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001360 SDValue Offset, AMOpc;
1361 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1362 unsigned Opcode = 0;
1363 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001364 if (LoadedVT == MVT::i32 && isPre &&
1365 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1366 Opcode = ARM::LDR_PRE_IMM;
1367 Match = true;
1368 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001369 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001370 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001371 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001372 } else if (LoadedVT == MVT::i32 &&
1373 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001374 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001375 Match = true;
1376
Owen Anderson9f944592009-08-11 20:47:22 +00001377 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001378 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001379 Match = true;
1380 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1381 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1382 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001383 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001384 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001385 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001386 Match = true;
1387 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1388 }
1389 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001390 if (isPre &&
1391 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001392 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001393 Opcode = ARM::LDRB_PRE_IMM;
1394 } else if (!isPre &&
1395 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1396 Match = true;
1397 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001398 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1399 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001400 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001401 }
1402 }
1403 }
1404
1405 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001406 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1407 SDValue Chain = LD->getChain();
1408 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001409 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001410 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001411 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1412 MVT::Other, Ops);
1413 transferMemOperands(N, New);
1414 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001415 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001416 } else {
1417 SDValue Chain = LD->getChain();
1418 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001419 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001420 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001421 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1422 MVT::Other, Ops);
1423 transferMemOperands(N, New);
1424 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001425 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001426 }
Evan Chengd9c55362009-07-02 01:23:32 +00001427 }
1428
Justin Bogner45571362016-05-12 00:31:09 +00001429 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001430}
1431
James Molloyb3326df2016-07-15 08:03:56 +00001432bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *N) {
1433 LoadSDNode *LD = cast<LoadSDNode>(N);
1434 EVT LoadedVT = LD->getMemoryVT();
1435 ISD::MemIndexedMode AM = LD->getAddressingMode();
Chandler Carruth5589aa62016-11-03 17:42:02 +00001436 if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD ||
1437 LoadedVT.getSimpleVT().SimpleTy != MVT::i32)
James Molloyb3326df2016-07-15 08:03:56 +00001438 return false;
1439
1440 auto *COffs = dyn_cast<ConstantSDNode>(LD->getOffset());
1441 if (!COffs || COffs->getZExtValue() != 4)
1442 return false;
1443
1444 // A T1 post-indexed load is just a single register LDM: LDM r0!, {r1}.
1445 // The encoding of LDM is not how the rest of ISel expects a post-inc load to
1446 // look however, so we use a pseudo here and switch it for a tLDMIA_UPD after
1447 // ISel.
1448 SDValue Chain = LD->getChain();
1449 SDValue Base = LD->getBasePtr();
1450 SDValue Ops[]= { Base, getAL(CurDAG, SDLoc(N)),
1451 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001452 SDNode *New = CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(N), MVT::i32,
1453 MVT::i32, MVT::Other, Ops);
1454 transferMemOperands(N, New);
1455 ReplaceNode(N, New);
James Molloyb3326df2016-07-15 08:03:56 +00001456 return true;
1457}
1458
Justin Bogner45571362016-05-12 00:31:09 +00001459bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001460 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001461 ISD::MemIndexedMode AM = LD->getAddressingMode();
1462 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001463 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001464
Owen Anderson53aa7a92009-08-10 22:56:29 +00001465 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001466 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001467 SDValue Offset;
1468 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1469 unsigned Opcode = 0;
1470 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001471 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001472 switch (LoadedVT.getSimpleVT().SimpleTy) {
1473 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001474 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1475 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001476 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001477 if (isSExtLd)
1478 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1479 else
1480 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001481 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001482 case MVT::i8:
1483 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001484 if (isSExtLd)
1485 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1486 else
1487 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001488 break;
1489 default:
Justin Bogner45571362016-05-12 00:31:09 +00001490 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001491 }
1492 Match = true;
1493 }
1494
1495 if (Match) {
1496 SDValue Chain = LD->getChain();
1497 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001498 SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)),
Owen Anderson9f944592009-08-11 20:47:22 +00001499 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001500 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1501 MVT::Other, Ops);
1502 transferMemOperands(N, New);
1503 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001504 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001505 }
1506
Justin Bogner45571362016-05-12 00:31:09 +00001507 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001508}
1509
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001510/// Form a GPRPair pseudo register from a pair of GPR regs.
Weiming Zhao8f56f882012-11-16 21:55:34 +00001511SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001512 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001513 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001514 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1515 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1516 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001517 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001518 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001519}
1520
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001521/// Form a D register from a pair of S registers.
Weiming Zhao95782222012-11-17 00:23:35 +00001522SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001523 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001524 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001525 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1526 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1527 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001528 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001529 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001530}
1531
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001532/// Form a quad register from a pair of D registers.
Weiming Zhao95782222012-11-17 00:23:35 +00001533SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001534 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001535 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1536 MVT::i32);
1537 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1538 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001539 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001540 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001541}
1542
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001543/// Form 4 consecutive D registers from a pair of Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +00001544SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001545 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001546 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1547 MVT::i32);
1548 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1549 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001550 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001551 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001552}
1553
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001554/// Form 4 consecutive S registers.
Weiming Zhao95782222012-11-17 00:23:35 +00001555SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001556 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001557 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001558 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001559 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1560 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1561 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1562 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1563 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001564 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1565 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001566 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001567}
1568
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001569/// Form 4 consecutive D registers.
Weiming Zhao95782222012-11-17 00:23:35 +00001570SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001571 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001572 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001573 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1574 MVT::i32);
1575 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1576 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1577 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1578 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001579 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1580 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001581 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001582}
1583
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001584/// Form 4 consecutive Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +00001585SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001586 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001587 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001588 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1589 MVT::i32);
1590 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1591 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1592 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1593 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001594 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1595 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001596 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001597}
1598
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001599/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1600/// of a NEON VLD or VST instruction. The supported values depend on the
1601/// number of registers being loaded.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001602SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, const SDLoc &dl,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001603 unsigned NumVecs, bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001604 unsigned NumRegs = NumVecs;
1605 if (!is64BitVector && NumVecs < 3)
1606 NumRegs *= 2;
1607
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001608 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001609 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001610 Alignment = 32;
1611 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1612 Alignment = 16;
1613 else if (Alignment >= 8)
1614 Alignment = 8;
1615 else
1616 Alignment = 0;
1617
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001618 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001619}
1620
Jiangning Liu4df23632014-01-16 09:16:13 +00001621static bool isVLDfixed(unsigned Opc)
1622{
1623 switch (Opc) {
1624 default: return false;
1625 case ARM::VLD1d8wb_fixed : return true;
1626 case ARM::VLD1d16wb_fixed : return true;
1627 case ARM::VLD1d64Qwb_fixed : return true;
1628 case ARM::VLD1d32wb_fixed : return true;
1629 case ARM::VLD1d64wb_fixed : return true;
1630 case ARM::VLD1d64TPseudoWB_fixed : return true;
1631 case ARM::VLD1d64QPseudoWB_fixed : return true;
1632 case ARM::VLD1q8wb_fixed : return true;
1633 case ARM::VLD1q16wb_fixed : return true;
1634 case ARM::VLD1q32wb_fixed : return true;
1635 case ARM::VLD1q64wb_fixed : return true;
Eli Friedmanf624ec22016-12-16 18:44:08 +00001636 case ARM::VLD1DUPd8wb_fixed : return true;
1637 case ARM::VLD1DUPd16wb_fixed : return true;
1638 case ARM::VLD1DUPd32wb_fixed : return true;
1639 case ARM::VLD1DUPq8wb_fixed : return true;
1640 case ARM::VLD1DUPq16wb_fixed : return true;
1641 case ARM::VLD1DUPq32wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001642 case ARM::VLD2d8wb_fixed : return true;
1643 case ARM::VLD2d16wb_fixed : return true;
1644 case ARM::VLD2d32wb_fixed : return true;
1645 case ARM::VLD2q8PseudoWB_fixed : return true;
1646 case ARM::VLD2q16PseudoWB_fixed : return true;
1647 case ARM::VLD2q32PseudoWB_fixed : return true;
1648 case ARM::VLD2DUPd8wb_fixed : return true;
1649 case ARM::VLD2DUPd16wb_fixed : return true;
1650 case ARM::VLD2DUPd32wb_fixed : return true;
1651 }
1652}
1653
1654static bool isVSTfixed(unsigned Opc)
1655{
1656 switch (Opc) {
1657 default: return false;
1658 case ARM::VST1d8wb_fixed : return true;
1659 case ARM::VST1d16wb_fixed : return true;
1660 case ARM::VST1d32wb_fixed : return true;
1661 case ARM::VST1d64wb_fixed : return true;
Jim Grosbach1a597112014-04-03 23:43:18 +00001662 case ARM::VST1q8wb_fixed : return true;
1663 case ARM::VST1q16wb_fixed : return true;
1664 case ARM::VST1q32wb_fixed : return true;
1665 case ARM::VST1q64wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001666 case ARM::VST1d64TPseudoWB_fixed : return true;
1667 case ARM::VST1d64QPseudoWB_fixed : return true;
1668 case ARM::VST2d8wb_fixed : return true;
1669 case ARM::VST2d16wb_fixed : return true;
1670 case ARM::VST2d32wb_fixed : return true;
1671 case ARM::VST2q8PseudoWB_fixed : return true;
1672 case ARM::VST2q16PseudoWB_fixed : return true;
1673 case ARM::VST2q32PseudoWB_fixed : return true;
1674 }
1675}
1676
Jim Grosbach2098cb12011-10-24 21:45:13 +00001677// Get the register stride update opcode of a VLD/VST instruction that
1678// is otherwise equivalent to the given fixed stride updating instruction.
1679static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
Jiangning Liu4df23632014-01-16 09:16:13 +00001680 assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1681 && "Incorrect fixed stride updating instruction.");
Jim Grosbach2098cb12011-10-24 21:45:13 +00001682 switch (Opc) {
1683 default: break;
1684 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1685 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1686 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1687 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1688 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1689 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1690 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1691 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jiangning Liu4df23632014-01-16 09:16:13 +00001692 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1693 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1694 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1695 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
Eli Friedmanf624ec22016-12-16 18:44:08 +00001696 case ARM::VLD1DUPd8wb_fixed : return ARM::VLD1DUPd8wb_register;
1697 case ARM::VLD1DUPd16wb_fixed : return ARM::VLD1DUPd16wb_register;
1698 case ARM::VLD1DUPd32wb_fixed : return ARM::VLD1DUPd32wb_register;
1699 case ARM::VLD1DUPq8wb_fixed : return ARM::VLD1DUPq8wb_register;
1700 case ARM::VLD1DUPq16wb_fixed : return ARM::VLD1DUPq16wb_register;
1701 case ARM::VLD1DUPq32wb_fixed : return ARM::VLD1DUPq32wb_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001702
1703 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1704 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1705 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1706 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1707 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1708 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1709 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1710 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001711 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001712 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001713
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001714 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1715 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1716 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001717 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1718 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1719 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1720
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001721 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1722 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1723 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001724 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1725 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1726 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001727
Jim Grosbach13a292c2012-03-06 22:01:44 +00001728 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1729 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1730 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001731 }
1732 return Opc; // If not one we handle, return it unchanged.
1733}
1734
Tim Northover8b1240b2017-04-20 19:54:02 +00001735/// Returns true if the given increment is a Constant known to be equal to the
1736/// access size performed by a NEON load/store. This means the "[rN]!" form can
1737/// be used.
1738static bool isPerfectIncrement(SDValue Inc, EVT VecTy, unsigned NumVecs) {
1739 auto C = dyn_cast<ConstantSDNode>(Inc);
1740 return C && C->getZExtValue() == VecTy.getSizeInBits() / 8 * NumVecs;
1741}
1742
Justin Bogner45571362016-05-12 00:31:09 +00001743void ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
1744 const uint16_t *DOpcodes,
1745 const uint16_t *QOpcodes0,
1746 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001747 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001748 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001749
Bob Wilsonae08a732010-03-20 22:13:40 +00001750 SDValue MemAddr, Align;
Ivan A. Kosarev72315982018-06-27 13:57:52 +00001751 bool IsIntrinsic = !isUpdating; // By coincidence, all supported updating
1752 // nodes are not intrinsics.
1753 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
Bob Wilson06fce872011-02-07 17:43:21 +00001754 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001755 return;
Bob Wilson12b47992009-10-14 17:28:52 +00001756
1757 SDValue Chain = N->getOperand(0);
1758 EVT VT = N->getValueType(0);
1759 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001760 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001761
Bob Wilson12b47992009-10-14 17:28:52 +00001762 unsigned OpcodeIndex;
1763 switch (VT.getSimpleVT().SimpleTy) {
1764 default: llvm_unreachable("unhandled vld type");
1765 // Double-register operations:
1766 case MVT::v8i8: OpcodeIndex = 0; break;
1767 case MVT::v4i16: OpcodeIndex = 1; break;
1768 case MVT::v2f32:
1769 case MVT::v2i32: OpcodeIndex = 2; break;
1770 case MVT::v1i64: OpcodeIndex = 3; break;
1771 // Quad-register operations:
1772 case MVT::v16i8: OpcodeIndex = 0; break;
1773 case MVT::v8i16: OpcodeIndex = 1; break;
1774 case MVT::v4f32:
1775 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001776 case MVT::v2f64:
Ivan A. Kosarev60a991e2018-06-02 16:40:03 +00001777 case MVT::v2i64: OpcodeIndex = 3; break;
Bob Wilson12b47992009-10-14 17:28:52 +00001778 }
1779
Bob Wilson35fafca2010-09-03 18:16:02 +00001780 EVT ResTy;
1781 if (NumVecs == 1)
1782 ResTy = VT;
1783 else {
1784 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1785 if (!is64BitVector)
1786 ResTyElts *= 2;
1787 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1788 }
Bob Wilson06fce872011-02-07 17:43:21 +00001789 std::vector<EVT> ResTys;
1790 ResTys.push_back(ResTy);
1791 if (isUpdating)
1792 ResTys.push_back(MVT::i32);
1793 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001794
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001795 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001796 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001797 SDNode *VLd;
1798 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001799
Bob Wilson06fce872011-02-07 17:43:21 +00001800 // Double registers and VLD1/VLD2 quad registers are directly supported.
1801 if (is64BitVector || NumVecs <= 2) {
1802 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1803 QOpcodes0[OpcodeIndex]);
1804 Ops.push_back(MemAddr);
1805 Ops.push_back(Align);
1806 if (isUpdating) {
1807 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Tim Northover8b1240b2017-04-20 19:54:02 +00001808 bool IsImmUpdate = isPerfectIncrement(Inc, VT, NumVecs);
Florian Hahn9deef202018-03-02 13:02:55 +00001809 if (!IsImmUpdate) {
1810 // We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
1811 // check for the opcode rather than the number of vector elements.
1812 if (isVLDfixed(Opc))
1813 Opc = getVLDSTRegisterUpdateOpcode(Opc);
1814 Ops.push_back(Inc);
1815 // VLD1/VLD2 fixed increment does not need Reg0 so only include it in
1816 // the operands if not such an opcode.
1817 } else if (!isVLDfixed(Opc))
1818 Ops.push_back(Reg0);
Evan Cheng630063a2010-05-10 21:26:24 +00001819 }
Bob Wilson06fce872011-02-07 17:43:21 +00001820 Ops.push_back(Pred);
1821 Ops.push_back(Reg0);
1822 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001823 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001824
Bob Wilson12b47992009-10-14 17:28:52 +00001825 } else {
1826 // Otherwise, quad registers are loaded with two separate instructions,
1827 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001828 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001829
Bob Wilson06fce872011-02-07 17:43:21 +00001830 // Load the even subregs. This is always an updating load, so that it
1831 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001832 SDValue ImplDef =
1833 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1834 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001835 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001836 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001837 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001838
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001839 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001840 Ops.push_back(SDValue(VLdA, 1));
1841 Ops.push_back(Align);
1842 if (isUpdating) {
1843 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1844 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1845 "only constant post-increment update allowed for VLD3/4");
1846 (void)Inc;
1847 Ops.push_back(Reg0);
1848 }
1849 Ops.push_back(SDValue(VLdA, 0));
1850 Ops.push_back(Pred);
1851 Ops.push_back(Reg0);
1852 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001853 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001854 }
Bob Wilson12b47992009-10-14 17:28:52 +00001855
Evan Cheng40791332011-04-19 00:04:03 +00001856 // Transfer memoperands.
1857 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1858 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1859 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1860
Justin Bogner45571362016-05-12 00:31:09 +00001861 if (NumVecs == 1) {
1862 ReplaceNode(N, VLd);
1863 return;
1864 }
Bob Wilson06fce872011-02-07 17:43:21 +00001865
1866 // Extract out the subregisters.
1867 SDValue SuperReg = SDValue(VLd, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00001868 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
1869 ARM::qsub_3 == ARM::qsub_0 + 3,
1870 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00001871 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1872 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1873 ReplaceUses(SDValue(N, Vec),
1874 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1875 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1876 if (isUpdating)
1877 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00001878 CurDAG->RemoveDeadNode(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001879}
1880
Justin Bogner45571362016-05-12 00:31:09 +00001881void ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
1882 const uint16_t *DOpcodes,
1883 const uint16_t *QOpcodes0,
1884 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001885 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001886 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001887
Bob Wilsonae08a732010-03-20 22:13:40 +00001888 SDValue MemAddr, Align;
Ivan A. Kosarev72315982018-06-27 13:57:52 +00001889 bool IsIntrinsic = !isUpdating; // By coincidence, all supported updating
1890 // nodes are not intrinsics.
1891 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
Bob Wilson06fce872011-02-07 17:43:21 +00001892 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1893 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001894 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001895
Evan Cheng40791332011-04-19 00:04:03 +00001896 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1897 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1898
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001899 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00001900 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001901 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001902 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001903
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001904 unsigned OpcodeIndex;
1905 switch (VT.getSimpleVT().SimpleTy) {
1906 default: llvm_unreachable("unhandled vst type");
1907 // Double-register operations:
1908 case MVT::v8i8: OpcodeIndex = 0; break;
Sjoerd Meijerd16037d2018-03-19 13:35:25 +00001909 case MVT::v4f16:
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001910 case MVT::v4i16: OpcodeIndex = 1; break;
1911 case MVT::v2f32:
1912 case MVT::v2i32: OpcodeIndex = 2; break;
1913 case MVT::v1i64: OpcodeIndex = 3; break;
1914 // Quad-register operations:
1915 case MVT::v16i8: OpcodeIndex = 0; break;
Sjoerd Meijerd16037d2018-03-19 13:35:25 +00001916 case MVT::v8f16:
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001917 case MVT::v8i16: OpcodeIndex = 1; break;
1918 case MVT::v4f32:
1919 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001920 case MVT::v2f64:
Ivan A. Kosarev847daa12018-06-10 09:27:27 +00001921 case MVT::v2i64: OpcodeIndex = 3; break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001922 }
1923
Bob Wilson06fce872011-02-07 17:43:21 +00001924 std::vector<EVT> ResTys;
1925 if (isUpdating)
1926 ResTys.push_back(MVT::i32);
1927 ResTys.push_back(MVT::Other);
1928
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001929 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001930 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001931 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00001932
Bob Wilson06fce872011-02-07 17:43:21 +00001933 // Double registers and VST1/VST2 quad registers are directly supported.
1934 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00001935 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00001936 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00001937 SrcReg = N->getOperand(Vec0Idx);
1938 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00001939 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00001940 SDValue V0 = N->getOperand(Vec0Idx + 0);
1941 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00001942 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00001943 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001944 else {
Bob Wilson06fce872011-02-07 17:43:21 +00001945 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00001946 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00001947 // an undef.
1948 SDValue V3 = (NumVecs == 3)
1949 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00001950 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00001951 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001952 }
Bob Wilson950882b2010-08-28 05:12:57 +00001953 } else {
1954 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00001955 SDValue Q0 = N->getOperand(Vec0Idx);
1956 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00001957 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001958 }
Bob Wilson06fce872011-02-07 17:43:21 +00001959
1960 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1961 QOpcodes0[OpcodeIndex]);
1962 Ops.push_back(MemAddr);
1963 Ops.push_back(Align);
1964 if (isUpdating) {
1965 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Tim Northover8b1240b2017-04-20 19:54:02 +00001966 bool IsImmUpdate = isPerfectIncrement(Inc, VT, NumVecs);
Florian Hahn9deef202018-03-02 13:02:55 +00001967 if (!IsImmUpdate) {
1968 // We use a VST1 for v1i64 even if the pseudo says VST2/3/4, so
1969 // check for the opcode rather than the number of vector elements.
1970 if (isVSTfixed(Opc))
1971 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001972 Ops.push_back(Inc);
Florian Hahn9deef202018-03-02 13:02:55 +00001973 }
1974 // VST1/VST2 fixed increment does not need Reg0 so only include it in
1975 // the operands if not such an opcode.
1976 else if (!isVSTfixed(Opc))
Jiangning Liu4df23632014-01-16 09:16:13 +00001977 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00001978 }
1979 Ops.push_back(SrcReg);
1980 Ops.push_back(Pred);
1981 Ops.push_back(Reg0);
1982 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001983 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00001984
1985 // Transfer memoperands.
1986 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
1987
Justin Bogner45571362016-05-12 00:31:09 +00001988 ReplaceNode(N, VSt);
1989 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001990 }
1991
1992 // Otherwise, quad registers are stored with two separate instructions,
1993 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00001994
Bob Wilson01ac8f92010-06-16 21:34:01 +00001995 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00001996 SDValue V0 = N->getOperand(Vec0Idx + 0);
1997 SDValue V1 = N->getOperand(Vec0Idx + 1);
1998 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00001999 SDValue V3 = (NumVecs == 3)
2000 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002001 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002002 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002003
Bob Wilson06fce872011-02-07 17:43:21 +00002004 // Store the even D registers. This is always an updating store, so that it
2005 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00002006 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2007 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2008 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00002009 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00002010 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002011 Chain = SDValue(VStA, 1);
2012
2013 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00002014 Ops.push_back(SDValue(VStA, 0));
2015 Ops.push_back(Align);
2016 if (isUpdating) {
2017 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2018 assert(isa<ConstantSDNode>(Inc.getNode()) &&
2019 "only constant post-increment update allowed for VST3/4");
2020 (void)Inc;
2021 Ops.push_back(Reg0);
2022 }
2023 Ops.push_back(RegSeq);
2024 Ops.push_back(Pred);
2025 Ops.push_back(Reg0);
2026 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00002027 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00002028 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002029 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002030 ReplaceNode(N, VStB);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002031}
2032
Justin Bogner45571362016-05-12 00:31:09 +00002033void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
2034 unsigned NumVecs,
2035 const uint16_t *DOpcodes,
2036 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002037 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002038 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002039
Bob Wilsonae08a732010-03-20 22:13:40 +00002040 SDValue MemAddr, Align;
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002041 bool IsIntrinsic = !isUpdating; // By coincidence, all supported updating
2042 // nodes are not intrinsics.
2043 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
Bob Wilson06fce872011-02-07 17:43:21 +00002044 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2045 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002046 return;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002047
Evan Cheng40791332011-04-19 00:04:03 +00002048 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2049 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2050
Bob Wilson4145e3a2009-10-14 16:19:03 +00002051 SDValue Chain = N->getOperand(0);
2052 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002053 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2054 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002055 bool is64BitVector = VT.is64BitVector();
2056
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002057 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002058 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002059 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Sanjay Patel1ed771f2016-09-14 16:37:15 +00002060 unsigned NumBytes = NumVecs * VT.getScalarSizeInBits() / 8;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002061 if (Alignment > NumBytes)
2062 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002063 if (Alignment < 8 && Alignment < NumBytes)
2064 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002065 // Alignment must be a power of two; make sure of that.
2066 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002067 if (Alignment == 1)
2068 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002069 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002070 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002071
Bob Wilson4145e3a2009-10-14 16:19:03 +00002072 unsigned OpcodeIndex;
2073 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002074 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002075 // Double-register operations:
2076 case MVT::v8i8: OpcodeIndex = 0; break;
2077 case MVT::v4i16: OpcodeIndex = 1; break;
2078 case MVT::v2f32:
2079 case MVT::v2i32: OpcodeIndex = 2; break;
2080 // Quad-register operations:
2081 case MVT::v8i16: OpcodeIndex = 0; break;
2082 case MVT::v4f32:
2083 case MVT::v4i32: OpcodeIndex = 1; break;
2084 }
2085
Bob Wilson06fce872011-02-07 17:43:21 +00002086 std::vector<EVT> ResTys;
2087 if (IsLoad) {
2088 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2089 if (!is64BitVector)
2090 ResTyElts *= 2;
2091 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2092 MVT::i64, ResTyElts));
2093 }
2094 if (isUpdating)
2095 ResTys.push_back(MVT::i32);
2096 ResTys.push_back(MVT::Other);
2097
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002098 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002099 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002100
Bob Wilson06fce872011-02-07 17:43:21 +00002101 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002102 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002103 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002104 if (isUpdating) {
2105 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Tim Northover8b1240b2017-04-20 19:54:02 +00002106 bool IsImmUpdate =
2107 isPerfectIncrement(Inc, VT.getVectorElementType(), NumVecs);
2108 Ops.push_back(IsImmUpdate ? Reg0 : Inc);
Bob Wilson06fce872011-02-07 17:43:21 +00002109 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002110
Bob Wilsond5c57a52010-09-13 23:01:35 +00002111 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002112 SDValue V0 = N->getOperand(Vec0Idx + 0);
2113 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002114 if (NumVecs == 2) {
2115 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002116 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002117 else
Weiming Zhao95782222012-11-17 00:23:35 +00002118 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002119 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002120 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002121 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002122 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2123 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002124 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002125 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002126 else
Weiming Zhao95782222012-11-17 00:23:35 +00002127 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002128 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002129 Ops.push_back(SuperReg);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002130 Ops.push_back(getI32Imm(Lane, dl));
Evan Chenga33fc862009-11-21 06:21:52 +00002131 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002132 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002133 Ops.push_back(Chain);
2134
Bob Wilson06fce872011-02-07 17:43:21 +00002135 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2136 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002137 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002138 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002139 if (!IsLoad) {
2140 ReplaceNode(N, VLdLn);
2141 return;
2142 }
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002143
Bob Wilsond5c57a52010-09-13 23:01:35 +00002144 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002145 SuperReg = SDValue(VLdLn, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00002146 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2147 ARM::qsub_3 == ARM::qsub_0 + 3,
2148 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00002149 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002150 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2151 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002152 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2153 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2154 if (isUpdating)
2155 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002156 CurDAG->RemoveDeadNode(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002157}
2158
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002159void ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool IsIntrinsic,
2160 bool isUpdating, unsigned NumVecs,
Eli Friedmanf624ec22016-12-16 18:44:08 +00002161 const uint16_t *DOpcodes,
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002162 const uint16_t *QOpcodes0,
2163 const uint16_t *QOpcodes1) {
Eli Friedmanf624ec22016-12-16 18:44:08 +00002164 assert(NumVecs >= 1 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002165 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002166
2167 SDValue MemAddr, Align;
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002168 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1;
2169 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002170 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00002171
2172 SDValue Chain = N->getOperand(0);
2173 EVT VT = N->getValueType(0);
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002174 bool is64BitVector = VT.is64BitVector();
Bob Wilson2d790df2010-11-28 06:51:26 +00002175
2176 unsigned Alignment = 0;
2177 if (NumVecs != 3) {
2178 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Sanjay Patel1ed771f2016-09-14 16:37:15 +00002179 unsigned NumBytes = NumVecs * VT.getScalarSizeInBits() / 8;
Bob Wilson2d790df2010-11-28 06:51:26 +00002180 if (Alignment > NumBytes)
2181 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002182 if (Alignment < 8 && Alignment < NumBytes)
2183 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002184 // Alignment must be a power of two; make sure of that.
2185 Alignment = (Alignment & -Alignment);
2186 if (Alignment == 1)
2187 Alignment = 0;
2188 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002189 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson2d790df2010-11-28 06:51:26 +00002190
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002191 unsigned OpcodeIndex;
Bob Wilson2d790df2010-11-28 06:51:26 +00002192 switch (VT.getSimpleVT().SimpleTy) {
2193 default: llvm_unreachable("unhandled vld-dup type");
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002194 case MVT::v8i8:
2195 case MVT::v16i8: OpcodeIndex = 0; break;
2196 case MVT::v4i16:
2197 case MVT::v8i16: OpcodeIndex = 1; break;
Bob Wilson2d790df2010-11-28 06:51:26 +00002198 case MVT::v2f32:
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002199 case MVT::v2i32:
Eli Friedmanf624ec22016-12-16 18:44:08 +00002200 case MVT::v4f32:
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002201 case MVT::v4i32: OpcodeIndex = 2; break;
2202 case MVT::v1f64:
2203 case MVT::v1i64: OpcodeIndex = 3; break;
Bob Wilson2d790df2010-11-28 06:51:26 +00002204 }
2205
Bob Wilson2d790df2010-11-28 06:51:26 +00002206 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002207 if (!is64BitVector)
2208 ResTyElts *= 2;
2209 EVT ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
2210
Bob Wilson06fce872011-02-07 17:43:21 +00002211 std::vector<EVT> ResTys;
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002212 ResTys.push_back(ResTy);
Bob Wilson06fce872011-02-07 17:43:21 +00002213 if (isUpdating)
2214 ResTys.push_back(MVT::i32);
2215 ResTys.push_back(MVT::Other);
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002216
2217 SDValue Pred = getAL(CurDAG, dl);
2218 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2219
2220 SDNode *VLdDup;
2221 if (is64BitVector || NumVecs == 1) {
2222 SmallVector<SDValue, 6> Ops;
2223 Ops.push_back(MemAddr);
2224 Ops.push_back(Align);
2225 unsigned Opc = is64BitVector ? DOpcodes[OpcodeIndex] :
2226 QOpcodes0[OpcodeIndex];
2227 if (isUpdating) {
2228 // fixed-stride update instructions don't have an explicit writeback
2229 // operand. It's implicit in the opcode itself.
2230 SDValue Inc = N->getOperand(2);
2231 bool IsImmUpdate =
2232 isPerfectIncrement(Inc, VT.getVectorElementType(), NumVecs);
2233 if (NumVecs <= 2 && !IsImmUpdate)
2234 Opc = getVLDSTRegisterUpdateOpcode(Opc);
2235 if (!IsImmUpdate)
2236 Ops.push_back(Inc);
2237 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2238 else if (NumVecs > 2)
2239 Ops.push_back(Reg0);
2240 }
2241 Ops.push_back(Pred);
2242 Ops.push_back(Reg0);
2243 Ops.push_back(Chain);
2244 VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2245 } else if (NumVecs == 2) {
2246 const SDValue OpsA[] = { MemAddr, Align, Pred, Reg0, Chain };
2247 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex],
2248 dl, ResTys, OpsA);
2249
2250 Chain = SDValue(VLdA, 1);
2251 const SDValue OpsB[] = { MemAddr, Align, Pred, Reg0, Chain };
2252 VLdDup = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, OpsB);
2253 } else {
2254 SDValue ImplDef =
2255 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
2256 const SDValue OpsA[] = { MemAddr, Align, ImplDef, Pred, Reg0, Chain };
2257 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex],
2258 dl, ResTys, OpsA);
2259
2260 SDValue SuperReg = SDValue(VLdA, 0);
2261 Chain = SDValue(VLdA, 1);
2262 const SDValue OpsB[] = { MemAddr, Align, SuperReg, Pred, Reg0, Chain };
2263 VLdDup = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, OpsB);
2264 }
2265
2266 // Transfer memoperands.
2267 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2268 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
Evan Cheng40791332011-04-19 00:04:03 +00002269 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002270
2271 // Extract the subregisters.
Eli Friedmanf624ec22016-12-16 18:44:08 +00002272 if (NumVecs == 1) {
2273 ReplaceUses(SDValue(N, 0), SDValue(VLdDup, 0));
2274 } else {
2275 SDValue SuperReg = SDValue(VLdDup, 0);
2276 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7, "Unexpected subreg numbering");
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002277 unsigned SubIdx = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
2278 for (unsigned Vec = 0; Vec != NumVecs; ++Vec) {
Eli Friedmanf624ec22016-12-16 18:44:08 +00002279 ReplaceUses(SDValue(N, Vec),
2280 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Ivan A. Kosarev72315982018-06-27 13:57:52 +00002281 }
Eli Friedmanf624ec22016-12-16 18:44:08 +00002282 }
Bob Wilson06fce872011-02-07 17:43:21 +00002283 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2284 if (isUpdating)
2285 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002286 CurDAG->RemoveDeadNode(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002287}
2288
Justin Bogner45571362016-05-12 00:31:09 +00002289bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002290 if (!Subtarget->hasV6T2Ops())
Justin Bogner45571362016-05-12 00:31:09 +00002291 return false;
Bob Wilson93117bc2009-10-14 16:46:45 +00002292
Evan Chengeae6d2c2012-12-19 20:16:09 +00002293 unsigned Opc = isSigned
2294 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002295 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002296 SDLoc dl(N);
Jim Grosbach825cb292010-04-22 23:24:18 +00002297
Jim Grosbach825cb292010-04-22 23:24:18 +00002298 // For unsigned extracts, check for a shift right and mask
2299 unsigned And_imm = 0;
2300 if (N->getOpcode() == ISD::AND) {
2301 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2302
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002303 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002304 if (And_imm & (And_imm + 1))
Justin Bogner45571362016-05-12 00:31:09 +00002305 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002306
2307 unsigned Srl_imm = 0;
2308 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2309 Srl_imm)) {
2310 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2311
Jim Grosbach03f56d92011-07-27 21:09:25 +00002312 // Note: The width operand is encoded as width-1.
Benjamin Kramer5f6a9072015-02-12 15:35:40 +00002313 unsigned Width = countTrailingOnes(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002314 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002315
Jim Grosbach825cb292010-04-22 23:24:18 +00002316 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002317
2318 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2319 // It's cheaper to use a right shift to extract the top bits.
2320 if (Subtarget->isThumb()) {
2321 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2322 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002323 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2324 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002325 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2326 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002327 }
2328
2329 // ARM models shift instructions as MOVsi with shifter operand.
2330 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2331 SDValue ShOpc =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002332 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), dl,
Evan Chengeae6d2c2012-12-19 20:16:09 +00002333 MVT::i32);
2334 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002335 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002336 CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops);
2337 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002338 }
2339
Jim Grosbach825cb292010-04-22 23:24:18 +00002340 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002341 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2342 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2343 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002344 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2345 return true;
Jim Grosbach825cb292010-04-22 23:24:18 +00002346 }
2347 }
Justin Bogner45571362016-05-12 00:31:09 +00002348 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002349 }
2350
2351 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002352 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002353 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002354 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2355 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002356 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002357 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002358 // Note: The width operand is encoded as width-1.
2359 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002360 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002361 if (LSB < 0)
Justin Bogner45571362016-05-12 00:31:09 +00002362 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002363 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002364 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002365 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2366 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2367 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002368 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2369 return true;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002370 }
2371 }
Tim Northover14ff2df2014-07-23 13:59:12 +00002372
Oliver Stannard92ca83c2016-06-01 12:01:01 +00002373 // Or we are looking for a shift of an and, with a mask operand
2374 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, And_imm) &&
2375 isShiftedMask_32(And_imm)) {
2376 unsigned Srl_imm = 0;
2377 unsigned LSB = countTrailingZeros(And_imm);
2378 // Shift must be the same as the ands lsb
2379 if (isInt32Immediate(N->getOperand(1), Srl_imm) && Srl_imm == LSB) {
2380 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2381 unsigned MSB = 31 - countLeadingZeros(And_imm);
2382 // Note: The width operand is encoded as width-1.
2383 unsigned Width = MSB - LSB;
2384 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2385 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2386 CurDAG->getTargetConstant(Srl_imm, dl, MVT::i32),
2387 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2388 getAL(CurDAG, dl), Reg0 };
2389 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2390 return true;
2391 }
2392 }
2393
Tim Northover14ff2df2014-07-23 13:59:12 +00002394 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
2395 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2396 unsigned LSB = 0;
2397 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) &&
2398 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB))
Justin Bogner45571362016-05-12 00:31:09 +00002399 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002400
2401 if (LSB + Width > 32)
Justin Bogner45571362016-05-12 00:31:09 +00002402 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002403
2404 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2405 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002406 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2407 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
2408 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002409 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2410 return true;
Tim Northover14ff2df2014-07-23 13:59:12 +00002411 }
2412
Justin Bogner45571362016-05-12 00:31:09 +00002413 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002414}
2415
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002416/// Target-specific DAG combining for ISD::XOR.
2417/// Target-independent combining lowers SELECT_CC nodes of the form
2418/// select_cc setg[ge] X, 0, X, -X
2419/// select_cc setgt X, -1, X, -X
2420/// select_cc setl[te] X, 0, -X, X
2421/// select_cc setlt X, 1, -X, X
2422/// which represent Integer ABS into:
2423/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2424/// ARM instruction selection detects the latter and matches it to
2425/// ARM::ABS or ARM::t2ABS machine node.
Justin Bogner45571362016-05-12 00:31:09 +00002426bool ARMDAGToDAGISel::tryABSOp(SDNode *N){
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002427 SDValue XORSrc0 = N->getOperand(0);
2428 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002429 EVT VT = N->getValueType(0);
2430
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002431 if (Subtarget->isThumb1Only())
Justin Bogner45571362016-05-12 00:31:09 +00002432 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002433
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002434 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Justin Bogner45571362016-05-12 00:31:09 +00002435 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002436
2437 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2438 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2439 SDValue SRASrc0 = XORSrc1.getOperand(0);
2440 SDValue SRASrc1 = XORSrc1.getOperand(1);
2441 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2442 EVT XType = SRASrc0.getValueType();
2443 unsigned Size = XType.getSizeInBits() - 1;
2444
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002445 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
Craig Topper062a2ba2014-04-25 05:30:21 +00002446 XType.isInteger() && SRAConstant != nullptr &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002447 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002448 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Justin Bogner45571362016-05-12 00:31:09 +00002449 CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2450 return true;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002451 }
2452
Justin Bogner45571362016-05-12 00:31:09 +00002453 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002454}
2455
Tim Northoverb629c772016-04-18 21:48:55 +00002456/// We've got special pseudo-instructions for these
Justin Bogner45571362016-05-12 00:31:09 +00002457void ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *N) {
Tim Northoverb629c772016-04-18 21:48:55 +00002458 unsigned Opcode;
2459 EVT MemTy = cast<MemSDNode>(N)->getMemoryVT();
2460 if (MemTy == MVT::i8)
2461 Opcode = ARM::CMP_SWAP_8;
2462 else if (MemTy == MVT::i16)
2463 Opcode = ARM::CMP_SWAP_16;
2464 else if (MemTy == MVT::i32)
2465 Opcode = ARM::CMP_SWAP_32;
2466 else
2467 llvm_unreachable("Unknown AtomicCmpSwap type");
2468
2469 SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3),
2470 N->getOperand(0)};
2471 SDNode *CmpSwap = CurDAG->getMachineNode(
2472 Opcode, SDLoc(N),
2473 CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other), Ops);
2474
2475 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2476 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
2477 cast<MachineSDNode>(CmpSwap)->setMemRefs(MemOp, MemOp + 1);
2478
2479 ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0));
2480 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002481 CurDAG->RemoveDeadNode(N);
Tim Northoverb629c772016-04-18 21:48:55 +00002482}
2483
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002484static Optional<std::pair<unsigned, unsigned>>
2485getContiguousRangeOfSetBits(const APInt &A) {
2486 unsigned FirstOne = A.getBitWidth() - A.countLeadingZeros() - 1;
2487 unsigned LastOne = A.countTrailingZeros();
2488 if (A.countPopulation() != (FirstOne - LastOne + 1))
2489 return Optional<std::pair<unsigned,unsigned>>();
2490 return std::make_pair(FirstOne, LastOne);
2491}
2492
2493void ARMDAGToDAGISel::SelectCMPZ(SDNode *N, bool &SwitchEQNEToPLMI) {
2494 assert(N->getOpcode() == ARMISD::CMPZ);
2495 SwitchEQNEToPLMI = false;
2496
2497 if (!Subtarget->isThumb())
2498 // FIXME: Work out whether it is profitable to do this in A32 mode - LSL and
2499 // LSR don't exist as standalone instructions - they need the barrel shifter.
2500 return;
2501
2502 // select (cmpz (and X, C), #0) -> (LSLS X) or (LSRS X) or (LSRS (LSLS X))
2503 SDValue And = N->getOperand(0);
2504 if (!And->hasOneUse())
2505 return;
2506
2507 SDValue Zero = N->getOperand(1);
2508 if (!isa<ConstantSDNode>(Zero) || !cast<ConstantSDNode>(Zero)->isNullValue() ||
2509 And->getOpcode() != ISD::AND)
2510 return;
2511 SDValue X = And.getOperand(0);
2512 auto C = dyn_cast<ConstantSDNode>(And.getOperand(1));
2513
Eli Friedman864df222018-06-08 21:16:56 +00002514 if (!C)
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002515 return;
2516 auto Range = getContiguousRangeOfSetBits(C->getAPIntValue());
2517 if (!Range)
2518 return;
2519
2520 // There are several ways to lower this:
2521 SDNode *NewN;
2522 SDLoc dl(N);
2523
2524 auto EmitShift = [&](unsigned Opc, SDValue Src, unsigned Imm) -> SDNode* {
2525 if (Subtarget->isThumb2()) {
2526 Opc = (Opc == ARM::tLSLri) ? ARM::t2LSLri : ARM::t2LSRri;
2527 SDValue Ops[] = { Src, CurDAG->getTargetConstant(Imm, dl, MVT::i32),
2528 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
2529 CurDAG->getRegister(0, MVT::i32) };
2530 return CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
2531 } else {
2532 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), Src,
2533 CurDAG->getTargetConstant(Imm, dl, MVT::i32),
2534 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
2535 return CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
2536 }
2537 };
2538
2539 if (Range->second == 0) {
2540 // 1. Mask includes the LSB -> Simply shift the top N bits off
2541 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2542 ReplaceNode(And.getNode(), NewN);
2543 } else if (Range->first == 31) {
2544 // 2. Mask includes the MSB -> Simply shift the bottom N bits off
2545 NewN = EmitShift(ARM::tLSRri, X, Range->second);
2546 ReplaceNode(And.getNode(), NewN);
2547 } else if (Range->first == Range->second) {
2548 // 3. Only one bit is set. We can shift this into the sign bit and use a
2549 // PL/MI comparison.
2550 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2551 ReplaceNode(And.getNode(), NewN);
2552
2553 SwitchEQNEToPLMI = true;
2554 } else if (!Subtarget->hasV6T2Ops()) {
2555 // 4. Do a double shift to clear bottom and top bits, but only in
2556 // thumb-1 mode as in thumb-2 we can use UBFX.
2557 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2558 NewN = EmitShift(ARM::tLSRri, SDValue(NewN, 0),
2559 Range->second + (31 - Range->first));
2560 ReplaceNode(And.getNode(), NewN);
2561 }
2562
2563}
2564
Justin Bogner45571362016-05-12 00:31:09 +00002565void ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002566 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002567
Tim Northover31d093c2013-09-22 08:21:56 +00002568 if (N->isMachineOpcode()) {
2569 N->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00002570 return; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00002571 }
Rafael Espindola4e760152006-06-12 12:28:08 +00002572
2573 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002574 default: break;
Justin Bogner45571362016-05-12 00:31:09 +00002575 case ISD::WRITE_REGISTER:
2576 if (tryWriteRegister(N))
2577 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002578 break;
Justin Bogner45571362016-05-12 00:31:09 +00002579 case ISD::READ_REGISTER:
2580 if (tryReadRegister(N))
2581 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002582 break;
Justin Bogner45571362016-05-12 00:31:09 +00002583 case ISD::INLINEASM:
2584 if (tryInlineAsm(N))
2585 return;
Weiming Zhaoc5987002013-02-14 18:10:21 +00002586 break;
Justin Bogner45571362016-05-12 00:31:09 +00002587 case ISD::XOR:
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002588 // Select special operations if XOR node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +00002589 if (tryABSOp(N))
2590 return;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002591 // Other cases are autogenerated.
2592 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002593 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002594 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
John Brawn056e6782015-09-14 15:19:41 +00002595 // If we can't materialize the constant we need to use a literal pool
2596 if (ConstantMaterializationCost(Val) > 2) {
Eric Christopherb17140d2014-10-08 07:32:17 +00002597 SDValue CPIdx = CurDAG->getTargetConstantPool(
2598 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
Mehdi Amini44ede332015-07-09 02:09:04 +00002599 TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng1526ba52007-01-24 08:53:17 +00002600
2601 SDNode *ResNode;
Tim Northover55c625f2014-01-23 13:43:47 +00002602 if (Subtarget->isThumb()) {
Sam Parker28934482017-07-14 08:23:56 +00002603 SDValue Ops[] = {
2604 CPIdx,
2605 getAL(CurDAG, dl),
2606 CurDAG->getRegister(0, MVT::i32),
2607 CurDAG->getEntryNode()
2608 };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002609 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002610 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002611 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002612 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002613 CPIdx,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002614 CurDAG->getTargetConstant(0, dl, MVT::i32),
2615 getAL(CurDAG, dl),
Owen Anderson9f944592009-08-11 20:47:22 +00002616 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002617 CurDAG->getEntryNode()
2618 };
Justin Bogner45571362016-05-12 00:31:09 +00002619 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
2620 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002621 }
Sam Parker28934482017-07-14 08:23:56 +00002622 // Annotate the Node with memory operand information so that MachineInstr
2623 // queries work properly. This e.g. gives the register allocation the
2624 // required information for rematerialization.
2625 MachineFunction& MF = CurDAG->getMachineFunction();
2626 MachineSDNode::mmo_iterator MemOp = MF.allocateMemRefsArray(1);
2627 MemOp[0] = MF.getMachineMemOperand(
2628 MachinePointerInfo::getConstantPool(MF),
2629 MachineMemOperand::MOLoad, 4, 4);
2630
2631 cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp+1);
2632
Justin Bognered4f3782016-05-12 00:20:19 +00002633 ReplaceNode(N, ResNode);
Justin Bogner45571362016-05-12 00:31:09 +00002634 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002635 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002636
Evan Cheng10043e22007-01-19 07:51:42 +00002637 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002638 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002639 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002640 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002641 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002642 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00002643 SDValue TFI = CurDAG->getTargetFrameIndex(
2644 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin22c2fba2009-07-08 23:10:31 +00002645 if (Subtarget->isThumb1Only()) {
Renato Golinb9887ef2015-02-25 14:41:06 +00002646 // Set the alignment of the frame object to 4, to avoid having to generate
2647 // more than one ADD
Matthias Braun941a7052016-07-28 18:40:00 +00002648 MachineFrameInfo &MFI = MF->getFrameInfo();
2649 if (MFI.getObjectAlignment(FI) < 4)
2650 MFI.setObjectAlignment(FI, 4);
Justin Bogner45571362016-05-12 00:31:09 +00002651 CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
2652 CurDAG->getTargetConstant(0, dl, MVT::i32));
2653 return;
Jim Grosbachfde21102009-04-07 20:34:09 +00002654 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002655 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2656 ARM::t2ADDri : ARM::ADDri);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002657 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
2658 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002659 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002660 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2661 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00002662 }
Evan Cheng10043e22007-01-19 07:51:42 +00002663 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002664 case ISD::SRL:
Justin Bogner45571362016-05-12 00:31:09 +00002665 if (tryV6T2BitfieldExtractOp(N, false))
2666 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002667 break;
Tim Northover14ff2df2014-07-23 13:59:12 +00002668 case ISD::SIGN_EXTEND_INREG:
Sandeep Patel423e42b2009-10-13 18:59:48 +00002669 case ISD::SRA:
Justin Bogner45571362016-05-12 00:31:09 +00002670 if (tryV6T2BitfieldExtractOp(N, true))
2671 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002672 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002673 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002674 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002675 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002676 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002677 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002678 if (!RHSV) break;
2679 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002680 unsigned ShImm = Log2_32(RHSV-1);
2681 if (ShImm >= 32)
2682 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002683 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002684 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002685 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002686 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002687 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002688 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002689 CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
2690 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002691 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002692 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2693 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002694 CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
2695 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002696 }
Evan Cheng10043e22007-01-19 07:51:42 +00002697 }
2698 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002699 unsigned ShImm = Log2_32(RHSV+1);
2700 if (ShImm >= 32)
2701 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002702 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002703 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002704 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002705 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002706 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002707 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002708 CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
2709 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002710 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002711 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2712 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002713 CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
2714 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002715 }
Evan Cheng10043e22007-01-19 07:51:42 +00002716 }
2717 }
2718 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002719 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002720 // Check for unsigned bitfield extract
Justin Bogner45571362016-05-12 00:31:09 +00002721 if (tryV6T2BitfieldExtractOp(N, false))
2722 return;
Jim Grosbach825cb292010-04-22 23:24:18 +00002723
James Molloyae5ff992016-07-05 12:37:13 +00002724 // If an immediate is used in an AND node, it is possible that the immediate
2725 // can be more optimally materialized when negated. If this is the case we
2726 // can negate the immediate and use a BIC instead.
2727 auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1));
2728 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
2729 uint32_t Imm = (uint32_t) N1C->getZExtValue();
2730
2731 // In Thumb2 mode, an AND can take a 12-bit immediate. If this
2732 // immediate can be negated and fit in the immediate operand of
2733 // a t2BIC, don't do any manual transform here as this can be
2734 // handled by the generic ISel machinery.
2735 bool PreferImmediateEncoding =
2736 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm));
2737 if (!PreferImmediateEncoding &&
2738 ConstantMaterializationCost(Imm) >
2739 ConstantMaterializationCost(~Imm)) {
2740 // The current immediate costs more to materialize than a negated
2741 // immediate, so negate the immediate and use a BIC.
2742 SDValue NewImm =
2743 CurDAG->getConstant(~N1C->getZExtValue(), dl, MVT::i32);
2744 // If the new constant didn't exist before, reposition it in the topological
2745 // ordering so it is just before N. Otherwise, don't touch its location.
2746 if (NewImm->getNodeId() == -1)
2747 CurDAG->RepositionNode(N->getIterator(), NewImm.getNode());
2748
2749 if (!Subtarget->hasThumb2()) {
2750 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
2751 N->getOperand(0), NewImm, getAL(CurDAG, dl),
2752 CurDAG->getRegister(0, MVT::i32)};
2753 ReplaceNode(N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32, Ops));
2754 return;
2755 } else {
2756 SDValue Ops[] = {N->getOperand(0), NewImm, getAL(CurDAG, dl),
2757 CurDAG->getRegister(0, MVT::i32),
2758 CurDAG->getRegister(0, MVT::i32)};
2759 ReplaceNode(N,
2760 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32, Ops));
2761 return;
2762 }
2763 }
2764 }
2765
Evan Cheng786b15f2009-10-21 08:15:52 +00002766 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2767 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2768 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2769 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2770 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002771 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002772 if (VT != MVT::i32)
2773 break;
2774 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2775 ? ARM::t2MOVTi16
2776 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2777 if (!Opc)
2778 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002779 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
James Molloyae5ff992016-07-05 12:37:13 +00002780 N1C = dyn_cast<ConstantSDNode>(N1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002781 if (!N1C)
2782 break;
2783 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2784 SDValue N2 = N0.getOperand(1);
2785 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2786 if (!N2C)
2787 break;
2788 unsigned N1CVal = N1C->getZExtValue();
2789 unsigned N2CVal = N2C->getZExtValue();
2790 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2791 (N1CVal & 0xffffU) == 0xffffU &&
2792 (N2CVal & 0xffffU) == 0x0U) {
2793 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002794 dl, MVT::i32);
Evan Cheng786b15f2009-10-21 08:15:52 +00002795 SDValue Ops[] = { N0.getOperand(0), Imm16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002796 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002797 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
2798 return;
Evan Cheng786b15f2009-10-21 08:15:52 +00002799 }
2800 }
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002801
Evan Cheng786b15f2009-10-21 08:15:52 +00002802 break;
2803 }
Sam Parkerd616cf02016-06-20 16:47:09 +00002804 case ARMISD::UMAAL: {
2805 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
2806 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2807 N->getOperand(2), N->getOperand(3),
2808 getAL(CurDAG, dl),
2809 CurDAG->getRegister(0, MVT::i32) };
2810 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::i32, Ops));
2811 return;
2812 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002813 case ARMISD::UMLAL:{
2814 if (Subtarget->isThumb()) {
2815 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002816 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002817 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002818 ReplaceNode(
2819 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops));
2820 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002821 }else{
2822 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002823 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002824 CurDAG->getRegister(0, MVT::i32),
2825 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002826 ReplaceNode(N, CurDAG->getMachineNode(
2827 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl,
2828 MVT::i32, MVT::i32, Ops));
2829 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002830 }
2831 }
2832 case ARMISD::SMLAL:{
2833 if (Subtarget->isThumb()) {
2834 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002835 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002836 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002837 ReplaceNode(
2838 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops));
2839 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002840 }else{
2841 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002842 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002843 CurDAG->getRegister(0, MVT::i32),
2844 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002845 ReplaceNode(N, CurDAG->getMachineNode(
2846 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl,
2847 MVT::i32, MVT::i32, Ops));
2848 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002849 }
2850 }
Sam Parker68c71cd2016-07-25 09:20:20 +00002851 case ARMISD::SUBE: {
Andre Vieira26b9de92018-01-12 09:21:09 +00002852 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
Sam Parker68c71cd2016-07-25 09:20:20 +00002853 break;
2854 // Look for a pattern to match SMMLS
2855 // (sube a, (smul_loHi a, b), (subc 0, (smul_LOhi(a, b))))
2856 if (N->getOperand(1).getOpcode() != ISD::SMUL_LOHI ||
Tim Northover765777c2016-08-02 23:12:36 +00002857 N->getOperand(2).getOpcode() != ARMISD::SUBC ||
2858 !SDValue(N, 1).use_empty())
Sam Parker68c71cd2016-07-25 09:20:20 +00002859 break;
2860
2861 if (Subtarget->isThumb())
2862 assert(Subtarget->hasThumb2() &&
2863 "This pattern should not be generated for Thumb");
2864
2865 SDValue SmulLoHi = N->getOperand(1);
2866 SDValue Subc = N->getOperand(2);
2867 auto *Zero = dyn_cast<ConstantSDNode>(Subc.getOperand(0));
2868
2869 if (!Zero || Zero->getZExtValue() != 0 ||
2870 Subc.getOperand(1) != SmulLoHi.getValue(0) ||
2871 N->getOperand(1) != SmulLoHi.getValue(1) ||
2872 N->getOperand(2) != Subc.getValue(1))
2873 break;
2874
2875 unsigned Opc = Subtarget->isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
2876 SDValue Ops[] = { SmulLoHi.getOperand(0), SmulLoHi.getOperand(1),
2877 N->getOperand(0), getAL(CurDAG, dl),
2878 CurDAG->getRegister(0, MVT::i32) };
2879 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops));
2880 return;
2881 }
Evan Cheng10043e22007-01-19 07:51:42 +00002882 case ISD::LOAD: {
Justin Bogner45571362016-05-12 00:31:09 +00002883 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
2884 if (tryT2IndexedLoad(N))
2885 return;
James Molloyb3326df2016-07-15 08:03:56 +00002886 } else if (Subtarget->isThumb()) {
2887 if (tryT1IndexedLoad(N))
2888 return;
Justin Bogner45571362016-05-12 00:31:09 +00002889 } else if (tryARMIndexedLoad(N))
2890 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002891 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002892 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00002893 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002894 case ARMISD::BRCOND: {
2895 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2896 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2897 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00002898
Evan Cheng7e90b112007-07-05 07:15:27 +00002899 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2900 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2901 // Pattern complexity = 6 cost = 1 size = 0
2902
David Goodwin27303cd2009-06-30 18:04:13 +00002903 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2904 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2905 // Pattern complexity = 6 cost = 1 size = 0
2906
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002907 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00002908 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002909 SDValue Chain = N->getOperand(0);
2910 SDValue N1 = N->getOperand(1);
2911 SDValue N2 = N->getOperand(2);
2912 SDValue N3 = N->getOperand(3);
2913 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00002914 assert(N1.getOpcode() == ISD::BasicBlock);
2915 assert(N2.getOpcode() == ISD::Constant);
2916 assert(N3.getOpcode() == ISD::Register);
2917
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002918 unsigned CC = (unsigned) cast<ConstantSDNode>(N2)->getZExtValue();
2919
2920 if (InFlag.getOpcode() == ARMISD::CMPZ) {
2921 bool SwitchEQNEToPLMI;
2922 SelectCMPZ(InFlag.getNode(), SwitchEQNEToPLMI);
2923 InFlag = N->getOperand(4);
2924
2925 if (SwitchEQNEToPLMI) {
2926 switch ((ARMCC::CondCodes)CC) {
2927 default: llvm_unreachable("CMPZ must be either NE or EQ!");
2928 case ARMCC::NE:
2929 CC = (unsigned)ARMCC::MI;
2930 break;
2931 case ARMCC::EQ:
2932 CC = (unsigned)ARMCC::PL;
2933 break;
2934 }
2935 }
2936 }
2937
2938 SDValue Tmp2 = CurDAG->getTargetConstant(CC, dl, MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002939 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00002940 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002941 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002942 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002943 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002944 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002945 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00002946 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002947 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00002948 SDValue(Chain.getNode(), Chain.getResNo()));
Justin Bognered4f3782016-05-12 00:20:19 +00002949 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00002950 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00002951 }
James Molloy4d86bed2016-09-09 12:52:24 +00002952
2953 case ARMISD::CMPZ: {
2954 // select (CMPZ X, #-C) -> (CMPZ (ADDS X, #C), #0)
2955 // This allows us to avoid materializing the expensive negative constant.
2956 // The CMPZ #0 is useless and will be peepholed away but we need to keep it
2957 // for its glue output.
2958 SDValue X = N->getOperand(0);
2959 auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1).getNode());
2960 if (C && C->getSExtValue() < 0 && Subtarget->isThumb()) {
2961 int64_t Addend = -C->getSExtValue();
2962
2963 SDNode *Add = nullptr;
Artyom Skrobov4592f622017-02-17 18:59:16 +00002964 // ADDS can be better than CMN if the immediate fits in a
James Molloy4d86bed2016-09-09 12:52:24 +00002965 // 16-bit ADDS, which means either [0,256) for tADDi8 or [0,8) for tADDi3.
2966 // Outside that range we can just use a CMN which is 32-bit but has a
2967 // 12-bit immediate range.
Artyom Skrobov4592f622017-02-17 18:59:16 +00002968 if (Addend < 1<<8) {
2969 if (Subtarget->isThumb2()) {
2970 SDValue Ops[] = { X, CurDAG->getTargetConstant(Addend, dl, MVT::i32),
2971 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
2972 CurDAG->getRegister(0, MVT::i32) };
2973 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl, MVT::i32, Ops);
2974 } else {
2975 unsigned Opc = (Addend < 1<<3) ? ARM::tADDi3 : ARM::tADDi8;
2976 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), X,
2977 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
2978 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
2979 Add = CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
2980 }
James Molloy4d86bed2016-09-09 12:52:24 +00002981 }
2982 if (Add) {
2983 SDValue Ops2[] = {SDValue(Add, 0), CurDAG->getConstant(0, dl, MVT::i32)};
2984 CurDAG->MorphNodeTo(N, ARMISD::CMPZ, CurDAG->getVTList(MVT::Glue), Ops2);
2985 }
2986 }
2987 // Other cases are autogenerated.
2988 break;
2989 }
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002990
2991 case ARMISD::CMOV: {
2992 SDValue InFlag = N->getOperand(4);
2993
2994 if (InFlag.getOpcode() == ARMISD::CMPZ) {
2995 bool SwitchEQNEToPLMI;
2996 SelectCMPZ(InFlag.getNode(), SwitchEQNEToPLMI);
2997
2998 if (SwitchEQNEToPLMI) {
2999 SDValue ARMcc = N->getOperand(2);
3000 ARMCC::CondCodes CC =
3001 (ARMCC::CondCodes)cast<ConstantSDNode>(ARMcc)->getZExtValue();
3002
3003 switch (CC) {
3004 default: llvm_unreachable("CMPZ must be either NE or EQ!");
3005 case ARMCC::NE:
3006 CC = ARMCC::MI;
3007 break;
3008 case ARMCC::EQ:
3009 CC = ARMCC::PL;
3010 break;
3011 }
3012 SDValue NewARMcc = CurDAG->getConstant((unsigned)CC, dl, MVT::i32);
3013 SDValue Ops[] = {N->getOperand(0), N->getOperand(1), NewARMcc,
3014 N->getOperand(3), N->getOperand(4)};
3015 CurDAG->MorphNodeTo(N, ARMISD::CMOV, N->getVTList(), Ops);
3016 }
3017
3018 }
3019 // Other cases are autogenerated.
3020 break;
3021 }
James Molloy4d86bed2016-09-09 12:52:24 +00003022
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003023 case ARMISD::VZIP: {
3024 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003025 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003026 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003027 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003028 case MVT::v8i8: Opc = ARM::VZIPd8; break;
3029 case MVT::v4i16: Opc = ARM::VZIPd16; break;
3030 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00003031 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3032 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003033 case MVT::v16i8: Opc = ARM::VZIPq8; break;
3034 case MVT::v8i16: Opc = ARM::VZIPq16; break;
3035 case MVT::v4f32:
3036 case MVT::v4i32: Opc = ARM::VZIPq32; break;
3037 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003038 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003039 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3040 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003041 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3042 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003043 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003044 case ARMISD::VUZP: {
3045 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003046 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003047 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003048 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003049 case MVT::v8i8: Opc = ARM::VUZPd8; break;
3050 case MVT::v4i16: Opc = ARM::VUZPd16; break;
3051 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00003052 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
3053 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003054 case MVT::v16i8: Opc = ARM::VUZPq8; break;
3055 case MVT::v8i16: Opc = ARM::VUZPq16; break;
3056 case MVT::v4f32:
3057 case MVT::v4i32: Opc = ARM::VUZPq32; break;
3058 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003059 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003060 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3061 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003062 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3063 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003064 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003065 case ARMISD::VTRN: {
3066 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003067 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003068 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00003069 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00003070 case MVT::v8i8: Opc = ARM::VTRNd8; break;
3071 case MVT::v4i16: Opc = ARM::VTRNd16; break;
3072 case MVT::v2f32:
3073 case MVT::v2i32: Opc = ARM::VTRNd32; break;
3074 case MVT::v16i8: Opc = ARM::VTRNq8; break;
3075 case MVT::v8i16: Opc = ARM::VTRNq16; break;
3076 case MVT::v4f32:
3077 case MVT::v4i32: Opc = ARM::VTRNq32; break;
3078 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003079 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00003080 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
3081 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00003082 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
3083 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003084 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003085 case ARMISD::BUILD_VECTOR: {
3086 EVT VecVT = N->getValueType(0);
3087 EVT EltVT = VecVT.getVectorElementType();
3088 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00003089 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00003090 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003091 ReplaceNode(
3092 N, createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3093 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003094 }
Duncan Sands14627772010-11-03 12:17:33 +00003095 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003096 if (NumElts == 2) {
3097 ReplaceNode(
3098 N, createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3099 return;
3100 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003101 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003102 ReplaceNode(N,
3103 createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
3104 N->getOperand(2), N->getOperand(3)));
3105 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003106 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003107
Eli Friedmanf624ec22016-12-16 18:44:08 +00003108 case ARMISD::VLD1DUP: {
3109 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8, ARM::VLD1DUPd16,
3110 ARM::VLD1DUPd32 };
3111 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8, ARM::VLD1DUPq16,
3112 ARM::VLD1DUPq32 };
Ivan A. Kosarev72315982018-06-27 13:57:52 +00003113 SelectVLDDup(N, /* IsIntrinsic= */ false, false, 1, DOpcodes, QOpcodes);
Eli Friedmanf624ec22016-12-16 18:44:08 +00003114 return;
3115 }
3116
Bob Wilson2d790df2010-11-28 06:51:26 +00003117 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003118 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
3119 ARM::VLD2DUPd32 };
Ivan A. Kosarev72315982018-06-27 13:57:52 +00003120 SelectVLDDup(N, /* IsIntrinsic= */ false, false, 2, Opcodes);
Justin Bogner45571362016-05-12 00:31:09 +00003121 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00003122 }
3123
Bob Wilson77ab1652010-11-29 19:35:29 +00003124 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003125 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
3126 ARM::VLD3DUPd16Pseudo,
3127 ARM::VLD3DUPd32Pseudo };
Ivan A. Kosarev72315982018-06-27 13:57:52 +00003128 SelectVLDDup(N, /* IsIntrinsic= */ false, false, 3, Opcodes);
Justin Bogner45571362016-05-12 00:31:09 +00003129 return;
Bob Wilson77ab1652010-11-29 19:35:29 +00003130 }
3131
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003132 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003133 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
3134 ARM::VLD4DUPd16Pseudo,
3135 ARM::VLD4DUPd32Pseudo };
Ivan A. Kosarev72315982018-06-27 13:57:52 +00003136 SelectVLDDup(N, /* IsIntrinsic= */ false, false, 4, Opcodes);
Justin Bogner45571362016-05-12 00:31:09 +00003137 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003138 }
3139
Eli Friedmanf624ec22016-12-16 18:44:08 +00003140 case ARMISD::VLD1DUP_UPD: {
3141 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8wb_fixed,
3142 ARM::VLD1DUPd16wb_fixed,
3143 ARM::VLD1DUPd32wb_fixed };
3144 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8wb_fixed,
3145 ARM::VLD1DUPq16wb_fixed,
3146 ARM::VLD1DUPq32wb_fixed };
Ivan A. Kosarev72315982018-06-27 13:57:52 +00003147 SelectVLDDup(N, /* IsIntrinsic= */ false, true, 1, DOpcodes, QOpcodes);
Eli Friedmanf624ec22016-12-16 18:44:08 +00003148 return;
3149 }
3150
Bob Wilson06fce872011-02-07 17:43:21 +00003151 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003152 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
3153 ARM::VLD2DUPd16wb_fixed,
3154 ARM::VLD2DUPd32wb_fixed };
Ivan A. Kosarev72315982018-06-27 13:57:52 +00003155 SelectVLDDup(N, /* IsIntrinsic= */ false, true, 2, Opcodes);
Justin Bogner45571362016-05-12 00:31:09 +00003156 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003157 }
3158
3159 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003160 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
3161 ARM::VLD3DUPd16Pseudo_UPD,
3162 ARM::VLD3DUPd32Pseudo_UPD };
Ivan A. Kosarev72315982018-06-27 13:57:52 +00003163 SelectVLDDup(N, /* IsIntrinsic= */ false, true, 3, Opcodes);
Justin Bogner45571362016-05-12 00:31:09 +00003164 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003165 }
3166
3167 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003168 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
3169 ARM::VLD4DUPd16Pseudo_UPD,
3170 ARM::VLD4DUPd32Pseudo_UPD };
Ivan A. Kosarev72315982018-06-27 13:57:52 +00003171 SelectVLDDup(N, /* IsIntrinsic= */ false, true, 4, Opcodes);
Justin Bogner45571362016-05-12 00:31:09 +00003172 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003173 }
3174
3175 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003176 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
3177 ARM::VLD1d16wb_fixed,
3178 ARM::VLD1d32wb_fixed,
3179 ARM::VLD1d64wb_fixed };
3180 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
3181 ARM::VLD1q16wb_fixed,
3182 ARM::VLD1q32wb_fixed,
3183 ARM::VLD1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003184 SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
3185 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003186 }
3187
3188 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003189 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
3190 ARM::VLD2d16wb_fixed,
3191 ARM::VLD2d32wb_fixed,
3192 ARM::VLD1q64wb_fixed};
3193 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
3194 ARM::VLD2q16PseudoWB_fixed,
3195 ARM::VLD2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003196 SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
3197 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003198 }
3199
3200 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003201 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
3202 ARM::VLD3d16Pseudo_UPD,
3203 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003204 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003205 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3206 ARM::VLD3q16Pseudo_UPD,
3207 ARM::VLD3q32Pseudo_UPD };
3208 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3209 ARM::VLD3q16oddPseudo_UPD,
3210 ARM::VLD3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003211 SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3212 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003213 }
3214
3215 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003216 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3217 ARM::VLD4d16Pseudo_UPD,
3218 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003219 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003220 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3221 ARM::VLD4q16Pseudo_UPD,
3222 ARM::VLD4q32Pseudo_UPD };
3223 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3224 ARM::VLD4q16oddPseudo_UPD,
3225 ARM::VLD4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003226 SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3227 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003228 }
3229
3230 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003231 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3232 ARM::VLD2LNd16Pseudo_UPD,
3233 ARM::VLD2LNd32Pseudo_UPD };
3234 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3235 ARM::VLD2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003236 SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3237 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003238 }
3239
3240 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003241 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3242 ARM::VLD3LNd16Pseudo_UPD,
3243 ARM::VLD3LNd32Pseudo_UPD };
3244 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3245 ARM::VLD3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003246 SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3247 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003248 }
3249
3250 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003251 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3252 ARM::VLD4LNd16Pseudo_UPD,
3253 ARM::VLD4LNd32Pseudo_UPD };
3254 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3255 ARM::VLD4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003256 SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3257 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003258 }
3259
3260 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003261 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3262 ARM::VST1d16wb_fixed,
3263 ARM::VST1d32wb_fixed,
3264 ARM::VST1d64wb_fixed };
3265 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3266 ARM::VST1q16wb_fixed,
3267 ARM::VST1q32wb_fixed,
3268 ARM::VST1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003269 SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
3270 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003271 }
3272
3273 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003274 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3275 ARM::VST2d16wb_fixed,
3276 ARM::VST2d32wb_fixed,
3277 ARM::VST1q64wb_fixed};
3278 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3279 ARM::VST2q16PseudoWB_fixed,
3280 ARM::VST2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003281 SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
3282 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003283 }
3284
3285 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003286 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3287 ARM::VST3d16Pseudo_UPD,
3288 ARM::VST3d32Pseudo_UPD,
3289 ARM::VST1d64TPseudoWB_fixed};
3290 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3291 ARM::VST3q16Pseudo_UPD,
3292 ARM::VST3q32Pseudo_UPD };
3293 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3294 ARM::VST3q16oddPseudo_UPD,
3295 ARM::VST3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003296 SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3297 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003298 }
3299
3300 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003301 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3302 ARM::VST4d16Pseudo_UPD,
3303 ARM::VST4d32Pseudo_UPD,
3304 ARM::VST1d64QPseudoWB_fixed};
3305 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3306 ARM::VST4q16Pseudo_UPD,
3307 ARM::VST4q32Pseudo_UPD };
3308 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3309 ARM::VST4q16oddPseudo_UPD,
3310 ARM::VST4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003311 SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3312 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003313 }
3314
3315 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003316 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3317 ARM::VST2LNd16Pseudo_UPD,
3318 ARM::VST2LNd32Pseudo_UPD };
3319 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3320 ARM::VST2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003321 SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3322 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003323 }
3324
3325 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003326 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3327 ARM::VST3LNd16Pseudo_UPD,
3328 ARM::VST3LNd32Pseudo_UPD };
3329 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3330 ARM::VST3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003331 SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3332 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003333 }
3334
3335 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003336 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3337 ARM::VST4LNd16Pseudo_UPD,
3338 ARM::VST4LNd32Pseudo_UPD };
3339 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3340 ARM::VST4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003341 SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
3342 return;
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003343 }
3344
Bob Wilsone0636a72009-08-26 17:39:53 +00003345 case ISD::INTRINSIC_VOID:
3346 case ISD::INTRINSIC_W_CHAIN: {
3347 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003348 switch (IntNo) {
3349 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003350 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003351
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003352 case Intrinsic::arm_mrrc:
3353 case Intrinsic::arm_mrrc2: {
3354 SDLoc dl(N);
3355 SDValue Chain = N->getOperand(0);
3356 unsigned Opc;
3357
3358 if (Subtarget->isThumb())
3359 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
3360 else
3361 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
3362
3363 SmallVector<SDValue, 5> Ops;
3364 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(), dl)); /* coproc */
3365 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(), dl)); /* opc */
3366 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(4))->getZExtValue(), dl)); /* CRm */
3367
3368 // The mrrc2 instruction in ARM doesn't allow predicates, the top 4 bits of the encoded
3369 // instruction will always be '1111' but it is possible in assembly language to specify
3370 // AL as a predicate to mrrc2 but it doesn't make any difference to the encoded instruction.
3371 if (Opc != ARM::MRRC2) {
3372 Ops.push_back(getAL(CurDAG, dl));
3373 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3374 }
3375
3376 Ops.push_back(Chain);
3377
3378 // Writes to two registers.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003379 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003380
3381 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, RetType, Ops));
3382 return;
3383 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003384 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003385 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003386 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003387 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003388 SDValue MemAddr = N->getOperand(2);
Bradley Smith433c22e2016-01-15 10:26:51 +00003389 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
Tim Northover1ff5f292014-03-26 14:39:31 +00003390
3391 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3392 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3393 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003394
3395 // arm_ldrexd returns a i64 value in {i32, i32}
3396 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003397 if (isThumb) {
3398 ResTys.push_back(MVT::i32);
3399 ResTys.push_back(MVT::i32);
3400 } else
3401 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003402 ResTys.push_back(MVT::Other);
3403
Weiming Zhao8f56f882012-11-16 21:55:34 +00003404 // Place arguments in the right order.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003405 SDValue Ops[] = {MemAddr, getAL(CurDAG, dl),
3406 CurDAG->getRegister(0, MVT::i32), Chain};
Michael Liaob53d8962013-04-19 22:22:57 +00003407 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003408 // Transfer memoperands.
3409 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3410 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3411 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3412
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003413 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003414 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003415 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003416 SDValue Result;
3417 if (isThumb)
3418 Result = SDValue(Ld, 0);
3419 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003420 SDValue SubRegIdx =
3421 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003422 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003423 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003424 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003425 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003426 ReplaceUses(SDValue(N, 0), Result);
3427 }
3428 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003429 SDValue Result;
3430 if (isThumb)
3431 Result = SDValue(Ld, 1);
3432 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003433 SDValue SubRegIdx =
3434 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003435 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003436 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003437 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003438 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003439 ReplaceUses(SDValue(N, 1), Result);
3440 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003441 ReplaceUses(SDValue(N, 2), OutChain);
Justin Bognered4f3782016-05-12 00:20:19 +00003442 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003443 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003444 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003445 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003446 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003447 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003448 SDValue Chain = N->getOperand(0);
3449 SDValue Val0 = N->getOperand(2);
3450 SDValue Val1 = N->getOperand(3);
3451 SDValue MemAddr = N->getOperand(4);
3452
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003453 // Store exclusive double return a i32 value which is the return status
3454 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003455 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003456
Weiming Zhao8f56f882012-11-16 21:55:34 +00003457 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3458 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003459 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003460 if (isThumb) {
3461 Ops.push_back(Val0);
3462 Ops.push_back(Val1);
3463 } else
3464 // arm_strexd uses GPRPair.
3465 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003466 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003467 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003468 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3469 Ops.push_back(Chain);
3470
Tim Northover1ff5f292014-03-26 14:39:31 +00003471 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3472 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3473 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003474
Michael Liaob53d8962013-04-19 22:22:57 +00003475 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003476 // Transfer memoperands.
3477 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3478 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3479 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3480
Justin Bogner45571362016-05-12 00:31:09 +00003481 ReplaceNode(N, St);
3482 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003483 }
3484
Bob Wilson340861d2010-03-23 05:25:43 +00003485 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003486 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3487 ARM::VLD1d32, ARM::VLD1d64 };
3488 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3489 ARM::VLD1q32, ARM::VLD1q64};
Justin Bogner45571362016-05-12 00:31:09 +00003490 SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
3491 return;
Bob Wilson340861d2010-03-23 05:25:43 +00003492 }
3493
Ivan A. Kosarev60a991e2018-06-02 16:40:03 +00003494 case Intrinsic::arm_neon_vld1x2: {
3495 static const uint16_t DOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3496 ARM::VLD1q32, ARM::VLD1q64 };
3497 static const uint16_t QOpcodes[] = { ARM::VLD1d8QPseudo,
3498 ARM::VLD1d16QPseudo,
3499 ARM::VLD1d32QPseudo,
3500 ARM::VLD1d64QPseudo };
3501 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3502 return;
3503 }
3504
3505 case Intrinsic::arm_neon_vld1x3: {
3506 static const uint16_t DOpcodes[] = { ARM::VLD1d8TPseudo,
3507 ARM::VLD1d16TPseudo,
3508 ARM::VLD1d32TPseudo,
3509 ARM::VLD1d64TPseudo };
3510 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowTPseudo_UPD,
3511 ARM::VLD1q16LowTPseudo_UPD,
3512 ARM::VLD1q32LowTPseudo_UPD,
3513 ARM::VLD1q64LowTPseudo_UPD };
3514 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighTPseudo,
3515 ARM::VLD1q16HighTPseudo,
3516 ARM::VLD1q32HighTPseudo,
3517 ARM::VLD1q64HighTPseudo };
3518 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3519 return;
3520 }
3521
3522 case Intrinsic::arm_neon_vld1x4: {
3523 static const uint16_t DOpcodes[] = { ARM::VLD1d8QPseudo,
3524 ARM::VLD1d16QPseudo,
3525 ARM::VLD1d32QPseudo,
3526 ARM::VLD1d64QPseudo };
3527 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowQPseudo_UPD,
3528 ARM::VLD1q16LowQPseudo_UPD,
3529 ARM::VLD1q32LowQPseudo_UPD,
3530 ARM::VLD1q64LowQPseudo_UPD };
3531 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighQPseudo,
3532 ARM::VLD1q16HighQPseudo,
3533 ARM::VLD1q32HighQPseudo,
3534 ARM::VLD1q64HighQPseudo };
3535 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3536 return;
3537 }
3538
Bob Wilsone0636a72009-08-26 17:39:53 +00003539 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003540 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3541 ARM::VLD2d32, ARM::VLD1q64 };
3542 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3543 ARM::VLD2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003544 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3545 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003546 }
3547
3548 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003549 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3550 ARM::VLD3d16Pseudo,
3551 ARM::VLD3d32Pseudo,
3552 ARM::VLD1d64TPseudo };
3553 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3554 ARM::VLD3q16Pseudo_UPD,
3555 ARM::VLD3q32Pseudo_UPD };
3556 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3557 ARM::VLD3q16oddPseudo,
3558 ARM::VLD3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003559 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3560 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003561 }
3562
3563 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003564 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3565 ARM::VLD4d16Pseudo,
3566 ARM::VLD4d32Pseudo,
3567 ARM::VLD1d64QPseudo };
3568 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3569 ARM::VLD4q16Pseudo_UPD,
3570 ARM::VLD4q32Pseudo_UPD };
3571 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3572 ARM::VLD4q16oddPseudo,
3573 ARM::VLD4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003574 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3575 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003576 }
3577
Ivan A. Kosarev72315982018-06-27 13:57:52 +00003578 case Intrinsic::arm_neon_vld2dup: {
3579 static const uint16_t DOpcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
3580 ARM::VLD2DUPd32, ARM::VLD1q64 };
3581 static const uint16_t QOpcodes0[] = { ARM::VLD2DUPq8EvenPseudo,
3582 ARM::VLD2DUPq16EvenPseudo,
3583 ARM::VLD2DUPq32EvenPseudo };
3584 static const uint16_t QOpcodes1[] = { ARM::VLD2DUPq8OddPseudo,
3585 ARM::VLD2DUPq16OddPseudo,
3586 ARM::VLD2DUPq32OddPseudo };
3587 SelectVLDDup(N, /* IsIntrinsic= */ true, false, 2,
3588 DOpcodes, QOpcodes0, QOpcodes1);
3589 return;
3590 }
3591
3592 case Intrinsic::arm_neon_vld3dup: {
3593 static const uint16_t DOpcodes[] = { ARM::VLD3DUPd8Pseudo,
3594 ARM::VLD3DUPd16Pseudo,
3595 ARM::VLD3DUPd32Pseudo,
3596 ARM::VLD1d64TPseudo };
3597 static const uint16_t QOpcodes0[] = { ARM::VLD3DUPq8EvenPseudo,
3598 ARM::VLD3DUPq16EvenPseudo,
3599 ARM::VLD3DUPq32EvenPseudo };
3600 static const uint16_t QOpcodes1[] = { ARM::VLD3DUPq8OddPseudo,
3601 ARM::VLD3DUPq16OddPseudo,
3602 ARM::VLD3DUPq32OddPseudo };
3603 SelectVLDDup(N, /* IsIntrinsic= */ true, false, 3,
3604 DOpcodes, QOpcodes0, QOpcodes1);
3605 return;
3606 }
3607
3608 case Intrinsic::arm_neon_vld4dup: {
3609 static const uint16_t DOpcodes[] = { ARM::VLD4DUPd8Pseudo,
3610 ARM::VLD4DUPd16Pseudo,
3611 ARM::VLD4DUPd32Pseudo,
3612 ARM::VLD1d64QPseudo };
3613 static const uint16_t QOpcodes0[] = { ARM::VLD4DUPq8EvenPseudo,
3614 ARM::VLD4DUPq16EvenPseudo,
3615 ARM::VLD4DUPq32EvenPseudo };
3616 static const uint16_t QOpcodes1[] = { ARM::VLD4DUPq8OddPseudo,
3617 ARM::VLD4DUPq16OddPseudo,
3618 ARM::VLD4DUPq32OddPseudo };
3619 SelectVLDDup(N, /* IsIntrinsic= */ true, false, 4,
3620 DOpcodes, QOpcodes0, QOpcodes1);
3621 return;
3622 }
3623
Bob Wilsonda9817c2009-09-01 04:26:28 +00003624 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003625 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3626 ARM::VLD2LNd16Pseudo,
3627 ARM::VLD2LNd32Pseudo };
3628 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3629 ARM::VLD2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003630 SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
3631 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003632 }
3633
3634 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003635 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3636 ARM::VLD3LNd16Pseudo,
3637 ARM::VLD3LNd32Pseudo };
3638 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3639 ARM::VLD3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003640 SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
3641 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003642 }
3643
3644 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003645 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3646 ARM::VLD4LNd16Pseudo,
3647 ARM::VLD4LNd32Pseudo };
3648 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3649 ARM::VLD4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003650 SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
3651 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003652 }
3653
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003654 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003655 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3656 ARM::VST1d32, ARM::VST1d64 };
3657 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3658 ARM::VST1q32, ARM::VST1q64 };
Justin Bogner45571362016-05-12 00:31:09 +00003659 SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
3660 return;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003661 }
3662
Ivan A. Kosarev847daa12018-06-10 09:27:27 +00003663 case Intrinsic::arm_neon_vst1x2: {
3664 static const uint16_t DOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3665 ARM::VST1q32, ARM::VST1q64 };
3666 static const uint16_t QOpcodes[] = { ARM::VST1d8QPseudo,
3667 ARM::VST1d16QPseudo,
3668 ARM::VST1d32QPseudo,
3669 ARM::VST1d64QPseudo };
3670 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3671 return;
3672 }
3673
3674 case Intrinsic::arm_neon_vst1x3: {
3675 static const uint16_t DOpcodes[] = { ARM::VST1d8TPseudo,
3676 ARM::VST1d16TPseudo,
3677 ARM::VST1d32TPseudo,
3678 ARM::VST1d64TPseudo };
3679 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowTPseudo_UPD,
3680 ARM::VST1q16LowTPseudo_UPD,
3681 ARM::VST1q32LowTPseudo_UPD,
3682 ARM::VST1q64LowTPseudo_UPD };
3683 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighTPseudo,
3684 ARM::VST1q16HighTPseudo,
3685 ARM::VST1q32HighTPseudo,
3686 ARM::VST1q64HighTPseudo };
3687 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3688 return;
3689 }
3690
3691 case Intrinsic::arm_neon_vst1x4: {
3692 static const uint16_t DOpcodes[] = { ARM::VST1d8QPseudo,
3693 ARM::VST1d16QPseudo,
3694 ARM::VST1d32QPseudo,
3695 ARM::VST1d64QPseudo };
3696 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowQPseudo_UPD,
3697 ARM::VST1q16LowQPseudo_UPD,
3698 ARM::VST1q32LowQPseudo_UPD,
3699 ARM::VST1q64LowQPseudo_UPD };
3700 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighQPseudo,
3701 ARM::VST1q16HighQPseudo,
3702 ARM::VST1q32HighQPseudo,
3703 ARM::VST1q64HighQPseudo };
3704 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3705 return;
3706 }
3707
Bob Wilsone0636a72009-08-26 17:39:53 +00003708 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003709 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3710 ARM::VST2d32, ARM::VST1q64 };
Benjamin Kramerf690da42016-06-17 14:14:29 +00003711 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3712 ARM::VST2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003713 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3714 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003715 }
3716
3717 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003718 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3719 ARM::VST3d16Pseudo,
3720 ARM::VST3d32Pseudo,
3721 ARM::VST1d64TPseudo };
3722 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3723 ARM::VST3q16Pseudo_UPD,
3724 ARM::VST3q32Pseudo_UPD };
3725 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3726 ARM::VST3q16oddPseudo,
3727 ARM::VST3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003728 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3729 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003730 }
3731
3732 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003733 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3734 ARM::VST4d16Pseudo,
3735 ARM::VST4d32Pseudo,
3736 ARM::VST1d64QPseudo };
3737 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3738 ARM::VST4q16Pseudo_UPD,
3739 ARM::VST4q32Pseudo_UPD };
3740 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3741 ARM::VST4q16oddPseudo,
3742 ARM::VST4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003743 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3744 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003745 }
Bob Wilsond7797752009-09-01 18:51:56 +00003746
3747 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003748 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3749 ARM::VST2LNd16Pseudo,
3750 ARM::VST2LNd32Pseudo };
3751 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3752 ARM::VST2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003753 SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
3754 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003755 }
3756
3757 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003758 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3759 ARM::VST3LNd16Pseudo,
3760 ARM::VST3LNd32Pseudo };
3761 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3762 ARM::VST3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003763 SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
3764 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003765 }
3766
3767 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003768 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3769 ARM::VST4LNd16Pseudo,
3770 ARM::VST4LNd32Pseudo };
3771 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3772 ARM::VST4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003773 SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
3774 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003775 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003776 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003777 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003778 }
Evan Chengd85631e2010-05-05 18:28:36 +00003779
Tim Northoverb629c772016-04-18 21:48:55 +00003780 case ISD::ATOMIC_CMP_SWAP:
Justin Bogner45571362016-05-12 00:31:09 +00003781 SelectCMP_SWAP(N);
3782 return;
Evan Chengd85631e2010-05-05 18:28:36 +00003783 }
Evan Chengd5021732008-12-10 21:54:21 +00003784
Justin Bogner45571362016-05-12 00:31:09 +00003785 SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003786}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003787
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003788// Inspect a register string of the form
3789// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3790// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3791// and obtain the integer operands from them, adding these operands to the
3792// provided vector.
3793static void getIntOperandsFromRegisterString(StringRef RegString,
Benjamin Kramerbdc49562016-06-12 15:39:02 +00003794 SelectionDAG *CurDAG,
3795 const SDLoc &DL,
3796 std::vector<SDValue> &Ops) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003797 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003798 RegString.split(Fields, ':');
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003799
3800 if (Fields.size() > 1) {
3801 bool AllIntFields = true;
3802
3803 for (StringRef Field : Fields) {
3804 // Need to trim out leading 'cp' characters and get the integer field.
3805 unsigned IntField;
3806 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3807 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3808 }
3809
3810 assert(AllIntFields &&
3811 "Unexpected non-integer value in special register string.");
3812 }
3813}
3814
3815// Maps a Banked Register string to its mask value. The mask value returned is
3816// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3817// mask operand, which expresses which register is to be used, e.g. r8, and in
3818// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3819// was invalid.
3820static inline int getBankedRegisterMask(StringRef RegString) {
Javed Absar054d1ae2017-08-03 01:24:12 +00003821 auto TheReg = ARMBankedReg::lookupBankedRegByName(RegString.lower());
3822 if (!TheReg)
3823 return -1;
3824 return TheReg->Encoding;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003825}
3826
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003827// The flags here are common to those allowed for apsr in the A class cores and
3828// those allowed for the special registers in the M class cores. Returns a
3829// value representing which flags were present, -1 if invalid.
John Brawne60f4e42017-02-10 17:41:08 +00003830static inline int getMClassFlagsMask(StringRef Flags) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003831 return StringSwitch<int>(Flags)
John Brawne60f4e42017-02-10 17:41:08 +00003832 .Case("", 0x2) // no flags means nzcvq for psr registers, and 0x2 is
3833 // correct when flags are not permitted
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003834 .Case("g", 0x1)
3835 .Case("nzcvq", 0x2)
3836 .Case("nzcvqg", 0x3)
3837 .Default(-1);
3838}
3839
Javed Absar2cb0c952017-07-19 12:57:16 +00003840// Maps MClass special registers string to its value for use in the
3841// t2MRS_M/t2MSR_M instruction nodes as the SYSm value operand.
3842// Returns -1 to signify that the string was invalid.
3843static int getMClassRegisterMask(StringRef Reg, const ARMSubtarget *Subtarget) {
3844 auto TheReg = ARMSysReg::lookupMClassSysRegByName(Reg);
3845 const FeatureBitset &FeatureBits = Subtarget->getFeatureBits();
3846 if (!TheReg || !TheReg->hasRequiredFeatures(FeatureBits))
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003847 return -1;
Javed Absar2cb0c952017-07-19 12:57:16 +00003848 return (int)(TheReg->Encoding & 0xFFF); // SYSm value
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003849}
3850
3851static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
3852 // The mask operand contains the special register (R Bit) in bit 4, whether
3853 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
3854 // bits 3-0 contains the fields to be accessed in the special register, set by
3855 // the flags provided with the register.
3856 int Mask = 0;
3857 if (Reg == "apsr") {
3858 // The flags permitted for apsr are the same flags that are allowed in
3859 // M class registers. We get the flag value and then shift the flags into
3860 // the correct place to combine with the mask.
John Brawne60f4e42017-02-10 17:41:08 +00003861 Mask = getMClassFlagsMask(Flags);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003862 if (Mask == -1)
3863 return -1;
3864 return Mask << 2;
3865 }
3866
3867 if (Reg != "cpsr" && Reg != "spsr") {
3868 return -1;
3869 }
3870
3871 // This is the same as if the flags were "fc"
3872 if (Flags.empty() || Flags == "all")
3873 return Mask | 0x9;
3874
3875 // Inspect the supplied flags string and set the bits in the mask for
3876 // the relevant and valid flags allowed for cpsr and spsr.
3877 for (char Flag : Flags) {
3878 int FlagVal;
3879 switch (Flag) {
3880 case 'c':
3881 FlagVal = 0x1;
3882 break;
3883 case 'x':
3884 FlagVal = 0x2;
3885 break;
3886 case 's':
3887 FlagVal = 0x4;
3888 break;
3889 case 'f':
3890 FlagVal = 0x8;
3891 break;
3892 default:
3893 FlagVal = 0;
3894 }
3895
3896 // This avoids allowing strings where the same flag bit appears twice.
3897 if (!FlagVal || (Mask & FlagVal))
3898 return -1;
3899 Mask |= FlagVal;
3900 }
3901
3902 // If the register is spsr then we need to set the R bit.
3903 if (Reg == "spsr")
3904 Mask |= 0x10;
3905
3906 return Mask;
3907}
3908
3909// Lower the read_register intrinsic to ARM specific DAG nodes
3910// using the supplied metadata string to select the instruction node to use
3911// and the registers/masks to construct as operands for the node.
Justin Bogner45571362016-05-12 00:31:09 +00003912bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003913 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3914 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3915 bool IsThumb2 = Subtarget->isThumb2();
3916 SDLoc DL(N);
3917
3918 std::vector<SDValue> Ops;
3919 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3920
3921 if (!Ops.empty()) {
3922 // If the special register string was constructed of fields (as defined
3923 // in the ACLE) then need to lower to MRC node (32 bit) or
3924 // MRRC node(64 bit), we can make the distinction based on the number of
3925 // operands we have.
3926 unsigned Opcode;
3927 SmallVector<EVT, 3> ResTypes;
3928 if (Ops.size() == 5){
3929 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
3930 ResTypes.append({ MVT::i32, MVT::Other });
3931 } else {
3932 assert(Ops.size() == 3 &&
3933 "Invalid number of fields in special register string.");
3934 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
3935 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
3936 }
3937
3938 Ops.push_back(getAL(CurDAG, DL));
3939 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3940 Ops.push_back(N->getOperand(0));
Justin Bogner45571362016-05-12 00:31:09 +00003941 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops));
3942 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003943 }
3944
3945 std::string SpecialReg = RegString->getString().lower();
3946
3947 int BankedReg = getBankedRegisterMask(SpecialReg);
3948 if (BankedReg != -1) {
3949 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
3950 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3951 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003952 ReplaceNode(
3953 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
3954 DL, MVT::i32, MVT::Other, Ops));
3955 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003956 }
3957
3958 // The VFP registers are read by creating SelectionDAG nodes with opcodes
3959 // corresponding to the register that is being read from. So we switch on the
3960 // string to find which opcode we need to use.
3961 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3962 .Case("fpscr", ARM::VMRS)
3963 .Case("fpexc", ARM::VMRS_FPEXC)
3964 .Case("fpsid", ARM::VMRS_FPSID)
3965 .Case("mvfr0", ARM::VMRS_MVFR0)
3966 .Case("mvfr1", ARM::VMRS_MVFR1)
3967 .Case("mvfr2", ARM::VMRS_MVFR2)
3968 .Case("fpinst", ARM::VMRS_FPINST)
3969 .Case("fpinst2", ARM::VMRS_FPINST2)
3970 .Default(0);
3971
3972 // If an opcode was found then we can lower the read to a VFP instruction.
3973 if (Opcode) {
3974 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00003975 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003976 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
Justin Bogner45571362016-05-12 00:31:09 +00003977 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003978
3979 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3980 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003981 ReplaceNode(N,
3982 CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops));
3983 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003984 }
3985
3986 // If the target is M Class then need to validate that the register string
3987 // is an acceptable value, so check that a mask can be constructed from the
3988 // string.
3989 if (Subtarget->isMClass()) {
Javed Absar2cb0c952017-07-19 12:57:16 +00003990 int SYSmValue = getMClassRegisterMask(SpecialReg, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003991 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00003992 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003993
3994 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
3995 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3996 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003997 ReplaceNode(
3998 N, CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops));
3999 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004000 }
4001
4002 // Here we know the target is not M Class so we need to check if it is one
4003 // of the remaining possible values which are apsr, cpsr or spsr.
4004 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
4005 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4006 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004007 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
4008 DL, MVT::i32, MVT::Other, Ops));
4009 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004010 }
4011
4012 if (SpecialReg == "spsr") {
4013 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4014 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004015 ReplaceNode(
4016 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys, DL,
4017 MVT::i32, MVT::Other, Ops));
4018 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004019 }
4020
Justin Bogner45571362016-05-12 00:31:09 +00004021 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004022}
4023
4024// Lower the write_register intrinsic to ARM specific DAG nodes
4025// using the supplied metadata string to select the instruction node to use
4026// and the registers/masks to use in the nodes
Justin Bogner45571362016-05-12 00:31:09 +00004027bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004028 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
4029 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
4030 bool IsThumb2 = Subtarget->isThumb2();
4031 SDLoc DL(N);
4032
4033 std::vector<SDValue> Ops;
4034 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
4035
4036 if (!Ops.empty()) {
4037 // If the special register string was constructed of fields (as defined
4038 // in the ACLE) then need to lower to MCR node (32 bit) or
4039 // MCRR node(64 bit), we can make the distinction based on the number of
4040 // operands we have.
4041 unsigned Opcode;
4042 if (Ops.size() == 5) {
4043 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
4044 Ops.insert(Ops.begin()+2, N->getOperand(2));
4045 } else {
4046 assert(Ops.size() == 3 &&
4047 "Invalid number of fields in special register string.");
4048 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
4049 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
4050 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
4051 }
4052
4053 Ops.push_back(getAL(CurDAG, DL));
4054 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
4055 Ops.push_back(N->getOperand(0));
4056
Justin Bogner45571362016-05-12 00:31:09 +00004057 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4058 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004059 }
4060
4061 std::string SpecialReg = RegString->getString().lower();
4062 int BankedReg = getBankedRegisterMask(SpecialReg);
4063 if (BankedReg != -1) {
4064 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
4065 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4066 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004067 ReplaceNode(
4068 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
4069 DL, MVT::Other, Ops));
4070 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004071 }
4072
4073 // The VFP registers are written to by creating SelectionDAG nodes with
4074 // opcodes corresponding to the register that is being written. So we switch
4075 // on the string to find which opcode we need to use.
4076 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
4077 .Case("fpscr", ARM::VMSR)
4078 .Case("fpexc", ARM::VMSR_FPEXC)
4079 .Case("fpsid", ARM::VMSR_FPSID)
4080 .Case("fpinst", ARM::VMSR_FPINST)
4081 .Case("fpinst2", ARM::VMSR_FPINST2)
4082 .Default(0);
4083
4084 if (Opcode) {
4085 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00004086 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004087 Ops = { N->getOperand(2), getAL(CurDAG, DL),
4088 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004089 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
4090 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004091 }
4092
Bradley Smithf277c8a2016-01-25 11:25:36 +00004093 std::pair<StringRef, StringRef> Fields;
4094 Fields = StringRef(SpecialReg).rsplit('_');
4095 std::string Reg = Fields.first.str();
4096 StringRef Flags = Fields.second;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004097
4098 // If the target was M Class then need to validate the special register value
4099 // and retrieve the mask for use in the instruction node.
4100 if (Subtarget->isMClass()) {
Javed Absar2cb0c952017-07-19 12:57:16 +00004101 int SYSmValue = getMClassRegisterMask(SpecialReg, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004102 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00004103 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004104
4105 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
4106 N->getOperand(2), getAL(CurDAG, DL),
4107 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004108 ReplaceNode(N, CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops));
4109 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004110 }
4111
4112 // We then check to see if a valid mask can be constructed for one of the
4113 // register string values permitted for the A and R class cores. These values
4114 // are apsr, spsr and cpsr; these are also valid on older cores.
4115 int Mask = getARClassRegisterMask(Reg, Flags);
4116 if (Mask != -1) {
4117 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
4118 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
4119 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00004120 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
4121 DL, MVT::Other, Ops));
4122 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004123 }
4124
Justin Bogner45571362016-05-12 00:31:09 +00004125 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00004126}
4127
Justin Bogner45571362016-05-12 00:31:09 +00004128bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){
Weiming Zhaoc5987002013-02-14 18:10:21 +00004129 std::vector<SDValue> AsmNodeOperands;
4130 unsigned Flag, Kind;
4131 bool Changed = false;
4132 unsigned NumOps = N->getNumOperands();
4133
Weiming Zhaoc5987002013-02-14 18:10:21 +00004134 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
4135 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
4136 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
4137 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004138 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
4139 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
4140 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00004141
Andrew Trickef9de2a2013-05-25 02:42:55 +00004142 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00004143 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
4144 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004145
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004146 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004147 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004148 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00004149 SDValue op = N->getOperand(i);
4150 AsmNodeOperands.push_back(op);
4151
4152 if (i < InlineAsm::Op_FirstOperand)
4153 continue;
4154
4155 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
4156 Flag = C->getZExtValue();
4157 Kind = InlineAsm::getKind(Flag);
4158 }
4159 else
4160 continue;
4161
Joey Gouly392cdad2013-07-08 19:52:51 +00004162 // Immediate operands to inline asm in the SelectionDAG are modeled with
4163 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
4164 // the second is a constant with the value of the immediate. If we get here
4165 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00004166 if (Kind == InlineAsm::Kind_Imm) {
4167 SDValue op = N->getOperand(++i);
4168 AsmNodeOperands.push_back(op);
4169 continue;
4170 }
4171
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004172 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
4173 if (NumRegs)
4174 OpChanged.push_back(false);
4175
4176 unsigned DefIdx = 0;
4177 bool IsTiedToChangedOp = false;
4178 // If it's a use that is tied with a previous def, it has no
4179 // reg class constraint.
4180 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
4181 IsTiedToChangedOp = OpChanged[DefIdx];
4182
Diana Picusf345d402016-07-20 09:48:24 +00004183 // Memory operands to inline asm in the SelectionDAG are modeled with two
4184 // operands: a constant of value InlineAsm::Kind_Mem followed by the input
4185 // operand. If we get here and we have a Kind_Mem, skip the next operand (so
4186 // it doesn't get misinterpreted), and continue. We do this here because
4187 // it's important to update the OpChanged array correctly before moving on.
4188 if (Kind == InlineAsm::Kind_Mem) {
4189 SDValue op = N->getOperand(++i);
4190 AsmNodeOperands.push_back(op);
4191 continue;
4192 }
4193
Weiming Zhaoc5987002013-02-14 18:10:21 +00004194 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
4195 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
4196 continue;
4197
Weiming Zhaoc5987002013-02-14 18:10:21 +00004198 unsigned RC;
4199 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004200 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
4201 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00004202 continue;
4203
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004204 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00004205 SDValue V0 = N->getOperand(i+1);
4206 SDValue V1 = N->getOperand(i+2);
4207 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
4208 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
4209 SDValue PairedReg;
4210 MachineRegisterInfo &MRI = MF->getRegInfo();
4211
4212 if (Kind == InlineAsm::Kind_RegDef ||
4213 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
4214 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
4215 // the original GPRs.
4216
4217 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4218 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4219 SDValue Chain = SDValue(N,0);
4220
4221 SDNode *GU = N->getGluedUser();
4222 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
4223 Chain.getValue(1));
4224
4225 // Extract values from a GPRPair reg and copy to the original GPR reg.
4226 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4227 RegCopy);
4228 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4229 RegCopy);
4230 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
4231 RegCopy.getValue(1));
4232 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
4233
4234 // Update the original glue user.
4235 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
4236 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00004237 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004238 }
4239 else {
4240 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
4241 // GPRPair and then pass the GPRPair to the inline asm.
4242 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
4243
4244 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
4245 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
4246 Chain.getValue(1));
4247 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
4248 T0.getValue(1));
4249 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
4250
4251 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
4252 // i32 VRs of inline asm with it.
4253 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4254 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4255 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
4256
4257 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
4258 Glue = Chain.getValue(1);
4259 }
4260
4261 Changed = true;
4262
4263 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004264 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004265 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00004266 if (IsTiedToChangedOp)
4267 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
4268 else
4269 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004270 // Replace the current flag.
4271 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00004272 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004273 // Add the new register node and skip the original two GPRs.
4274 AsmNodeOperands.push_back(PairedReg);
4275 // Skip the next two GPRs.
4276 i += 2;
4277 }
4278 }
4279
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004280 if (Glue.getNode())
4281 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004282 if (!Changed)
Justin Bogner45571362016-05-12 00:31:09 +00004283 return false;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004284
Andrew Trickef9de2a2013-05-25 02:42:55 +00004285 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00004286 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004287 New->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00004288 ReplaceNode(N, New.getNode());
4289 return true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004290}
4291
4292
Bob Wilsona2c462b2009-05-19 05:53:42 +00004293bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00004294SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00004295 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004296 switch(ConstraintID) {
4297 default:
4298 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00004299 case InlineAsm::Constraint_i:
4300 // FIXME: It seems strange that 'i' is needed here since it's supposed to
4301 // be an immediate and not a memory constraint.
Justin Bognerb03fd122016-08-17 05:10:15 +00004302 LLVM_FALLTHROUGH;
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004303 case InlineAsm::Constraint_m:
James Molloy72222f52015-10-26 10:04:52 +00004304 case InlineAsm::Constraint_o:
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004305 case InlineAsm::Constraint_Q:
4306 case InlineAsm::Constraint_Um:
4307 case InlineAsm::Constraint_Un:
4308 case InlineAsm::Constraint_Uq:
4309 case InlineAsm::Constraint_Us:
4310 case InlineAsm::Constraint_Ut:
4311 case InlineAsm::Constraint_Uv:
4312 case InlineAsm::Constraint_Uy:
4313 // Require the address to be in a register. That is safe for all ARM
4314 // variants and it is hard to do anything much smarter without knowing
4315 // how the operand is used.
4316 OutOps.push_back(Op);
4317 return false;
4318 }
4319 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00004320}
4321
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004322/// createARMISelDag - This pass converts a legalized DAG into a
4323/// ARM-specific DAG, ready for instruction scheduling.
4324///
Bob Wilson2dd957f2009-09-28 14:30:20 +00004325FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
4326 CodeGenOpt::Level OptLevel) {
4327 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004328}