blob: 8d32510e2004a2f17efbccf43033bb5fe58df7af [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
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000100 bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
101 bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);
102
Tim Northover42180442013-08-22 09:57:11 +0000103 bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) {
104 const ConstantSDNode *CN = cast<ConstantSDNode>(N);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000105 Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32);
Tim Northover42180442013-08-22 09:57:11 +0000106 Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32);
107 return true;
108 }
109
Owen Anderson2aedba62011-07-26 20:54:26 +0000110 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
111 SDValue &Offset, SDValue &Opc);
112 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000113 SDValue &Offset, SDValue &Opc);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000114 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
115 SDValue &Offset, SDValue &Opc);
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000116 bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000117 bool SelectAddrMode3(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000118 SDValue &Offset, SDValue &Opc);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000119 bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000120 SDValue &Offset, SDValue &Opc);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000121 bool SelectAddrMode5(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000122 SDValue &Offset);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000123 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
Bob Wilsone3ecd5f2011-02-25 06:42:42 +0000124 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000125
Evan Chengdfce83c2011-01-17 08:03:18 +0000126 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
Evan Cheng10043e22007-01-19 07:51:42 +0000127
Bill Wendling092a7bd2010-12-14 03:36:38 +0000128 // Thumb Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000129 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
Bill Wendling092a7bd2010-12-14 03:36:38 +0000130 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
131 SDValue &OffImm);
132 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
133 SDValue &OffImm);
134 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
135 SDValue &OffImm);
136 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
137 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000138 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +0000139
Bill Wendling092a7bd2010-12-14 03:36:38 +0000140 // Thumb 2 Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000141 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
142 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000143 SDValue &OffImm);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000144 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +0000145 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000146 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000147 SDValue &OffReg, SDValue &ShImm);
Tim Northovera7ecd242013-07-16 09:46:55 +0000148 bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Chengb23b50d2009-06-29 07:51:04 +0000149
Evan Cheng0fc80842010-11-12 22:42:47 +0000150 inline bool is_so_imm(unsigned Imm) const {
151 return ARM_AM::getSOImmVal(Imm) != -1;
152 }
153
154 inline bool is_so_imm_not(unsigned Imm) const {
155 return ARM_AM::getSOImmVal(~Imm) != -1;
156 }
157
158 inline bool is_t2_so_imm(unsigned Imm) const {
159 return ARM_AM::getT2SOImmVal(Imm) != -1;
160 }
161
162 inline bool is_t2_so_imm_not(unsigned Imm) const {
163 return ARM_AM::getT2SOImmVal(~Imm) != -1;
164 }
165
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000166 // Include the pieces autogenerated from the target description.
167#include "ARMGenDAGISel.inc"
Bob Wilsona2c462b2009-05-19 05:53:42 +0000168
169private:
Tim Northovereaee28b2016-09-19 09:11:09 +0000170 void transferMemOperands(SDNode *Src, SDNode *Dst);
171
Justin Bogner45571362016-05-12 00:31:09 +0000172 /// Indexed (pre/post inc/dec) load matching code for ARM.
173 bool tryARMIndexedLoad(SDNode *N);
James Molloyb3326df2016-07-15 08:03:56 +0000174 bool tryT1IndexedLoad(SDNode *N);
Justin Bogner45571362016-05-12 00:31:09 +0000175 bool tryT2IndexedLoad(SDNode *N);
Evan Cheng84c6cda2009-07-02 07:28:31 +0000176
Bob Wilson340861d2010-03-23 05:25:43 +0000177 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
178 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson12b47992009-10-14 17:28:52 +0000179 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson340861d2010-03-23 05:25:43 +0000180 /// For NumVecs <= 2, QOpcodes1 is not used.
Justin Bogner45571362016-05-12 00:31:09 +0000181 void SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
182 const uint16_t *DOpcodes, const uint16_t *QOpcodes0,
183 const uint16_t *QOpcodes1);
Bob Wilson12b47992009-10-14 17:28:52 +0000184
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000185 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000186 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000187 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000188 /// For NumVecs <= 2, QOpcodes1 is not used.
Justin Bogner45571362016-05-12 00:31:09 +0000189 void SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
190 const uint16_t *DOpcodes, const uint16_t *QOpcodes0,
191 const uint16_t *QOpcodes1);
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000192
Bob Wilson93117bc2009-10-14 16:46:45 +0000193 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilson4145e3a2009-10-14 16:19:03 +0000194 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsond5c57a52010-09-13 23:01:35 +0000195 /// load/store of D registers and Q registers.
Justin Bogner45571362016-05-12 00:31:09 +0000196 void SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
197 unsigned NumVecs, const uint16_t *DOpcodes,
198 const uint16_t *QOpcodes);
Bob Wilson4145e3a2009-10-14 16:19:03 +0000199
Bob Wilson2d790df2010-11-28 06:51:26 +0000200 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
Eli Friedmanf624ec22016-12-16 18:44:08 +0000201 /// should be 1, 2, 3 or 4. The opcode array specifies the instructions used
Bob Wilson2d790df2010-11-28 06:51:26 +0000202 /// for loading D registers. (Q registers are not supported.)
Justin Bogner45571362016-05-12 00:31:09 +0000203 void SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Eli Friedmanf624ec22016-12-16 18:44:08 +0000204 const uint16_t *DOpcodes,
205 const uint16_t *QOpcodes = nullptr);
Bob Wilson2d790df2010-11-28 06:51:26 +0000206
Justin Bogner45571362016-05-12 00:31:09 +0000207 /// Try to select SBFX/UBFX instructions for ARM.
208 bool tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000209
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000210 // Select special operations if node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +0000211 bool tryABSOp(SDNode *N);
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000212
Justin Bogner45571362016-05-12 00:31:09 +0000213 bool tryReadRegister(SDNode *N);
214 bool tryWriteRegister(SDNode *N);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +0000215
Justin Bogner45571362016-05-12 00:31:09 +0000216 bool tryInlineAsm(SDNode *N);
Weiming Zhaoc5987002013-02-14 18:10:21 +0000217
Sjoerd Meijer96e10b52016-12-15 09:38:59 +0000218 void SelectCMPZ(SDNode *N, bool &SwitchEQNEToPLMI);
James Molloye7d97362016-11-03 14:08:01 +0000219
Justin Bogner45571362016-05-12 00:31:09 +0000220 void SelectCMP_SWAP(SDNode *N);
Tim Northoverb629c772016-04-18 21:48:55 +0000221
Evan Chengd9c55362009-07-02 01:23:32 +0000222 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
223 /// inline asm expressions.
Daniel Sanders60f1db02015-03-13 12:45:09 +0000224 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Craig Topper6bc27bf2014-03-10 02:09:33 +0000225 std::vector<SDValue> &OutOps) override;
Bob Wilsone6b778d2009-10-06 22:01:59 +0000226
Weiming Zhao95782222012-11-17 00:23:35 +0000227 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhao8f56f882012-11-16 21:55:34 +0000228 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao95782222012-11-17 00:23:35 +0000229 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
230 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
231 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Chengc2ae5f52010-05-10 17:34:18 +0000232
Bob Wilsond8a9a042010-06-04 00:04:02 +0000233 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +0000234 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
235 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
236 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000237
238 // Get the alignment operand for a NEON VLD or VST instruction.
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000239 SDValue GetVLDSTAlign(SDValue Align, const SDLoc &dl, unsigned NumVecs,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000240 bool is64BitVector);
John Brawn056e6782015-09-14 15:19:41 +0000241
242 /// Returns the number of instructions required to materialize the given
243 /// constant in a register, or 3 if a literal pool load is needed.
244 unsigned ConstantMaterializationCost(unsigned Val) const;
245
246 /// Checks if N is a multiplication by a constant where we can extract out a
247 /// power of two from the constant so that it can be used in a shift, but only
248 /// if it simplifies the materialization of the constant. Returns true if it
249 /// is, and assigns to PowerOfTwo the power of two that should be extracted
250 /// out and to NewMulConst the new constant to be multiplied by.
251 bool canExtractShiftFromMul(const SDValue &N, unsigned MaxShift,
252 unsigned &PowerOfTwo, SDValue &NewMulConst) const;
253
254 /// Replace N with M in CurDAG, in a way that also ensures that M gets
255 /// selected when N would have been selected.
256 void replaceDAGValue(const SDValue &N, SDValue M);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000257};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000258}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000259
Sandeep Patel423e42b2009-10-13 18:59:48 +0000260/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
261/// operand. If so Imm will receive the 32-bit value.
262static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
263 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
264 Imm = cast<ConstantSDNode>(N)->getZExtValue();
265 return true;
266 }
267 return false;
268}
269
270// isInt32Immediate - This method tests to see if a constant operand.
271// If so Imm will receive the 32 bit value.
272static bool isInt32Immediate(SDValue N, unsigned &Imm) {
273 return isInt32Immediate(N.getNode(), Imm);
274}
275
276// isOpcWithIntImmediate - This method tests to see if the node is a specific
277// opcode and that it has a immediate integer right operand.
278// If so Imm will receive the 32 bit value.
279static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
280 return N->getOpcode() == Opc &&
281 isInt32Immediate(N->getOperand(1).getNode(), Imm);
282}
283
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000284/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000285/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000286///
287/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000288static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000289 int RangeMin, int RangeMax,
290 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000291 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000292
293 // Check that this is a constant.
294 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
295 if (!C)
296 return false;
297
298 ScaledConstant = (int) C->getZExtValue();
299 if ((ScaledConstant % Scale) != 0)
300 return false;
301
302 ScaledConstant /= Scale;
303 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
304}
305
Evan Chengeae6d2c2012-12-19 20:16:09 +0000306void ARMDAGToDAGISel::PreprocessISelDAG() {
307 if (!Subtarget->hasV6T2Ops())
308 return;
309
310 bool isThumb2 = Subtarget->isThumb();
311 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
312 E = CurDAG->allnodes_end(); I != E; ) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000313 SDNode *N = &*I++; // Preincrement iterator to avoid invalidation issues.
Evan Chengeae6d2c2012-12-19 20:16:09 +0000314
315 if (N->getOpcode() != ISD::ADD)
316 continue;
317
318 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
319 // leading zeros, followed by consecutive set bits, followed by 1 or 2
320 // trailing zeros, e.g. 1020.
321 // Transform the expression to
322 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
323 // of trailing zeros of c2. The left shift would be folded as an shifter
324 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
325 // node (UBFX).
326
327 SDValue N0 = N->getOperand(0);
328 SDValue N1 = N->getOperand(1);
329 unsigned And_imm = 0;
330 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
331 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
332 std::swap(N0, N1);
333 }
334 if (!And_imm)
335 continue;
336
337 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000338 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000339 if (TZ != 1 && TZ != 2)
340 // Be conservative here. Shifter operands aren't always free. e.g. On
341 // Swift, left shifter operand of 1 / 2 for free but others are not.
342 // e.g.
343 // ubfx r3, r1, #16, #8
344 // ldr.w r3, [r0, r3, lsl #2]
345 // vs.
346 // mov.w r9, #1020
347 // and.w r2, r9, r1, lsr #14
348 // ldr r2, [r0, r2]
349 continue;
350 And_imm >>= TZ;
351 if (And_imm & (And_imm + 1))
352 continue;
353
354 // Look for (and (srl X, c1), c2).
355 SDValue Srl = N1.getOperand(0);
356 unsigned Srl_imm = 0;
357 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
358 (Srl_imm <= 2))
359 continue;
360
361 // Make sure first operand is not a shifter operand which would prevent
362 // folding of the left shift.
363 SDValue CPTmp0;
364 SDValue CPTmp1;
365 SDValue CPTmp2;
366 if (isThumb2) {
John Brawnd8b405a2015-09-07 11:45:18 +0000367 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
Evan Chengeae6d2c2012-12-19 20:16:09 +0000368 continue;
369 } else {
370 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
371 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
372 continue;
373 }
374
375 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000376 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000377 Srl.getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000378 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl),
379 MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000380 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000381 Srl,
382 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000383 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000384 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32));
Evan Chengeae6d2c2012-12-19 20:16:09 +0000385 CurDAG->UpdateNodeOperands(N, N0, N1);
Jim Grosbach1a597112014-04-03 23:43:18 +0000386 }
Evan Chengeae6d2c2012-12-19 20:16:09 +0000387}
388
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000389/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
390/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
391/// least on current ARM implementations) which should be avoidded.
392bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
393 if (OptLevel == CodeGenOpt::None)
394 return true;
395
Diana Picus575f2bb2016-07-07 09:11:39 +0000396 if (!Subtarget->hasVMLxHazards())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000397 return true;
398
399 if (!N->hasOneUse())
400 return false;
401
402 SDNode *Use = *N->use_begin();
403 if (Use->getOpcode() == ISD::CopyToReg)
404 return true;
405 if (Use->isMachineOpcode()) {
Eric Christopher2f991c92014-07-03 22:24:49 +0000406 const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>(
Eric Christopherfc6de422014-08-05 02:39:49 +0000407 CurDAG->getSubtarget().getInstrInfo());
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000408
Evan Cheng6cc775f2011-06-28 19:10:37 +0000409 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
410 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000411 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000412 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000413 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
414 return true;
415 // vmlx feeding into another vmlx. We actually want to unfold
416 // the use later in the MLxExpansion pass. e.g.
417 // vmla
418 // vmla (stall 8 cycles)
419 //
420 // vmul (5 cycles)
421 // vadd (5 cycles)
422 // vmla
423 // This adds up to about 18 - 19 cycles.
424 //
425 // vmla
426 // vmul (stall 4 cycles)
427 // vadd adds up to about 14 cycles.
428 return TII->isFpMLxInstruction(Opcode);
429 }
430
431 return false;
432}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000433
Evan Cheng59bbc542010-10-27 23:41:30 +0000434bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
435 ARM_AM::ShiftOpc ShOpcVal,
436 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000437 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000438 return true;
439 if (Shift.hasOneUse())
440 return true;
441 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000442 return ShOpcVal == ARM_AM::lsl &&
443 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000444}
445
John Brawn056e6782015-09-14 15:19:41 +0000446unsigned ARMDAGToDAGISel::ConstantMaterializationCost(unsigned Val) const {
447 if (Subtarget->isThumb()) {
448 if (Val <= 255) return 1; // MOV
Weiming Zhaof68a6a72016-08-05 20:58:29 +0000449 if (Subtarget->hasV6T2Ops() &&
450 (Val <= 0xffff || ARM_AM::getT2SOImmValSplatVal(Val) != -1))
451 return 1; // MOVW
James Molloy65b6be12016-06-14 13:33:07 +0000452 if (Val <= 510) return 2; // MOV + ADDi8
John Brawn056e6782015-09-14 15:19:41 +0000453 if (~Val <= 255) return 2; // MOV + MVN
454 if (ARM_AM::isThumbImmShiftedVal(Val)) return 2; // MOV + LSL
455 } else {
456 if (ARM_AM::getSOImmVal(Val) != -1) return 1; // MOV
457 if (ARM_AM::getSOImmVal(~Val) != -1) return 1; // MVN
458 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
459 if (ARM_AM::isSOImmTwoPartVal(Val)) return 2; // two instrs
460 }
461 if (Subtarget->useMovt(*MF)) return 2; // MOVW + MOVT
462 return 3; // Literal pool load
463}
464
465bool ARMDAGToDAGISel::canExtractShiftFromMul(const SDValue &N,
466 unsigned MaxShift,
467 unsigned &PowerOfTwo,
468 SDValue &NewMulConst) const {
469 assert(N.getOpcode() == ISD::MUL);
470 assert(MaxShift > 0);
471
472 // If the multiply is used in more than one place then changing the constant
473 // will make other uses incorrect, so don't.
474 if (!N.hasOneUse()) return false;
475 // Check if the multiply is by a constant
476 ConstantSDNode *MulConst = dyn_cast<ConstantSDNode>(N.getOperand(1));
477 if (!MulConst) return false;
478 // If the constant is used in more than one place then modifying it will mean
479 // we need to materialize two constants instead of one, which is a bad idea.
480 if (!MulConst->hasOneUse()) return false;
481 unsigned MulConstVal = MulConst->getZExtValue();
482 if (MulConstVal == 0) return false;
483
484 // Find the largest power of 2 that MulConstVal is a multiple of
485 PowerOfTwo = MaxShift;
486 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
487 --PowerOfTwo;
488 if (PowerOfTwo == 0) return false;
489 }
490
491 // Only optimise if the new cost is better
492 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
493 NewMulConst = CurDAG->getConstant(NewMulConstVal, SDLoc(N), MVT::i32);
494 unsigned OldCost = ConstantMaterializationCost(MulConstVal);
495 unsigned NewCost = ConstantMaterializationCost(NewMulConstVal);
496 return NewCost < OldCost;
497}
498
499void ARMDAGToDAGISel::replaceDAGValue(const SDValue &N, SDValue M) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000500 CurDAG->RepositionNode(N.getNode()->getIterator(), M.getNode());
John Brawn056e6782015-09-14 15:19:41 +0000501 CurDAG->ReplaceAllUsesWith(N, M);
502}
503
Owen Andersonb595ed02011-07-21 18:54:16 +0000504bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000505 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000506 SDValue &Opc,
507 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000508 if (DisableShifterOp)
509 return false;
510
John Brawn056e6782015-09-14 15:19:41 +0000511 // If N is a multiply-by-constant and it's profitable to extract a shift and
512 // use it in a shifted operand do so.
513 if (N.getOpcode() == ISD::MUL) {
514 unsigned PowerOfTwo = 0;
515 SDValue NewMulConst;
516 if (canExtractShiftFromMul(N, 31, PowerOfTwo, NewMulConst)) {
Justin Bogner8752be72016-05-05 01:43:49 +0000517 HandleSDNode Handle(N);
Benjamin Kramer58dadd52017-04-20 18:29:14 +0000518 SDLoc Loc(N);
John Brawn056e6782015-09-14 15:19:41 +0000519 replaceDAGValue(N.getOperand(1), NewMulConst);
Justin Bogner8752be72016-05-05 01:43:49 +0000520 BaseReg = Handle.getValue();
Benjamin Kramer58dadd52017-04-20 18:29:14 +0000521 Opc = CurDAG->getTargetConstant(
522 ARM_AM::getSORegOpc(ARM_AM::lsl, PowerOfTwo), Loc, MVT::i32);
John Brawn056e6782015-09-14 15:19:41 +0000523 return true;
524 }
525 }
526
Evan Chenga20cde32011-07-20 23:34:39 +0000527 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000528
529 // Don't match base register only case. That is matched to a separate
530 // lower complexity pattern with explicit register operand.
531 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000532
Evan Chengb23b50d2009-06-29 07:51:04 +0000533 BaseReg = N.getOperand(0);
534 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000535 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
536 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000537 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000538 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000539 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000540 return true;
541}
542
Owen Andersonb595ed02011-07-21 18:54:16 +0000543bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
544 SDValue &BaseReg,
545 SDValue &ShReg,
546 SDValue &Opc,
547 bool CheckProfitability) {
548 if (DisableShifterOp)
549 return false;
550
551 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
552
553 // Don't match base register only case. That is matched to a separate
554 // lower complexity pattern with explicit register operand.
555 if (ShOpcVal == ARM_AM::no_shift) return false;
556
557 BaseReg = N.getOperand(0);
558 unsigned ShImmVal = 0;
559 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
560 if (RHS) return false;
561
562 ShReg = N.getOperand(1);
563 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
564 return false;
565 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000566 SDLoc(N), MVT::i32);
Owen Andersonb595ed02011-07-21 18:54:16 +0000567 return true;
568}
569
570
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000571bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
572 SDValue &Base,
573 SDValue &OffImm) {
574 // Match simple R + imm12 operands.
575
576 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000577 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
578 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000579 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000580 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000581 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000582 Base = CurDAG->getTargetFrameIndex(
583 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000584 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000585 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000586 }
Owen Anderson6d557452011-03-18 19:46:58 +0000587
Chris Lattner46c01a32011-02-13 22:25:43 +0000588 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000589 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000590 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000591 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000592 Base = N.getOperand(0);
593 } else
594 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000595 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000596 return true;
597 }
598
599 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Renato Golin63e27982014-09-09 09:57:59 +0000600 int RHSC = (int)RHS->getSExtValue();
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000601 if (N.getOpcode() == ISD::SUB)
602 RHSC = -RHSC;
603
Renato Golin63e27982014-09-09 09:57:59 +0000604 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000605 Base = N.getOperand(0);
606 if (Base.getOpcode() == ISD::FrameIndex) {
607 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000608 Base = CurDAG->getTargetFrameIndex(
609 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000610 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000611 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000612 return true;
613 }
614 }
615
616 // Base only.
617 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000618 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000619 return true;
620}
621
622
623
624bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
625 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000626 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000627 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000628 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
629 // X * [3,5,9] -> X + X * [2,4,8] etc.
630 int RHSC = (int)RHS->getZExtValue();
631 if (RHSC & 1) {
632 RHSC = RHSC & ~1;
633 ARM_AM::AddrOpc AddSub = ARM_AM::add;
634 if (RHSC < 0) {
635 AddSub = ARM_AM::sub;
636 RHSC = - RHSC;
637 }
638 if (isPowerOf2_32(RHSC)) {
639 unsigned ShAmt = Log2_32(RHSC);
640 Base = Offset = N.getOperand(0);
641 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
642 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000643 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000644 return true;
645 }
646 }
647 }
648 }
649
Chris Lattner46c01a32011-02-13 22:25:43 +0000650 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
651 // ISD::OR that is equivalent to an ISD::ADD.
652 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000653 return false;
654
655 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000656 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000657 int RHSC;
658 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
659 -0x1000+1, 0x1000, RHSC)) // 12 bits.
660 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000661 }
662
663 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000664 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000665 ARM_AM::ShiftOpc ShOpcVal =
666 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000667 unsigned ShAmt = 0;
668
669 Base = N.getOperand(0);
670 Offset = N.getOperand(1);
671
672 if (ShOpcVal != ARM_AM::no_shift) {
673 // Check to see if the RHS of the shift is a constant, if not, we can't fold
674 // it.
675 if (ConstantSDNode *Sh =
676 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
677 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000678 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
679 Offset = N.getOperand(1).getOperand(0);
680 else {
681 ShAmt = 0;
682 ShOpcVal = ARM_AM::no_shift;
683 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000684 } else {
685 ShOpcVal = ARM_AM::no_shift;
686 }
687 }
688
689 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000690 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000691 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
692 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000693 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000694 if (ShOpcVal != ARM_AM::no_shift) {
695 // Check to see if the RHS of the shift is a constant, if not, we can't
696 // fold it.
697 if (ConstantSDNode *Sh =
698 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
699 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000700 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000701 Offset = N.getOperand(0).getOperand(0);
702 Base = N.getOperand(1);
703 } else {
704 ShAmt = 0;
705 ShOpcVal = ARM_AM::no_shift;
706 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000707 } else {
708 ShOpcVal = ARM_AM::no_shift;
709 }
710 }
711 }
712
John Brawn056e6782015-09-14 15:19:41 +0000713 // If Offset is a multiply-by-constant and it's profitable to extract a shift
714 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +0000715 if (Offset.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +0000716 unsigned PowerOfTwo = 0;
717 SDValue NewMulConst;
718 if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) {
Tim Northover4a01ffb2017-05-02 22:45:19 +0000719 HandleSDNode Handle(Offset);
John Brawn056e6782015-09-14 15:19:41 +0000720 replaceDAGValue(Offset.getOperand(1), NewMulConst);
Tim Northover4a01ffb2017-05-02 22:45:19 +0000721 Offset = Handle.getValue();
John Brawn056e6782015-09-14 15:19:41 +0000722 ShAmt = PowerOfTwo;
723 ShOpcVal = ARM_AM::lsl;
724 }
725 }
726
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000727 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000728 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000729 return true;
730}
731
Owen Anderson2aedba62011-07-26 20:54:26 +0000732bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000733 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000734 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000735 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
736 ? cast<LoadSDNode>(Op)->getAddressingMode()
737 : cast<StoreSDNode>(Op)->getAddressingMode();
738 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
739 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000740 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000741 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
742 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000743
744 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000745 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000746 unsigned ShAmt = 0;
747 if (ShOpcVal != ARM_AM::no_shift) {
748 // Check to see if the RHS of the shift is a constant, if not, we can't fold
749 // it.
750 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000751 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000752 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
753 Offset = N.getOperand(0);
754 else {
755 ShAmt = 0;
756 ShOpcVal = ARM_AM::no_shift;
757 }
Evan Cheng10043e22007-01-19 07:51:42 +0000758 } else {
759 ShOpcVal = ARM_AM::no_shift;
760 }
761 }
762
763 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000764 SDLoc(N), MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000765 return true;
766}
767
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000768bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
769 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000770 unsigned Opcode = Op->getOpcode();
771 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
772 ? cast<LoadSDNode>(Op)->getAddressingMode()
773 : cast<StoreSDNode>(Op)->getAddressingMode();
774 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
775 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000776 int Val;
777 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000778 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000779 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000780 Opc = CurDAG->getTargetConstant(Val, SDLoc(Op), MVT::i32);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000781 return true;
782 }
783
784 return false;
785}
786
787
Owen Anderson2aedba62011-07-26 20:54:26 +0000788bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
789 SDValue &Offset, SDValue &Opc) {
790 unsigned Opcode = Op->getOpcode();
791 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
792 ? cast<LoadSDNode>(Op)->getAddressingMode()
793 : cast<StoreSDNode>(Op)->getAddressingMode();
794 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
795 ? ARM_AM::add : ARM_AM::sub;
796 int Val;
797 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
798 Offset = CurDAG->getRegister(0, MVT::i32);
799 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
800 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000801 SDLoc(Op), MVT::i32);
Owen Anderson2aedba62011-07-26 20:54:26 +0000802 return true;
803 }
804
805 return false;
806}
807
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000808bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
809 Base = N;
810 return true;
811}
Evan Cheng10043e22007-01-19 07:51:42 +0000812
Chris Lattner0e023ea2010-09-21 20:31:19 +0000813bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000814 SDValue &Base, SDValue &Offset,
815 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000816 if (N.getOpcode() == ISD::SUB) {
817 // X - C is canonicalize to X + -C, no need to handle it here.
818 Base = N.getOperand(0);
819 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000820 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0), SDLoc(N),
821 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000822 return true;
823 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000824
Chris Lattner46c01a32011-02-13 22:25:43 +0000825 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000826 Base = N;
827 if (N.getOpcode() == ISD::FrameIndex) {
828 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000829 Base = CurDAG->getTargetFrameIndex(
830 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +0000831 }
Owen Anderson9f944592009-08-11 20:47:22 +0000832 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000833 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 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
Evan Cheng10043e22007-01-19 07:51:42 +0000838 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000839 int RHSC;
840 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
841 -256 + 1, 256, RHSC)) { // 8 bits.
842 Base = N.getOperand(0);
843 if (Base.getOpcode() == ISD::FrameIndex) {
844 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000845 Base = CurDAG->getTargetFrameIndex(
846 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +0000847 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000848 Offset = CurDAG->getRegister(0, MVT::i32);
849
850 ARM_AM::AddrOpc AddSub = ARM_AM::add;
851 if (RHSC < 0) {
852 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000853 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000854 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000855 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC), SDLoc(N),
856 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000857 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000858 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000859
Evan Cheng10043e22007-01-19 07:51:42 +0000860 Base = N.getOperand(0);
861 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000862 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
863 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000864 return true;
865}
866
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000867bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000868 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000869 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000870 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
871 ? cast<LoadSDNode>(Op)->getAddressingMode()
872 : cast<StoreSDNode>(Op)->getAddressingMode();
873 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
874 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000875 int Val;
876 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
877 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000878 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), SDLoc(Op),
879 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000880 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000881 }
882
883 Offset = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000884 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), SDLoc(Op),
885 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000886 return true;
887}
888
Jim Grosbachd37f0712010-10-21 19:38:40 +0000889bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000890 SDValue &Base, SDValue &Offset) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000891 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000892 Base = N;
893 if (N.getOpcode() == ISD::FrameIndex) {
894 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000895 Base = CurDAG->getTargetFrameIndex(
896 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +0000897 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000898 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +0000899 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000900 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000901 Base = N.getOperand(0);
902 }
903 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000904 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000905 return true;
906 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000907
Evan Cheng10043e22007-01-19 07:51:42 +0000908 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000909 int RHSC;
910 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
911 -256 + 1, 256, RHSC)) {
912 Base = N.getOperand(0);
913 if (Base.getOpcode() == ISD::FrameIndex) {
914 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000915 Base = CurDAG->getTargetFrameIndex(
916 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +0000917 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000918
919 ARM_AM::AddrOpc AddSub = ARM_AM::add;
920 if (RHSC < 0) {
921 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000922 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000923 }
924 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000925 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000926 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000927 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000928
Evan Cheng10043e22007-01-19 07:51:42 +0000929 Base = N;
930 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000931 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000932 return true;
933}
934
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000935bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
936 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +0000937 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000938
939 unsigned Alignment = 0;
Ahmed Bougachadb141ac2015-02-19 23:52:41 +0000940
941 MemSDNode *MemN = cast<MemSDNode>(Parent);
942
943 if (isa<LSBaseSDNode>(MemN) ||
944 ((MemN->getOpcode() == ARMISD::VST1_UPD ||
945 MemN->getOpcode() == ARMISD::VLD1_UPD) &&
946 MemN->getConstantOperandVal(MemN->getNumOperands() - 1) == 1)) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000947 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
948 // The maximum alignment is equal to the memory size being referenced.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +0000949 unsigned MMOAlign = MemN->getAlignment();
950 unsigned MemSize = MemN->getMemoryVT().getSizeInBits() / 8;
951 if (MMOAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000952 Alignment = MemSize;
953 } else {
954 // All other uses of addrmode6 are for intrinsics. For now just record
955 // the raw alignment value; it will be refined later based on the legal
956 // alignment operands for the intrinsic.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +0000957 Alignment = MemN->getAlignment();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000958 }
959
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000960 Align = CurDAG->getTargetConstant(Alignment, SDLoc(N), MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +0000961 return true;
962}
963
Bob Wilsone3ecd5f2011-02-25 06:42:42 +0000964bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
965 SDValue &Offset) {
966 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
967 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
968 if (AM != ISD::POST_INC)
969 return false;
970 Offset = N;
971 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
972 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
973 Offset = CurDAG->getRegister(0, MVT::i32);
974 }
975 return true;
976}
977
Chris Lattner0e023ea2010-09-21 20:31:19 +0000978bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +0000979 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +0000980 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
981 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000982 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +0000983 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000984 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000985 return true;
986 }
Bill Wendling092a7bd2010-12-14 03:36:38 +0000987
Evan Cheng10043e22007-01-19 07:51:42 +0000988 return false;
989}
990
Bill Wendling092a7bd2010-12-14 03:36:38 +0000991
992//===----------------------------------------------------------------------===//
993// Thumb Addressing Modes
994//===----------------------------------------------------------------------===//
995
Chris Lattner0e023ea2010-09-21 20:31:19 +0000996bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000997 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +0000998 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +0000999 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001000 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001001 return false;
1002
1003 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001004 return true;
1005 }
1006
Evan Cheng10043e22007-01-19 07:51:42 +00001007 Base = N.getOperand(0);
1008 Offset = N.getOperand(1);
1009 return true;
1010}
1011
Evan Cheng139edae2007-01-24 02:21:22 +00001012bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001013ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1014 SDValue &Base, SDValue &OffImm) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001015 if (!CurDAG->isBaseWithConstantOffset(N)) {
John Brawn68acdcb2015-08-13 10:48:22 +00001016 if (N.getOpcode() == ISD::ADD) {
1017 return false; // We want to select register offset instead
1018 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001019 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001020 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
James Molloyb7de4972016-10-05 14:52:13 +00001021 N.getOperand(0).getOpcode() != ISD::TargetConstantPool &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001022 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001023 Base = N.getOperand(0);
1024 } else {
1025 Base = N;
1026 }
1027
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001028 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001029 return true;
1030 }
1031
Evan Cheng10043e22007-01-19 07:51:42 +00001032 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001033 int RHSC;
1034 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1035 Base = N.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001036 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001037 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001038 }
1039
John Brawn68acdcb2015-08-13 10:48:22 +00001040 // Offset is too large, so use register offset instead.
1041 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001042}
1043
Bill Wendling092a7bd2010-12-14 03:36:38 +00001044bool
1045ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1046 SDValue &OffImm) {
1047 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001048}
1049
Bill Wendling092a7bd2010-12-14 03:36:38 +00001050bool
1051ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1052 SDValue &OffImm) {
1053 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001054}
1055
Bill Wendling092a7bd2010-12-14 03:36:38 +00001056bool
1057ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1058 SDValue &OffImm) {
1059 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001060}
1061
Chris Lattner0e023ea2010-09-21 20:31:19 +00001062bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1063 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001064 if (N.getOpcode() == ISD::FrameIndex) {
1065 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001066 // Only multiples of 4 are allowed for the offset, so the frame object
1067 // alignment must be at least 4.
Matthias Braun941a7052016-07-28 18:40:00 +00001068 MachineFrameInfo &MFI = MF->getFrameInfo();
1069 if (MFI.getObjectAlignment(FI) < 4)
1070 MFI.setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001071 Base = CurDAG->getTargetFrameIndex(
1072 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001073 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001074 return true;
1075 }
Evan Cheng139edae2007-01-24 02:21:22 +00001076
Chris Lattner46c01a32011-02-13 22:25:43 +00001077 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001078 return false;
1079
1080 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001081 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1082 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001083 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001084 int RHSC;
1085 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1086 Base = N.getOperand(0);
1087 if (Base.getOpcode() == ISD::FrameIndex) {
1088 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001089 // For LHS+RHS to result in an offset that's a multiple of 4 the object
1090 // indexed by the LHS must be 4-byte aligned.
Matthias Braun941a7052016-07-28 18:40:00 +00001091 MachineFrameInfo &MFI = MF->getFrameInfo();
1092 if (MFI.getObjectAlignment(FI) < 4)
1093 MFI.setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001094 Base = CurDAG->getTargetFrameIndex(
1095 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng139edae2007-01-24 02:21:22 +00001096 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001097 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001098 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001099 }
1100 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001101
Evan Cheng10043e22007-01-19 07:51:42 +00001102 return false;
1103}
1104
Bill Wendling092a7bd2010-12-14 03:36:38 +00001105
1106//===----------------------------------------------------------------------===//
1107// Thumb 2 Addressing Modes
1108//===----------------------------------------------------------------------===//
1109
1110
Chris Lattner0e023ea2010-09-21 20:31:19 +00001111bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001112 SDValue &Base, SDValue &OffImm) {
1113 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001114
Evan Cheng36064672009-08-11 08:52:18 +00001115 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001116 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1117 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001118 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001119 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001120 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001121 Base = CurDAG->getTargetFrameIndex(
1122 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001123 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001124 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001125 }
Owen Anderson6d557452011-03-18 19:46:58 +00001126
Chris Lattner46c01a32011-02-13 22:25:43 +00001127 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001128 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
Saleem Abdulrasoolf36005a2016-02-03 18:21:59 +00001129 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001130 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng36064672009-08-11 08:52:18 +00001131 Base = N.getOperand(0);
1132 if (Base.getOpcode() == ISD::TargetConstantPool)
1133 return false; // We want to select t2LDRpci instead.
1134 } else
1135 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001136 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001137 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001138 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001139
1140 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001141 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001142 // Let t2LDRi8 handle (R - imm8).
1143 return false;
1144
Evan Chengb23b50d2009-06-29 07:51:04 +00001145 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001146 if (N.getOpcode() == ISD::SUB)
1147 RHSC = -RHSC;
1148
1149 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001150 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001151 if (Base.getOpcode() == ISD::FrameIndex) {
1152 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001153 Base = CurDAG->getTargetFrameIndex(
1154 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin79c079b2009-07-30 18:56:48 +00001155 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001156 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001157 return true;
1158 }
1159 }
1160
Evan Cheng36064672009-08-11 08:52:18 +00001161 // Base only.
1162 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001163 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001164 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001165}
1166
Chris Lattner0e023ea2010-09-21 20:31:19 +00001167bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001168 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001169 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001170 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1171 !CurDAG->isBaseWithConstantOffset(N))
1172 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001173
Chris Lattner46c01a32011-02-13 22:25:43 +00001174 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1175 int RHSC = (int)RHS->getSExtValue();
1176 if (N.getOpcode() == ISD::SUB)
1177 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001178
Chris Lattner46c01a32011-02-13 22:25:43 +00001179 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1180 Base = N.getOperand(0);
1181 if (Base.getOpcode() == ISD::FrameIndex) {
1182 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001183 Base = CurDAG->getTargetFrameIndex(
1184 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Chengb23b50d2009-06-29 07:51:04 +00001185 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001186 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Chris Lattner46c01a32011-02-13 22:25:43 +00001187 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001188 }
1189 }
1190
1191 return false;
1192}
1193
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001194bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001195 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001196 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001197 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1198 ? cast<LoadSDNode>(Op)->getAddressingMode()
1199 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001200 int RHSC;
1201 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1202 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001203 ? CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32)
1204 : CurDAG->getTargetConstant(-RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001205 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001206 }
1207
1208 return false;
1209}
1210
Chris Lattner0e023ea2010-09-21 20:31:19 +00001211bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001212 SDValue &Base,
1213 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001214 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001215 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001216 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001217
Evan Cheng36064672009-08-11 08:52:18 +00001218 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1219 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1220 int RHSC = (int)RHS->getZExtValue();
1221 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1222 return false;
1223 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001224 return false;
1225 }
1226
Evan Chengb23b50d2009-06-29 07:51:04 +00001227 // Look for (R + R) or (R + (R << [1,2,3])).
1228 unsigned ShAmt = 0;
1229 Base = N.getOperand(0);
1230 OffReg = N.getOperand(1);
1231
1232 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001233 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001234 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001235 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001236 if (ShOpcVal == ARM_AM::lsl)
1237 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001238 }
1239
Evan Chengb23b50d2009-06-29 07:51:04 +00001240 if (ShOpcVal == ARM_AM::lsl) {
1241 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1242 // it.
1243 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1244 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001245 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1246 OffReg = OffReg.getOperand(0);
1247 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001248 ShAmt = 0;
Evan Cheng59bbc542010-10-27 23:41:30 +00001249 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001250 }
David Goodwinf3912052009-07-15 15:50:19 +00001251 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001252
John Brawn056e6782015-09-14 15:19:41 +00001253 // If OffReg is a multiply-by-constant and it's profitable to extract a shift
1254 // and use it in a shifted operand do so.
Tim Northoverc4093c32016-01-29 19:18:46 +00001255 if (OffReg.getOpcode() == ISD::MUL && N.hasOneUse()) {
John Brawn056e6782015-09-14 15:19:41 +00001256 unsigned PowerOfTwo = 0;
1257 SDValue NewMulConst;
1258 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
Tim Northover4a01ffb2017-05-02 22:45:19 +00001259 HandleSDNode Handle(OffReg);
John Brawn056e6782015-09-14 15:19:41 +00001260 replaceDAGValue(OffReg.getOperand(1), NewMulConst);
Tim Northover4a01ffb2017-05-02 22:45:19 +00001261 OffReg = Handle.getValue();
John Brawn056e6782015-09-14 15:19:41 +00001262 ShAmt = PowerOfTwo;
1263 }
1264 }
1265
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001266 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001267
1268 return true;
1269}
1270
Tim Northovera7ecd242013-07-16 09:46:55 +00001271bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1272 SDValue &OffImm) {
Alp Tokercb402912014-01-24 17:20:08 +00001273 // This *must* succeed since it's used for the irreplaceable ldrex and strex
Tim Northovera7ecd242013-07-16 09:46:55 +00001274 // instructions.
1275 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001276 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001277
1278 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1279 return true;
1280
1281 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1282 if (!RHS)
1283 return true;
1284
1285 uint32_t RHSC = (int)RHS->getZExtValue();
1286 if (RHSC > 1020 || RHSC % 4 != 0)
1287 return true;
1288
1289 Base = N.getOperand(0);
1290 if (Base.getOpcode() == ISD::FrameIndex) {
1291 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001292 Base = CurDAG->getTargetFrameIndex(
1293 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Tim Northovera7ecd242013-07-16 09:46:55 +00001294 }
1295
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001296 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001297 return true;
1298}
1299
Evan Chengb23b50d2009-06-29 07:51:04 +00001300//===--------------------------------------------------------------------===//
1301
Evan Cheng7e90b112007-07-05 07:15:27 +00001302/// getAL - Returns a ARMCC::AL immediate node.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001303static inline SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001304 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001305}
1306
Tim Northovereaee28b2016-09-19 09:11:09 +00001307void ARMDAGToDAGISel::transferMemOperands(SDNode *N, SDNode *Result) {
1308 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1309 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
1310 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
1311}
1312
Justin Bogner45571362016-05-12 00:31:09 +00001313bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001314 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001315 ISD::MemIndexedMode AM = LD->getAddressingMode();
1316 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001317 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001318
Owen Anderson53aa7a92009-08-10 22:56:29 +00001319 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001320 SDValue Offset, AMOpc;
1321 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1322 unsigned Opcode = 0;
1323 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001324 if (LoadedVT == MVT::i32 && isPre &&
1325 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1326 Opcode = ARM::LDR_PRE_IMM;
1327 Match = true;
1328 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001329 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001330 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001331 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001332 } else if (LoadedVT == MVT::i32 &&
1333 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001334 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001335 Match = true;
1336
Owen Anderson9f944592009-08-11 20:47:22 +00001337 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001338 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001339 Match = true;
1340 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1341 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1342 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001343 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001344 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001345 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001346 Match = true;
1347 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1348 }
1349 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001350 if (isPre &&
1351 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001352 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001353 Opcode = ARM::LDRB_PRE_IMM;
1354 } else if (!isPre &&
1355 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1356 Match = true;
1357 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001358 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1359 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001360 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001361 }
1362 }
1363 }
1364
1365 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001366 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1367 SDValue Chain = LD->getChain();
1368 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001369 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001370 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001371 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1372 MVT::Other, Ops);
1373 transferMemOperands(N, New);
1374 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001375 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001376 } else {
1377 SDValue Chain = LD->getChain();
1378 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001379 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001380 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001381 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1382 MVT::Other, Ops);
1383 transferMemOperands(N, New);
1384 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001385 return true;
Owen Andersonfd60f602011-08-26 21:12:37 +00001386 }
Evan Chengd9c55362009-07-02 01:23:32 +00001387 }
1388
Justin Bogner45571362016-05-12 00:31:09 +00001389 return false;
Evan Chengd9c55362009-07-02 01:23:32 +00001390}
1391
James Molloyb3326df2016-07-15 08:03:56 +00001392bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *N) {
1393 LoadSDNode *LD = cast<LoadSDNode>(N);
1394 EVT LoadedVT = LD->getMemoryVT();
1395 ISD::MemIndexedMode AM = LD->getAddressingMode();
Chandler Carruth5589aa62016-11-03 17:42:02 +00001396 if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD ||
1397 LoadedVT.getSimpleVT().SimpleTy != MVT::i32)
James Molloyb3326df2016-07-15 08:03:56 +00001398 return false;
1399
1400 auto *COffs = dyn_cast<ConstantSDNode>(LD->getOffset());
1401 if (!COffs || COffs->getZExtValue() != 4)
1402 return false;
1403
1404 // A T1 post-indexed load is just a single register LDM: LDM r0!, {r1}.
1405 // The encoding of LDM is not how the rest of ISel expects a post-inc load to
1406 // look however, so we use a pseudo here and switch it for a tLDMIA_UPD after
1407 // ISel.
1408 SDValue Chain = LD->getChain();
1409 SDValue Base = LD->getBasePtr();
1410 SDValue Ops[]= { Base, getAL(CurDAG, SDLoc(N)),
1411 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001412 SDNode *New = CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(N), MVT::i32,
1413 MVT::i32, MVT::Other, Ops);
1414 transferMemOperands(N, New);
1415 ReplaceNode(N, New);
James Molloyb3326df2016-07-15 08:03:56 +00001416 return true;
1417}
1418
Justin Bogner45571362016-05-12 00:31:09 +00001419bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *N) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001420 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001421 ISD::MemIndexedMode AM = LD->getAddressingMode();
1422 if (AM == ISD::UNINDEXED)
Justin Bogner45571362016-05-12 00:31:09 +00001423 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001424
Owen Anderson53aa7a92009-08-10 22:56:29 +00001425 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001426 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001427 SDValue Offset;
1428 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1429 unsigned Opcode = 0;
1430 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001431 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001432 switch (LoadedVT.getSimpleVT().SimpleTy) {
1433 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001434 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1435 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001436 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001437 if (isSExtLd)
1438 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1439 else
1440 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001441 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001442 case MVT::i8:
1443 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001444 if (isSExtLd)
1445 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1446 else
1447 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001448 break;
1449 default:
Justin Bogner45571362016-05-12 00:31:09 +00001450 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001451 }
1452 Match = true;
1453 }
1454
1455 if (Match) {
1456 SDValue Chain = LD->getChain();
1457 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001458 SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)),
Owen Anderson9f944592009-08-11 20:47:22 +00001459 CurDAG->getRegister(0, MVT::i32), Chain };
Tim Northovereaee28b2016-09-19 09:11:09 +00001460 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
1461 MVT::Other, Ops);
1462 transferMemOperands(N, New);
1463 ReplaceNode(N, New);
Justin Bogner45571362016-05-12 00:31:09 +00001464 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001465 }
1466
Justin Bogner45571362016-05-12 00:31:09 +00001467 return false;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001468}
1469
Weiming Zhao8f56f882012-11-16 21:55:34 +00001470/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1471SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001472 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001473 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001474 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1475 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1476 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001477 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001478 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001479}
1480
Weiming Zhao95782222012-11-17 00:23:35 +00001481/// \brief Form a D register from a pair of S registers.
1482SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001483 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001484 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001485 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1486 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1487 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001488 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001489 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001490}
1491
Weiming Zhao95782222012-11-17 00:23:35 +00001492/// \brief Form a quad register from a pair of D registers.
1493SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001494 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001495 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1496 MVT::i32);
1497 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1498 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001499 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001500 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001501}
1502
Weiming Zhao95782222012-11-17 00:23:35 +00001503/// \brief Form 4 consecutive D registers from a pair of Q registers.
1504SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001505 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001506 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1507 MVT::i32);
1508 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1509 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001510 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001511 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001512}
1513
Weiming Zhao95782222012-11-17 00:23:35 +00001514/// \brief Form 4 consecutive S registers.
1515SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001516 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001517 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001518 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001519 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1520 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1521 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1522 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1523 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001524 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1525 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001526 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001527}
1528
Weiming Zhao95782222012-11-17 00:23:35 +00001529/// \brief Form 4 consecutive D registers.
1530SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001531 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001532 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001533 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1534 MVT::i32);
1535 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1536 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1537 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1538 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001539 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1540 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001541 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001542}
1543
Weiming Zhao95782222012-11-17 00:23:35 +00001544/// \brief Form 4 consecutive Q registers.
1545SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001546 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001547 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001548 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1549 MVT::i32);
1550 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1551 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1552 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1553 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001554 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1555 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001556 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001557}
1558
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001559/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1560/// of a NEON VLD or VST instruction. The supported values depend on the
1561/// number of registers being loaded.
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001562SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, const SDLoc &dl,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001563 unsigned NumVecs, bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001564 unsigned NumRegs = NumVecs;
1565 if (!is64BitVector && NumVecs < 3)
1566 NumRegs *= 2;
1567
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001568 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001569 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001570 Alignment = 32;
1571 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1572 Alignment = 16;
1573 else if (Alignment >= 8)
1574 Alignment = 8;
1575 else
1576 Alignment = 0;
1577
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001578 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001579}
1580
Jiangning Liu4df23632014-01-16 09:16:13 +00001581static bool isVLDfixed(unsigned Opc)
1582{
1583 switch (Opc) {
1584 default: return false;
1585 case ARM::VLD1d8wb_fixed : return true;
1586 case ARM::VLD1d16wb_fixed : return true;
1587 case ARM::VLD1d64Qwb_fixed : return true;
1588 case ARM::VLD1d32wb_fixed : return true;
1589 case ARM::VLD1d64wb_fixed : return true;
1590 case ARM::VLD1d64TPseudoWB_fixed : return true;
1591 case ARM::VLD1d64QPseudoWB_fixed : return true;
1592 case ARM::VLD1q8wb_fixed : return true;
1593 case ARM::VLD1q16wb_fixed : return true;
1594 case ARM::VLD1q32wb_fixed : return true;
1595 case ARM::VLD1q64wb_fixed : return true;
Eli Friedmanf624ec22016-12-16 18:44:08 +00001596 case ARM::VLD1DUPd8wb_fixed : return true;
1597 case ARM::VLD1DUPd16wb_fixed : return true;
1598 case ARM::VLD1DUPd32wb_fixed : return true;
1599 case ARM::VLD1DUPq8wb_fixed : return true;
1600 case ARM::VLD1DUPq16wb_fixed : return true;
1601 case ARM::VLD1DUPq32wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001602 case ARM::VLD2d8wb_fixed : return true;
1603 case ARM::VLD2d16wb_fixed : return true;
1604 case ARM::VLD2d32wb_fixed : return true;
1605 case ARM::VLD2q8PseudoWB_fixed : return true;
1606 case ARM::VLD2q16PseudoWB_fixed : return true;
1607 case ARM::VLD2q32PseudoWB_fixed : return true;
1608 case ARM::VLD2DUPd8wb_fixed : return true;
1609 case ARM::VLD2DUPd16wb_fixed : return true;
1610 case ARM::VLD2DUPd32wb_fixed : return true;
1611 }
1612}
1613
1614static bool isVSTfixed(unsigned Opc)
1615{
1616 switch (Opc) {
1617 default: return false;
1618 case ARM::VST1d8wb_fixed : return true;
1619 case ARM::VST1d16wb_fixed : return true;
1620 case ARM::VST1d32wb_fixed : return true;
1621 case ARM::VST1d64wb_fixed : return true;
Jim Grosbach1a597112014-04-03 23:43:18 +00001622 case ARM::VST1q8wb_fixed : return true;
1623 case ARM::VST1q16wb_fixed : return true;
1624 case ARM::VST1q32wb_fixed : return true;
1625 case ARM::VST1q64wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001626 case ARM::VST1d64TPseudoWB_fixed : return true;
1627 case ARM::VST1d64QPseudoWB_fixed : return true;
1628 case ARM::VST2d8wb_fixed : return true;
1629 case ARM::VST2d16wb_fixed : return true;
1630 case ARM::VST2d32wb_fixed : return true;
1631 case ARM::VST2q8PseudoWB_fixed : return true;
1632 case ARM::VST2q16PseudoWB_fixed : return true;
1633 case ARM::VST2q32PseudoWB_fixed : return true;
1634 }
1635}
1636
Jim Grosbach2098cb12011-10-24 21:45:13 +00001637// Get the register stride update opcode of a VLD/VST instruction that
1638// is otherwise equivalent to the given fixed stride updating instruction.
1639static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
Jiangning Liu4df23632014-01-16 09:16:13 +00001640 assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1641 && "Incorrect fixed stride updating instruction.");
Jim Grosbach2098cb12011-10-24 21:45:13 +00001642 switch (Opc) {
1643 default: break;
1644 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1645 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1646 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1647 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1648 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1649 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1650 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1651 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jiangning Liu4df23632014-01-16 09:16:13 +00001652 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1653 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1654 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1655 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
Eli Friedmanf624ec22016-12-16 18:44:08 +00001656 case ARM::VLD1DUPd8wb_fixed : return ARM::VLD1DUPd8wb_register;
1657 case ARM::VLD1DUPd16wb_fixed : return ARM::VLD1DUPd16wb_register;
1658 case ARM::VLD1DUPd32wb_fixed : return ARM::VLD1DUPd32wb_register;
1659 case ARM::VLD1DUPq8wb_fixed : return ARM::VLD1DUPq8wb_register;
1660 case ARM::VLD1DUPq16wb_fixed : return ARM::VLD1DUPq16wb_register;
1661 case ARM::VLD1DUPq32wb_fixed : return ARM::VLD1DUPq32wb_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001662
1663 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1664 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1665 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1666 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1667 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1668 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1669 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1670 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001671 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001672 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001673
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001674 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1675 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1676 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001677 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1678 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1679 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1680
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001681 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1682 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1683 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001684 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1685 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1686 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001687
Jim Grosbach13a292c2012-03-06 22:01:44 +00001688 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1689 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1690 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001691 }
1692 return Opc; // If not one we handle, return it unchanged.
1693}
1694
Tim Northover8b1240b2017-04-20 19:54:02 +00001695/// Returns true if the given increment is a Constant known to be equal to the
1696/// access size performed by a NEON load/store. This means the "[rN]!" form can
1697/// be used.
1698static bool isPerfectIncrement(SDValue Inc, EVT VecTy, unsigned NumVecs) {
1699 auto C = dyn_cast<ConstantSDNode>(Inc);
1700 return C && C->getZExtValue() == VecTy.getSizeInBits() / 8 * NumVecs;
1701}
1702
Justin Bogner45571362016-05-12 00:31:09 +00001703void ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
1704 const uint16_t *DOpcodes,
1705 const uint16_t *QOpcodes0,
1706 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001707 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001708 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001709
Bob Wilsonae08a732010-03-20 22:13:40 +00001710 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001711 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1712 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001713 return;
Bob Wilson12b47992009-10-14 17:28:52 +00001714
1715 SDValue Chain = N->getOperand(0);
1716 EVT VT = N->getValueType(0);
1717 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001718 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001719
Bob Wilson12b47992009-10-14 17:28:52 +00001720 unsigned OpcodeIndex;
1721 switch (VT.getSimpleVT().SimpleTy) {
1722 default: llvm_unreachable("unhandled vld type");
1723 // Double-register operations:
1724 case MVT::v8i8: OpcodeIndex = 0; break;
1725 case MVT::v4i16: OpcodeIndex = 1; break;
1726 case MVT::v2f32:
1727 case MVT::v2i32: OpcodeIndex = 2; break;
1728 case MVT::v1i64: OpcodeIndex = 3; break;
1729 // Quad-register operations:
1730 case MVT::v16i8: OpcodeIndex = 0; break;
1731 case MVT::v8i16: OpcodeIndex = 1; break;
1732 case MVT::v4f32:
1733 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001734 case MVT::v2f64:
Bob Wilson340861d2010-03-23 05:25:43 +00001735 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001736 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson340861d2010-03-23 05:25:43 +00001737 break;
Bob Wilson12b47992009-10-14 17:28:52 +00001738 }
1739
Bob Wilson35fafca2010-09-03 18:16:02 +00001740 EVT ResTy;
1741 if (NumVecs == 1)
1742 ResTy = VT;
1743 else {
1744 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1745 if (!is64BitVector)
1746 ResTyElts *= 2;
1747 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1748 }
Bob Wilson06fce872011-02-07 17:43:21 +00001749 std::vector<EVT> ResTys;
1750 ResTys.push_back(ResTy);
1751 if (isUpdating)
1752 ResTys.push_back(MVT::i32);
1753 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001754
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001755 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001756 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001757 SDNode *VLd;
1758 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001759
Bob Wilson06fce872011-02-07 17:43:21 +00001760 // Double registers and VLD1/VLD2 quad registers are directly supported.
1761 if (is64BitVector || NumVecs <= 2) {
1762 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1763 QOpcodes0[OpcodeIndex]);
1764 Ops.push_back(MemAddr);
1765 Ops.push_back(Align);
1766 if (isUpdating) {
1767 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachd146a022011-12-09 21:28:25 +00001768 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach2098cb12011-10-24 21:45:13 +00001769 // case entirely when the rest are updated to that form, too.
Tim Northover8b1240b2017-04-20 19:54:02 +00001770 bool IsImmUpdate = isPerfectIncrement(Inc, VT, NumVecs);
1771 if ((NumVecs <= 2) && !IsImmUpdate)
Jim Grosbach2098cb12011-10-24 21:45:13 +00001772 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001773 // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001774 // check for that explicitly too. Horribly hacky, but temporary.
Tim Northover8b1240b2017-04-20 19:54:02 +00001775 if ((NumVecs > 2 && !isVLDfixed(Opc)) || !IsImmUpdate)
1776 Ops.push_back(IsImmUpdate ? Reg0 : Inc);
Evan Cheng630063a2010-05-10 21:26:24 +00001777 }
Bob Wilson06fce872011-02-07 17:43:21 +00001778 Ops.push_back(Pred);
1779 Ops.push_back(Reg0);
1780 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001781 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001782
Bob Wilson12b47992009-10-14 17:28:52 +00001783 } else {
1784 // Otherwise, quad registers are loaded with two separate instructions,
1785 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001786 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001787
Bob Wilson06fce872011-02-07 17:43:21 +00001788 // Load the even subregs. This is always an updating load, so that it
1789 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001790 SDValue ImplDef =
1791 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1792 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001793 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001794 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001795 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001796
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001797 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001798 Ops.push_back(SDValue(VLdA, 1));
1799 Ops.push_back(Align);
1800 if (isUpdating) {
1801 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1802 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1803 "only constant post-increment update allowed for VLD3/4");
1804 (void)Inc;
1805 Ops.push_back(Reg0);
1806 }
1807 Ops.push_back(SDValue(VLdA, 0));
1808 Ops.push_back(Pred);
1809 Ops.push_back(Reg0);
1810 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001811 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001812 }
Bob Wilson12b47992009-10-14 17:28:52 +00001813
Evan Cheng40791332011-04-19 00:04:03 +00001814 // Transfer memoperands.
1815 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1816 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1817 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1818
Justin Bogner45571362016-05-12 00:31:09 +00001819 if (NumVecs == 1) {
1820 ReplaceNode(N, VLd);
1821 return;
1822 }
Bob Wilson06fce872011-02-07 17:43:21 +00001823
1824 // Extract out the subregisters.
1825 SDValue SuperReg = SDValue(VLd, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00001826 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
1827 ARM::qsub_3 == ARM::qsub_0 + 3,
1828 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00001829 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1830 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1831 ReplaceUses(SDValue(N, Vec),
1832 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1833 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1834 if (isUpdating)
1835 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00001836 CurDAG->RemoveDeadNode(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001837}
1838
Justin Bogner45571362016-05-12 00:31:09 +00001839void ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
1840 const uint16_t *DOpcodes,
1841 const uint16_t *QOpcodes0,
1842 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001843 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001844 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001845
Bob Wilsonae08a732010-03-20 22:13:40 +00001846 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001847 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1848 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1849 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001850 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001851
Evan Cheng40791332011-04-19 00:04:03 +00001852 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1853 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1854
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001855 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00001856 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001857 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001858 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001859
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001860 unsigned OpcodeIndex;
1861 switch (VT.getSimpleVT().SimpleTy) {
1862 default: llvm_unreachable("unhandled vst type");
1863 // Double-register operations:
1864 case MVT::v8i8: OpcodeIndex = 0; break;
1865 case MVT::v4i16: OpcodeIndex = 1; break;
1866 case MVT::v2f32:
1867 case MVT::v2i32: OpcodeIndex = 2; break;
1868 case MVT::v1i64: OpcodeIndex = 3; break;
1869 // Quad-register operations:
1870 case MVT::v16i8: OpcodeIndex = 0; break;
1871 case MVT::v8i16: OpcodeIndex = 1; break;
1872 case MVT::v4f32:
1873 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001874 case MVT::v2f64:
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001875 case MVT::v2i64: OpcodeIndex = 3;
1876 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
1877 break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001878 }
1879
Bob Wilson06fce872011-02-07 17:43:21 +00001880 std::vector<EVT> ResTys;
1881 if (isUpdating)
1882 ResTys.push_back(MVT::i32);
1883 ResTys.push_back(MVT::Other);
1884
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001885 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001886 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001887 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00001888
Bob Wilson06fce872011-02-07 17:43:21 +00001889 // Double registers and VST1/VST2 quad registers are directly supported.
1890 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00001891 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00001892 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00001893 SrcReg = N->getOperand(Vec0Idx);
1894 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00001895 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00001896 SDValue V0 = N->getOperand(Vec0Idx + 0);
1897 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00001898 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00001899 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001900 else {
Bob Wilson06fce872011-02-07 17:43:21 +00001901 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00001902 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00001903 // an undef.
1904 SDValue V3 = (NumVecs == 3)
1905 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00001906 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00001907 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001908 }
Bob Wilson950882b2010-08-28 05:12:57 +00001909 } else {
1910 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00001911 SDValue Q0 = N->getOperand(Vec0Idx);
1912 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00001913 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001914 }
Bob Wilson06fce872011-02-07 17:43:21 +00001915
1916 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1917 QOpcodes0[OpcodeIndex]);
1918 Ops.push_back(MemAddr);
1919 Ops.push_back(Align);
1920 if (isUpdating) {
1921 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbach88ac7612011-12-14 21:32:11 +00001922 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach05df4602011-10-31 21:50:31 +00001923 // case entirely when the rest are updated to that form, too.
Tim Northover8b1240b2017-04-20 19:54:02 +00001924 bool IsImmUpdate = isPerfectIncrement(Inc, VT, NumVecs);
1925 if (NumVecs <= 2 && !IsImmUpdate)
Jim Grosbach05df4602011-10-31 21:50:31 +00001926 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001927 // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001928 // check for that explicitly too. Horribly hacky, but temporary.
Tim Northover8b1240b2017-04-20 19:54:02 +00001929 if (!IsImmUpdate)
Jiangning Liu4df23632014-01-16 09:16:13 +00001930 Ops.push_back(Inc);
1931 else if (NumVecs > 2 && !isVSTfixed(Opc))
1932 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00001933 }
1934 Ops.push_back(SrcReg);
1935 Ops.push_back(Pred);
1936 Ops.push_back(Reg0);
1937 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001938 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00001939
1940 // Transfer memoperands.
1941 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
1942
Justin Bogner45571362016-05-12 00:31:09 +00001943 ReplaceNode(N, VSt);
1944 return;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001945 }
1946
1947 // Otherwise, quad registers are stored with two separate instructions,
1948 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00001949
Bob Wilson01ac8f92010-06-16 21:34:01 +00001950 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00001951 SDValue V0 = N->getOperand(Vec0Idx + 0);
1952 SDValue V1 = N->getOperand(Vec0Idx + 1);
1953 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00001954 SDValue V3 = (NumVecs == 3)
1955 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00001956 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00001957 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00001958
Bob Wilson06fce872011-02-07 17:43:21 +00001959 // Store the even D registers. This is always an updating store, so that it
1960 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00001961 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
1962 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
1963 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00001964 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00001965 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00001966 Chain = SDValue(VStA, 1);
1967
1968 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00001969 Ops.push_back(SDValue(VStA, 0));
1970 Ops.push_back(Align);
1971 if (isUpdating) {
1972 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1973 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1974 "only constant post-increment update allowed for VST3/4");
1975 (void)Inc;
1976 Ops.push_back(Reg0);
1977 }
1978 Ops.push_back(RegSeq);
1979 Ops.push_back(Pred);
1980 Ops.push_back(Reg0);
1981 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00001982 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00001983 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00001984 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00001985 ReplaceNode(N, VStB);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001986}
1987
Justin Bogner45571362016-05-12 00:31:09 +00001988void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
1989 unsigned NumVecs,
1990 const uint16_t *DOpcodes,
1991 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00001992 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001993 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00001994
Bob Wilsonae08a732010-03-20 22:13:40 +00001995 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001996 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1997 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1998 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00001999 return;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002000
Evan Cheng40791332011-04-19 00:04:03 +00002001 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2002 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2003
Bob Wilson4145e3a2009-10-14 16:19:03 +00002004 SDValue Chain = N->getOperand(0);
2005 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002006 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2007 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002008 bool is64BitVector = VT.is64BitVector();
2009
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002010 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002011 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002012 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Sanjay Patel1ed771f2016-09-14 16:37:15 +00002013 unsigned NumBytes = NumVecs * VT.getScalarSizeInBits() / 8;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002014 if (Alignment > NumBytes)
2015 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002016 if (Alignment < 8 && Alignment < NumBytes)
2017 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002018 // Alignment must be a power of two; make sure of that.
2019 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002020 if (Alignment == 1)
2021 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002022 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002023 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002024
Bob Wilson4145e3a2009-10-14 16:19:03 +00002025 unsigned OpcodeIndex;
2026 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002027 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002028 // Double-register operations:
2029 case MVT::v8i8: OpcodeIndex = 0; break;
2030 case MVT::v4i16: OpcodeIndex = 1; break;
2031 case MVT::v2f32:
2032 case MVT::v2i32: OpcodeIndex = 2; break;
2033 // Quad-register operations:
2034 case MVT::v8i16: OpcodeIndex = 0; break;
2035 case MVT::v4f32:
2036 case MVT::v4i32: OpcodeIndex = 1; break;
2037 }
2038
Bob Wilson06fce872011-02-07 17:43:21 +00002039 std::vector<EVT> ResTys;
2040 if (IsLoad) {
2041 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2042 if (!is64BitVector)
2043 ResTyElts *= 2;
2044 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2045 MVT::i64, ResTyElts));
2046 }
2047 if (isUpdating)
2048 ResTys.push_back(MVT::i32);
2049 ResTys.push_back(MVT::Other);
2050
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002051 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002052 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002053
Bob Wilson06fce872011-02-07 17:43:21 +00002054 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002055 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002056 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002057 if (isUpdating) {
2058 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Tim Northover8b1240b2017-04-20 19:54:02 +00002059 bool IsImmUpdate =
2060 isPerfectIncrement(Inc, VT.getVectorElementType(), NumVecs);
2061 Ops.push_back(IsImmUpdate ? Reg0 : Inc);
Bob Wilson06fce872011-02-07 17:43:21 +00002062 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002063
Bob Wilsond5c57a52010-09-13 23:01:35 +00002064 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002065 SDValue V0 = N->getOperand(Vec0Idx + 0);
2066 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002067 if (NumVecs == 2) {
2068 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002069 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002070 else
Weiming Zhao95782222012-11-17 00:23:35 +00002071 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002072 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002073 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002074 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002075 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2076 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002077 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002078 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002079 else
Weiming Zhao95782222012-11-17 00:23:35 +00002080 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002081 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002082 Ops.push_back(SuperReg);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002083 Ops.push_back(getI32Imm(Lane, dl));
Evan Chenga33fc862009-11-21 06:21:52 +00002084 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002085 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002086 Ops.push_back(Chain);
2087
Bob Wilson06fce872011-02-07 17:43:21 +00002088 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2089 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002090 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002091 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Justin Bogner45571362016-05-12 00:31:09 +00002092 if (!IsLoad) {
2093 ReplaceNode(N, VLdLn);
2094 return;
2095 }
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002096
Bob Wilsond5c57a52010-09-13 23:01:35 +00002097 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002098 SuperReg = SDValue(VLdLn, 0);
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00002099 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 &&
2100 ARM::qsub_3 == ARM::qsub_0 + 3,
2101 "Unexpected subreg numbering");
Bob Wilson06fce872011-02-07 17:43:21 +00002102 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002103 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2104 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002105 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2106 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2107 if (isUpdating)
2108 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002109 CurDAG->RemoveDeadNode(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002110}
2111
Justin Bogner45571362016-05-12 00:31:09 +00002112void ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Eli Friedmanf624ec22016-12-16 18:44:08 +00002113 const uint16_t *DOpcodes,
2114 const uint16_t *QOpcodes) {
2115 assert(NumVecs >= 1 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002116 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002117
2118 SDValue MemAddr, Align;
2119 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
Justin Bogner45571362016-05-12 00:31:09 +00002120 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00002121
Evan Cheng40791332011-04-19 00:04:03 +00002122 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2123 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2124
Bob Wilson2d790df2010-11-28 06:51:26 +00002125 SDValue Chain = N->getOperand(0);
2126 EVT VT = N->getValueType(0);
2127
2128 unsigned Alignment = 0;
2129 if (NumVecs != 3) {
2130 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Sanjay Patel1ed771f2016-09-14 16:37:15 +00002131 unsigned NumBytes = NumVecs * VT.getScalarSizeInBits() / 8;
Bob Wilson2d790df2010-11-28 06:51:26 +00002132 if (Alignment > NumBytes)
2133 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002134 if (Alignment < 8 && Alignment < NumBytes)
2135 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002136 // Alignment must be a power of two; make sure of that.
2137 Alignment = (Alignment & -Alignment);
2138 if (Alignment == 1)
2139 Alignment = 0;
2140 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002141 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson2d790df2010-11-28 06:51:26 +00002142
Eli Friedmanf624ec22016-12-16 18:44:08 +00002143 unsigned Opc;
Bob Wilson2d790df2010-11-28 06:51:26 +00002144 switch (VT.getSimpleVT().SimpleTy) {
2145 default: llvm_unreachable("unhandled vld-dup type");
Eli Friedmanf624ec22016-12-16 18:44:08 +00002146 case MVT::v8i8: Opc = DOpcodes[0]; break;
2147 case MVT::v16i8: Opc = QOpcodes[0]; break;
2148 case MVT::v4i16: Opc = DOpcodes[1]; break;
2149 case MVT::v8i16: Opc = QOpcodes[1]; break;
Bob Wilson2d790df2010-11-28 06:51:26 +00002150 case MVT::v2f32:
Eli Friedmanf624ec22016-12-16 18:44:08 +00002151 case MVT::v2i32: Opc = DOpcodes[2]; break;
2152 case MVT::v4f32:
2153 case MVT::v4i32: Opc = QOpcodes[2]; break;
Bob Wilson2d790df2010-11-28 06:51:26 +00002154 }
2155
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002156 SDValue Pred = getAL(CurDAG, dl);
Bob Wilson2d790df2010-11-28 06:51:26 +00002157 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00002158 SmallVector<SDValue, 6> Ops;
2159 Ops.push_back(MemAddr);
2160 Ops.push_back(Align);
2161 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002162 // fixed-stride update instructions don't have an explicit writeback
2163 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002164 SDValue Inc = N->getOperand(2);
Tim Northover8b1240b2017-04-20 19:54:02 +00002165 bool IsImmUpdate =
2166 isPerfectIncrement(Inc, VT.getVectorElementType(), NumVecs);
2167 if (NumVecs <= 2 && !IsImmUpdate)
Eli Friedmanf624ec22016-12-16 18:44:08 +00002168 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Tim Northover8b1240b2017-04-20 19:54:02 +00002169 if (!IsImmUpdate)
Jim Grosbachc80a2642011-12-21 19:40:55 +00002170 Ops.push_back(Inc);
2171 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2172 else if (NumVecs > 2)
2173 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002174 }
2175 Ops.push_back(Pred);
2176 Ops.push_back(Reg0);
2177 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002178
2179 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002180 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002181 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002182 if (isUpdating)
2183 ResTys.push_back(MVT::i32);
2184 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002185 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002186 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002187
2188 // Extract the subregisters.
Eli Friedmanf624ec22016-12-16 18:44:08 +00002189 if (NumVecs == 1) {
2190 ReplaceUses(SDValue(N, 0), SDValue(VLdDup, 0));
2191 } else {
2192 SDValue SuperReg = SDValue(VLdDup, 0);
2193 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7, "Unexpected subreg numbering");
2194 unsigned SubIdx = ARM::dsub_0;
2195 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2196 ReplaceUses(SDValue(N, Vec),
2197 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
2198 }
Bob Wilson06fce872011-02-07 17:43:21 +00002199 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2200 if (isUpdating)
2201 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002202 CurDAG->RemoveDeadNode(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002203}
2204
Justin Bogner45571362016-05-12 00:31:09 +00002205bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002206 if (!Subtarget->hasV6T2Ops())
Justin Bogner45571362016-05-12 00:31:09 +00002207 return false;
Bob Wilson93117bc2009-10-14 16:46:45 +00002208
Evan Chengeae6d2c2012-12-19 20:16:09 +00002209 unsigned Opc = isSigned
2210 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002211 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002212 SDLoc dl(N);
Jim Grosbach825cb292010-04-22 23:24:18 +00002213
Jim Grosbach825cb292010-04-22 23:24:18 +00002214 // For unsigned extracts, check for a shift right and mask
2215 unsigned And_imm = 0;
2216 if (N->getOpcode() == ISD::AND) {
2217 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2218
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002219 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002220 if (And_imm & (And_imm + 1))
Justin Bogner45571362016-05-12 00:31:09 +00002221 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002222
2223 unsigned Srl_imm = 0;
2224 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2225 Srl_imm)) {
2226 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2227
Jim Grosbach03f56d92011-07-27 21:09:25 +00002228 // Note: The width operand is encoded as width-1.
Benjamin Kramer5f6a9072015-02-12 15:35:40 +00002229 unsigned Width = countTrailingOnes(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002230 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002231
Jim Grosbach825cb292010-04-22 23:24:18 +00002232 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002233
2234 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2235 // It's cheaper to use a right shift to extract the top bits.
2236 if (Subtarget->isThumb()) {
2237 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2238 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002239 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2240 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002241 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2242 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002243 }
2244
2245 // ARM models shift instructions as MOVsi with shifter operand.
2246 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2247 SDValue ShOpc =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002248 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), dl,
Evan Chengeae6d2c2012-12-19 20:16:09 +00002249 MVT::i32);
2250 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002251 getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002252 CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops);
2253 return true;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002254 }
2255
Jim Grosbach825cb292010-04-22 23:24:18 +00002256 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002257 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2258 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2259 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002260 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2261 return true;
Jim Grosbach825cb292010-04-22 23:24:18 +00002262 }
2263 }
Justin Bogner45571362016-05-12 00:31:09 +00002264 return false;
Jim Grosbach825cb292010-04-22 23:24:18 +00002265 }
2266
2267 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002268 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002269 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002270 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2271 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002272 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002273 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002274 // Note: The width operand is encoded as width-1.
2275 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002276 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002277 if (LSB < 0)
Justin Bogner45571362016-05-12 00:31:09 +00002278 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002279 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002280 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002281 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2282 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2283 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002284 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2285 return true;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002286 }
2287 }
Tim Northover14ff2df2014-07-23 13:59:12 +00002288
Oliver Stannard92ca83c2016-06-01 12:01:01 +00002289 // Or we are looking for a shift of an and, with a mask operand
2290 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, And_imm) &&
2291 isShiftedMask_32(And_imm)) {
2292 unsigned Srl_imm = 0;
2293 unsigned LSB = countTrailingZeros(And_imm);
2294 // Shift must be the same as the ands lsb
2295 if (isInt32Immediate(N->getOperand(1), Srl_imm) && Srl_imm == LSB) {
2296 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2297 unsigned MSB = 31 - countLeadingZeros(And_imm);
2298 // Note: The width operand is encoded as width-1.
2299 unsigned Width = MSB - LSB;
2300 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2301 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2302 CurDAG->getTargetConstant(Srl_imm, dl, MVT::i32),
2303 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2304 getAL(CurDAG, dl), Reg0 };
2305 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2306 return true;
2307 }
2308 }
2309
Tim Northover14ff2df2014-07-23 13:59:12 +00002310 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
2311 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2312 unsigned LSB = 0;
2313 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) &&
2314 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB))
Justin Bogner45571362016-05-12 00:31:09 +00002315 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002316
2317 if (LSB + Width > 32)
Justin Bogner45571362016-05-12 00:31:09 +00002318 return false;
Tim Northover14ff2df2014-07-23 13:59:12 +00002319
2320 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2321 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002322 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2323 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
2324 getAL(CurDAG, dl), Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002325 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2326 return true;
Tim Northover14ff2df2014-07-23 13:59:12 +00002327 }
2328
Justin Bogner45571362016-05-12 00:31:09 +00002329 return false;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002330}
2331
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002332/// Target-specific DAG combining for ISD::XOR.
2333/// Target-independent combining lowers SELECT_CC nodes of the form
2334/// select_cc setg[ge] X, 0, X, -X
2335/// select_cc setgt X, -1, X, -X
2336/// select_cc setl[te] X, 0, -X, X
2337/// select_cc setlt X, 1, -X, X
2338/// which represent Integer ABS into:
2339/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2340/// ARM instruction selection detects the latter and matches it to
2341/// ARM::ABS or ARM::t2ABS machine node.
Justin Bogner45571362016-05-12 00:31:09 +00002342bool ARMDAGToDAGISel::tryABSOp(SDNode *N){
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002343 SDValue XORSrc0 = N->getOperand(0);
2344 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002345 EVT VT = N->getValueType(0);
2346
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002347 if (Subtarget->isThumb1Only())
Justin Bogner45571362016-05-12 00:31:09 +00002348 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002349
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002350 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Justin Bogner45571362016-05-12 00:31:09 +00002351 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002352
2353 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2354 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2355 SDValue SRASrc0 = XORSrc1.getOperand(0);
2356 SDValue SRASrc1 = XORSrc1.getOperand(1);
2357 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2358 EVT XType = SRASrc0.getValueType();
2359 unsigned Size = XType.getSizeInBits() - 1;
2360
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002361 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
Craig Topper062a2ba2014-04-25 05:30:21 +00002362 XType.isInteger() && SRAConstant != nullptr &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002363 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002364 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Justin Bogner45571362016-05-12 00:31:09 +00002365 CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2366 return true;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002367 }
2368
Justin Bogner45571362016-05-12 00:31:09 +00002369 return false;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002370}
2371
Tim Northoverb629c772016-04-18 21:48:55 +00002372/// We've got special pseudo-instructions for these
Justin Bogner45571362016-05-12 00:31:09 +00002373void ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *N) {
Tim Northoverb629c772016-04-18 21:48:55 +00002374 unsigned Opcode;
2375 EVT MemTy = cast<MemSDNode>(N)->getMemoryVT();
2376 if (MemTy == MVT::i8)
2377 Opcode = ARM::CMP_SWAP_8;
2378 else if (MemTy == MVT::i16)
2379 Opcode = ARM::CMP_SWAP_16;
2380 else if (MemTy == MVT::i32)
2381 Opcode = ARM::CMP_SWAP_32;
2382 else
2383 llvm_unreachable("Unknown AtomicCmpSwap type");
2384
2385 SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3),
2386 N->getOperand(0)};
2387 SDNode *CmpSwap = CurDAG->getMachineNode(
2388 Opcode, SDLoc(N),
2389 CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other), Ops);
2390
2391 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2392 MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
2393 cast<MachineSDNode>(CmpSwap)->setMemRefs(MemOp, MemOp + 1);
2394
2395 ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0));
2396 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2));
Justin Bognered4f3782016-05-12 00:20:19 +00002397 CurDAG->RemoveDeadNode(N);
Tim Northoverb629c772016-04-18 21:48:55 +00002398}
2399
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002400static Optional<std::pair<unsigned, unsigned>>
2401getContiguousRangeOfSetBits(const APInt &A) {
2402 unsigned FirstOne = A.getBitWidth() - A.countLeadingZeros() - 1;
2403 unsigned LastOne = A.countTrailingZeros();
2404 if (A.countPopulation() != (FirstOne - LastOne + 1))
2405 return Optional<std::pair<unsigned,unsigned>>();
2406 return std::make_pair(FirstOne, LastOne);
2407}
2408
2409void ARMDAGToDAGISel::SelectCMPZ(SDNode *N, bool &SwitchEQNEToPLMI) {
2410 assert(N->getOpcode() == ARMISD::CMPZ);
2411 SwitchEQNEToPLMI = false;
2412
2413 if (!Subtarget->isThumb())
2414 // FIXME: Work out whether it is profitable to do this in A32 mode - LSL and
2415 // LSR don't exist as standalone instructions - they need the barrel shifter.
2416 return;
2417
2418 // select (cmpz (and X, C), #0) -> (LSLS X) or (LSRS X) or (LSRS (LSLS X))
2419 SDValue And = N->getOperand(0);
2420 if (!And->hasOneUse())
2421 return;
2422
2423 SDValue Zero = N->getOperand(1);
2424 if (!isa<ConstantSDNode>(Zero) || !cast<ConstantSDNode>(Zero)->isNullValue() ||
2425 And->getOpcode() != ISD::AND)
2426 return;
2427 SDValue X = And.getOperand(0);
2428 auto C = dyn_cast<ConstantSDNode>(And.getOperand(1));
2429
2430 if (!C || !X->hasOneUse())
2431 return;
2432 auto Range = getContiguousRangeOfSetBits(C->getAPIntValue());
2433 if (!Range)
2434 return;
2435
2436 // There are several ways to lower this:
2437 SDNode *NewN;
2438 SDLoc dl(N);
2439
2440 auto EmitShift = [&](unsigned Opc, SDValue Src, unsigned Imm) -> SDNode* {
2441 if (Subtarget->isThumb2()) {
2442 Opc = (Opc == ARM::tLSLri) ? ARM::t2LSLri : ARM::t2LSRri;
2443 SDValue Ops[] = { Src, CurDAG->getTargetConstant(Imm, dl, MVT::i32),
2444 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
2445 CurDAG->getRegister(0, MVT::i32) };
2446 return CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
2447 } else {
2448 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), Src,
2449 CurDAG->getTargetConstant(Imm, dl, MVT::i32),
2450 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
2451 return CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
2452 }
2453 };
2454
2455 if (Range->second == 0) {
2456 // 1. Mask includes the LSB -> Simply shift the top N bits off
2457 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2458 ReplaceNode(And.getNode(), NewN);
2459 } else if (Range->first == 31) {
2460 // 2. Mask includes the MSB -> Simply shift the bottom N bits off
2461 NewN = EmitShift(ARM::tLSRri, X, Range->second);
2462 ReplaceNode(And.getNode(), NewN);
2463 } else if (Range->first == Range->second) {
2464 // 3. Only one bit is set. We can shift this into the sign bit and use a
2465 // PL/MI comparison.
2466 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2467 ReplaceNode(And.getNode(), NewN);
2468
2469 SwitchEQNEToPLMI = true;
2470 } else if (!Subtarget->hasV6T2Ops()) {
2471 // 4. Do a double shift to clear bottom and top bits, but only in
2472 // thumb-1 mode as in thumb-2 we can use UBFX.
2473 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first);
2474 NewN = EmitShift(ARM::tLSRri, SDValue(NewN, 0),
2475 Range->second + (31 - Range->first));
2476 ReplaceNode(And.getNode(), NewN);
2477 }
2478
2479}
2480
Justin Bogner45571362016-05-12 00:31:09 +00002481void ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002482 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002483
Tim Northover31d093c2013-09-22 08:21:56 +00002484 if (N->isMachineOpcode()) {
2485 N->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00002486 return; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00002487 }
Rafael Espindola4e760152006-06-12 12:28:08 +00002488
2489 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002490 default: break;
Justin Bogner45571362016-05-12 00:31:09 +00002491 case ISD::WRITE_REGISTER:
2492 if (tryWriteRegister(N))
2493 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002494 break;
Justin Bogner45571362016-05-12 00:31:09 +00002495 case ISD::READ_REGISTER:
2496 if (tryReadRegister(N))
2497 return;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002498 break;
Justin Bogner45571362016-05-12 00:31:09 +00002499 case ISD::INLINEASM:
2500 if (tryInlineAsm(N))
2501 return;
Weiming Zhaoc5987002013-02-14 18:10:21 +00002502 break;
Justin Bogner45571362016-05-12 00:31:09 +00002503 case ISD::XOR:
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002504 // Select special operations if XOR node forms integer ABS pattern
Justin Bogner45571362016-05-12 00:31:09 +00002505 if (tryABSOp(N))
2506 return;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002507 // Other cases are autogenerated.
2508 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002509 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002510 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
John Brawn056e6782015-09-14 15:19:41 +00002511 // If we can't materialize the constant we need to use a literal pool
2512 if (ConstantMaterializationCost(Val) > 2) {
Eric Christopherb17140d2014-10-08 07:32:17 +00002513 SDValue CPIdx = CurDAG->getTargetConstantPool(
2514 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
Mehdi Amini44ede332015-07-09 02:09:04 +00002515 TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng1526ba52007-01-24 08:53:17 +00002516
2517 SDNode *ResNode;
Tim Northover55c625f2014-01-23 13:43:47 +00002518 if (Subtarget->isThumb()) {
Sam Parker28934482017-07-14 08:23:56 +00002519 SDValue Ops[] = {
2520 CPIdx,
2521 getAL(CurDAG, dl),
2522 CurDAG->getRegister(0, MVT::i32),
2523 CurDAG->getEntryNode()
2524 };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002525 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002526 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002527 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002528 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002529 CPIdx,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002530 CurDAG->getTargetConstant(0, dl, MVT::i32),
2531 getAL(CurDAG, dl),
Owen Anderson9f944592009-08-11 20:47:22 +00002532 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002533 CurDAG->getEntryNode()
2534 };
Justin Bogner45571362016-05-12 00:31:09 +00002535 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
2536 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002537 }
Sam Parker28934482017-07-14 08:23:56 +00002538 // Annotate the Node with memory operand information so that MachineInstr
2539 // queries work properly. This e.g. gives the register allocation the
2540 // required information for rematerialization.
2541 MachineFunction& MF = CurDAG->getMachineFunction();
2542 MachineSDNode::mmo_iterator MemOp = MF.allocateMemRefsArray(1);
2543 MemOp[0] = MF.getMachineMemOperand(
2544 MachinePointerInfo::getConstantPool(MF),
2545 MachineMemOperand::MOLoad, 4, 4);
2546
2547 cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp+1);
2548
Justin Bognered4f3782016-05-12 00:20:19 +00002549 ReplaceNode(N, ResNode);
Justin Bogner45571362016-05-12 00:31:09 +00002550 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002551 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002552
Evan Cheng10043e22007-01-19 07:51:42 +00002553 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002554 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002555 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002556 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002557 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002558 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00002559 SDValue TFI = CurDAG->getTargetFrameIndex(
2560 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin22c2fba2009-07-08 23:10:31 +00002561 if (Subtarget->isThumb1Only()) {
Renato Golinb9887ef2015-02-25 14:41:06 +00002562 // Set the alignment of the frame object to 4, to avoid having to generate
2563 // more than one ADD
Matthias Braun941a7052016-07-28 18:40:00 +00002564 MachineFrameInfo &MFI = MF->getFrameInfo();
2565 if (MFI.getObjectAlignment(FI) < 4)
2566 MFI.setObjectAlignment(FI, 4);
Justin Bogner45571362016-05-12 00:31:09 +00002567 CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
2568 CurDAG->getTargetConstant(0, dl, MVT::i32));
2569 return;
Jim Grosbachfde21102009-04-07 20:34:09 +00002570 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002571 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2572 ARM::t2ADDri : ARM::ADDri);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002573 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
2574 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002575 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002576 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2577 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00002578 }
Evan Cheng10043e22007-01-19 07:51:42 +00002579 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002580 case ISD::SRL:
Justin Bogner45571362016-05-12 00:31:09 +00002581 if (tryV6T2BitfieldExtractOp(N, false))
2582 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002583 break;
Tim Northover14ff2df2014-07-23 13:59:12 +00002584 case ISD::SIGN_EXTEND_INREG:
Sandeep Patel423e42b2009-10-13 18:59:48 +00002585 case ISD::SRA:
Justin Bogner45571362016-05-12 00:31:09 +00002586 if (tryV6T2BitfieldExtractOp(N, true))
2587 return;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002588 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002589 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002590 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002591 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002592 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002593 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002594 if (!RHSV) break;
2595 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002596 unsigned ShImm = Log2_32(RHSV-1);
2597 if (ShImm >= 32)
2598 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002599 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002600 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002601 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002602 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002603 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002604 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002605 CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
2606 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002607 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002608 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2609 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002610 CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
2611 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002612 }
Evan Cheng10043e22007-01-19 07:51:42 +00002613 }
2614 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002615 unsigned ShImm = Log2_32(RHSV+1);
2616 if (ShImm >= 32)
2617 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002618 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002619 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002620 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002621 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002622 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002623 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002624 CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
2625 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002626 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002627 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2628 Reg0 };
Justin Bogner45571362016-05-12 00:31:09 +00002629 CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
2630 return;
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002631 }
Evan Cheng10043e22007-01-19 07:51:42 +00002632 }
2633 }
2634 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002635 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002636 // Check for unsigned bitfield extract
Justin Bogner45571362016-05-12 00:31:09 +00002637 if (tryV6T2BitfieldExtractOp(N, false))
2638 return;
Jim Grosbach825cb292010-04-22 23:24:18 +00002639
James Molloyae5ff992016-07-05 12:37:13 +00002640 // If an immediate is used in an AND node, it is possible that the immediate
2641 // can be more optimally materialized when negated. If this is the case we
2642 // can negate the immediate and use a BIC instead.
2643 auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1));
2644 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
2645 uint32_t Imm = (uint32_t) N1C->getZExtValue();
2646
2647 // In Thumb2 mode, an AND can take a 12-bit immediate. If this
2648 // immediate can be negated and fit in the immediate operand of
2649 // a t2BIC, don't do any manual transform here as this can be
2650 // handled by the generic ISel machinery.
2651 bool PreferImmediateEncoding =
2652 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm));
2653 if (!PreferImmediateEncoding &&
2654 ConstantMaterializationCost(Imm) >
2655 ConstantMaterializationCost(~Imm)) {
2656 // The current immediate costs more to materialize than a negated
2657 // immediate, so negate the immediate and use a BIC.
2658 SDValue NewImm =
2659 CurDAG->getConstant(~N1C->getZExtValue(), dl, MVT::i32);
2660 // If the new constant didn't exist before, reposition it in the topological
2661 // ordering so it is just before N. Otherwise, don't touch its location.
2662 if (NewImm->getNodeId() == -1)
2663 CurDAG->RepositionNode(N->getIterator(), NewImm.getNode());
2664
2665 if (!Subtarget->hasThumb2()) {
2666 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
2667 N->getOperand(0), NewImm, getAL(CurDAG, dl),
2668 CurDAG->getRegister(0, MVT::i32)};
2669 ReplaceNode(N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32, Ops));
2670 return;
2671 } else {
2672 SDValue Ops[] = {N->getOperand(0), NewImm, getAL(CurDAG, dl),
2673 CurDAG->getRegister(0, MVT::i32),
2674 CurDAG->getRegister(0, MVT::i32)};
2675 ReplaceNode(N,
2676 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32, Ops));
2677 return;
2678 }
2679 }
2680 }
2681
Evan Cheng786b15f2009-10-21 08:15:52 +00002682 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2683 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2684 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2685 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2686 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002687 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002688 if (VT != MVT::i32)
2689 break;
2690 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2691 ? ARM::t2MOVTi16
2692 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2693 if (!Opc)
2694 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002695 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
James Molloyae5ff992016-07-05 12:37:13 +00002696 N1C = dyn_cast<ConstantSDNode>(N1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002697 if (!N1C)
2698 break;
2699 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2700 SDValue N2 = N0.getOperand(1);
2701 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2702 if (!N2C)
2703 break;
2704 unsigned N1CVal = N1C->getZExtValue();
2705 unsigned N2CVal = N2C->getZExtValue();
2706 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2707 (N1CVal & 0xffffU) == 0xffffU &&
2708 (N2CVal & 0xffffU) == 0x0U) {
2709 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002710 dl, MVT::i32);
Evan Cheng786b15f2009-10-21 08:15:52 +00002711 SDValue Ops[] = { N0.getOperand(0), Imm16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002712 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002713 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
2714 return;
Evan Cheng786b15f2009-10-21 08:15:52 +00002715 }
2716 }
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002717
Evan Cheng786b15f2009-10-21 08:15:52 +00002718 break;
2719 }
Sam Parkerd616cf02016-06-20 16:47:09 +00002720 case ARMISD::UMAAL: {
2721 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL;
2722 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
2723 N->getOperand(2), N->getOperand(3),
2724 getAL(CurDAG, dl),
2725 CurDAG->getRegister(0, MVT::i32) };
2726 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::i32, Ops));
2727 return;
2728 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002729 case ARMISD::UMLAL:{
2730 if (Subtarget->isThumb()) {
2731 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002732 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002733 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002734 ReplaceNode(
2735 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops));
2736 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002737 }else{
2738 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002739 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002740 CurDAG->getRegister(0, MVT::i32),
2741 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002742 ReplaceNode(N, CurDAG->getMachineNode(
2743 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl,
2744 MVT::i32, MVT::i32, Ops));
2745 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002746 }
2747 }
2748 case ARMISD::SMLAL:{
2749 if (Subtarget->isThumb()) {
2750 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002751 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002752 CurDAG->getRegister(0, MVT::i32)};
Justin Bogner45571362016-05-12 00:31:09 +00002753 ReplaceNode(
2754 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops));
2755 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002756 }else{
2757 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002758 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002759 CurDAG->getRegister(0, MVT::i32),
2760 CurDAG->getRegister(0, MVT::i32) };
Justin Bogner45571362016-05-12 00:31:09 +00002761 ReplaceNode(N, CurDAG->getMachineNode(
2762 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl,
2763 MVT::i32, MVT::i32, Ops));
2764 return;
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002765 }
2766 }
Sam Parker68c71cd2016-07-25 09:20:20 +00002767 case ARMISD::SUBE: {
2768 if (!Subtarget->hasV6Ops())
2769 break;
2770 // Look for a pattern to match SMMLS
2771 // (sube a, (smul_loHi a, b), (subc 0, (smul_LOhi(a, b))))
2772 if (N->getOperand(1).getOpcode() != ISD::SMUL_LOHI ||
Tim Northover765777c2016-08-02 23:12:36 +00002773 N->getOperand(2).getOpcode() != ARMISD::SUBC ||
2774 !SDValue(N, 1).use_empty())
Sam Parker68c71cd2016-07-25 09:20:20 +00002775 break;
2776
2777 if (Subtarget->isThumb())
2778 assert(Subtarget->hasThumb2() &&
2779 "This pattern should not be generated for Thumb");
2780
2781 SDValue SmulLoHi = N->getOperand(1);
2782 SDValue Subc = N->getOperand(2);
2783 auto *Zero = dyn_cast<ConstantSDNode>(Subc.getOperand(0));
2784
2785 if (!Zero || Zero->getZExtValue() != 0 ||
2786 Subc.getOperand(1) != SmulLoHi.getValue(0) ||
2787 N->getOperand(1) != SmulLoHi.getValue(1) ||
2788 N->getOperand(2) != Subc.getValue(1))
2789 break;
2790
2791 unsigned Opc = Subtarget->isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
2792 SDValue Ops[] = { SmulLoHi.getOperand(0), SmulLoHi.getOperand(1),
2793 N->getOperand(0), getAL(CurDAG, dl),
2794 CurDAG->getRegister(0, MVT::i32) };
2795 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops));
2796 return;
2797 }
Evan Cheng10043e22007-01-19 07:51:42 +00002798 case ISD::LOAD: {
Justin Bogner45571362016-05-12 00:31:09 +00002799 if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
2800 if (tryT2IndexedLoad(N))
2801 return;
James Molloyb3326df2016-07-15 08:03:56 +00002802 } else if (Subtarget->isThumb()) {
2803 if (tryT1IndexedLoad(N))
2804 return;
Justin Bogner45571362016-05-12 00:31:09 +00002805 } else if (tryARMIndexedLoad(N))
2806 return;
Evan Cheng10043e22007-01-19 07:51:42 +00002807 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002808 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00002809 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002810 case ARMISD::BRCOND: {
2811 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2812 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2813 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00002814
Evan Cheng7e90b112007-07-05 07:15:27 +00002815 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2816 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2817 // Pattern complexity = 6 cost = 1 size = 0
2818
David Goodwin27303cd2009-06-30 18:04:13 +00002819 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2820 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2821 // Pattern complexity = 6 cost = 1 size = 0
2822
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002823 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00002824 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002825 SDValue Chain = N->getOperand(0);
2826 SDValue N1 = N->getOperand(1);
2827 SDValue N2 = N->getOperand(2);
2828 SDValue N3 = N->getOperand(3);
2829 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00002830 assert(N1.getOpcode() == ISD::BasicBlock);
2831 assert(N2.getOpcode() == ISD::Constant);
2832 assert(N3.getOpcode() == ISD::Register);
2833
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002834 unsigned CC = (unsigned) cast<ConstantSDNode>(N2)->getZExtValue();
2835
2836 if (InFlag.getOpcode() == ARMISD::CMPZ) {
2837 bool SwitchEQNEToPLMI;
2838 SelectCMPZ(InFlag.getNode(), SwitchEQNEToPLMI);
2839 InFlag = N->getOperand(4);
2840
2841 if (SwitchEQNEToPLMI) {
2842 switch ((ARMCC::CondCodes)CC) {
2843 default: llvm_unreachable("CMPZ must be either NE or EQ!");
2844 case ARMCC::NE:
2845 CC = (unsigned)ARMCC::MI;
2846 break;
2847 case ARMCC::EQ:
2848 CC = (unsigned)ARMCC::PL;
2849 break;
2850 }
2851 }
2852 }
2853
2854 SDValue Tmp2 = CurDAG->getTargetConstant(CC, dl, MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002855 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00002856 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002857 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002858 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002859 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002860 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002861 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00002862 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002863 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00002864 SDValue(Chain.getNode(), Chain.getResNo()));
Justin Bognered4f3782016-05-12 00:20:19 +00002865 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00002866 return;
Evan Cheng7e90b112007-07-05 07:15:27 +00002867 }
James Molloy4d86bed2016-09-09 12:52:24 +00002868
2869 case ARMISD::CMPZ: {
2870 // select (CMPZ X, #-C) -> (CMPZ (ADDS X, #C), #0)
2871 // This allows us to avoid materializing the expensive negative constant.
2872 // The CMPZ #0 is useless and will be peepholed away but we need to keep it
2873 // for its glue output.
2874 SDValue X = N->getOperand(0);
2875 auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1).getNode());
2876 if (C && C->getSExtValue() < 0 && Subtarget->isThumb()) {
2877 int64_t Addend = -C->getSExtValue();
2878
2879 SDNode *Add = nullptr;
Artyom Skrobov4592f622017-02-17 18:59:16 +00002880 // ADDS can be better than CMN if the immediate fits in a
James Molloy4d86bed2016-09-09 12:52:24 +00002881 // 16-bit ADDS, which means either [0,256) for tADDi8 or [0,8) for tADDi3.
2882 // Outside that range we can just use a CMN which is 32-bit but has a
2883 // 12-bit immediate range.
Artyom Skrobov4592f622017-02-17 18:59:16 +00002884 if (Addend < 1<<8) {
2885 if (Subtarget->isThumb2()) {
2886 SDValue Ops[] = { X, CurDAG->getTargetConstant(Addend, dl, MVT::i32),
2887 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
2888 CurDAG->getRegister(0, MVT::i32) };
2889 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl, MVT::i32, Ops);
2890 } else {
2891 unsigned Opc = (Addend < 1<<3) ? ARM::tADDi3 : ARM::tADDi8;
2892 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), X,
2893 CurDAG->getTargetConstant(Addend, dl, MVT::i32),
2894 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)};
2895 Add = CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops);
2896 }
James Molloy4d86bed2016-09-09 12:52:24 +00002897 }
2898 if (Add) {
2899 SDValue Ops2[] = {SDValue(Add, 0), CurDAG->getConstant(0, dl, MVT::i32)};
2900 CurDAG->MorphNodeTo(N, ARMISD::CMPZ, CurDAG->getVTList(MVT::Glue), Ops2);
2901 }
2902 }
2903 // Other cases are autogenerated.
2904 break;
2905 }
Sjoerd Meijer96e10b52016-12-15 09:38:59 +00002906
2907 case ARMISD::CMOV: {
2908 SDValue InFlag = N->getOperand(4);
2909
2910 if (InFlag.getOpcode() == ARMISD::CMPZ) {
2911 bool SwitchEQNEToPLMI;
2912 SelectCMPZ(InFlag.getNode(), SwitchEQNEToPLMI);
2913
2914 if (SwitchEQNEToPLMI) {
2915 SDValue ARMcc = N->getOperand(2);
2916 ARMCC::CondCodes CC =
2917 (ARMCC::CondCodes)cast<ConstantSDNode>(ARMcc)->getZExtValue();
2918
2919 switch (CC) {
2920 default: llvm_unreachable("CMPZ must be either NE or EQ!");
2921 case ARMCC::NE:
2922 CC = ARMCC::MI;
2923 break;
2924 case ARMCC::EQ:
2925 CC = ARMCC::PL;
2926 break;
2927 }
2928 SDValue NewARMcc = CurDAG->getConstant((unsigned)CC, dl, MVT::i32);
2929 SDValue Ops[] = {N->getOperand(0), N->getOperand(1), NewARMcc,
2930 N->getOperand(3), N->getOperand(4)};
2931 CurDAG->MorphNodeTo(N, ARMISD::CMOV, N->getVTList(), Ops);
2932 }
2933
2934 }
2935 // Other cases are autogenerated.
2936 break;
2937 }
James Molloy4d86bed2016-09-09 12:52:24 +00002938
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002939 case ARMISD::VZIP: {
2940 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002941 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002942 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00002943 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002944 case MVT::v8i8: Opc = ARM::VZIPd8; break;
2945 case MVT::v4i16: Opc = ARM::VZIPd16; break;
2946 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00002947 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2948 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002949 case MVT::v16i8: Opc = ARM::VZIPq8; break;
2950 case MVT::v8i16: Opc = ARM::VZIPq16; break;
2951 case MVT::v4f32:
2952 case MVT::v4i32: Opc = ARM::VZIPq32; break;
2953 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002954 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002955 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2956 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00002957 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
2958 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002959 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002960 case ARMISD::VUZP: {
2961 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002962 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002963 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00002964 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002965 case MVT::v8i8: Opc = ARM::VUZPd8; break;
2966 case MVT::v4i16: Opc = ARM::VUZPd16; break;
2967 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00002968 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2969 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002970 case MVT::v16i8: Opc = ARM::VUZPq8; break;
2971 case MVT::v8i16: Opc = ARM::VUZPq16; break;
2972 case MVT::v4f32:
2973 case MVT::v4i32: Opc = ARM::VUZPq32; break;
2974 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002975 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002976 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2977 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00002978 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
2979 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002980 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002981 case ARMISD::VTRN: {
2982 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002983 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002984 switch (VT.getSimpleVT().SimpleTy) {
Justin Bogner45571362016-05-12 00:31:09 +00002985 default: return;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002986 case MVT::v8i8: Opc = ARM::VTRNd8; break;
2987 case MVT::v4i16: Opc = ARM::VTRNd16; break;
2988 case MVT::v2f32:
2989 case MVT::v2i32: Opc = ARM::VTRNd32; break;
2990 case MVT::v16i8: Opc = ARM::VTRNq8; break;
2991 case MVT::v8i16: Opc = ARM::VTRNq16; break;
2992 case MVT::v4f32:
2993 case MVT::v4i32: Opc = ARM::VTRNq32; break;
2994 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002995 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002996 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2997 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Justin Bogner45571362016-05-12 00:31:09 +00002998 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops));
2999 return;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00003000 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003001 case ARMISD::BUILD_VECTOR: {
3002 EVT VecVT = N->getValueType(0);
3003 EVT EltVT = VecVT.getVectorElementType();
3004 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00003005 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00003006 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003007 ReplaceNode(
3008 N, createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3009 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003010 }
Duncan Sands14627772010-11-03 12:17:33 +00003011 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003012 if (NumElts == 2) {
3013 ReplaceNode(
3014 N, createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)));
3015 return;
3016 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00003017 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Justin Bogner45571362016-05-12 00:31:09 +00003018 ReplaceNode(N,
3019 createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
3020 N->getOperand(2), N->getOperand(3)));
3021 return;
Bob Wilsond8a9a042010-06-04 00:04:02 +00003022 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003023
Eli Friedmanf624ec22016-12-16 18:44:08 +00003024 case ARMISD::VLD1DUP: {
3025 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8, ARM::VLD1DUPd16,
3026 ARM::VLD1DUPd32 };
3027 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8, ARM::VLD1DUPq16,
3028 ARM::VLD1DUPq32 };
3029 SelectVLDDup(N, false, 1, DOpcodes, QOpcodes);
3030 return;
3031 }
3032
Bob Wilson2d790df2010-11-28 06:51:26 +00003033 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003034 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
3035 ARM::VLD2DUPd32 };
Justin Bogner45571362016-05-12 00:31:09 +00003036 SelectVLDDup(N, false, 2, Opcodes);
3037 return;
Bob Wilson2d790df2010-11-28 06:51:26 +00003038 }
3039
Bob Wilson77ab1652010-11-29 19:35:29 +00003040 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003041 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
3042 ARM::VLD3DUPd16Pseudo,
3043 ARM::VLD3DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003044 SelectVLDDup(N, false, 3, Opcodes);
3045 return;
Bob Wilson77ab1652010-11-29 19:35:29 +00003046 }
3047
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003048 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00003049 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
3050 ARM::VLD4DUPd16Pseudo,
3051 ARM::VLD4DUPd32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003052 SelectVLDDup(N, false, 4, Opcodes);
3053 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003054 }
3055
Eli Friedmanf624ec22016-12-16 18:44:08 +00003056 case ARMISD::VLD1DUP_UPD: {
3057 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8wb_fixed,
3058 ARM::VLD1DUPd16wb_fixed,
3059 ARM::VLD1DUPd32wb_fixed };
3060 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8wb_fixed,
3061 ARM::VLD1DUPq16wb_fixed,
3062 ARM::VLD1DUPq32wb_fixed };
3063 SelectVLDDup(N, true, 1, DOpcodes, QOpcodes);
3064 return;
3065 }
3066
Bob Wilson06fce872011-02-07 17:43:21 +00003067 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003068 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
3069 ARM::VLD2DUPd16wb_fixed,
3070 ARM::VLD2DUPd32wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003071 SelectVLDDup(N, true, 2, Opcodes);
3072 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003073 }
3074
3075 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003076 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
3077 ARM::VLD3DUPd16Pseudo_UPD,
3078 ARM::VLD3DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003079 SelectVLDDup(N, true, 3, Opcodes);
3080 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003081 }
3082
3083 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003084 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
3085 ARM::VLD4DUPd16Pseudo_UPD,
3086 ARM::VLD4DUPd32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003087 SelectVLDDup(N, true, 4, Opcodes);
3088 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003089 }
3090
3091 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003092 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
3093 ARM::VLD1d16wb_fixed,
3094 ARM::VLD1d32wb_fixed,
3095 ARM::VLD1d64wb_fixed };
3096 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
3097 ARM::VLD1q16wb_fixed,
3098 ARM::VLD1q32wb_fixed,
3099 ARM::VLD1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003100 SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
3101 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003102 }
3103
3104 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003105 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
3106 ARM::VLD2d16wb_fixed,
3107 ARM::VLD2d32wb_fixed,
3108 ARM::VLD1q64wb_fixed};
3109 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
3110 ARM::VLD2q16PseudoWB_fixed,
3111 ARM::VLD2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003112 SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
3113 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003114 }
3115
3116 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003117 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
3118 ARM::VLD3d16Pseudo_UPD,
3119 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003120 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003121 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3122 ARM::VLD3q16Pseudo_UPD,
3123 ARM::VLD3q32Pseudo_UPD };
3124 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3125 ARM::VLD3q16oddPseudo_UPD,
3126 ARM::VLD3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003127 SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3128 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003129 }
3130
3131 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003132 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3133 ARM::VLD4d16Pseudo_UPD,
3134 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00003135 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00003136 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3137 ARM::VLD4q16Pseudo_UPD,
3138 ARM::VLD4q32Pseudo_UPD };
3139 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3140 ARM::VLD4q16oddPseudo_UPD,
3141 ARM::VLD4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003142 SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3143 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003144 }
3145
3146 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003147 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3148 ARM::VLD2LNd16Pseudo_UPD,
3149 ARM::VLD2LNd32Pseudo_UPD };
3150 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3151 ARM::VLD2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003152 SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3153 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003154 }
3155
3156 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003157 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3158 ARM::VLD3LNd16Pseudo_UPD,
3159 ARM::VLD3LNd32Pseudo_UPD };
3160 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3161 ARM::VLD3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003162 SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3163 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003164 }
3165
3166 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003167 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3168 ARM::VLD4LNd16Pseudo_UPD,
3169 ARM::VLD4LNd32Pseudo_UPD };
3170 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3171 ARM::VLD4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003172 SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3173 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003174 }
3175
3176 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003177 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3178 ARM::VST1d16wb_fixed,
3179 ARM::VST1d32wb_fixed,
3180 ARM::VST1d64wb_fixed };
3181 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3182 ARM::VST1q16wb_fixed,
3183 ARM::VST1q32wb_fixed,
3184 ARM::VST1q64wb_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003185 SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
3186 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003187 }
3188
3189 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003190 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3191 ARM::VST2d16wb_fixed,
3192 ARM::VST2d32wb_fixed,
3193 ARM::VST1q64wb_fixed};
3194 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3195 ARM::VST2q16PseudoWB_fixed,
3196 ARM::VST2q32PseudoWB_fixed };
Justin Bogner45571362016-05-12 00:31:09 +00003197 SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
3198 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003199 }
3200
3201 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003202 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3203 ARM::VST3d16Pseudo_UPD,
3204 ARM::VST3d32Pseudo_UPD,
3205 ARM::VST1d64TPseudoWB_fixed};
3206 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3207 ARM::VST3q16Pseudo_UPD,
3208 ARM::VST3q32Pseudo_UPD };
3209 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3210 ARM::VST3q16oddPseudo_UPD,
3211 ARM::VST3q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003212 SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3213 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003214 }
3215
3216 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003217 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3218 ARM::VST4d16Pseudo_UPD,
3219 ARM::VST4d32Pseudo_UPD,
3220 ARM::VST1d64QPseudoWB_fixed};
3221 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3222 ARM::VST4q16Pseudo_UPD,
3223 ARM::VST4q32Pseudo_UPD };
3224 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3225 ARM::VST4q16oddPseudo_UPD,
3226 ARM::VST4q32oddPseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003227 SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3228 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003229 }
3230
3231 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003232 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3233 ARM::VST2LNd16Pseudo_UPD,
3234 ARM::VST2LNd32Pseudo_UPD };
3235 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3236 ARM::VST2LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003237 SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3238 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003239 }
3240
3241 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003242 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3243 ARM::VST3LNd16Pseudo_UPD,
3244 ARM::VST3LNd32Pseudo_UPD };
3245 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3246 ARM::VST3LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003247 SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3248 return;
Bob Wilson06fce872011-02-07 17:43:21 +00003249 }
3250
3251 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003252 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3253 ARM::VST4LNd16Pseudo_UPD,
3254 ARM::VST4LNd32Pseudo_UPD };
3255 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3256 ARM::VST4LNq32Pseudo_UPD };
Justin Bogner45571362016-05-12 00:31:09 +00003257 SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
3258 return;
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003259 }
3260
Bob Wilsone0636a72009-08-26 17:39:53 +00003261 case ISD::INTRINSIC_VOID:
3262 case ISD::INTRINSIC_W_CHAIN: {
3263 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003264 switch (IntNo) {
3265 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003266 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003267
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003268 case Intrinsic::arm_mrrc:
3269 case Intrinsic::arm_mrrc2: {
3270 SDLoc dl(N);
3271 SDValue Chain = N->getOperand(0);
3272 unsigned Opc;
3273
3274 if (Subtarget->isThumb())
3275 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
3276 else
3277 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
3278
3279 SmallVector<SDValue, 5> Ops;
3280 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(), dl)); /* coproc */
3281 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(), dl)); /* opc */
3282 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(4))->getZExtValue(), dl)); /* CRm */
3283
3284 // The mrrc2 instruction in ARM doesn't allow predicates, the top 4 bits of the encoded
3285 // instruction will always be '1111' but it is possible in assembly language to specify
3286 // AL as a predicate to mrrc2 but it doesn't make any difference to the encoded instruction.
3287 if (Opc != ARM::MRRC2) {
3288 Ops.push_back(getAL(CurDAG, dl));
3289 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3290 }
3291
3292 Ops.push_back(Chain);
3293
3294 // Writes to two registers.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003295 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other};
Ranjeet Singh39d2d092016-06-17 00:52:41 +00003296
3297 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, RetType, Ops));
3298 return;
3299 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003300 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003301 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003302 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003303 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003304 SDValue MemAddr = N->getOperand(2);
Bradley Smith433c22e2016-01-15 10:26:51 +00003305 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
Tim Northover1ff5f292014-03-26 14:39:31 +00003306
3307 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3308 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3309 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003310
3311 // arm_ldrexd returns a i64 value in {i32, i32}
3312 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003313 if (isThumb) {
3314 ResTys.push_back(MVT::i32);
3315 ResTys.push_back(MVT::i32);
3316 } else
3317 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003318 ResTys.push_back(MVT::Other);
3319
Weiming Zhao8f56f882012-11-16 21:55:34 +00003320 // Place arguments in the right order.
Benjamin Kramerf690da42016-06-17 14:14:29 +00003321 SDValue Ops[] = {MemAddr, getAL(CurDAG, dl),
3322 CurDAG->getRegister(0, MVT::i32), Chain};
Michael Liaob53d8962013-04-19 22:22:57 +00003323 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003324 // Transfer memoperands.
3325 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3326 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3327 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3328
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003329 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003330 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003331 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003332 SDValue Result;
3333 if (isThumb)
3334 Result = SDValue(Ld, 0);
3335 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003336 SDValue SubRegIdx =
3337 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003338 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003339 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003340 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003341 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003342 ReplaceUses(SDValue(N, 0), Result);
3343 }
3344 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003345 SDValue Result;
3346 if (isThumb)
3347 Result = SDValue(Ld, 1);
3348 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003349 SDValue SubRegIdx =
3350 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003351 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003352 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003353 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003354 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003355 ReplaceUses(SDValue(N, 1), Result);
3356 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003357 ReplaceUses(SDValue(N, 2), OutChain);
Justin Bognered4f3782016-05-12 00:20:19 +00003358 CurDAG->RemoveDeadNode(N);
Justin Bogner45571362016-05-12 00:31:09 +00003359 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003360 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003361 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003362 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003363 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003364 SDValue Chain = N->getOperand(0);
3365 SDValue Val0 = N->getOperand(2);
3366 SDValue Val1 = N->getOperand(3);
3367 SDValue MemAddr = N->getOperand(4);
3368
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003369 // Store exclusive double return a i32 value which is the return status
3370 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003371 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003372
Weiming Zhao8f56f882012-11-16 21:55:34 +00003373 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3374 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003375 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003376 if (isThumb) {
3377 Ops.push_back(Val0);
3378 Ops.push_back(Val1);
3379 } else
3380 // arm_strexd uses GPRPair.
3381 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003382 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003383 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003384 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3385 Ops.push_back(Chain);
3386
Tim Northover1ff5f292014-03-26 14:39:31 +00003387 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3388 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3389 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003390
Michael Liaob53d8962013-04-19 22:22:57 +00003391 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003392 // Transfer memoperands.
3393 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3394 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3395 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3396
Justin Bogner45571362016-05-12 00:31:09 +00003397 ReplaceNode(N, St);
3398 return;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003399 }
3400
Bob Wilson340861d2010-03-23 05:25:43 +00003401 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003402 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3403 ARM::VLD1d32, ARM::VLD1d64 };
3404 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3405 ARM::VLD1q32, ARM::VLD1q64};
Justin Bogner45571362016-05-12 00:31:09 +00003406 SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
3407 return;
Bob Wilson340861d2010-03-23 05:25:43 +00003408 }
3409
Bob Wilsone0636a72009-08-26 17:39:53 +00003410 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003411 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3412 ARM::VLD2d32, ARM::VLD1q64 };
3413 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3414 ARM::VLD2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003415 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
3416 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003417 }
3418
3419 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003420 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3421 ARM::VLD3d16Pseudo,
3422 ARM::VLD3d32Pseudo,
3423 ARM::VLD1d64TPseudo };
3424 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3425 ARM::VLD3q16Pseudo_UPD,
3426 ARM::VLD3q32Pseudo_UPD };
3427 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3428 ARM::VLD3q16oddPseudo,
3429 ARM::VLD3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003430 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3431 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003432 }
3433
3434 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003435 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3436 ARM::VLD4d16Pseudo,
3437 ARM::VLD4d32Pseudo,
3438 ARM::VLD1d64QPseudo };
3439 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3440 ARM::VLD4q16Pseudo_UPD,
3441 ARM::VLD4q32Pseudo_UPD };
3442 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3443 ARM::VLD4q16oddPseudo,
3444 ARM::VLD4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003445 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3446 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003447 }
3448
Bob Wilsonda9817c2009-09-01 04:26:28 +00003449 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003450 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3451 ARM::VLD2LNd16Pseudo,
3452 ARM::VLD2LNd32Pseudo };
3453 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3454 ARM::VLD2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003455 SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
3456 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003457 }
3458
3459 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003460 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3461 ARM::VLD3LNd16Pseudo,
3462 ARM::VLD3LNd32Pseudo };
3463 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3464 ARM::VLD3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003465 SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
3466 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003467 }
3468
3469 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003470 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3471 ARM::VLD4LNd16Pseudo,
3472 ARM::VLD4LNd32Pseudo };
3473 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3474 ARM::VLD4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003475 SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
3476 return;
Bob Wilsonda9817c2009-09-01 04:26:28 +00003477 }
3478
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003479 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003480 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3481 ARM::VST1d32, ARM::VST1d64 };
3482 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3483 ARM::VST1q32, ARM::VST1q64 };
Justin Bogner45571362016-05-12 00:31:09 +00003484 SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
3485 return;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003486 }
3487
Bob Wilsone0636a72009-08-26 17:39:53 +00003488 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003489 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3490 ARM::VST2d32, ARM::VST1q64 };
Benjamin Kramerf690da42016-06-17 14:14:29 +00003491 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3492 ARM::VST2q32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003493 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
3494 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003495 }
3496
3497 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003498 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3499 ARM::VST3d16Pseudo,
3500 ARM::VST3d32Pseudo,
3501 ARM::VST1d64TPseudo };
3502 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3503 ARM::VST3q16Pseudo_UPD,
3504 ARM::VST3q32Pseudo_UPD };
3505 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3506 ARM::VST3q16oddPseudo,
3507 ARM::VST3q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003508 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
3509 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003510 }
3511
3512 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003513 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3514 ARM::VST4d16Pseudo,
3515 ARM::VST4d32Pseudo,
3516 ARM::VST1d64QPseudo };
3517 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3518 ARM::VST4q16Pseudo_UPD,
3519 ARM::VST4q32Pseudo_UPD };
3520 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3521 ARM::VST4q16oddPseudo,
3522 ARM::VST4q32oddPseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003523 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
3524 return;
Bob Wilsone0636a72009-08-26 17:39:53 +00003525 }
Bob Wilsond7797752009-09-01 18:51:56 +00003526
3527 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003528 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3529 ARM::VST2LNd16Pseudo,
3530 ARM::VST2LNd32Pseudo };
3531 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3532 ARM::VST2LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003533 SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
3534 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003535 }
3536
3537 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003538 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3539 ARM::VST3LNd16Pseudo,
3540 ARM::VST3LNd32Pseudo };
3541 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3542 ARM::VST3LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003543 SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
3544 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003545 }
3546
3547 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003548 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3549 ARM::VST4LNd16Pseudo,
3550 ARM::VST4LNd32Pseudo };
3551 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3552 ARM::VST4LNq32Pseudo };
Justin Bogner45571362016-05-12 00:31:09 +00003553 SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
3554 return;
Bob Wilsond7797752009-09-01 18:51:56 +00003555 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003556 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003557 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003558 }
Evan Chengd85631e2010-05-05 18:28:36 +00003559
Tim Northoverb629c772016-04-18 21:48:55 +00003560 case ISD::ATOMIC_CMP_SWAP:
Justin Bogner45571362016-05-12 00:31:09 +00003561 SelectCMP_SWAP(N);
3562 return;
Evan Chengd85631e2010-05-05 18:28:36 +00003563 }
Evan Chengd5021732008-12-10 21:54:21 +00003564
Justin Bogner45571362016-05-12 00:31:09 +00003565 SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003566}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003567
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003568// Inspect a register string of the form
3569// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3570// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3571// and obtain the integer operands from them, adding these operands to the
3572// provided vector.
3573static void getIntOperandsFromRegisterString(StringRef RegString,
Benjamin Kramerbdc49562016-06-12 15:39:02 +00003574 SelectionDAG *CurDAG,
3575 const SDLoc &DL,
3576 std::vector<SDValue> &Ops) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003577 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003578 RegString.split(Fields, ':');
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003579
3580 if (Fields.size() > 1) {
3581 bool AllIntFields = true;
3582
3583 for (StringRef Field : Fields) {
3584 // Need to trim out leading 'cp' characters and get the integer field.
3585 unsigned IntField;
3586 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3587 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3588 }
3589
3590 assert(AllIntFields &&
3591 "Unexpected non-integer value in special register string.");
3592 }
3593}
3594
3595// Maps a Banked Register string to its mask value. The mask value returned is
3596// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3597// mask operand, which expresses which register is to be used, e.g. r8, and in
3598// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3599// was invalid.
3600static inline int getBankedRegisterMask(StringRef RegString) {
Javed Absar054d1ae2017-08-03 01:24:12 +00003601 auto TheReg = ARMBankedReg::lookupBankedRegByName(RegString.lower());
3602 if (!TheReg)
3603 return -1;
3604 return TheReg->Encoding;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003605}
3606
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003607// The flags here are common to those allowed for apsr in the A class cores and
3608// those allowed for the special registers in the M class cores. Returns a
3609// value representing which flags were present, -1 if invalid.
John Brawne60f4e42017-02-10 17:41:08 +00003610static inline int getMClassFlagsMask(StringRef Flags) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003611 return StringSwitch<int>(Flags)
John Brawne60f4e42017-02-10 17:41:08 +00003612 .Case("", 0x2) // no flags means nzcvq for psr registers, and 0x2 is
3613 // correct when flags are not permitted
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003614 .Case("g", 0x1)
3615 .Case("nzcvq", 0x2)
3616 .Case("nzcvqg", 0x3)
3617 .Default(-1);
3618}
3619
Javed Absar2cb0c952017-07-19 12:57:16 +00003620// Maps MClass special registers string to its value for use in the
3621// t2MRS_M/t2MSR_M instruction nodes as the SYSm value operand.
3622// Returns -1 to signify that the string was invalid.
3623static int getMClassRegisterMask(StringRef Reg, const ARMSubtarget *Subtarget) {
3624 auto TheReg = ARMSysReg::lookupMClassSysRegByName(Reg);
3625 const FeatureBitset &FeatureBits = Subtarget->getFeatureBits();
3626 if (!TheReg || !TheReg->hasRequiredFeatures(FeatureBits))
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003627 return -1;
Javed Absar2cb0c952017-07-19 12:57:16 +00003628 return (int)(TheReg->Encoding & 0xFFF); // SYSm value
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003629}
3630
3631static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
3632 // The mask operand contains the special register (R Bit) in bit 4, whether
3633 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
3634 // bits 3-0 contains the fields to be accessed in the special register, set by
3635 // the flags provided with the register.
3636 int Mask = 0;
3637 if (Reg == "apsr") {
3638 // The flags permitted for apsr are the same flags that are allowed in
3639 // M class registers. We get the flag value and then shift the flags into
3640 // the correct place to combine with the mask.
John Brawne60f4e42017-02-10 17:41:08 +00003641 Mask = getMClassFlagsMask(Flags);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003642 if (Mask == -1)
3643 return -1;
3644 return Mask << 2;
3645 }
3646
3647 if (Reg != "cpsr" && Reg != "spsr") {
3648 return -1;
3649 }
3650
3651 // This is the same as if the flags were "fc"
3652 if (Flags.empty() || Flags == "all")
3653 return Mask | 0x9;
3654
3655 // Inspect the supplied flags string and set the bits in the mask for
3656 // the relevant and valid flags allowed for cpsr and spsr.
3657 for (char Flag : Flags) {
3658 int FlagVal;
3659 switch (Flag) {
3660 case 'c':
3661 FlagVal = 0x1;
3662 break;
3663 case 'x':
3664 FlagVal = 0x2;
3665 break;
3666 case 's':
3667 FlagVal = 0x4;
3668 break;
3669 case 'f':
3670 FlagVal = 0x8;
3671 break;
3672 default:
3673 FlagVal = 0;
3674 }
3675
3676 // This avoids allowing strings where the same flag bit appears twice.
3677 if (!FlagVal || (Mask & FlagVal))
3678 return -1;
3679 Mask |= FlagVal;
3680 }
3681
3682 // If the register is spsr then we need to set the R bit.
3683 if (Reg == "spsr")
3684 Mask |= 0x10;
3685
3686 return Mask;
3687}
3688
3689// Lower the read_register intrinsic to ARM specific DAG nodes
3690// using the supplied metadata string to select the instruction node to use
3691// and the registers/masks to construct as operands for the node.
Justin Bogner45571362016-05-12 00:31:09 +00003692bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003693 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3694 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3695 bool IsThumb2 = Subtarget->isThumb2();
3696 SDLoc DL(N);
3697
3698 std::vector<SDValue> Ops;
3699 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3700
3701 if (!Ops.empty()) {
3702 // If the special register string was constructed of fields (as defined
3703 // in the ACLE) then need to lower to MRC node (32 bit) or
3704 // MRRC node(64 bit), we can make the distinction based on the number of
3705 // operands we have.
3706 unsigned Opcode;
3707 SmallVector<EVT, 3> ResTypes;
3708 if (Ops.size() == 5){
3709 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
3710 ResTypes.append({ MVT::i32, MVT::Other });
3711 } else {
3712 assert(Ops.size() == 3 &&
3713 "Invalid number of fields in special register string.");
3714 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
3715 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
3716 }
3717
3718 Ops.push_back(getAL(CurDAG, DL));
3719 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3720 Ops.push_back(N->getOperand(0));
Justin Bogner45571362016-05-12 00:31:09 +00003721 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops));
3722 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003723 }
3724
3725 std::string SpecialReg = RegString->getString().lower();
3726
3727 int BankedReg = getBankedRegisterMask(SpecialReg);
3728 if (BankedReg != -1) {
3729 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
3730 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3731 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003732 ReplaceNode(
3733 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
3734 DL, MVT::i32, MVT::Other, Ops));
3735 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003736 }
3737
3738 // The VFP registers are read by creating SelectionDAG nodes with opcodes
3739 // corresponding to the register that is being read from. So we switch on the
3740 // string to find which opcode we need to use.
3741 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3742 .Case("fpscr", ARM::VMRS)
3743 .Case("fpexc", ARM::VMRS_FPEXC)
3744 .Case("fpsid", ARM::VMRS_FPSID)
3745 .Case("mvfr0", ARM::VMRS_MVFR0)
3746 .Case("mvfr1", ARM::VMRS_MVFR1)
3747 .Case("mvfr2", ARM::VMRS_MVFR2)
3748 .Case("fpinst", ARM::VMRS_FPINST)
3749 .Case("fpinst2", ARM::VMRS_FPINST2)
3750 .Default(0);
3751
3752 // If an opcode was found then we can lower the read to a VFP instruction.
3753 if (Opcode) {
3754 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00003755 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003756 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
Justin Bogner45571362016-05-12 00:31:09 +00003757 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003758
3759 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3760 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003761 ReplaceNode(N,
3762 CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops));
3763 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003764 }
3765
3766 // If the target is M Class then need to validate that the register string
3767 // is an acceptable value, so check that a mask can be constructed from the
3768 // string.
3769 if (Subtarget->isMClass()) {
Javed Absar2cb0c952017-07-19 12:57:16 +00003770 int SYSmValue = getMClassRegisterMask(SpecialReg, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003771 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00003772 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003773
3774 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
3775 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3776 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003777 ReplaceNode(
3778 N, CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops));
3779 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003780 }
3781
3782 // Here we know the target is not M Class so we need to check if it is one
3783 // of the remaining possible values which are apsr, cpsr or spsr.
3784 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
3785 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3786 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003787 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS,
3788 DL, MVT::i32, MVT::Other, Ops));
3789 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003790 }
3791
3792 if (SpecialReg == "spsr") {
3793 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3794 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003795 ReplaceNode(
3796 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys, DL,
3797 MVT::i32, MVT::Other, Ops));
3798 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003799 }
3800
Justin Bogner45571362016-05-12 00:31:09 +00003801 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003802}
3803
3804// Lower the write_register intrinsic to ARM specific DAG nodes
3805// using the supplied metadata string to select the instruction node to use
3806// and the registers/masks to use in the nodes
Justin Bogner45571362016-05-12 00:31:09 +00003807bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003808 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3809 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3810 bool IsThumb2 = Subtarget->isThumb2();
3811 SDLoc DL(N);
3812
3813 std::vector<SDValue> Ops;
3814 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3815
3816 if (!Ops.empty()) {
3817 // If the special register string was constructed of fields (as defined
3818 // in the ACLE) then need to lower to MCR node (32 bit) or
3819 // MCRR node(64 bit), we can make the distinction based on the number of
3820 // operands we have.
3821 unsigned Opcode;
3822 if (Ops.size() == 5) {
3823 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
3824 Ops.insert(Ops.begin()+2, N->getOperand(2));
3825 } else {
3826 assert(Ops.size() == 3 &&
3827 "Invalid number of fields in special register string.");
3828 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
3829 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
3830 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
3831 }
3832
3833 Ops.push_back(getAL(CurDAG, DL));
3834 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3835 Ops.push_back(N->getOperand(0));
3836
Justin Bogner45571362016-05-12 00:31:09 +00003837 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
3838 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003839 }
3840
3841 std::string SpecialReg = RegString->getString().lower();
3842 int BankedReg = getBankedRegisterMask(SpecialReg);
3843 if (BankedReg != -1) {
3844 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
3845 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3846 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003847 ReplaceNode(
3848 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
3849 DL, MVT::Other, Ops));
3850 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003851 }
3852
3853 // The VFP registers are written to by creating SelectionDAG nodes with
3854 // opcodes corresponding to the register that is being written. So we switch
3855 // on the string to find which opcode we need to use.
3856 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3857 .Case("fpscr", ARM::VMSR)
3858 .Case("fpexc", ARM::VMSR_FPEXC)
3859 .Case("fpsid", ARM::VMSR_FPSID)
3860 .Case("fpinst", ARM::VMSR_FPINST)
3861 .Case("fpinst2", ARM::VMSR_FPINST2)
3862 .Default(0);
3863
3864 if (Opcode) {
3865 if (!Subtarget->hasVFP2())
Justin Bogner45571362016-05-12 00:31:09 +00003866 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003867 Ops = { N->getOperand(2), getAL(CurDAG, DL),
3868 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003869 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
3870 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003871 }
3872
Bradley Smithf277c8a2016-01-25 11:25:36 +00003873 std::pair<StringRef, StringRef> Fields;
3874 Fields = StringRef(SpecialReg).rsplit('_');
3875 std::string Reg = Fields.first.str();
3876 StringRef Flags = Fields.second;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003877
3878 // If the target was M Class then need to validate the special register value
3879 // and retrieve the mask for use in the instruction node.
3880 if (Subtarget->isMClass()) {
Javed Absar2cb0c952017-07-19 12:57:16 +00003881 int SYSmValue = getMClassRegisterMask(SpecialReg, Subtarget);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003882 if (SYSmValue == -1)
Justin Bogner45571362016-05-12 00:31:09 +00003883 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003884
3885 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
3886 N->getOperand(2), getAL(CurDAG, DL),
3887 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003888 ReplaceNode(N, CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops));
3889 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003890 }
3891
3892 // We then check to see if a valid mask can be constructed for one of the
3893 // register string values permitted for the A and R class cores. These values
3894 // are apsr, spsr and cpsr; these are also valid on older cores.
3895 int Mask = getARClassRegisterMask(Reg, Flags);
3896 if (Mask != -1) {
3897 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
3898 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3899 N->getOperand(0) };
Justin Bogner45571362016-05-12 00:31:09 +00003900 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
3901 DL, MVT::Other, Ops));
3902 return true;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003903 }
3904
Justin Bogner45571362016-05-12 00:31:09 +00003905 return false;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003906}
3907
Justin Bogner45571362016-05-12 00:31:09 +00003908bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){
Weiming Zhaoc5987002013-02-14 18:10:21 +00003909 std::vector<SDValue> AsmNodeOperands;
3910 unsigned Flag, Kind;
3911 bool Changed = false;
3912 unsigned NumOps = N->getNumOperands();
3913
Weiming Zhaoc5987002013-02-14 18:10:21 +00003914 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
3915 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
3916 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
3917 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003918 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
3919 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
3920 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00003921
Andrew Trickef9de2a2013-05-25 02:42:55 +00003922 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00003923 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
3924 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003925
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003926 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003927 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003928 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00003929 SDValue op = N->getOperand(i);
3930 AsmNodeOperands.push_back(op);
3931
3932 if (i < InlineAsm::Op_FirstOperand)
3933 continue;
3934
3935 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
3936 Flag = C->getZExtValue();
3937 Kind = InlineAsm::getKind(Flag);
3938 }
3939 else
3940 continue;
3941
Joey Gouly392cdad2013-07-08 19:52:51 +00003942 // Immediate operands to inline asm in the SelectionDAG are modeled with
3943 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
3944 // the second is a constant with the value of the immediate. If we get here
3945 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00003946 if (Kind == InlineAsm::Kind_Imm) {
3947 SDValue op = N->getOperand(++i);
3948 AsmNodeOperands.push_back(op);
3949 continue;
3950 }
3951
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003952 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
3953 if (NumRegs)
3954 OpChanged.push_back(false);
3955
3956 unsigned DefIdx = 0;
3957 bool IsTiedToChangedOp = false;
3958 // If it's a use that is tied with a previous def, it has no
3959 // reg class constraint.
3960 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
3961 IsTiedToChangedOp = OpChanged[DefIdx];
3962
Diana Picusf345d402016-07-20 09:48:24 +00003963 // Memory operands to inline asm in the SelectionDAG are modeled with two
3964 // operands: a constant of value InlineAsm::Kind_Mem followed by the input
3965 // operand. If we get here and we have a Kind_Mem, skip the next operand (so
3966 // it doesn't get misinterpreted), and continue. We do this here because
3967 // it's important to update the OpChanged array correctly before moving on.
3968 if (Kind == InlineAsm::Kind_Mem) {
3969 SDValue op = N->getOperand(++i);
3970 AsmNodeOperands.push_back(op);
3971 continue;
3972 }
3973
Weiming Zhaoc5987002013-02-14 18:10:21 +00003974 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
3975 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
3976 continue;
3977
Weiming Zhaoc5987002013-02-14 18:10:21 +00003978 unsigned RC;
3979 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003980 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
3981 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00003982 continue;
3983
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003984 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00003985 SDValue V0 = N->getOperand(i+1);
3986 SDValue V1 = N->getOperand(i+2);
3987 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
3988 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
3989 SDValue PairedReg;
3990 MachineRegisterInfo &MRI = MF->getRegInfo();
3991
3992 if (Kind == InlineAsm::Kind_RegDef ||
3993 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
3994 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
3995 // the original GPRs.
3996
3997 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3998 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3999 SDValue Chain = SDValue(N,0);
4000
4001 SDNode *GU = N->getGluedUser();
4002 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
4003 Chain.getValue(1));
4004
4005 // Extract values from a GPRPair reg and copy to the original GPR reg.
4006 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
4007 RegCopy);
4008 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
4009 RegCopy);
4010 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
4011 RegCopy.getValue(1));
4012 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
4013
4014 // Update the original glue user.
4015 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
4016 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00004017 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004018 }
4019 else {
4020 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
4021 // GPRPair and then pass the GPRPair to the inline asm.
4022 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
4023
4024 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
4025 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
4026 Chain.getValue(1));
4027 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
4028 T0.getValue(1));
4029 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
4030
4031 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
4032 // i32 VRs of inline asm with it.
4033 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
4034 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
4035 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
4036
4037 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
4038 Glue = Chain.getValue(1);
4039 }
4040
4041 Changed = true;
4042
4043 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004044 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004045 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00004046 if (IsTiedToChangedOp)
4047 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
4048 else
4049 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004050 // Replace the current flag.
4051 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00004052 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004053 // Add the new register node and skip the original two GPRs.
4054 AsmNodeOperands.push_back(PairedReg);
4055 // Skip the next two GPRs.
4056 i += 2;
4057 }
4058 }
4059
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00004060 if (Glue.getNode())
4061 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004062 if (!Changed)
Justin Bogner45571362016-05-12 00:31:09 +00004063 return false;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004064
Andrew Trickef9de2a2013-05-25 02:42:55 +00004065 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00004066 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00004067 New->setNodeId(-1);
Justin Bogner45571362016-05-12 00:31:09 +00004068 ReplaceNode(N, New.getNode());
4069 return true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00004070}
4071
4072
Bob Wilsona2c462b2009-05-19 05:53:42 +00004073bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00004074SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00004075 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004076 switch(ConstraintID) {
4077 default:
4078 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00004079 case InlineAsm::Constraint_i:
4080 // FIXME: It seems strange that 'i' is needed here since it's supposed to
4081 // be an immediate and not a memory constraint.
Justin Bognerb03fd122016-08-17 05:10:15 +00004082 LLVM_FALLTHROUGH;
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004083 case InlineAsm::Constraint_m:
James Molloy72222f52015-10-26 10:04:52 +00004084 case InlineAsm::Constraint_o:
Daniel Sanders1f58ef72015-06-03 12:33:56 +00004085 case InlineAsm::Constraint_Q:
4086 case InlineAsm::Constraint_Um:
4087 case InlineAsm::Constraint_Un:
4088 case InlineAsm::Constraint_Uq:
4089 case InlineAsm::Constraint_Us:
4090 case InlineAsm::Constraint_Ut:
4091 case InlineAsm::Constraint_Uv:
4092 case InlineAsm::Constraint_Uy:
4093 // Require the address to be in a register. That is safe for all ARM
4094 // variants and it is hard to do anything much smarter without knowing
4095 // how the operand is used.
4096 OutOps.push_back(Op);
4097 return false;
4098 }
4099 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00004100}
4101
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004102/// createARMISelDag - This pass converts a legalized DAG into a
4103/// ARM-specific DAG, ready for instruction scheduling.
4104///
Bob Wilson2dd957f2009-09-28 14:30:20 +00004105FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
4106 CodeGenOpt::Level OptLevel) {
4107 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00004108}