blob: 4cb80da4839a7033c22f906bc77c9811c55b09c8 [file] [log] [blame]
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00001//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattnerf3ebc3f2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the ARM target.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARM.h"
Evan Cheng62c7b5b2010-12-05 22:04:16 +000015#include "ARMBaseInstrInfo.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000016#include "ARMTargetMachine.h"
Evan Chenga20cde32011-07-20 23:34:39 +000017#include "MCTargetDesc/ARMAddressingModes.h"
Luke Cheeseman85fd06d2015-06-01 12:02:47 +000018#include "llvm/ADT/StringSwitch.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000019#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineFunction.h"
21#include "llvm/CodeGen/MachineInstrBuilder.h"
Weiming Zhaoc5987002013-02-14 18:10:21 +000022#include "llvm/CodeGen/MachineRegisterInfo.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000023#include "llvm/CodeGen/SelectionDAG.h"
24#include "llvm/CodeGen/SelectionDAGISel.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000025#include "llvm/IR/CallingConv.h"
26#include "llvm/IR/Constants.h"
27#include "llvm/IR/DerivedTypes.h"
28#include "llvm/IR/Function.h"
29#include "llvm/IR/Intrinsics.h"
30#include "llvm/IR/LLVMContext.h"
Evan Cheng8e6b40a2010-05-04 20:39:49 +000031#include "llvm/Support/CommandLine.h"
Chris Lattner1770fb82008-02-03 05:43:57 +000032#include "llvm/Support/Compiler.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000033#include "llvm/Support/Debug.h"
Torok Edwinfb8d6d52009-07-08 20:53:28 +000034#include "llvm/Support/ErrorHandling.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000035#include "llvm/Target/TargetLowering.h"
36#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
Evan Cheng62c7b5b2010-12-05 22:04:16 +000047static cl::opt<bool>
48CheckVMLxHazard("check-vmlx-hazard", cl::Hidden,
49 cl::desc("Check fp vmla / vmls hazard at isel time"),
Bob Wilson0858c3a2011-04-19 18:11:57 +000050 cl::init(true));
Evan Cheng62c7b5b2010-12-05 22:04:16 +000051
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000052//===--------------------------------------------------------------------===//
53/// ARMDAGToDAGISel - ARM specific code to select ARM machine
54/// instructions for SelectionDAG operations.
55///
56namespace {
Jim Grosbach08605202010-09-29 19:03:54 +000057
58enum AddrMode2Type {
59 AM2_BASE, // Simple AM2 (+-imm12)
60 AM2_SHOP // Shifter-op AM2
61};
62
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000063class ARMDAGToDAGISel : public SelectionDAGISel {
Evan Cheng10043e22007-01-19 07:51:42 +000064 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
65 /// make the right decision when generating code for different targets.
66 const ARMSubtarget *Subtarget;
67
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000068public:
Eric Christopher2f991c92014-07-03 22:24:49 +000069 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, CodeGenOpt::Level OptLevel)
70 : SelectionDAGISel(tm, OptLevel) {}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000071
Eric Christopher0e6e7cf2014-05-22 02:00:27 +000072 bool runOnMachineFunction(MachineFunction &MF) override {
73 // Reset the subtarget each time through.
Eric Christopher22b2ad22015-02-20 08:24:37 +000074 Subtarget = &MF.getSubtarget<ARMSubtarget>();
Eric Christopher0e6e7cf2014-05-22 02:00:27 +000075 SelectionDAGISel::runOnMachineFunction(MF);
76 return true;
77 }
78
Craig Topper6bc27bf2014-03-10 02:09:33 +000079 const char *getPassName() const override {
Evan Cheng10043e22007-01-19 07:51:42 +000080 return "ARM Instruction Selection";
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000081 }
82
Craig Topper6bc27bf2014-03-10 02:09:33 +000083 void PreprocessISelDAG() override;
Evan Chengeae6d2c2012-12-19 20:16:09 +000084
Bob Wilson4facd962009-10-08 18:51:31 +000085 /// getI32Imm - Return a target constant of type i32 with the specified
86 /// value.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +000087 inline SDValue getI32Imm(unsigned Imm, SDLoc dl) {
88 return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000089 }
90
Craig Topper6bc27bf2014-03-10 02:09:33 +000091 SDNode *Select(SDNode *N) override;
Evan Cheng5e73ff22010-02-15 19:41:07 +000092
Evan Cheng62c7b5b2010-12-05 22:04:16 +000093
94 bool hasNoVMLxHazardUse(SDNode *N) const;
Evan Cheng59bbc542010-10-27 23:41:30 +000095 bool isShifterOpProfitable(const SDValue &Shift,
96 ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt);
Owen Andersonb595ed02011-07-21 18:54:16 +000097 bool SelectRegShifterOperand(SDValue N, SDValue &A,
98 SDValue &B, SDValue &C,
99 bool CheckProfitability = true);
100 bool SelectImmShifterOperand(SDValue N, SDValue &A,
Owen Anderson04912702011-07-21 23:38:37 +0000101 SDValue &B, bool CheckProfitability = true);
102 bool SelectShiftRegShifterOperand(SDValue N, SDValue &A,
Owen Anderson6d557452011-03-18 19:46:58 +0000103 SDValue &B, SDValue &C) {
104 // Don't apply the profitability check
Owen Anderson04912702011-07-21 23:38:37 +0000105 return SelectRegShifterOperand(N, A, B, C, false);
106 }
107 bool SelectShiftImmShifterOperand(SDValue N, SDValue &A,
108 SDValue &B) {
109 // Don't apply the profitability check
110 return SelectImmShifterOperand(N, A, B, false);
Owen Anderson6d557452011-03-18 19:46:58 +0000111 }
112
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000113 bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
114 bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);
115
Jim Grosbach08605202010-09-29 19:03:54 +0000116 AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base,
117 SDValue &Offset, SDValue &Opc);
118 bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset,
119 SDValue &Opc) {
120 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE;
121 }
122
123 bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset,
124 SDValue &Opc) {
125 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP;
126 }
127
128 bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset,
129 SDValue &Opc) {
130 SelectAddrMode2Worker(N, Base, Offset, Opc);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000131// return SelectAddrMode2ShOp(N, Base, Offset, Opc);
Jim Grosbach08605202010-09-29 19:03:54 +0000132 // This always matches one way or another.
133 return true;
134 }
135
Tim Northover42180442013-08-22 09:57:11 +0000136 bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) {
137 const ConstantSDNode *CN = cast<ConstantSDNode>(N);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000138 Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32);
Tim Northover42180442013-08-22 09:57:11 +0000139 Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32);
140 return true;
141 }
142
Owen Anderson2aedba62011-07-26 20:54:26 +0000143 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
144 SDValue &Offset, SDValue &Opc);
145 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000146 SDValue &Offset, SDValue &Opc);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000147 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
148 SDValue &Offset, SDValue &Opc);
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000149 bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000150 bool SelectAddrMode3(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000151 SDValue &Offset, SDValue &Opc);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000152 bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000153 SDValue &Offset, SDValue &Opc);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000154 bool SelectAddrMode5(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000155 SDValue &Offset);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000156 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
Bob Wilsone3ecd5f2011-02-25 06:42:42 +0000157 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000158
Evan Chengdfce83c2011-01-17 08:03:18 +0000159 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
Evan Cheng10043e22007-01-19 07:51:42 +0000160
Bill Wendling092a7bd2010-12-14 03:36:38 +0000161 // Thumb Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000162 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
Bill Wendling092a7bd2010-12-14 03:36:38 +0000163 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
164 SDValue &OffImm);
165 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
166 SDValue &OffImm);
167 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
168 SDValue &OffImm);
169 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
170 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000171 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +0000172
Bill Wendling092a7bd2010-12-14 03:36:38 +0000173 // Thumb 2 Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000174 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
175 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000176 SDValue &OffImm);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000177 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +0000178 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000179 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000180 SDValue &OffReg, SDValue &ShImm);
Tim Northovera7ecd242013-07-16 09:46:55 +0000181 bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Chengb23b50d2009-06-29 07:51:04 +0000182
Evan Cheng0fc80842010-11-12 22:42:47 +0000183 inline bool is_so_imm(unsigned Imm) const {
184 return ARM_AM::getSOImmVal(Imm) != -1;
185 }
186
187 inline bool is_so_imm_not(unsigned Imm) const {
188 return ARM_AM::getSOImmVal(~Imm) != -1;
189 }
190
191 inline bool is_t2_so_imm(unsigned Imm) const {
192 return ARM_AM::getT2SOImmVal(Imm) != -1;
193 }
194
195 inline bool is_t2_so_imm_not(unsigned Imm) const {
196 return ARM_AM::getT2SOImmVal(~Imm) != -1;
197 }
198
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000199 // Include the pieces autogenerated from the target description.
200#include "ARMGenDAGISel.inc"
Bob Wilsona2c462b2009-05-19 05:53:42 +0000201
202private:
Evan Cheng84c6cda2009-07-02 07:28:31 +0000203 /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
204 /// ARM.
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000205 SDNode *SelectARMIndexedLoad(SDNode *N);
206 SDNode *SelectT2IndexedLoad(SDNode *N);
Evan Cheng84c6cda2009-07-02 07:28:31 +0000207
Bob Wilson340861d2010-03-23 05:25:43 +0000208 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
209 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson12b47992009-10-14 17:28:52 +0000210 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson340861d2010-03-23 05:25:43 +0000211 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson06fce872011-02-07 17:43:21 +0000212 SDNode *SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000213 const uint16_t *DOpcodes,
214 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilson12b47992009-10-14 17:28:52 +0000215
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000216 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000217 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000218 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000219 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson06fce872011-02-07 17:43:21 +0000220 SDNode *SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000221 const uint16_t *DOpcodes,
222 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000223
Bob Wilson93117bc2009-10-14 16:46:45 +0000224 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilson4145e3a2009-10-14 16:19:03 +0000225 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsond5c57a52010-09-13 23:01:35 +0000226 /// load/store of D registers and Q registers.
Bob Wilson06fce872011-02-07 17:43:21 +0000227 SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad,
228 bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000229 const uint16_t *DOpcodes, const uint16_t *QOpcodes);
Bob Wilson4145e3a2009-10-14 16:19:03 +0000230
Bob Wilson2d790df2010-11-28 06:51:26 +0000231 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
232 /// should be 2, 3 or 4. The opcode array specifies the instructions used
233 /// for loading D registers. (Q registers are not supported.)
Bob Wilson06fce872011-02-07 17:43:21 +0000234 SDNode *SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000235 const uint16_t *Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +0000236
Bob Wilson5bc8a792010-07-07 00:08:54 +0000237 /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2,
238 /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be
239 /// generated to force the table registers to be consecutive.
240 SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc);
Bob Wilson3ed511b2010-07-06 23:36:25 +0000241
Sandeep Patel7460e082009-10-13 20:25:58 +0000242 /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
Jim Grosbach825cb292010-04-22 23:24:18 +0000243 SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000244
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000245 // Select special operations if node forms integer ABS pattern
246 SDNode *SelectABSOp(SDNode *N);
247
Luke Cheeseman85fd06d2015-06-01 12:02:47 +0000248 SDNode *SelectReadRegister(SDNode *N);
249 SDNode *SelectWriteRegister(SDNode *N);
250
Weiming Zhaoc5987002013-02-14 18:10:21 +0000251 SDNode *SelectInlineAsm(SDNode *N);
252
Evan Chengd85631e2010-05-05 18:28:36 +0000253 SDNode *SelectConcatVector(SDNode *N);
254
Evan Chengd9c55362009-07-02 01:23:32 +0000255 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
256 /// inline asm expressions.
Daniel Sanders60f1db02015-03-13 12:45:09 +0000257 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Craig Topper6bc27bf2014-03-10 02:09:33 +0000258 std::vector<SDValue> &OutOps) override;
Bob Wilsone6b778d2009-10-06 22:01:59 +0000259
Weiming Zhao95782222012-11-17 00:23:35 +0000260 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhao8f56f882012-11-16 21:55:34 +0000261 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao95782222012-11-17 00:23:35 +0000262 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
263 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
264 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Chengc2ae5f52010-05-10 17:34:18 +0000265
Bob Wilsond8a9a042010-06-04 00:04:02 +0000266 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +0000267 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
268 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
269 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000270
271 // Get the alignment operand for a NEON VLD or VST instruction.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000272 SDValue GetVLDSTAlign(SDValue Align, SDLoc dl, unsigned NumVecs,
273 bool is64BitVector);
John Brawn056e6782015-09-14 15:19:41 +0000274
275 /// Returns the number of instructions required to materialize the given
276 /// constant in a register, or 3 if a literal pool load is needed.
277 unsigned ConstantMaterializationCost(unsigned Val) const;
278
279 /// Checks if N is a multiplication by a constant where we can extract out a
280 /// power of two from the constant so that it can be used in a shift, but only
281 /// if it simplifies the materialization of the constant. Returns true if it
282 /// is, and assigns to PowerOfTwo the power of two that should be extracted
283 /// out and to NewMulConst the new constant to be multiplied by.
284 bool canExtractShiftFromMul(const SDValue &N, unsigned MaxShift,
285 unsigned &PowerOfTwo, SDValue &NewMulConst) const;
286
287 /// Replace N with M in CurDAG, in a way that also ensures that M gets
288 /// selected when N would have been selected.
289 void replaceDAGValue(const SDValue &N, SDValue M);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000290};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000291}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000292
Sandeep Patel423e42b2009-10-13 18:59:48 +0000293/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
294/// operand. If so Imm will receive the 32-bit value.
295static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
296 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
297 Imm = cast<ConstantSDNode>(N)->getZExtValue();
298 return true;
299 }
300 return false;
301}
302
303// isInt32Immediate - This method tests to see if a constant operand.
304// If so Imm will receive the 32 bit value.
305static bool isInt32Immediate(SDValue N, unsigned &Imm) {
306 return isInt32Immediate(N.getNode(), Imm);
307}
308
309// isOpcWithIntImmediate - This method tests to see if the node is a specific
310// opcode and that it has a immediate integer right operand.
311// If so Imm will receive the 32 bit value.
312static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
313 return N->getOpcode() == Opc &&
314 isInt32Immediate(N->getOperand(1).getNode(), Imm);
315}
316
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000317/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000318/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000319///
320/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000321static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000322 int RangeMin, int RangeMax,
323 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000324 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000325
326 // Check that this is a constant.
327 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
328 if (!C)
329 return false;
330
331 ScaledConstant = (int) C->getZExtValue();
332 if ((ScaledConstant % Scale) != 0)
333 return false;
334
335 ScaledConstant /= Scale;
336 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
337}
338
Evan Chengeae6d2c2012-12-19 20:16:09 +0000339void ARMDAGToDAGISel::PreprocessISelDAG() {
340 if (!Subtarget->hasV6T2Ops())
341 return;
342
343 bool isThumb2 = Subtarget->isThumb();
344 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
345 E = CurDAG->allnodes_end(); I != E; ) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000346 SDNode *N = &*I++; // Preincrement iterator to avoid invalidation issues.
Evan Chengeae6d2c2012-12-19 20:16:09 +0000347
348 if (N->getOpcode() != ISD::ADD)
349 continue;
350
351 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
352 // leading zeros, followed by consecutive set bits, followed by 1 or 2
353 // trailing zeros, e.g. 1020.
354 // Transform the expression to
355 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
356 // of trailing zeros of c2. The left shift would be folded as an shifter
357 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
358 // node (UBFX).
359
360 SDValue N0 = N->getOperand(0);
361 SDValue N1 = N->getOperand(1);
362 unsigned And_imm = 0;
363 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
364 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
365 std::swap(N0, N1);
366 }
367 if (!And_imm)
368 continue;
369
370 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000371 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000372 if (TZ != 1 && TZ != 2)
373 // Be conservative here. Shifter operands aren't always free. e.g. On
374 // Swift, left shifter operand of 1 / 2 for free but others are not.
375 // e.g.
376 // ubfx r3, r1, #16, #8
377 // ldr.w r3, [r0, r3, lsl #2]
378 // vs.
379 // mov.w r9, #1020
380 // and.w r2, r9, r1, lsr #14
381 // ldr r2, [r0, r2]
382 continue;
383 And_imm >>= TZ;
384 if (And_imm & (And_imm + 1))
385 continue;
386
387 // Look for (and (srl X, c1), c2).
388 SDValue Srl = N1.getOperand(0);
389 unsigned Srl_imm = 0;
390 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
391 (Srl_imm <= 2))
392 continue;
393
394 // Make sure first operand is not a shifter operand which would prevent
395 // folding of the left shift.
396 SDValue CPTmp0;
397 SDValue CPTmp1;
398 SDValue CPTmp2;
399 if (isThumb2) {
John Brawnd8b405a2015-09-07 11:45:18 +0000400 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1))
Evan Chengeae6d2c2012-12-19 20:16:09 +0000401 continue;
402 } else {
403 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
404 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
405 continue;
406 }
407
408 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000409 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000410 Srl.getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000411 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl),
412 MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000413 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000414 Srl,
415 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000416 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000417 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32));
Evan Chengeae6d2c2012-12-19 20:16:09 +0000418 CurDAG->UpdateNodeOperands(N, N0, N1);
Jim Grosbach1a597112014-04-03 23:43:18 +0000419 }
Evan Chengeae6d2c2012-12-19 20:16:09 +0000420}
421
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000422/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
423/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
424/// least on current ARM implementations) which should be avoidded.
425bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
426 if (OptLevel == CodeGenOpt::None)
427 return true;
428
429 if (!CheckVMLxHazard)
430 return true;
Bob Wilsone8a549c2012-09-29 21:43:49 +0000431
Tim Northover0feb91e2014-04-01 14:10:07 +0000432 if (!Subtarget->isCortexA7() && !Subtarget->isCortexA8() &&
433 !Subtarget->isCortexA9() && !Subtarget->isSwift())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000434 return true;
435
436 if (!N->hasOneUse())
437 return false;
438
439 SDNode *Use = *N->use_begin();
440 if (Use->getOpcode() == ISD::CopyToReg)
441 return true;
442 if (Use->isMachineOpcode()) {
Eric Christopher2f991c92014-07-03 22:24:49 +0000443 const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>(
Eric Christopherfc6de422014-08-05 02:39:49 +0000444 CurDAG->getSubtarget().getInstrInfo());
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000445
Evan Cheng6cc775f2011-06-28 19:10:37 +0000446 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
447 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000448 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000449 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000450 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
451 return true;
452 // vmlx feeding into another vmlx. We actually want to unfold
453 // the use later in the MLxExpansion pass. e.g.
454 // vmla
455 // vmla (stall 8 cycles)
456 //
457 // vmul (5 cycles)
458 // vadd (5 cycles)
459 // vmla
460 // This adds up to about 18 - 19 cycles.
461 //
462 // vmla
463 // vmul (stall 4 cycles)
464 // vadd adds up to about 14 cycles.
465 return TII->isFpMLxInstruction(Opcode);
466 }
467
468 return false;
469}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000470
Evan Cheng59bbc542010-10-27 23:41:30 +0000471bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
472 ARM_AM::ShiftOpc ShOpcVal,
473 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000474 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000475 return true;
476 if (Shift.hasOneUse())
477 return true;
478 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000479 return ShOpcVal == ARM_AM::lsl &&
480 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000481}
482
John Brawn056e6782015-09-14 15:19:41 +0000483unsigned ARMDAGToDAGISel::ConstantMaterializationCost(unsigned Val) const {
484 if (Subtarget->isThumb()) {
485 if (Val <= 255) return 1; // MOV
486 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
487 if (~Val <= 255) return 2; // MOV + MVN
488 if (ARM_AM::isThumbImmShiftedVal(Val)) return 2; // MOV + LSL
489 } else {
490 if (ARM_AM::getSOImmVal(Val) != -1) return 1; // MOV
491 if (ARM_AM::getSOImmVal(~Val) != -1) return 1; // MVN
492 if (Subtarget->hasV6T2Ops() && Val <= 0xffff) return 1; // MOVW
493 if (ARM_AM::isSOImmTwoPartVal(Val)) return 2; // two instrs
494 }
495 if (Subtarget->useMovt(*MF)) return 2; // MOVW + MOVT
496 return 3; // Literal pool load
497}
498
499bool ARMDAGToDAGISel::canExtractShiftFromMul(const SDValue &N,
500 unsigned MaxShift,
501 unsigned &PowerOfTwo,
502 SDValue &NewMulConst) const {
503 assert(N.getOpcode() == ISD::MUL);
504 assert(MaxShift > 0);
505
506 // If the multiply is used in more than one place then changing the constant
507 // will make other uses incorrect, so don't.
508 if (!N.hasOneUse()) return false;
509 // Check if the multiply is by a constant
510 ConstantSDNode *MulConst = dyn_cast<ConstantSDNode>(N.getOperand(1));
511 if (!MulConst) return false;
512 // If the constant is used in more than one place then modifying it will mean
513 // we need to materialize two constants instead of one, which is a bad idea.
514 if (!MulConst->hasOneUse()) return false;
515 unsigned MulConstVal = MulConst->getZExtValue();
516 if (MulConstVal == 0) return false;
517
518 // Find the largest power of 2 that MulConstVal is a multiple of
519 PowerOfTwo = MaxShift;
520 while ((MulConstVal % (1 << PowerOfTwo)) != 0) {
521 --PowerOfTwo;
522 if (PowerOfTwo == 0) return false;
523 }
524
525 // Only optimise if the new cost is better
526 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo);
527 NewMulConst = CurDAG->getConstant(NewMulConstVal, SDLoc(N), MVT::i32);
528 unsigned OldCost = ConstantMaterializationCost(MulConstVal);
529 unsigned NewCost = ConstantMaterializationCost(NewMulConstVal);
530 return NewCost < OldCost;
531}
532
533void ARMDAGToDAGISel::replaceDAGValue(const SDValue &N, SDValue M) {
Duncan P. N. Exon Smith9f9559e2015-10-19 23:25:57 +0000534 CurDAG->RepositionNode(N.getNode()->getIterator(), M.getNode());
John Brawn056e6782015-09-14 15:19:41 +0000535 CurDAG->ReplaceAllUsesWith(N, M);
536}
537
Owen Andersonb595ed02011-07-21 18:54:16 +0000538bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000539 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000540 SDValue &Opc,
541 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000542 if (DisableShifterOp)
543 return false;
544
John Brawn056e6782015-09-14 15:19:41 +0000545 // If N is a multiply-by-constant and it's profitable to extract a shift and
546 // use it in a shifted operand do so.
547 if (N.getOpcode() == ISD::MUL) {
548 unsigned PowerOfTwo = 0;
549 SDValue NewMulConst;
550 if (canExtractShiftFromMul(N, 31, PowerOfTwo, NewMulConst)) {
Tim Northoverd91d6352015-12-09 15:54:50 +0000551 BaseReg = SDValue(Select(CurDAG->getNode(ISD::MUL, SDLoc(N), MVT::i32,
552 N.getOperand(0), NewMulConst)
553 .getNode()),
554 0);
John Brawn056e6782015-09-14 15:19:41 +0000555 replaceDAGValue(N.getOperand(1), NewMulConst);
John Brawn056e6782015-09-14 15:19:41 +0000556 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ARM_AM::lsl,
557 PowerOfTwo),
558 SDLoc(N), MVT::i32);
559 return true;
560 }
561 }
562
Evan Chenga20cde32011-07-20 23:34:39 +0000563 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000564
565 // Don't match base register only case. That is matched to a separate
566 // lower complexity pattern with explicit register operand.
567 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000568
Evan Chengb23b50d2009-06-29 07:51:04 +0000569 BaseReg = N.getOperand(0);
570 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000571 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
572 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000573 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000574 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000575 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000576 return true;
577}
578
Owen Andersonb595ed02011-07-21 18:54:16 +0000579bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
580 SDValue &BaseReg,
581 SDValue &ShReg,
582 SDValue &Opc,
583 bool CheckProfitability) {
584 if (DisableShifterOp)
585 return false;
586
587 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
588
589 // Don't match base register only case. That is matched to a separate
590 // lower complexity pattern with explicit register operand.
591 if (ShOpcVal == ARM_AM::no_shift) return false;
592
593 BaseReg = N.getOperand(0);
594 unsigned ShImmVal = 0;
595 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
596 if (RHS) return false;
597
598 ShReg = N.getOperand(1);
599 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
600 return false;
601 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000602 SDLoc(N), MVT::i32);
Owen Andersonb595ed02011-07-21 18:54:16 +0000603 return true;
604}
605
606
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000607bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
608 SDValue &Base,
609 SDValue &OffImm) {
610 // Match simple R + imm12 operands.
611
612 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000613 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
614 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000615 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000616 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000617 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000618 Base = CurDAG->getTargetFrameIndex(
619 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000620 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000621 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000622 }
Owen Anderson6d557452011-03-18 19:46:58 +0000623
Chris Lattner46c01a32011-02-13 22:25:43 +0000624 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000625 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
626 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000627 Base = N.getOperand(0);
628 } else
629 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000630 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000631 return true;
632 }
633
634 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Renato Golin63e27982014-09-09 09:57:59 +0000635 int RHSC = (int)RHS->getSExtValue();
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000636 if (N.getOpcode() == ISD::SUB)
637 RHSC = -RHSC;
638
Renato Golin63e27982014-09-09 09:57:59 +0000639 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000640 Base = N.getOperand(0);
641 if (Base.getOpcode() == ISD::FrameIndex) {
642 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000643 Base = CurDAG->getTargetFrameIndex(
644 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000645 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000646 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000647 return true;
648 }
649 }
650
651 // Base only.
652 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000653 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000654 return true;
655}
656
657
658
659bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
660 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000661 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000662 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000663 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
664 // X * [3,5,9] -> X + X * [2,4,8] etc.
665 int RHSC = (int)RHS->getZExtValue();
666 if (RHSC & 1) {
667 RHSC = RHSC & ~1;
668 ARM_AM::AddrOpc AddSub = ARM_AM::add;
669 if (RHSC < 0) {
670 AddSub = ARM_AM::sub;
671 RHSC = - RHSC;
672 }
673 if (isPowerOf2_32(RHSC)) {
674 unsigned ShAmt = Log2_32(RHSC);
675 Base = Offset = N.getOperand(0);
676 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
677 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000678 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000679 return true;
680 }
681 }
682 }
683 }
684
Chris Lattner46c01a32011-02-13 22:25:43 +0000685 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
686 // ISD::OR that is equivalent to an ISD::ADD.
687 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000688 return false;
689
690 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000691 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000692 int RHSC;
693 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
694 -0x1000+1, 0x1000, RHSC)) // 12 bits.
695 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000696 }
697
698 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000699 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000700 ARM_AM::ShiftOpc ShOpcVal =
701 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000702 unsigned ShAmt = 0;
703
704 Base = N.getOperand(0);
705 Offset = N.getOperand(1);
706
707 if (ShOpcVal != ARM_AM::no_shift) {
708 // Check to see if the RHS of the shift is a constant, if not, we can't fold
709 // it.
710 if (ConstantSDNode *Sh =
711 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
712 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000713 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
714 Offset = N.getOperand(1).getOperand(0);
715 else {
716 ShAmt = 0;
717 ShOpcVal = ARM_AM::no_shift;
718 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000719 } else {
720 ShOpcVal = ARM_AM::no_shift;
721 }
722 }
723
724 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000725 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000726 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
727 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000728 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000729 if (ShOpcVal != ARM_AM::no_shift) {
730 // Check to see if the RHS of the shift is a constant, if not, we can't
731 // fold it.
732 if (ConstantSDNode *Sh =
733 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
734 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000735 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000736 Offset = N.getOperand(0).getOperand(0);
737 Base = N.getOperand(1);
738 } else {
739 ShAmt = 0;
740 ShOpcVal = ARM_AM::no_shift;
741 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000742 } else {
743 ShOpcVal = ARM_AM::no_shift;
744 }
745 }
746 }
747
John Brawn056e6782015-09-14 15:19:41 +0000748 // If Offset is a multiply-by-constant and it's profitable to extract a shift
749 // and use it in a shifted operand do so.
750 if (Offset.getOpcode() == ISD::MUL) {
751 unsigned PowerOfTwo = 0;
752 SDValue NewMulConst;
753 if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) {
754 replaceDAGValue(Offset.getOperand(1), NewMulConst);
755 ShAmt = PowerOfTwo;
756 ShOpcVal = ARM_AM::lsl;
757 }
758 }
759
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000760 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000761 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000762 return true;
763}
764
765
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000766//-----
767
Jim Grosbach08605202010-09-29 19:03:54 +0000768AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
769 SDValue &Base,
770 SDValue &Offset,
771 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000772 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000773 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000774 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
775 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmaneffb8942008-09-12 16:56:44 +0000776 int RHSC = (int)RHS->getZExtValue();
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000777 if (RHSC & 1) {
778 RHSC = RHSC & ~1;
779 ARM_AM::AddrOpc AddSub = ARM_AM::add;
780 if (RHSC < 0) {
781 AddSub = ARM_AM::sub;
782 RHSC = - RHSC;
783 }
784 if (isPowerOf2_32(RHSC)) {
785 unsigned ShAmt = Log2_32(RHSC);
786 Base = Offset = N.getOperand(0);
787 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
788 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000789 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000790 return AM2_SHOP;
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000791 }
792 }
793 }
794 }
795
Chris Lattner46c01a32011-02-13 22:25:43 +0000796 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
797 // ISD::OR that is equivalent to an ADD.
798 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000799 Base = N;
800 if (N.getOpcode() == ISD::FrameIndex) {
801 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000802 Base = CurDAG->getTargetFrameIndex(
803 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +0000804 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +0000805 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
806 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000807 Base = N.getOperand(0);
808 }
Owen Anderson9f944592009-08-11 20:47:22 +0000809 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000810 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
811 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000812 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000813 return AM2_BASE;
Rafael Espindola708cb602006-11-08 17:07:32 +0000814 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000815
Evan Cheng10043e22007-01-19 07:51:42 +0000816 // Match simple R +/- imm12 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +0000817 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000818 int RHSC;
819 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
820 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
821 Base = N.getOperand(0);
822 if (Base.getOpcode() == ISD::FrameIndex) {
823 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000824 Base = CurDAG->getTargetFrameIndex(
825 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Rafael Espindola708cb602006-11-08 17:07:32 +0000826 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000827 Offset = CurDAG->getRegister(0, MVT::i32);
828
829 ARM_AM::AddrOpc AddSub = ARM_AM::add;
830 if (RHSC < 0) {
831 AddSub = ARM_AM::sub;
832 RHSC = - RHSC;
833 }
834 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
835 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000836 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000837 return AM2_BASE;
Evan Cheng10043e22007-01-19 07:51:42 +0000838 }
Jim Grosbachc7b10f32010-09-29 17:32:29 +0000839 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000840
Bob Wilsone8a549c2012-09-29 21:43:49 +0000841 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000842 // Compute R +/- (R << N) and reuse it.
843 Base = N;
844 Offset = CurDAG->getRegister(0, MVT::i32);
845 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
846 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000847 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000848 return AM2_BASE;
849 }
850
Johnny Chenb678a562009-10-27 17:25:15 +0000851 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000852 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chenga20cde32011-07-20 23:34:39 +0000853 ARM_AM::ShiftOpc ShOpcVal =
854 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000855 unsigned ShAmt = 0;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000856
Evan Cheng10043e22007-01-19 07:51:42 +0000857 Base = N.getOperand(0);
858 Offset = N.getOperand(1);
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000859
Evan Cheng10043e22007-01-19 07:51:42 +0000860 if (ShOpcVal != ARM_AM::no_shift) {
861 // Check to see if the RHS of the shift is a constant, if not, we can't fold
862 // it.
863 if (ConstantSDNode *Sh =
864 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000865 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000866 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
867 Offset = N.getOperand(1).getOperand(0);
868 else {
869 ShAmt = 0;
870 ShOpcVal = ARM_AM::no_shift;
871 }
Evan Cheng10043e22007-01-19 07:51:42 +0000872 } else {
873 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola708cb602006-11-08 17:07:32 +0000874 }
875 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000876
Evan Cheng10043e22007-01-19 07:51:42 +0000877 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000878 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000879 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
880 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000881 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000882 if (ShOpcVal != ARM_AM::no_shift) {
883 // Check to see if the RHS of the shift is a constant, if not, we can't
884 // fold it.
885 if (ConstantSDNode *Sh =
886 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000887 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000888 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000889 Offset = N.getOperand(0).getOperand(0);
890 Base = N.getOperand(1);
891 } else {
892 ShAmt = 0;
893 ShOpcVal = ARM_AM::no_shift;
894 }
Evan Cheng10043e22007-01-19 07:51:42 +0000895 } else {
896 ShOpcVal = ARM_AM::no_shift;
897 }
898 }
899 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000900
Evan Cheng10043e22007-01-19 07:51:42 +0000901 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000902 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000903 return AM2_SHOP;
Rafael Espindola708cb602006-11-08 17:07:32 +0000904}
905
Owen Anderson2aedba62011-07-26 20:54:26 +0000906bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000907 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000908 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000909 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
910 ? cast<LoadSDNode>(Op)->getAddressingMode()
911 : cast<StoreSDNode>(Op)->getAddressingMode();
912 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
913 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000914 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000915 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
916 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000917
918 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000919 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000920 unsigned ShAmt = 0;
921 if (ShOpcVal != ARM_AM::no_shift) {
922 // Check to see if the RHS of the shift is a constant, if not, we can't fold
923 // it.
924 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000925 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000926 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
927 Offset = N.getOperand(0);
928 else {
929 ShAmt = 0;
930 ShOpcVal = ARM_AM::no_shift;
931 }
Evan Cheng10043e22007-01-19 07:51:42 +0000932 } else {
933 ShOpcVal = ARM_AM::no_shift;
934 }
935 }
936
937 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000938 SDLoc(N), MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000939 return true;
940}
941
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000942bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
943 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000944 unsigned Opcode = Op->getOpcode();
945 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
946 ? cast<LoadSDNode>(Op)->getAddressingMode()
947 : cast<StoreSDNode>(Op)->getAddressingMode();
948 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
949 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000950 int Val;
951 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000952 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000953 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000954 Opc = CurDAG->getTargetConstant(Val, SDLoc(Op), MVT::i32);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000955 return true;
956 }
957
958 return false;
959}
960
961
Owen Anderson2aedba62011-07-26 20:54:26 +0000962bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
963 SDValue &Offset, SDValue &Opc) {
964 unsigned Opcode = Op->getOpcode();
965 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
966 ? cast<LoadSDNode>(Op)->getAddressingMode()
967 : cast<StoreSDNode>(Op)->getAddressingMode();
968 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
969 ? ARM_AM::add : ARM_AM::sub;
970 int Val;
971 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
972 Offset = CurDAG->getRegister(0, MVT::i32);
973 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
974 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000975 SDLoc(Op), MVT::i32);
Owen Anderson2aedba62011-07-26 20:54:26 +0000976 return true;
977 }
978
979 return false;
980}
981
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000982bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
983 Base = N;
984 return true;
985}
Evan Cheng10043e22007-01-19 07:51:42 +0000986
Chris Lattner0e023ea2010-09-21 20:31:19 +0000987bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000988 SDValue &Base, SDValue &Offset,
989 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000990 if (N.getOpcode() == ISD::SUB) {
991 // X - C is canonicalize to X + -C, no need to handle it here.
992 Base = N.getOperand(0);
993 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000994 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0), SDLoc(N),
995 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000996 return true;
997 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000998
Chris Lattner46c01a32011-02-13 22:25:43 +0000999 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +00001000 Base = N;
1001 if (N.getOpcode() == ISD::FrameIndex) {
1002 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001003 Base = CurDAG->getTargetFrameIndex(
1004 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001005 }
Owen Anderson9f944592009-08-11 20:47:22 +00001006 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001007 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1008 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001009 return true;
1010 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001011
Evan Cheng10043e22007-01-19 07:51:42 +00001012 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001013 int RHSC;
1014 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
1015 -256 + 1, 256, RHSC)) { // 8 bits.
1016 Base = N.getOperand(0);
1017 if (Base.getOpcode() == ISD::FrameIndex) {
1018 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001019 Base = CurDAG->getTargetFrameIndex(
1020 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001021 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001022 Offset = CurDAG->getRegister(0, MVT::i32);
1023
1024 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1025 if (RHSC < 0) {
1026 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001027 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001028 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001029 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC), SDLoc(N),
1030 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001031 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001032 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001033
Evan Cheng10043e22007-01-19 07:51:42 +00001034 Base = N.getOperand(0);
1035 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001036 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
1037 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001038 return true;
1039}
1040
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001041bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001042 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001043 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +00001044 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1045 ? cast<LoadSDNode>(Op)->getAddressingMode()
1046 : cast<StoreSDNode>(Op)->getAddressingMode();
1047 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
1048 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001049 int Val;
1050 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
1051 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001052 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), SDLoc(Op),
1053 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001054 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001055 }
1056
1057 Offset = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001058 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), SDLoc(Op),
1059 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001060 return true;
1061}
1062
Jim Grosbachd37f0712010-10-21 19:38:40 +00001063bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001064 SDValue &Base, SDValue &Offset) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001065 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +00001066 Base = N;
1067 if (N.getOpcode() == ISD::FrameIndex) {
1068 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001069 Base = CurDAG->getTargetFrameIndex(
1070 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Anton Korobeynikov25229082009-11-24 00:44:37 +00001071 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001072 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
1073 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +00001074 Base = N.getOperand(0);
1075 }
1076 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001077 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001078 return true;
1079 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001080
Evan Cheng10043e22007-01-19 07:51:42 +00001081 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001082 int RHSC;
1083 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
1084 -256 + 1, 256, RHSC)) {
1085 Base = N.getOperand(0);
1086 if (Base.getOpcode() == ISD::FrameIndex) {
1087 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001088 Base = CurDAG->getTargetFrameIndex(
1089 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng10043e22007-01-19 07:51:42 +00001090 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001091
1092 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1093 if (RHSC < 0) {
1094 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +00001095 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001096 }
1097 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001098 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001099 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001100 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001101
Evan Cheng10043e22007-01-19 07:51:42 +00001102 Base = N;
1103 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001104 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001105 return true;
1106}
1107
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001108bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
1109 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +00001110 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001111
1112 unsigned Alignment = 0;
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001113
1114 MemSDNode *MemN = cast<MemSDNode>(Parent);
1115
1116 if (isa<LSBaseSDNode>(MemN) ||
1117 ((MemN->getOpcode() == ARMISD::VST1_UPD ||
1118 MemN->getOpcode() == ARMISD::VLD1_UPD) &&
1119 MemN->getConstantOperandVal(MemN->getNumOperands() - 1) == 1)) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001120 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
1121 // The maximum alignment is equal to the memory size being referenced.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001122 unsigned MMOAlign = MemN->getAlignment();
1123 unsigned MemSize = MemN->getMemoryVT().getSizeInBits() / 8;
1124 if (MMOAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001125 Alignment = MemSize;
1126 } else {
1127 // All other uses of addrmode6 are for intrinsics. For now just record
1128 // the raw alignment value; it will be refined later based on the legal
1129 // alignment operands for the intrinsic.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001130 Alignment = MemN->getAlignment();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001131 }
1132
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001133 Align = CurDAG->getTargetConstant(Alignment, SDLoc(N), MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001134 return true;
1135}
1136
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001137bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1138 SDValue &Offset) {
1139 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1140 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1141 if (AM != ISD::POST_INC)
1142 return false;
1143 Offset = N;
1144 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1145 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1146 Offset = CurDAG->getRegister(0, MVT::i32);
1147 }
1148 return true;
1149}
1150
Chris Lattner0e023ea2010-09-21 20:31:19 +00001151bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001152 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001153 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1154 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001155 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001156 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001157 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001158 return true;
1159 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001160
Evan Cheng10043e22007-01-19 07:51:42 +00001161 return false;
1162}
1163
Bill Wendling092a7bd2010-12-14 03:36:38 +00001164
1165//===----------------------------------------------------------------------===//
1166// Thumb Addressing Modes
1167//===----------------------------------------------------------------------===//
1168
Chris Lattner0e023ea2010-09-21 20:31:19 +00001169bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001170 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001171 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001172 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001173 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001174 return false;
1175
1176 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001177 return true;
1178 }
1179
Evan Cheng10043e22007-01-19 07:51:42 +00001180 Base = N.getOperand(0);
1181 Offset = N.getOperand(1);
1182 return true;
1183}
1184
Evan Cheng139edae2007-01-24 02:21:22 +00001185bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001186ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1187 SDValue &Base, SDValue &OffImm) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001188 if (!CurDAG->isBaseWithConstantOffset(N)) {
John Brawn68acdcb2015-08-13 10:48:22 +00001189 if (N.getOpcode() == ISD::ADD) {
1190 return false; // We want to select register offset instead
1191 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001192 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
1193 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001194 Base = N.getOperand(0);
1195 } else {
1196 Base = N;
1197 }
1198
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001199 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001200 return true;
1201 }
1202
Evan Cheng10043e22007-01-19 07:51:42 +00001203 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001204 int RHSC;
1205 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1206 Base = N.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001207 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001208 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001209 }
1210
John Brawn68acdcb2015-08-13 10:48:22 +00001211 // Offset is too large, so use register offset instead.
1212 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001213}
1214
Bill Wendling092a7bd2010-12-14 03:36:38 +00001215bool
1216ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1217 SDValue &OffImm) {
1218 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001219}
1220
Bill Wendling092a7bd2010-12-14 03:36:38 +00001221bool
1222ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1223 SDValue &OffImm) {
1224 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001225}
1226
Bill Wendling092a7bd2010-12-14 03:36:38 +00001227bool
1228ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1229 SDValue &OffImm) {
1230 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001231}
1232
Chris Lattner0e023ea2010-09-21 20:31:19 +00001233bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1234 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001235 if (N.getOpcode() == ISD::FrameIndex) {
1236 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001237 // Only multiples of 4 are allowed for the offset, so the frame object
1238 // alignment must be at least 4.
1239 MachineFrameInfo *MFI = MF->getFrameInfo();
1240 if (MFI->getObjectAlignment(FI) < 4)
1241 MFI->setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001242 Base = CurDAG->getTargetFrameIndex(
1243 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001244 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001245 return true;
1246 }
Evan Cheng139edae2007-01-24 02:21:22 +00001247
Chris Lattner46c01a32011-02-13 22:25:43 +00001248 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001249 return false;
1250
1251 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001252 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1253 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001254 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001255 int RHSC;
1256 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1257 Base = N.getOperand(0);
1258 if (Base.getOpcode() == ISD::FrameIndex) {
1259 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001260 // For LHS+RHS to result in an offset that's a multiple of 4 the object
1261 // indexed by the LHS must be 4-byte aligned.
1262 MachineFrameInfo *MFI = MF->getFrameInfo();
1263 if (MFI->getObjectAlignment(FI) < 4)
1264 MFI->setObjectAlignment(FI, 4);
Mehdi Amini44ede332015-07-09 02:09:04 +00001265 Base = CurDAG->getTargetFrameIndex(
1266 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng139edae2007-01-24 02:21:22 +00001267 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001268 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001269 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001270 }
1271 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001272
Evan Cheng10043e22007-01-19 07:51:42 +00001273 return false;
1274}
1275
Bill Wendling092a7bd2010-12-14 03:36:38 +00001276
1277//===----------------------------------------------------------------------===//
1278// Thumb 2 Addressing Modes
1279//===----------------------------------------------------------------------===//
1280
1281
Chris Lattner0e023ea2010-09-21 20:31:19 +00001282bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001283 SDValue &Base, SDValue &OffImm) {
1284 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001285
Evan Cheng36064672009-08-11 08:52:18 +00001286 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001287 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1288 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001289 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001290 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001291 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001292 Base = CurDAG->getTargetFrameIndex(
1293 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001294 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001295 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001296 }
Owen Anderson6d557452011-03-18 19:46:58 +00001297
Chris Lattner46c01a32011-02-13 22:25:43 +00001298 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northoverbd41cf82016-01-07 09:03:03 +00001299 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
1300 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
Evan Cheng36064672009-08-11 08:52:18 +00001301 Base = N.getOperand(0);
1302 if (Base.getOpcode() == ISD::TargetConstantPool)
1303 return false; // We want to select t2LDRpci instead.
1304 } else
1305 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001306 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001307 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001308 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001309
1310 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001311 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001312 // Let t2LDRi8 handle (R - imm8).
1313 return false;
1314
Evan Chengb23b50d2009-06-29 07:51:04 +00001315 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001316 if (N.getOpcode() == ISD::SUB)
1317 RHSC = -RHSC;
1318
1319 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001320 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001321 if (Base.getOpcode() == ISD::FrameIndex) {
1322 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001323 Base = CurDAG->getTargetFrameIndex(
1324 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin79c079b2009-07-30 18:56:48 +00001325 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001326 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001327 return true;
1328 }
1329 }
1330
Evan Cheng36064672009-08-11 08:52:18 +00001331 // Base only.
1332 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001333 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001334 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001335}
1336
Chris Lattner0e023ea2010-09-21 20:31:19 +00001337bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001338 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001339 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001340 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1341 !CurDAG->isBaseWithConstantOffset(N))
1342 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001343
Chris Lattner46c01a32011-02-13 22:25:43 +00001344 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1345 int RHSC = (int)RHS->getSExtValue();
1346 if (N.getOpcode() == ISD::SUB)
1347 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001348
Chris Lattner46c01a32011-02-13 22:25:43 +00001349 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1350 Base = N.getOperand(0);
1351 if (Base.getOpcode() == ISD::FrameIndex) {
1352 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001353 Base = CurDAG->getTargetFrameIndex(
1354 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Chengb23b50d2009-06-29 07:51:04 +00001355 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001356 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Chris Lattner46c01a32011-02-13 22:25:43 +00001357 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001358 }
1359 }
1360
1361 return false;
1362}
1363
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001364bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001365 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001366 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001367 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1368 ? cast<LoadSDNode>(Op)->getAddressingMode()
1369 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001370 int RHSC;
1371 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1372 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001373 ? CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32)
1374 : CurDAG->getTargetConstant(-RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001375 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001376 }
1377
1378 return false;
1379}
1380
Chris Lattner0e023ea2010-09-21 20:31:19 +00001381bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001382 SDValue &Base,
1383 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001384 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001385 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001386 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001387
Evan Cheng36064672009-08-11 08:52:18 +00001388 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1389 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1390 int RHSC = (int)RHS->getZExtValue();
1391 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1392 return false;
1393 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001394 return false;
1395 }
1396
Evan Chengb23b50d2009-06-29 07:51:04 +00001397 // Look for (R + R) or (R + (R << [1,2,3])).
1398 unsigned ShAmt = 0;
1399 Base = N.getOperand(0);
1400 OffReg = N.getOperand(1);
1401
1402 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001403 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001404 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001405 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001406 if (ShOpcVal == ARM_AM::lsl)
1407 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001408 }
1409
Evan Chengb23b50d2009-06-29 07:51:04 +00001410 if (ShOpcVal == ARM_AM::lsl) {
1411 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1412 // it.
1413 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1414 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001415 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1416 OffReg = OffReg.getOperand(0);
1417 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001418 ShAmt = 0;
Evan Cheng59bbc542010-10-27 23:41:30 +00001419 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001420 }
David Goodwinf3912052009-07-15 15:50:19 +00001421 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001422
John Brawn056e6782015-09-14 15:19:41 +00001423 // If OffReg is a multiply-by-constant and it's profitable to extract a shift
1424 // and use it in a shifted operand do so.
1425 if (OffReg.getOpcode() == ISD::MUL) {
1426 unsigned PowerOfTwo = 0;
1427 SDValue NewMulConst;
1428 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) {
1429 replaceDAGValue(OffReg.getOperand(1), NewMulConst);
1430 ShAmt = PowerOfTwo;
1431 }
1432 }
1433
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001434 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001435
1436 return true;
1437}
1438
Tim Northovera7ecd242013-07-16 09:46:55 +00001439bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1440 SDValue &OffImm) {
Alp Tokercb402912014-01-24 17:20:08 +00001441 // This *must* succeed since it's used for the irreplaceable ldrex and strex
Tim Northovera7ecd242013-07-16 09:46:55 +00001442 // instructions.
1443 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001444 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001445
1446 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1447 return true;
1448
1449 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1450 if (!RHS)
1451 return true;
1452
1453 uint32_t RHSC = (int)RHS->getZExtValue();
1454 if (RHSC > 1020 || RHSC % 4 != 0)
1455 return true;
1456
1457 Base = N.getOperand(0);
1458 if (Base.getOpcode() == ISD::FrameIndex) {
1459 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00001460 Base = CurDAG->getTargetFrameIndex(
1461 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
Tim Northovera7ecd242013-07-16 09:46:55 +00001462 }
1463
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001464 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001465 return true;
1466}
1467
Evan Chengb23b50d2009-06-29 07:51:04 +00001468//===--------------------------------------------------------------------===//
1469
Evan Cheng7e90b112007-07-05 07:15:27 +00001470/// getAL - Returns a ARMCC::AL immediate node.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001471static inline SDValue getAL(SelectionDAG *CurDAG, SDLoc dl) {
1472 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001473}
1474
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001475SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
1476 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001477 ISD::MemIndexedMode AM = LD->getAddressingMode();
1478 if (AM == ISD::UNINDEXED)
Craig Topper062a2ba2014-04-25 05:30:21 +00001479 return nullptr;
Evan Chengd9c55362009-07-02 01:23:32 +00001480
Owen Anderson53aa7a92009-08-10 22:56:29 +00001481 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001482 SDValue Offset, AMOpc;
1483 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1484 unsigned Opcode = 0;
1485 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001486 if (LoadedVT == MVT::i32 && isPre &&
1487 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1488 Opcode = ARM::LDR_PRE_IMM;
1489 Match = true;
1490 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001491 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001492 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001493 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001494 } else if (LoadedVT == MVT::i32 &&
1495 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001496 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001497 Match = true;
1498
Owen Anderson9f944592009-08-11 20:47:22 +00001499 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001500 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001501 Match = true;
1502 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1503 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1504 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001505 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001506 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001507 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001508 Match = true;
1509 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1510 }
1511 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001512 if (isPre &&
1513 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001514 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001515 Opcode = ARM::LDRB_PRE_IMM;
1516 } else if (!isPre &&
1517 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1518 Match = true;
1519 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001520 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1521 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001522 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001523 }
1524 }
1525 }
1526
1527 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001528 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1529 SDValue Chain = LD->getChain();
1530 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001531 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001532 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001533 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001534 MVT::i32, MVT::Other, Ops);
Owen Andersonfd60f602011-08-26 21:12:37 +00001535 } else {
1536 SDValue Chain = LD->getChain();
1537 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001538 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001539 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001540 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001541 MVT::i32, MVT::Other, Ops);
Owen Andersonfd60f602011-08-26 21:12:37 +00001542 }
Evan Chengd9c55362009-07-02 01:23:32 +00001543 }
1544
Craig Topper062a2ba2014-04-25 05:30:21 +00001545 return nullptr;
Evan Chengd9c55362009-07-02 01:23:32 +00001546}
1547
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001548SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
1549 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001550 ISD::MemIndexedMode AM = LD->getAddressingMode();
1551 if (AM == ISD::UNINDEXED)
Craig Topper062a2ba2014-04-25 05:30:21 +00001552 return nullptr;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001553
Owen Anderson53aa7a92009-08-10 22:56:29 +00001554 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001555 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001556 SDValue Offset;
1557 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1558 unsigned Opcode = 0;
1559 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001560 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001561 switch (LoadedVT.getSimpleVT().SimpleTy) {
1562 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001563 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1564 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001565 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001566 if (isSExtLd)
1567 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1568 else
1569 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001570 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001571 case MVT::i8:
1572 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001573 if (isSExtLd)
1574 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1575 else
1576 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001577 break;
1578 default:
Craig Topper062a2ba2014-04-25 05:30:21 +00001579 return nullptr;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001580 }
1581 Match = true;
1582 }
1583
1584 if (Match) {
1585 SDValue Chain = LD->getChain();
1586 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001587 SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)),
Owen Anderson9f944592009-08-11 20:47:22 +00001588 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001589 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001590 MVT::Other, Ops);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001591 }
1592
Craig Topper062a2ba2014-04-25 05:30:21 +00001593 return nullptr;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001594}
1595
Weiming Zhao8f56f882012-11-16 21:55:34 +00001596/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1597SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001598 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001599 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001600 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1601 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1602 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001603 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001604 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001605}
1606
Weiming Zhao95782222012-11-17 00:23:35 +00001607/// \brief Form a D register from a pair of S registers.
1608SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001609 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001610 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001611 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1612 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1613 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001614 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001615 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001616}
1617
Weiming Zhao95782222012-11-17 00:23:35 +00001618/// \brief Form a quad register from a pair of D registers.
1619SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001620 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001621 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1622 MVT::i32);
1623 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1624 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001625 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001626 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001627}
1628
Weiming Zhao95782222012-11-17 00:23:35 +00001629/// \brief Form 4 consecutive D registers from a pair of Q registers.
1630SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001631 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001632 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1633 MVT::i32);
1634 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1635 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001636 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001637 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001638}
1639
Weiming Zhao95782222012-11-17 00:23:35 +00001640/// \brief Form 4 consecutive S registers.
1641SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001642 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001643 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001644 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001645 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1646 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1647 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1648 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1649 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001650 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1651 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001652 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001653}
1654
Weiming Zhao95782222012-11-17 00:23:35 +00001655/// \brief Form 4 consecutive D registers.
1656SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001657 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001658 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001659 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1660 MVT::i32);
1661 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1662 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1663 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1664 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001665 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1666 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001667 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001668}
1669
Weiming Zhao95782222012-11-17 00:23:35 +00001670/// \brief Form 4 consecutive Q registers.
1671SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001672 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001673 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001674 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1675 MVT::i32);
1676 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1677 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1678 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1679 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001680 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1681 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001682 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001683}
1684
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001685/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1686/// of a NEON VLD or VST instruction. The supported values depend on the
1687/// number of registers being loaded.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001688SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, SDLoc dl,
1689 unsigned NumVecs, bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001690 unsigned NumRegs = NumVecs;
1691 if (!is64BitVector && NumVecs < 3)
1692 NumRegs *= 2;
1693
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001694 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001695 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001696 Alignment = 32;
1697 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1698 Alignment = 16;
1699 else if (Alignment >= 8)
1700 Alignment = 8;
1701 else
1702 Alignment = 0;
1703
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001704 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001705}
1706
Jiangning Liu4df23632014-01-16 09:16:13 +00001707static bool isVLDfixed(unsigned Opc)
1708{
1709 switch (Opc) {
1710 default: return false;
1711 case ARM::VLD1d8wb_fixed : return true;
1712 case ARM::VLD1d16wb_fixed : return true;
1713 case ARM::VLD1d64Qwb_fixed : return true;
1714 case ARM::VLD1d32wb_fixed : return true;
1715 case ARM::VLD1d64wb_fixed : return true;
1716 case ARM::VLD1d64TPseudoWB_fixed : return true;
1717 case ARM::VLD1d64QPseudoWB_fixed : return true;
1718 case ARM::VLD1q8wb_fixed : return true;
1719 case ARM::VLD1q16wb_fixed : return true;
1720 case ARM::VLD1q32wb_fixed : return true;
1721 case ARM::VLD1q64wb_fixed : return true;
1722 case ARM::VLD2d8wb_fixed : return true;
1723 case ARM::VLD2d16wb_fixed : return true;
1724 case ARM::VLD2d32wb_fixed : return true;
1725 case ARM::VLD2q8PseudoWB_fixed : return true;
1726 case ARM::VLD2q16PseudoWB_fixed : return true;
1727 case ARM::VLD2q32PseudoWB_fixed : return true;
1728 case ARM::VLD2DUPd8wb_fixed : return true;
1729 case ARM::VLD2DUPd16wb_fixed : return true;
1730 case ARM::VLD2DUPd32wb_fixed : return true;
1731 }
1732}
1733
1734static bool isVSTfixed(unsigned Opc)
1735{
1736 switch (Opc) {
1737 default: return false;
1738 case ARM::VST1d8wb_fixed : return true;
1739 case ARM::VST1d16wb_fixed : return true;
1740 case ARM::VST1d32wb_fixed : return true;
1741 case ARM::VST1d64wb_fixed : return true;
Jim Grosbach1a597112014-04-03 23:43:18 +00001742 case ARM::VST1q8wb_fixed : return true;
1743 case ARM::VST1q16wb_fixed : return true;
1744 case ARM::VST1q32wb_fixed : return true;
1745 case ARM::VST1q64wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001746 case ARM::VST1d64TPseudoWB_fixed : return true;
1747 case ARM::VST1d64QPseudoWB_fixed : return true;
1748 case ARM::VST2d8wb_fixed : return true;
1749 case ARM::VST2d16wb_fixed : return true;
1750 case ARM::VST2d32wb_fixed : return true;
1751 case ARM::VST2q8PseudoWB_fixed : return true;
1752 case ARM::VST2q16PseudoWB_fixed : return true;
1753 case ARM::VST2q32PseudoWB_fixed : return true;
1754 }
1755}
1756
Jim Grosbach2098cb12011-10-24 21:45:13 +00001757// Get the register stride update opcode of a VLD/VST instruction that
1758// is otherwise equivalent to the given fixed stride updating instruction.
1759static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
Jiangning Liu4df23632014-01-16 09:16:13 +00001760 assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1761 && "Incorrect fixed stride updating instruction.");
Jim Grosbach2098cb12011-10-24 21:45:13 +00001762 switch (Opc) {
1763 default: break;
1764 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1765 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1766 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1767 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1768 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1769 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1770 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1771 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jiangning Liu4df23632014-01-16 09:16:13 +00001772 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1773 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1774 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1775 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001776
1777 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1778 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1779 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1780 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1781 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1782 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1783 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1784 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001785 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001786 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001787
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001788 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1789 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1790 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001791 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1792 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1793 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1794
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001795 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1796 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1797 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001798 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1799 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1800 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001801
Jim Grosbach13a292c2012-03-06 22:01:44 +00001802 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1803 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1804 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001805 }
1806 return Opc; // If not one we handle, return it unchanged.
1807}
1808
Bob Wilson06fce872011-02-07 17:43:21 +00001809SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001810 const uint16_t *DOpcodes,
1811 const uint16_t *QOpcodes0,
1812 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001813 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001814 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001815
Bob Wilsonae08a732010-03-20 22:13:40 +00001816 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001817 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1818 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Craig Topper062a2ba2014-04-25 05:30:21 +00001819 return nullptr;
Bob Wilson12b47992009-10-14 17:28:52 +00001820
1821 SDValue Chain = N->getOperand(0);
1822 EVT VT = N->getValueType(0);
1823 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001824 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001825
Bob Wilson12b47992009-10-14 17:28:52 +00001826 unsigned OpcodeIndex;
1827 switch (VT.getSimpleVT().SimpleTy) {
1828 default: llvm_unreachable("unhandled vld type");
1829 // Double-register operations:
1830 case MVT::v8i8: OpcodeIndex = 0; break;
1831 case MVT::v4i16: OpcodeIndex = 1; break;
1832 case MVT::v2f32:
1833 case MVT::v2i32: OpcodeIndex = 2; break;
1834 case MVT::v1i64: OpcodeIndex = 3; break;
1835 // Quad-register operations:
1836 case MVT::v16i8: OpcodeIndex = 0; break;
1837 case MVT::v8i16: OpcodeIndex = 1; break;
1838 case MVT::v4f32:
1839 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001840 case MVT::v2f64:
Bob Wilson340861d2010-03-23 05:25:43 +00001841 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001842 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson340861d2010-03-23 05:25:43 +00001843 break;
Bob Wilson12b47992009-10-14 17:28:52 +00001844 }
1845
Bob Wilson35fafca2010-09-03 18:16:02 +00001846 EVT ResTy;
1847 if (NumVecs == 1)
1848 ResTy = VT;
1849 else {
1850 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1851 if (!is64BitVector)
1852 ResTyElts *= 2;
1853 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1854 }
Bob Wilson06fce872011-02-07 17:43:21 +00001855 std::vector<EVT> ResTys;
1856 ResTys.push_back(ResTy);
1857 if (isUpdating)
1858 ResTys.push_back(MVT::i32);
1859 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001860
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001861 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001862 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001863 SDNode *VLd;
1864 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001865
Bob Wilson06fce872011-02-07 17:43:21 +00001866 // Double registers and VLD1/VLD2 quad registers are directly supported.
1867 if (is64BitVector || NumVecs <= 2) {
1868 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1869 QOpcodes0[OpcodeIndex]);
1870 Ops.push_back(MemAddr);
1871 Ops.push_back(Align);
1872 if (isUpdating) {
1873 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachd146a022011-12-09 21:28:25 +00001874 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach2098cb12011-10-24 21:45:13 +00001875 // case entirely when the rest are updated to that form, too.
Jiangning Liu4df23632014-01-16 09:16:13 +00001876 if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001877 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001878 // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001879 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00001880 if ((NumVecs > 2 && !isVLDfixed(Opc)) ||
Jim Grosbach05df4602011-10-31 21:50:31 +00001881 !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001882 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Evan Cheng630063a2010-05-10 21:26:24 +00001883 }
Bob Wilson06fce872011-02-07 17:43:21 +00001884 Ops.push_back(Pred);
1885 Ops.push_back(Reg0);
1886 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001887 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001888
Bob Wilson12b47992009-10-14 17:28:52 +00001889 } else {
1890 // Otherwise, quad registers are loaded with two separate instructions,
1891 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001892 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001893
Bob Wilson06fce872011-02-07 17:43:21 +00001894 // Load the even subregs. This is always an updating load, so that it
1895 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001896 SDValue ImplDef =
1897 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1898 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001899 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001900 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001901 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001902
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001903 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001904 Ops.push_back(SDValue(VLdA, 1));
1905 Ops.push_back(Align);
1906 if (isUpdating) {
1907 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1908 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1909 "only constant post-increment update allowed for VLD3/4");
1910 (void)Inc;
1911 Ops.push_back(Reg0);
1912 }
1913 Ops.push_back(SDValue(VLdA, 0));
1914 Ops.push_back(Pred);
1915 Ops.push_back(Reg0);
1916 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001917 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001918 }
Bob Wilson12b47992009-10-14 17:28:52 +00001919
Evan Cheng40791332011-04-19 00:04:03 +00001920 // Transfer memoperands.
1921 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1922 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1923 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1924
Bob Wilson06fce872011-02-07 17:43:21 +00001925 if (NumVecs == 1)
1926 return VLd;
1927
1928 // Extract out the subregisters.
1929 SDValue SuperReg = SDValue(VLd, 0);
1930 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
1931 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
1932 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1933 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1934 ReplaceUses(SDValue(N, Vec),
1935 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1936 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1937 if (isUpdating)
1938 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Craig Topper062a2ba2014-04-25 05:30:21 +00001939 return nullptr;
Bob Wilson12b47992009-10-14 17:28:52 +00001940}
1941
Bob Wilson06fce872011-02-07 17:43:21 +00001942SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001943 const uint16_t *DOpcodes,
1944 const uint16_t *QOpcodes0,
1945 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001946 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001947 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001948
Bob Wilsonae08a732010-03-20 22:13:40 +00001949 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001950 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1951 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1952 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Craig Topper062a2ba2014-04-25 05:30:21 +00001953 return nullptr;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001954
Evan Cheng40791332011-04-19 00:04:03 +00001955 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1956 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1957
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001958 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00001959 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001960 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001961 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001962
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001963 unsigned OpcodeIndex;
1964 switch (VT.getSimpleVT().SimpleTy) {
1965 default: llvm_unreachable("unhandled vst type");
1966 // Double-register operations:
1967 case MVT::v8i8: OpcodeIndex = 0; break;
1968 case MVT::v4i16: OpcodeIndex = 1; break;
1969 case MVT::v2f32:
1970 case MVT::v2i32: OpcodeIndex = 2; break;
1971 case MVT::v1i64: OpcodeIndex = 3; break;
1972 // Quad-register operations:
1973 case MVT::v16i8: OpcodeIndex = 0; break;
1974 case MVT::v8i16: OpcodeIndex = 1; break;
1975 case MVT::v4f32:
1976 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001977 case MVT::v2f64:
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001978 case MVT::v2i64: OpcodeIndex = 3;
1979 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
1980 break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001981 }
1982
Bob Wilson06fce872011-02-07 17:43:21 +00001983 std::vector<EVT> ResTys;
1984 if (isUpdating)
1985 ResTys.push_back(MVT::i32);
1986 ResTys.push_back(MVT::Other);
1987
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001988 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001989 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001990 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00001991
Bob Wilson06fce872011-02-07 17:43:21 +00001992 // Double registers and VST1/VST2 quad registers are directly supported.
1993 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00001994 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00001995 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00001996 SrcReg = N->getOperand(Vec0Idx);
1997 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00001998 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00001999 SDValue V0 = N->getOperand(Vec0Idx + 0);
2000 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00002001 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002002 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002003 else {
Bob Wilson06fce872011-02-07 17:43:21 +00002004 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00002005 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00002006 // an undef.
2007 SDValue V3 = (NumVecs == 3)
2008 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002009 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002010 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00002011 }
Bob Wilson950882b2010-08-28 05:12:57 +00002012 } else {
2013 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00002014 SDValue Q0 = N->getOperand(Vec0Idx);
2015 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00002016 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002017 }
Bob Wilson06fce872011-02-07 17:43:21 +00002018
2019 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2020 QOpcodes0[OpcodeIndex]);
2021 Ops.push_back(MemAddr);
2022 Ops.push_back(Align);
2023 if (isUpdating) {
2024 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbach88ac7612011-12-14 21:32:11 +00002025 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach05df4602011-10-31 21:50:31 +00002026 // case entirely when the rest are updated to that form, too.
Jim Grosbach88ac7612011-12-14 21:32:11 +00002027 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach05df4602011-10-31 21:50:31 +00002028 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00002029 // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00002030 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00002031 if (!isa<ConstantSDNode>(Inc.getNode()))
2032 Ops.push_back(Inc);
2033 else if (NumVecs > 2 && !isVSTfixed(Opc))
2034 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002035 }
2036 Ops.push_back(SrcReg);
2037 Ops.push_back(Pred);
2038 Ops.push_back(Reg0);
2039 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00002040 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002041
2042 // Transfer memoperands.
2043 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
2044
2045 return VSt;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002046 }
2047
2048 // Otherwise, quad registers are stored with two separate instructions,
2049 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00002050
Bob Wilson01ac8f92010-06-16 21:34:01 +00002051 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00002052 SDValue V0 = N->getOperand(Vec0Idx + 0);
2053 SDValue V1 = N->getOperand(Vec0Idx + 1);
2054 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00002055 SDValue V3 = (NumVecs == 3)
2056 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002057 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002058 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002059
Bob Wilson06fce872011-02-07 17:43:21 +00002060 // Store the even D registers. This is always an updating store, so that it
2061 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00002062 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2063 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2064 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00002065 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00002066 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002067 Chain = SDValue(VStA, 1);
2068
2069 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00002070 Ops.push_back(SDValue(VStA, 0));
2071 Ops.push_back(Align);
2072 if (isUpdating) {
2073 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2074 assert(isa<ConstantSDNode>(Inc.getNode()) &&
2075 "only constant post-increment update allowed for VST3/4");
2076 (void)Inc;
2077 Ops.push_back(Reg0);
2078 }
2079 Ops.push_back(RegSeq);
2080 Ops.push_back(Pred);
2081 Ops.push_back(Reg0);
2082 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00002083 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00002084 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002085 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
2086 return VStB;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002087}
2088
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002089SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
Bob Wilson06fce872011-02-07 17:43:21 +00002090 bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00002091 const uint16_t *DOpcodes,
2092 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002093 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002094 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002095
Bob Wilsonae08a732010-03-20 22:13:40 +00002096 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00002097 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2098 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2099 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Craig Topper062a2ba2014-04-25 05:30:21 +00002100 return nullptr;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002101
Evan Cheng40791332011-04-19 00:04:03 +00002102 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2103 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2104
Bob Wilson4145e3a2009-10-14 16:19:03 +00002105 SDValue Chain = N->getOperand(0);
2106 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002107 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2108 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002109 bool is64BitVector = VT.is64BitVector();
2110
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002111 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002112 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002113 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002114 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2115 if (Alignment > NumBytes)
2116 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002117 if (Alignment < 8 && Alignment < NumBytes)
2118 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002119 // Alignment must be a power of two; make sure of that.
2120 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002121 if (Alignment == 1)
2122 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002123 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002124 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002125
Bob Wilson4145e3a2009-10-14 16:19:03 +00002126 unsigned OpcodeIndex;
2127 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002128 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002129 // Double-register operations:
2130 case MVT::v8i8: OpcodeIndex = 0; break;
2131 case MVT::v4i16: OpcodeIndex = 1; break;
2132 case MVT::v2f32:
2133 case MVT::v2i32: OpcodeIndex = 2; break;
2134 // Quad-register operations:
2135 case MVT::v8i16: OpcodeIndex = 0; break;
2136 case MVT::v4f32:
2137 case MVT::v4i32: OpcodeIndex = 1; break;
2138 }
2139
Bob Wilson06fce872011-02-07 17:43:21 +00002140 std::vector<EVT> ResTys;
2141 if (IsLoad) {
2142 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2143 if (!is64BitVector)
2144 ResTyElts *= 2;
2145 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2146 MVT::i64, ResTyElts));
2147 }
2148 if (isUpdating)
2149 ResTys.push_back(MVT::i32);
2150 ResTys.push_back(MVT::Other);
2151
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002152 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002153 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002154
Bob Wilson06fce872011-02-07 17:43:21 +00002155 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002156 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002157 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002158 if (isUpdating) {
2159 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2160 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
2161 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002162
Bob Wilsond5c57a52010-09-13 23:01:35 +00002163 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002164 SDValue V0 = N->getOperand(Vec0Idx + 0);
2165 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002166 if (NumVecs == 2) {
2167 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002168 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002169 else
Weiming Zhao95782222012-11-17 00:23:35 +00002170 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002171 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002172 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002173 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002174 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2175 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002176 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002177 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002178 else
Weiming Zhao95782222012-11-17 00:23:35 +00002179 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002180 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002181 Ops.push_back(SuperReg);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002182 Ops.push_back(getI32Imm(Lane, dl));
Evan Chenga33fc862009-11-21 06:21:52 +00002183 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002184 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002185 Ops.push_back(Chain);
2186
Bob Wilson06fce872011-02-07 17:43:21 +00002187 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2188 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002189 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002190 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson93117bc2009-10-14 16:46:45 +00002191 if (!IsLoad)
Bob Wilson06fce872011-02-07 17:43:21 +00002192 return VLdLn;
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002193
Bob Wilsond5c57a52010-09-13 23:01:35 +00002194 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002195 SuperReg = SDValue(VLdLn, 0);
2196 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
2197 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
2198 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002199 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2200 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002201 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2202 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2203 if (isUpdating)
2204 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Craig Topper062a2ba2014-04-25 05:30:21 +00002205 return nullptr;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002206}
2207
Bob Wilson06fce872011-02-07 17:43:21 +00002208SDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating,
Craig Topper01736f82012-05-24 05:17:00 +00002209 unsigned NumVecs,
2210 const uint16_t *Opcodes) {
Bob Wilson2d790df2010-11-28 06:51:26 +00002211 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002212 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002213
2214 SDValue MemAddr, Align;
2215 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
Craig Topper062a2ba2014-04-25 05:30:21 +00002216 return nullptr;
Bob Wilson2d790df2010-11-28 06:51:26 +00002217
Evan Cheng40791332011-04-19 00:04:03 +00002218 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2219 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2220
Bob Wilson2d790df2010-11-28 06:51:26 +00002221 SDValue Chain = N->getOperand(0);
2222 EVT VT = N->getValueType(0);
2223
2224 unsigned Alignment = 0;
2225 if (NumVecs != 3) {
2226 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2227 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2228 if (Alignment > NumBytes)
2229 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002230 if (Alignment < 8 && Alignment < NumBytes)
2231 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002232 // Alignment must be a power of two; make sure of that.
2233 Alignment = (Alignment & -Alignment);
2234 if (Alignment == 1)
2235 Alignment = 0;
2236 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002237 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson2d790df2010-11-28 06:51:26 +00002238
2239 unsigned OpcodeIndex;
2240 switch (VT.getSimpleVT().SimpleTy) {
2241 default: llvm_unreachable("unhandled vld-dup type");
2242 case MVT::v8i8: OpcodeIndex = 0; break;
2243 case MVT::v4i16: OpcodeIndex = 1; break;
2244 case MVT::v2f32:
2245 case MVT::v2i32: OpcodeIndex = 2; break;
2246 }
2247
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002248 SDValue Pred = getAL(CurDAG, dl);
Bob Wilson2d790df2010-11-28 06:51:26 +00002249 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2250 SDValue SuperReg;
2251 unsigned Opc = Opcodes[OpcodeIndex];
Bob Wilson06fce872011-02-07 17:43:21 +00002252 SmallVector<SDValue, 6> Ops;
2253 Ops.push_back(MemAddr);
2254 Ops.push_back(Align);
2255 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002256 // fixed-stride update instructions don't have an explicit writeback
2257 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002258 SDValue Inc = N->getOperand(2);
Jim Grosbachc80a2642011-12-21 19:40:55 +00002259 if (!isa<ConstantSDNode>(Inc.getNode()))
2260 Ops.push_back(Inc);
2261 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2262 else if (NumVecs > 2)
2263 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002264 }
2265 Ops.push_back(Pred);
2266 Ops.push_back(Reg0);
2267 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002268
2269 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002270 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002271 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002272 if (isUpdating)
2273 ResTys.push_back(MVT::i32);
2274 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002275 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002276 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002277 SuperReg = SDValue(VLdDup, 0);
Bob Wilson2d790df2010-11-28 06:51:26 +00002278
2279 // Extract the subregisters.
2280 assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
2281 unsigned SubIdx = ARM::dsub_0;
2282 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2283 ReplaceUses(SDValue(N, Vec),
2284 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Bob Wilson06fce872011-02-07 17:43:21 +00002285 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2286 if (isUpdating)
2287 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Craig Topper062a2ba2014-04-25 05:30:21 +00002288 return nullptr;
Bob Wilson2d790df2010-11-28 06:51:26 +00002289}
2290
Bob Wilson5bc8a792010-07-07 00:08:54 +00002291SDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2292 unsigned Opc) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00002293 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002294 SDLoc dl(N);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002295 EVT VT = N->getValueType(0);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002296 unsigned FirstTblReg = IsExt ? 2 : 1;
Bob Wilson3ed511b2010-07-06 23:36:25 +00002297
2298 // Form a REG_SEQUENCE to force register allocation.
2299 SDValue RegSeq;
Bob Wilson5bc8a792010-07-07 00:08:54 +00002300 SDValue V0 = N->getOperand(FirstTblReg + 0);
2301 SDValue V1 = N->getOperand(FirstTblReg + 1);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002302 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002303 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002304 else {
Bob Wilson5bc8a792010-07-07 00:08:54 +00002305 SDValue V2 = N->getOperand(FirstTblReg + 2);
Jim Grosbachd37f0712010-10-21 19:38:40 +00002306 // If it's a vtbl3, form a quad D-register and leave the last part as
Bob Wilson3ed511b2010-07-06 23:36:25 +00002307 // an undef.
2308 SDValue V3 = (NumVecs == 3)
2309 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson5bc8a792010-07-07 00:08:54 +00002310 : N->getOperand(FirstTblReg + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002311 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002312 }
2313
Bob Wilson5bc8a792010-07-07 00:08:54 +00002314 SmallVector<SDValue, 6> Ops;
2315 if (IsExt)
2316 Ops.push_back(N->getOperand(1));
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00002317 Ops.push_back(RegSeq);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002318 Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002319 Ops.push_back(getAL(CurDAG, dl)); // predicate
Bob Wilson3ed511b2010-07-06 23:36:25 +00002320 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
Michael Liaob53d8962013-04-19 22:22:57 +00002321 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002322}
2323
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002324SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
Jim Grosbach825cb292010-04-22 23:24:18 +00002325 bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002326 if (!Subtarget->hasV6T2Ops())
Craig Topper062a2ba2014-04-25 05:30:21 +00002327 return nullptr;
Bob Wilson93117bc2009-10-14 16:46:45 +00002328
Evan Chengeae6d2c2012-12-19 20:16:09 +00002329 unsigned Opc = isSigned
2330 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002331 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002332 SDLoc dl(N);
Jim Grosbach825cb292010-04-22 23:24:18 +00002333
Jim Grosbach825cb292010-04-22 23:24:18 +00002334 // For unsigned extracts, check for a shift right and mask
2335 unsigned And_imm = 0;
2336 if (N->getOpcode() == ISD::AND) {
2337 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2338
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002339 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002340 if (And_imm & (And_imm + 1))
Craig Topper062a2ba2014-04-25 05:30:21 +00002341 return nullptr;
Jim Grosbach825cb292010-04-22 23:24:18 +00002342
2343 unsigned Srl_imm = 0;
2344 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2345 Srl_imm)) {
2346 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2347
Jim Grosbach03f56d92011-07-27 21:09:25 +00002348 // Note: The width operand is encoded as width-1.
Benjamin Kramer5f6a9072015-02-12 15:35:40 +00002349 unsigned Width = countTrailingOnes(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002350 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002351
Jim Grosbach825cb292010-04-22 23:24:18 +00002352 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002353
2354 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2355 // It's cheaper to use a right shift to extract the top bits.
2356 if (Subtarget->isThumb()) {
2357 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2358 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002359 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2360 getAL(CurDAG, dl), Reg0, Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002361 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002362 }
2363
2364 // ARM models shift instructions as MOVsi with shifter operand.
2365 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2366 SDValue ShOpc =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002367 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), dl,
Evan Chengeae6d2c2012-12-19 20:16:09 +00002368 MVT::i32);
2369 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002370 getAL(CurDAG, dl), Reg0, Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002371 return CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002372 }
2373
Jim Grosbach825cb292010-04-22 23:24:18 +00002374 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002375 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2376 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2377 getAL(CurDAG, dl), Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002378 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
Jim Grosbach825cb292010-04-22 23:24:18 +00002379 }
2380 }
Craig Topper062a2ba2014-04-25 05:30:21 +00002381 return nullptr;
Jim Grosbach825cb292010-04-22 23:24:18 +00002382 }
2383
2384 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002385 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002386 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002387 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2388 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002389 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002390 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002391 // Note: The width operand is encoded as width-1.
2392 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002393 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002394 if (LSB < 0)
Craig Topper062a2ba2014-04-25 05:30:21 +00002395 return nullptr;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002396 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002397 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002398 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2399 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2400 getAL(CurDAG, dl), Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002401 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
Sandeep Patel423e42b2009-10-13 18:59:48 +00002402 }
2403 }
Tim Northover14ff2df2014-07-23 13:59:12 +00002404
2405 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
2406 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2407 unsigned LSB = 0;
2408 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) &&
2409 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB))
2410 return nullptr;
2411
2412 if (LSB + Width > 32)
2413 return nullptr;
2414
2415 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2416 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002417 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2418 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
2419 getAL(CurDAG, dl), Reg0 };
Tim Northover14ff2df2014-07-23 13:59:12 +00002420 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2421 }
2422
Craig Topper062a2ba2014-04-25 05:30:21 +00002423 return nullptr;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002424}
2425
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002426/// Target-specific DAG combining for ISD::XOR.
2427/// Target-independent combining lowers SELECT_CC nodes of the form
2428/// select_cc setg[ge] X, 0, X, -X
2429/// select_cc setgt X, -1, X, -X
2430/// select_cc setl[te] X, 0, -X, X
2431/// select_cc setlt X, 1, -X, X
2432/// which represent Integer ABS into:
2433/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2434/// ARM instruction selection detects the latter and matches it to
2435/// ARM::ABS or ARM::t2ABS machine node.
2436SDNode *ARMDAGToDAGISel::SelectABSOp(SDNode *N){
2437 SDValue XORSrc0 = N->getOperand(0);
2438 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002439 EVT VT = N->getValueType(0);
2440
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002441 if (Subtarget->isThumb1Only())
Craig Topper062a2ba2014-04-25 05:30:21 +00002442 return nullptr;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002443
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002444 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Craig Topper062a2ba2014-04-25 05:30:21 +00002445 return nullptr;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002446
2447 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2448 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2449 SDValue SRASrc0 = XORSrc1.getOperand(0);
2450 SDValue SRASrc1 = XORSrc1.getOperand(1);
2451 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2452 EVT XType = SRASrc0.getValueType();
2453 unsigned Size = XType.getSizeInBits() - 1;
2454
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002455 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
Craig Topper062a2ba2014-04-25 05:30:21 +00002456 XType.isInteger() && SRAConstant != nullptr &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002457 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002458 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002459 return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2460 }
2461
Craig Topper062a2ba2014-04-25 05:30:21 +00002462 return nullptr;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002463}
2464
Evan Chengd85631e2010-05-05 18:28:36 +00002465SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
2466 // The only time a CONCAT_VECTORS operation can have legal types is when
2467 // two 64-bit vectors are concatenated to a 128-bit vector.
2468 EVT VT = N->getValueType(0);
2469 if (!VT.is128BitVector() || N->getNumOperands() != 2)
2470 llvm_unreachable("unexpected CONCAT_VECTORS");
Weiming Zhao95782222012-11-17 00:23:35 +00002471 return createDRegPairNode(VT, N->getOperand(0), N->getOperand(1));
Evan Chengd85631e2010-05-05 18:28:36 +00002472}
2473
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002474SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002475 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002476
Tim Northover31d093c2013-09-22 08:21:56 +00002477 if (N->isMachineOpcode()) {
2478 N->setNodeId(-1);
Craig Topper062a2ba2014-04-25 05:30:21 +00002479 return nullptr; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00002480 }
Rafael Espindola4e760152006-06-12 12:28:08 +00002481
2482 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002483 default: break;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002484 case ISD::WRITE_REGISTER: {
2485 SDNode *ResNode = SelectWriteRegister(N);
2486 if (ResNode)
2487 return ResNode;
2488 break;
2489 }
2490 case ISD::READ_REGISTER: {
2491 SDNode *ResNode = SelectReadRegister(N);
2492 if (ResNode)
2493 return ResNode;
2494 break;
2495 }
Weiming Zhaoc5987002013-02-14 18:10:21 +00002496 case ISD::INLINEASM: {
2497 SDNode *ResNode = SelectInlineAsm(N);
2498 if (ResNode)
2499 return ResNode;
2500 break;
2501 }
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002502 case ISD::XOR: {
2503 // Select special operations if XOR node forms integer ABS pattern
2504 SDNode *ResNode = SelectABSOp(N);
2505 if (ResNode)
2506 return ResNode;
2507 // Other cases are autogenerated.
2508 break;
2509 }
Evan Cheng10043e22007-01-19 07:51:42 +00002510 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002511 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
John Brawn056e6782015-09-14 15:19:41 +00002512 // If we can't materialize the constant we need to use a literal pool
2513 if (ConstantMaterializationCost(Val) > 2) {
Eric Christopherb17140d2014-10-08 07:32:17 +00002514 SDValue CPIdx = CurDAG->getTargetConstantPool(
2515 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
Mehdi Amini44ede332015-07-09 02:09:04 +00002516 TLI->getPointerTy(CurDAG->getDataLayout()));
Evan Cheng1526ba52007-01-24 08:53:17 +00002517
2518 SDNode *ResNode;
Tim Northover55c625f2014-01-23 13:43:47 +00002519 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002520 SDValue Pred = getAL(CurDAG, dl);
Owen Anderson9f944592009-08-11 20:47:22 +00002521 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002522 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002523 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002524 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002525 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002526 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002527 CPIdx,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002528 CurDAG->getTargetConstant(0, dl, MVT::i32),
2529 getAL(CurDAG, dl),
Owen Anderson9f944592009-08-11 20:47:22 +00002530 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002531 CurDAG->getEntryNode()
2532 };
Dan Gohman32f71d72009-09-25 18:54:59 +00002533 ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002534 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002535 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002536 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
Craig Topper062a2ba2014-04-25 05:30:21 +00002537 return nullptr;
Evan Cheng10043e22007-01-19 07:51:42 +00002538 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002539
Evan Cheng10043e22007-01-19 07:51:42 +00002540 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002541 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002542 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002543 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002544 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002545 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +00002546 SDValue TFI = CurDAG->getTargetFrameIndex(
2547 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
David Goodwin22c2fba2009-07-08 23:10:31 +00002548 if (Subtarget->isThumb1Only()) {
Renato Golinb9887ef2015-02-25 14:41:06 +00002549 // Set the alignment of the frame object to 4, to avoid having to generate
2550 // more than one ADD
2551 MachineFrameInfo *MFI = MF->getFrameInfo();
2552 if (MFI->getObjectAlignment(FI) < 4)
2553 MFI->setObjectAlignment(FI, 4);
Tim Northover23075cc2014-10-20 21:28:41 +00002554 return CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002555 CurDAG->getTargetConstant(0, dl, MVT::i32));
Jim Grosbachfde21102009-04-07 20:34:09 +00002556 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002557 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2558 ARM::t2ADDri : ARM::ADDri);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002559 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
2560 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002561 CurDAG->getRegister(0, MVT::i32) };
Craig Topper481fb282014-04-27 19:21:11 +00002562 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
Evan Cheng7e90b112007-07-05 07:15:27 +00002563 }
Evan Cheng10043e22007-01-19 07:51:42 +00002564 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002565 case ISD::SRL:
Jim Grosbach825cb292010-04-22 23:24:18 +00002566 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
Sandeep Patel423e42b2009-10-13 18:59:48 +00002567 return I;
2568 break;
Tim Northover14ff2df2014-07-23 13:59:12 +00002569 case ISD::SIGN_EXTEND_INREG:
Sandeep Patel423e42b2009-10-13 18:59:48 +00002570 case ISD::SRA:
Jim Grosbach825cb292010-04-22 23:24:18 +00002571 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true))
Sandeep Patel423e42b2009-10-13 18:59:48 +00002572 return I;
2573 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002574 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002575 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002576 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002577 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002578 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002579 if (!RHSV) break;
2580 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002581 unsigned ShImm = Log2_32(RHSV-1);
2582 if (ShImm >= 32)
2583 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002584 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002585 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002586 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002587 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002588 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002589 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002590 return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002591 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002592 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2593 Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002594 return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002595 }
Evan Cheng10043e22007-01-19 07:51:42 +00002596 }
2597 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002598 unsigned ShImm = Log2_32(RHSV+1);
2599 if (ShImm >= 32)
2600 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002601 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002602 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002603 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002604 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002605 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002606 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002607 return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002608 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002609 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2610 Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002611 return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002612 }
Evan Cheng10043e22007-01-19 07:51:42 +00002613 }
2614 }
2615 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002616 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002617 // Check for unsigned bitfield extract
2618 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
2619 return I;
2620
Evan Cheng786b15f2009-10-21 08:15:52 +00002621 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2622 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2623 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2624 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2625 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002626 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002627 if (VT != MVT::i32)
2628 break;
2629 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2630 ? ARM::t2MOVTi16
2631 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2632 if (!Opc)
2633 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002634 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002635 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
2636 if (!N1C)
2637 break;
2638 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2639 SDValue N2 = N0.getOperand(1);
2640 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2641 if (!N2C)
2642 break;
2643 unsigned N1CVal = N1C->getZExtValue();
2644 unsigned N2CVal = N2C->getZExtValue();
2645 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2646 (N1CVal & 0xffffU) == 0xffffU &&
2647 (N2CVal & 0xffffU) == 0x0U) {
2648 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002649 dl, MVT::i32);
Evan Cheng786b15f2009-10-21 08:15:52 +00002650 SDValue Ops[] = { N0.getOperand(0), Imm16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002651 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002652 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
Evan Cheng786b15f2009-10-21 08:15:52 +00002653 }
2654 }
2655 break;
2656 }
Jim Grosbachd7cf55c2009-11-09 00:11:35 +00002657 case ARMISD::VMOVRRD:
2658 return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002659 N->getOperand(0), getAL(CurDAG, dl),
Dan Gohman32f71d72009-09-25 18:54:59 +00002660 CurDAG->getRegister(0, MVT::i32));
Dan Gohmana1603612007-10-08 18:33:35 +00002661 case ISD::UMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002662 if (Subtarget->isThumb1Only())
2663 break;
2664 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002665 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002666 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002667 return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002668 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002669 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002670 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002671 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov62acecd2011-01-01 20:38:38 +00002672 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2673 ARM::UMULL : ARM::UMULLv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002674 dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002675 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002676 }
Dan Gohmana1603612007-10-08 18:33:35 +00002677 case ISD::SMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002678 if (Subtarget->isThumb1Only())
2679 break;
2680 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002681 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002682 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002683 return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002684 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002685 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002686 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002687 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov62acecd2011-01-01 20:38:38 +00002688 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2689 ARM::SMULL : ARM::SMULLv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002690 dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002691 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002692 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002693 case ARMISD::UMLAL:{
2694 if (Subtarget->isThumb()) {
2695 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002696 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002697 CurDAG->getRegister(0, MVT::i32)};
Michael Liaob53d8962013-04-19 22:22:57 +00002698 return CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002699 }else{
2700 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002701 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002702 CurDAG->getRegister(0, MVT::i32),
2703 CurDAG->getRegister(0, MVT::i32) };
2704 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2705 ARM::UMLAL : ARM::UMLALv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002706 dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002707 }
2708 }
2709 case ARMISD::SMLAL:{
2710 if (Subtarget->isThumb()) {
2711 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002712 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002713 CurDAG->getRegister(0, MVT::i32)};
Michael Liaob53d8962013-04-19 22:22:57 +00002714 return CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002715 }else{
2716 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002717 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002718 CurDAG->getRegister(0, MVT::i32),
2719 CurDAG->getRegister(0, MVT::i32) };
2720 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2721 ARM::SMLAL : ARM::SMLALv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002722 dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002723 }
2724 }
Evan Cheng10043e22007-01-19 07:51:42 +00002725 case ISD::LOAD: {
Craig Topper062a2ba2014-04-25 05:30:21 +00002726 SDNode *ResNode = nullptr;
Evan Chengb24e51e2009-07-07 01:17:28 +00002727 if (Subtarget->isThumb() && Subtarget->hasThumb2())
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002728 ResNode = SelectT2IndexedLoad(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00002729 else
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002730 ResNode = SelectARMIndexedLoad(N);
Evan Chengd9c55362009-07-02 01:23:32 +00002731 if (ResNode)
2732 return ResNode;
Evan Cheng10043e22007-01-19 07:51:42 +00002733 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002734 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00002735 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002736 case ARMISD::BRCOND: {
2737 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2738 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2739 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00002740
Evan Cheng7e90b112007-07-05 07:15:27 +00002741 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2742 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2743 // Pattern complexity = 6 cost = 1 size = 0
2744
David Goodwin27303cd2009-06-30 18:04:13 +00002745 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2746 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2747 // Pattern complexity = 6 cost = 1 size = 0
2748
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002749 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00002750 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002751 SDValue Chain = N->getOperand(0);
2752 SDValue N1 = N->getOperand(1);
2753 SDValue N2 = N->getOperand(2);
2754 SDValue N3 = N->getOperand(3);
2755 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00002756 assert(N1.getOpcode() == ISD::BasicBlock);
2757 assert(N2.getOpcode() == ISD::Constant);
2758 assert(N3.getOpcode() == ISD::Register);
2759
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002760 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002761 cast<ConstantSDNode>(N2)->getZExtValue()), dl,
Owen Anderson9f944592009-08-11 20:47:22 +00002762 MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002763 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00002764 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002765 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002766 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002767 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002768 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002769 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00002770 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002771 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00002772 SDValue(Chain.getNode(), Chain.getResNo()));
Craig Topper062a2ba2014-04-25 05:30:21 +00002773 return nullptr;
Evan Cheng7e90b112007-07-05 07:15:27 +00002774 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002775 case ARMISD::VZIP: {
2776 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002777 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002778 switch (VT.getSimpleVT().SimpleTy) {
Craig Topper062a2ba2014-04-25 05:30:21 +00002779 default: return nullptr;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002780 case MVT::v8i8: Opc = ARM::VZIPd8; break;
2781 case MVT::v4i16: Opc = ARM::VZIPd16; break;
2782 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00002783 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2784 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002785 case MVT::v16i8: Opc = ARM::VZIPq8; break;
2786 case MVT::v8i16: Opc = ARM::VZIPq16; break;
2787 case MVT::v4f32:
2788 case MVT::v4i32: Opc = ARM::VZIPq32; break;
2789 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002790 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002791 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2792 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002793 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002794 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002795 case ARMISD::VUZP: {
2796 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002797 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002798 switch (VT.getSimpleVT().SimpleTy) {
Craig Topper062a2ba2014-04-25 05:30:21 +00002799 default: return nullptr;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002800 case MVT::v8i8: Opc = ARM::VUZPd8; break;
2801 case MVT::v4i16: Opc = ARM::VUZPd16; break;
2802 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00002803 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2804 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002805 case MVT::v16i8: Opc = ARM::VUZPq8; break;
2806 case MVT::v8i16: Opc = ARM::VUZPq16; break;
2807 case MVT::v4f32:
2808 case MVT::v4i32: Opc = ARM::VUZPq32; break;
2809 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002810 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002811 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2812 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002813 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002814 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002815 case ARMISD::VTRN: {
2816 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002817 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002818 switch (VT.getSimpleVT().SimpleTy) {
Craig Topper062a2ba2014-04-25 05:30:21 +00002819 default: return nullptr;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002820 case MVT::v8i8: Opc = ARM::VTRNd8; break;
2821 case MVT::v4i16: Opc = ARM::VTRNd16; break;
2822 case MVT::v2f32:
2823 case MVT::v2i32: Opc = ARM::VTRNd32; break;
2824 case MVT::v16i8: Opc = ARM::VTRNq8; break;
2825 case MVT::v8i16: Opc = ARM::VTRNq16; break;
2826 case MVT::v4f32:
2827 case MVT::v4i32: Opc = ARM::VTRNq32; break;
2828 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002829 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002830 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2831 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002832 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002833 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00002834 case ARMISD::BUILD_VECTOR: {
2835 EVT VecVT = N->getValueType(0);
2836 EVT EltVT = VecVT.getVectorElementType();
2837 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00002838 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00002839 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Weiming Zhao95782222012-11-17 00:23:35 +00002840 return createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilsond8a9a042010-06-04 00:04:02 +00002841 }
Duncan Sands14627772010-11-03 12:17:33 +00002842 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Bob Wilsond8a9a042010-06-04 00:04:02 +00002843 if (NumElts == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002844 return createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilsond8a9a042010-06-04 00:04:02 +00002845 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Weiming Zhao95782222012-11-17 00:23:35 +00002846 return createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
Bob Wilsond8a9a042010-06-04 00:04:02 +00002847 N->getOperand(2), N->getOperand(3));
2848 }
Bob Wilsone0636a72009-08-26 17:39:53 +00002849
Bob Wilson2d790df2010-11-28 06:51:26 +00002850 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002851 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
2852 ARM::VLD2DUPd32 };
Bob Wilson06fce872011-02-07 17:43:21 +00002853 return SelectVLDDup(N, false, 2, Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +00002854 }
2855
Bob Wilson77ab1652010-11-29 19:35:29 +00002856 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002857 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
2858 ARM::VLD3DUPd16Pseudo,
2859 ARM::VLD3DUPd32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00002860 return SelectVLDDup(N, false, 3, Opcodes);
Bob Wilson77ab1652010-11-29 19:35:29 +00002861 }
2862
Bob Wilson431ac4ef2010-11-30 00:00:35 +00002863 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002864 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
2865 ARM::VLD4DUPd16Pseudo,
2866 ARM::VLD4DUPd32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00002867 return SelectVLDDup(N, false, 4, Opcodes);
2868 }
2869
2870 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002871 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
2872 ARM::VLD2DUPd16wb_fixed,
2873 ARM::VLD2DUPd32wb_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00002874 return SelectVLDDup(N, true, 2, Opcodes);
2875 }
2876
2877 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002878 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
2879 ARM::VLD3DUPd16Pseudo_UPD,
2880 ARM::VLD3DUPd32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002881 return SelectVLDDup(N, true, 3, Opcodes);
2882 }
2883
2884 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002885 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
2886 ARM::VLD4DUPd16Pseudo_UPD,
2887 ARM::VLD4DUPd32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002888 return SelectVLDDup(N, true, 4, Opcodes);
2889 }
2890
2891 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002892 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
2893 ARM::VLD1d16wb_fixed,
2894 ARM::VLD1d32wb_fixed,
2895 ARM::VLD1d64wb_fixed };
2896 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
2897 ARM::VLD1q16wb_fixed,
2898 ARM::VLD1q32wb_fixed,
2899 ARM::VLD1q64wb_fixed };
Craig Topper062a2ba2014-04-25 05:30:21 +00002900 return SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
Bob Wilson06fce872011-02-07 17:43:21 +00002901 }
2902
2903 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002904 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
2905 ARM::VLD2d16wb_fixed,
2906 ARM::VLD2d32wb_fixed,
2907 ARM::VLD1q64wb_fixed};
2908 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
2909 ARM::VLD2q16PseudoWB_fixed,
2910 ARM::VLD2q32PseudoWB_fixed };
Craig Topper062a2ba2014-04-25 05:30:21 +00002911 return SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
Bob Wilson06fce872011-02-07 17:43:21 +00002912 }
2913
2914 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002915 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
2916 ARM::VLD3d16Pseudo_UPD,
2917 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00002918 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00002919 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
2920 ARM::VLD3q16Pseudo_UPD,
2921 ARM::VLD3q32Pseudo_UPD };
2922 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
2923 ARM::VLD3q16oddPseudo_UPD,
2924 ARM::VLD3q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002925 return SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
2926 }
2927
2928 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002929 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
2930 ARM::VLD4d16Pseudo_UPD,
2931 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00002932 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00002933 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
2934 ARM::VLD4q16Pseudo_UPD,
2935 ARM::VLD4q32Pseudo_UPD };
2936 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
2937 ARM::VLD4q16oddPseudo_UPD,
2938 ARM::VLD4q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002939 return SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
2940 }
2941
2942 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002943 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
2944 ARM::VLD2LNd16Pseudo_UPD,
2945 ARM::VLD2LNd32Pseudo_UPD };
2946 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
2947 ARM::VLD2LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002948 return SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
2949 }
2950
2951 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002952 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
2953 ARM::VLD3LNd16Pseudo_UPD,
2954 ARM::VLD3LNd32Pseudo_UPD };
2955 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
2956 ARM::VLD3LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002957 return SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
2958 }
2959
2960 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002961 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
2962 ARM::VLD4LNd16Pseudo_UPD,
2963 ARM::VLD4LNd32Pseudo_UPD };
2964 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
2965 ARM::VLD4LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002966 return SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
2967 }
2968
2969 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002970 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
2971 ARM::VST1d16wb_fixed,
2972 ARM::VST1d32wb_fixed,
2973 ARM::VST1d64wb_fixed };
2974 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
2975 ARM::VST1q16wb_fixed,
2976 ARM::VST1q32wb_fixed,
2977 ARM::VST1q64wb_fixed };
Craig Topper062a2ba2014-04-25 05:30:21 +00002978 return SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
Bob Wilson06fce872011-02-07 17:43:21 +00002979 }
2980
2981 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002982 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
2983 ARM::VST2d16wb_fixed,
2984 ARM::VST2d32wb_fixed,
2985 ARM::VST1q64wb_fixed};
2986 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
2987 ARM::VST2q16PseudoWB_fixed,
2988 ARM::VST2q32PseudoWB_fixed };
Craig Topper062a2ba2014-04-25 05:30:21 +00002989 return SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
Bob Wilson06fce872011-02-07 17:43:21 +00002990 }
2991
2992 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002993 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
2994 ARM::VST3d16Pseudo_UPD,
2995 ARM::VST3d32Pseudo_UPD,
2996 ARM::VST1d64TPseudoWB_fixed};
2997 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
2998 ARM::VST3q16Pseudo_UPD,
2999 ARM::VST3q32Pseudo_UPD };
3000 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3001 ARM::VST3q16oddPseudo_UPD,
3002 ARM::VST3q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003003 return SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3004 }
3005
3006 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003007 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3008 ARM::VST4d16Pseudo_UPD,
3009 ARM::VST4d32Pseudo_UPD,
3010 ARM::VST1d64QPseudoWB_fixed};
3011 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3012 ARM::VST4q16Pseudo_UPD,
3013 ARM::VST4q32Pseudo_UPD };
3014 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3015 ARM::VST4q16oddPseudo_UPD,
3016 ARM::VST4q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003017 return SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3018 }
3019
3020 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003021 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3022 ARM::VST2LNd16Pseudo_UPD,
3023 ARM::VST2LNd32Pseudo_UPD };
3024 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3025 ARM::VST2LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003026 return SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3027 }
3028
3029 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003030 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3031 ARM::VST3LNd16Pseudo_UPD,
3032 ARM::VST3LNd32Pseudo_UPD };
3033 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3034 ARM::VST3LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003035 return SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3036 }
3037
3038 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003039 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3040 ARM::VST4LNd16Pseudo_UPD,
3041 ARM::VST4LNd32Pseudo_UPD };
3042 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3043 ARM::VST4LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003044 return SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003045 }
3046
Bob Wilsone0636a72009-08-26 17:39:53 +00003047 case ISD::INTRINSIC_VOID:
3048 case ISD::INTRINSIC_W_CHAIN: {
3049 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003050 switch (IntNo) {
3051 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003052 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003053
Tim Northover1ff5f292014-03-26 14:39:31 +00003054 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003055 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003056 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003057 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003058 SDValue MemAddr = N->getOperand(2);
Bradley Smith433c22e2016-01-15 10:26:51 +00003059 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
Tim Northover1ff5f292014-03-26 14:39:31 +00003060
3061 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3062 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3063 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003064
3065 // arm_ldrexd returns a i64 value in {i32, i32}
3066 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003067 if (isThumb) {
3068 ResTys.push_back(MVT::i32);
3069 ResTys.push_back(MVT::i32);
3070 } else
3071 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003072 ResTys.push_back(MVT::Other);
3073
Weiming Zhao8f56f882012-11-16 21:55:34 +00003074 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003075 SmallVector<SDValue, 7> Ops;
3076 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003077 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003078 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3079 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00003080 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003081 // Transfer memoperands.
3082 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3083 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3084 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3085
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003086 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003087 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003088 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003089 SDValue Result;
3090 if (isThumb)
3091 Result = SDValue(Ld, 0);
3092 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003093 SDValue SubRegIdx =
3094 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003095 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003096 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003097 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003098 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003099 ReplaceUses(SDValue(N, 0), Result);
3100 }
3101 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003102 SDValue Result;
3103 if (isThumb)
3104 Result = SDValue(Ld, 1);
3105 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003106 SDValue SubRegIdx =
3107 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003108 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003109 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003110 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003111 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003112 ReplaceUses(SDValue(N, 1), Result);
3113 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003114 ReplaceUses(SDValue(N, 2), OutChain);
Craig Topper062a2ba2014-04-25 05:30:21 +00003115 return nullptr;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003116 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003117 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003118 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003119 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003120 SDValue Chain = N->getOperand(0);
3121 SDValue Val0 = N->getOperand(2);
3122 SDValue Val1 = N->getOperand(3);
3123 SDValue MemAddr = N->getOperand(4);
3124
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003125 // Store exclusive double return a i32 value which is the return status
3126 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003127 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003128
Weiming Zhao8f56f882012-11-16 21:55:34 +00003129 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3130 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003131 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003132 if (isThumb) {
3133 Ops.push_back(Val0);
3134 Ops.push_back(Val1);
3135 } else
3136 // arm_strexd uses GPRPair.
3137 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003138 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003139 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003140 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3141 Ops.push_back(Chain);
3142
Tim Northover1ff5f292014-03-26 14:39:31 +00003143 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3144 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3145 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003146
Michael Liaob53d8962013-04-19 22:22:57 +00003147 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003148 // Transfer memoperands.
3149 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3150 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3151 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3152
3153 return St;
3154 }
3155
Bob Wilson340861d2010-03-23 05:25:43 +00003156 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003157 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3158 ARM::VLD1d32, ARM::VLD1d64 };
3159 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3160 ARM::VLD1q32, ARM::VLD1q64};
Craig Topper062a2ba2014-04-25 05:30:21 +00003161 return SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
Bob Wilson340861d2010-03-23 05:25:43 +00003162 }
3163
Bob Wilsone0636a72009-08-26 17:39:53 +00003164 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003165 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3166 ARM::VLD2d32, ARM::VLD1q64 };
3167 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3168 ARM::VLD2q32Pseudo };
Craig Topper062a2ba2014-04-25 05:30:21 +00003169 return SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
Bob Wilsone0636a72009-08-26 17:39:53 +00003170 }
3171
3172 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003173 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3174 ARM::VLD3d16Pseudo,
3175 ARM::VLD3d32Pseudo,
3176 ARM::VLD1d64TPseudo };
3177 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3178 ARM::VLD3q16Pseudo_UPD,
3179 ARM::VLD3q32Pseudo_UPD };
3180 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3181 ARM::VLD3q16oddPseudo,
3182 ARM::VLD3q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003183 return SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003184 }
3185
3186 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003187 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3188 ARM::VLD4d16Pseudo,
3189 ARM::VLD4d32Pseudo,
3190 ARM::VLD1d64QPseudo };
3191 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3192 ARM::VLD4q16Pseudo_UPD,
3193 ARM::VLD4q32Pseudo_UPD };
3194 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3195 ARM::VLD4q16oddPseudo,
3196 ARM::VLD4q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003197 return SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003198 }
3199
Bob Wilsonda9817c2009-09-01 04:26:28 +00003200 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003201 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3202 ARM::VLD2LNd16Pseudo,
3203 ARM::VLD2LNd32Pseudo };
3204 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3205 ARM::VLD2LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003206 return SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003207 }
3208
3209 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003210 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3211 ARM::VLD3LNd16Pseudo,
3212 ARM::VLD3LNd32Pseudo };
3213 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3214 ARM::VLD3LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003215 return SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003216 }
3217
3218 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003219 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3220 ARM::VLD4LNd16Pseudo,
3221 ARM::VLD4LNd32Pseudo };
3222 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3223 ARM::VLD4LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003224 return SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003225 }
3226
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003227 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003228 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3229 ARM::VST1d32, ARM::VST1d64 };
3230 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3231 ARM::VST1q32, ARM::VST1q64 };
Craig Topper062a2ba2014-04-25 05:30:21 +00003232 return SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003233 }
3234
Bob Wilsone0636a72009-08-26 17:39:53 +00003235 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003236 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3237 ARM::VST2d32, ARM::VST1q64 };
3238 static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3239 ARM::VST2q32Pseudo };
Craig Topper062a2ba2014-04-25 05:30:21 +00003240 return SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
Bob Wilsone0636a72009-08-26 17:39:53 +00003241 }
3242
3243 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003244 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3245 ARM::VST3d16Pseudo,
3246 ARM::VST3d32Pseudo,
3247 ARM::VST1d64TPseudo };
3248 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3249 ARM::VST3q16Pseudo_UPD,
3250 ARM::VST3q32Pseudo_UPD };
3251 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3252 ARM::VST3q16oddPseudo,
3253 ARM::VST3q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003254 return SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003255 }
3256
3257 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003258 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3259 ARM::VST4d16Pseudo,
3260 ARM::VST4d32Pseudo,
3261 ARM::VST1d64QPseudo };
3262 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3263 ARM::VST4q16Pseudo_UPD,
3264 ARM::VST4q32Pseudo_UPD };
3265 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3266 ARM::VST4q16oddPseudo,
3267 ARM::VST4q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003268 return SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003269 }
Bob Wilsond7797752009-09-01 18:51:56 +00003270
3271 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003272 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3273 ARM::VST2LNd16Pseudo,
3274 ARM::VST2LNd32Pseudo };
3275 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3276 ARM::VST2LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003277 return SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003278 }
3279
3280 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003281 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3282 ARM::VST3LNd16Pseudo,
3283 ARM::VST3LNd32Pseudo };
3284 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3285 ARM::VST3LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003286 return SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003287 }
3288
3289 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003290 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3291 ARM::VST4LNd16Pseudo,
3292 ARM::VST4LNd32Pseudo };
3293 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3294 ARM::VST4LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003295 return SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003296 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003297 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003298 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003299 }
Evan Chengd85631e2010-05-05 18:28:36 +00003300
Bob Wilson3ed511b2010-07-06 23:36:25 +00003301 case ISD::INTRINSIC_WO_CHAIN: {
3302 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3303 switch (IntNo) {
3304 default:
3305 break;
3306
3307 case Intrinsic::arm_neon_vtbl2:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003308 return SelectVTBL(N, false, 2, ARM::VTBL2);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003309 case Intrinsic::arm_neon_vtbl3:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003310 return SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003311 case Intrinsic::arm_neon_vtbl4:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003312 return SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003313
3314 case Intrinsic::arm_neon_vtbx2:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003315 return SelectVTBL(N, true, 2, ARM::VTBX2);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003316 case Intrinsic::arm_neon_vtbx3:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003317 return SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003318 case Intrinsic::arm_neon_vtbx4:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003319 return SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003320 }
3321 break;
3322 }
3323
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003324 case ARMISD::VTBL1: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003325 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003326 EVT VT = N->getValueType(0);
3327 SmallVector<SDValue, 6> Ops;
3328
3329 Ops.push_back(N->getOperand(0));
3330 Ops.push_back(N->getOperand(1));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003331 Ops.push_back(getAL(CurDAG, dl)); // Predicate
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003332 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Michael Liaob53d8962013-04-19 22:22:57 +00003333 return CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003334 }
3335 case ARMISD::VTBL2: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003336 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003337 EVT VT = N->getValueType(0);
3338
3339 // Form a REG_SEQUENCE to force register allocation.
3340 SDValue V0 = N->getOperand(0);
3341 SDValue V1 = N->getOperand(1);
Weiming Zhao95782222012-11-17 00:23:35 +00003342 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003343
3344 SmallVector<SDValue, 6> Ops;
3345 Ops.push_back(RegSeq);
3346 Ops.push_back(N->getOperand(2));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003347 Ops.push_back(getAL(CurDAG, dl)); // Predicate
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003348 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Michael Liaob53d8962013-04-19 22:22:57 +00003349 return CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003350 }
3351
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003352 case ISD::CONCAT_VECTORS:
Evan Chengd85631e2010-05-05 18:28:36 +00003353 return SelectConcatVector(N);
3354 }
Evan Chengd5021732008-12-10 21:54:21 +00003355
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003356 return SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003357}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003358
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003359// Inspect a register string of the form
3360// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3361// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3362// and obtain the integer operands from them, adding these operands to the
3363// provided vector.
3364static void getIntOperandsFromRegisterString(StringRef RegString,
3365 SelectionDAG *CurDAG, SDLoc DL,
3366 std::vector<SDValue>& Ops) {
3367 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003368 RegString.split(Fields, ':');
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003369
3370 if (Fields.size() > 1) {
3371 bool AllIntFields = true;
3372
3373 for (StringRef Field : Fields) {
3374 // Need to trim out leading 'cp' characters and get the integer field.
3375 unsigned IntField;
3376 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3377 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3378 }
3379
3380 assert(AllIntFields &&
3381 "Unexpected non-integer value in special register string.");
3382 }
3383}
3384
3385// Maps a Banked Register string to its mask value. The mask value returned is
3386// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3387// mask operand, which expresses which register is to be used, e.g. r8, and in
3388// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3389// was invalid.
3390static inline int getBankedRegisterMask(StringRef RegString) {
3391 return StringSwitch<int>(RegString.lower())
3392 .Case("r8_usr", 0x00)
3393 .Case("r9_usr", 0x01)
3394 .Case("r10_usr", 0x02)
3395 .Case("r11_usr", 0x03)
3396 .Case("r12_usr", 0x04)
3397 .Case("sp_usr", 0x05)
3398 .Case("lr_usr", 0x06)
3399 .Case("r8_fiq", 0x08)
3400 .Case("r9_fiq", 0x09)
3401 .Case("r10_fiq", 0x0a)
3402 .Case("r11_fiq", 0x0b)
3403 .Case("r12_fiq", 0x0c)
3404 .Case("sp_fiq", 0x0d)
3405 .Case("lr_fiq", 0x0e)
3406 .Case("lr_irq", 0x10)
3407 .Case("sp_irq", 0x11)
3408 .Case("lr_svc", 0x12)
3409 .Case("sp_svc", 0x13)
3410 .Case("lr_abt", 0x14)
3411 .Case("sp_abt", 0x15)
3412 .Case("lr_und", 0x16)
3413 .Case("sp_und", 0x17)
3414 .Case("lr_mon", 0x1c)
3415 .Case("sp_mon", 0x1d)
3416 .Case("elr_hyp", 0x1e)
3417 .Case("sp_hyp", 0x1f)
3418 .Case("spsr_fiq", 0x2e)
3419 .Case("spsr_irq", 0x30)
3420 .Case("spsr_svc", 0x32)
3421 .Case("spsr_abt", 0x34)
3422 .Case("spsr_und", 0x36)
3423 .Case("spsr_mon", 0x3c)
3424 .Case("spsr_hyp", 0x3e)
3425 .Default(-1);
3426}
3427
3428// Maps a MClass special register string to its value for use in the
3429// t2MRS_M / t2MSR_M instruction nodes as the SYSm value operand.
3430// Returns -1 to signify that the string was invalid.
3431static inline int getMClassRegisterSYSmValueMask(StringRef RegString) {
3432 return StringSwitch<int>(RegString.lower())
3433 .Case("apsr", 0x0)
3434 .Case("iapsr", 0x1)
3435 .Case("eapsr", 0x2)
3436 .Case("xpsr", 0x3)
3437 .Case("ipsr", 0x5)
3438 .Case("epsr", 0x6)
3439 .Case("iepsr", 0x7)
3440 .Case("msp", 0x8)
3441 .Case("psp", 0x9)
3442 .Case("primask", 0x10)
3443 .Case("basepri", 0x11)
3444 .Case("basepri_max", 0x12)
3445 .Case("faultmask", 0x13)
3446 .Case("control", 0x14)
3447 .Default(-1);
3448}
3449
3450// The flags here are common to those allowed for apsr in the A class cores and
3451// those allowed for the special registers in the M class cores. Returns a
3452// value representing which flags were present, -1 if invalid.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003453static inline int getMClassFlagsMask(StringRef Flags, bool hasDSP) {
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003454 if (Flags.empty())
Artyom Skrobovcf296442015-09-24 17:31:16 +00003455 return 0x2 | (int)hasDSP;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003456
3457 return StringSwitch<int>(Flags)
3458 .Case("g", 0x1)
3459 .Case("nzcvq", 0x2)
3460 .Case("nzcvqg", 0x3)
3461 .Default(-1);
3462}
3463
3464static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead,
3465 const ARMSubtarget *Subtarget) {
3466 // Ensure that the register (without flags) was a valid M Class special
3467 // register.
3468 int SYSmvalue = getMClassRegisterSYSmValueMask(Reg);
3469 if (SYSmvalue == -1)
3470 return -1;
3471
3472 // basepri, basepri_max and faultmask are only valid for V7m.
3473 if (!Subtarget->hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
3474 return -1;
3475
3476 // If it was a read then we won't be expecting flags and so at this point
3477 // we can return the mask.
3478 if (IsRead) {
3479 assert (Flags.empty() && "Unexpected flags for reading M class register.");
3480 return SYSmvalue;
3481 }
3482
3483 // We know we are now handling a write so need to get the mask for the flags.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003484 int Mask = getMClassFlagsMask(Flags, Subtarget->hasDSP());
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003485
3486 // Only apsr, iapsr, eapsr, xpsr can have flags. The other register values
3487 // shouldn't have flags present.
3488 if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.empty()))
3489 return -1;
3490
3491 // The _g and _nzcvqg versions are only valid if the DSP extension is
3492 // available.
Artyom Skrobovcf296442015-09-24 17:31:16 +00003493 if (!Subtarget->hasDSP() && (Mask & 0x1))
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003494 return -1;
3495
3496 // The register was valid so need to put the mask in the correct place
3497 // (the flags need to be in bits 11-10) and combine with the SYSmvalue to
3498 // construct the operand for the instruction node.
3499 if (SYSmvalue < 0x4)
3500 return SYSmvalue | Mask << 10;
3501
3502 return SYSmvalue;
3503}
3504
3505static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
3506 // The mask operand contains the special register (R Bit) in bit 4, whether
3507 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
3508 // bits 3-0 contains the fields to be accessed in the special register, set by
3509 // the flags provided with the register.
3510 int Mask = 0;
3511 if (Reg == "apsr") {
3512 // The flags permitted for apsr are the same flags that are allowed in
3513 // M class registers. We get the flag value and then shift the flags into
3514 // the correct place to combine with the mask.
Artyom Skrobov6fbef2a2015-08-05 11:02:14 +00003515 Mask = getMClassFlagsMask(Flags, true);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003516 if (Mask == -1)
3517 return -1;
3518 return Mask << 2;
3519 }
3520
3521 if (Reg != "cpsr" && Reg != "spsr") {
3522 return -1;
3523 }
3524
3525 // This is the same as if the flags were "fc"
3526 if (Flags.empty() || Flags == "all")
3527 return Mask | 0x9;
3528
3529 // Inspect the supplied flags string and set the bits in the mask for
3530 // the relevant and valid flags allowed for cpsr and spsr.
3531 for (char Flag : Flags) {
3532 int FlagVal;
3533 switch (Flag) {
3534 case 'c':
3535 FlagVal = 0x1;
3536 break;
3537 case 'x':
3538 FlagVal = 0x2;
3539 break;
3540 case 's':
3541 FlagVal = 0x4;
3542 break;
3543 case 'f':
3544 FlagVal = 0x8;
3545 break;
3546 default:
3547 FlagVal = 0;
3548 }
3549
3550 // This avoids allowing strings where the same flag bit appears twice.
3551 if (!FlagVal || (Mask & FlagVal))
3552 return -1;
3553 Mask |= FlagVal;
3554 }
3555
3556 // If the register is spsr then we need to set the R bit.
3557 if (Reg == "spsr")
3558 Mask |= 0x10;
3559
3560 return Mask;
3561}
3562
3563// Lower the read_register intrinsic to ARM specific DAG nodes
3564// using the supplied metadata string to select the instruction node to use
3565// and the registers/masks to construct as operands for the node.
3566SDNode *ARMDAGToDAGISel::SelectReadRegister(SDNode *N){
3567 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3568 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3569 bool IsThumb2 = Subtarget->isThumb2();
3570 SDLoc DL(N);
3571
3572 std::vector<SDValue> Ops;
3573 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3574
3575 if (!Ops.empty()) {
3576 // If the special register string was constructed of fields (as defined
3577 // in the ACLE) then need to lower to MRC node (32 bit) or
3578 // MRRC node(64 bit), we can make the distinction based on the number of
3579 // operands we have.
3580 unsigned Opcode;
3581 SmallVector<EVT, 3> ResTypes;
3582 if (Ops.size() == 5){
3583 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
3584 ResTypes.append({ MVT::i32, MVT::Other });
3585 } else {
3586 assert(Ops.size() == 3 &&
3587 "Invalid number of fields in special register string.");
3588 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
3589 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
3590 }
3591
3592 Ops.push_back(getAL(CurDAG, DL));
3593 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3594 Ops.push_back(N->getOperand(0));
3595 return CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops);
3596 }
3597
3598 std::string SpecialReg = RegString->getString().lower();
3599
3600 int BankedReg = getBankedRegisterMask(SpecialReg);
3601 if (BankedReg != -1) {
3602 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
3603 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3604 N->getOperand(0) };
3605 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
3606 DL, MVT::i32, MVT::Other, Ops);
3607 }
3608
3609 // The VFP registers are read by creating SelectionDAG nodes with opcodes
3610 // corresponding to the register that is being read from. So we switch on the
3611 // string to find which opcode we need to use.
3612 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3613 .Case("fpscr", ARM::VMRS)
3614 .Case("fpexc", ARM::VMRS_FPEXC)
3615 .Case("fpsid", ARM::VMRS_FPSID)
3616 .Case("mvfr0", ARM::VMRS_MVFR0)
3617 .Case("mvfr1", ARM::VMRS_MVFR1)
3618 .Case("mvfr2", ARM::VMRS_MVFR2)
3619 .Case("fpinst", ARM::VMRS_FPINST)
3620 .Case("fpinst2", ARM::VMRS_FPINST2)
3621 .Default(0);
3622
3623 // If an opcode was found then we can lower the read to a VFP instruction.
3624 if (Opcode) {
3625 if (!Subtarget->hasVFP2())
3626 return nullptr;
3627 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
3628 return nullptr;
3629
3630 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3631 N->getOperand(0) };
3632 return CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops);
3633 }
3634
3635 // If the target is M Class then need to validate that the register string
3636 // is an acceptable value, so check that a mask can be constructed from the
3637 // string.
3638 if (Subtarget->isMClass()) {
3639 int SYSmValue = getMClassRegisterMask(SpecialReg, "", true, Subtarget);
3640 if (SYSmValue == -1)
3641 return nullptr;
3642
3643 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
3644 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3645 N->getOperand(0) };
3646 return CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops);
3647 }
3648
3649 // Here we know the target is not M Class so we need to check if it is one
3650 // of the remaining possible values which are apsr, cpsr or spsr.
3651 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
3652 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3653 N->getOperand(0) };
3654 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS, DL,
3655 MVT::i32, MVT::Other, Ops);
3656 }
3657
3658 if (SpecialReg == "spsr") {
3659 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3660 N->getOperand(0) };
3661 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys,
3662 DL, MVT::i32, MVT::Other, Ops);
3663 }
3664
3665 return nullptr;
3666}
3667
3668// Lower the write_register intrinsic to ARM specific DAG nodes
3669// using the supplied metadata string to select the instruction node to use
3670// and the registers/masks to use in the nodes
3671SDNode *ARMDAGToDAGISel::SelectWriteRegister(SDNode *N){
3672 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3673 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3674 bool IsThumb2 = Subtarget->isThumb2();
3675 SDLoc DL(N);
3676
3677 std::vector<SDValue> Ops;
3678 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3679
3680 if (!Ops.empty()) {
3681 // If the special register string was constructed of fields (as defined
3682 // in the ACLE) then need to lower to MCR node (32 bit) or
3683 // MCRR node(64 bit), we can make the distinction based on the number of
3684 // operands we have.
3685 unsigned Opcode;
3686 if (Ops.size() == 5) {
3687 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
3688 Ops.insert(Ops.begin()+2, N->getOperand(2));
3689 } else {
3690 assert(Ops.size() == 3 &&
3691 "Invalid number of fields in special register string.");
3692 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
3693 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
3694 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
3695 }
3696
3697 Ops.push_back(getAL(CurDAG, DL));
3698 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3699 Ops.push_back(N->getOperand(0));
3700
3701 return CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops);
3702 }
3703
3704 std::string SpecialReg = RegString->getString().lower();
3705 int BankedReg = getBankedRegisterMask(SpecialReg);
3706 if (BankedReg != -1) {
3707 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
3708 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3709 N->getOperand(0) };
3710 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
3711 DL, MVT::Other, Ops);
3712 }
3713
3714 // The VFP registers are written to by creating SelectionDAG nodes with
3715 // opcodes corresponding to the register that is being written. So we switch
3716 // on the string to find which opcode we need to use.
3717 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3718 .Case("fpscr", ARM::VMSR)
3719 .Case("fpexc", ARM::VMSR_FPEXC)
3720 .Case("fpsid", ARM::VMSR_FPSID)
3721 .Case("fpinst", ARM::VMSR_FPINST)
3722 .Case("fpinst2", ARM::VMSR_FPINST2)
3723 .Default(0);
3724
3725 if (Opcode) {
3726 if (!Subtarget->hasVFP2())
3727 return nullptr;
3728 Ops = { N->getOperand(2), getAL(CurDAG, DL),
3729 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
3730 return CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops);
3731 }
3732
3733 SmallVector<StringRef, 5> Fields;
Chandler Carruthe4405e92015-09-10 06:12:31 +00003734 StringRef(SpecialReg).split(Fields, '_', 1, false);
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003735 std::string Reg = Fields[0].str();
3736 StringRef Flags = Fields.size() == 2 ? Fields[1] : "";
3737
3738 // If the target was M Class then need to validate the special register value
3739 // and retrieve the mask for use in the instruction node.
3740 if (Subtarget->isMClass()) {
3741 // basepri_max gets split so need to correct Reg and Flags.
3742 if (SpecialReg == "basepri_max") {
3743 Reg = SpecialReg;
3744 Flags = "";
3745 }
3746 int SYSmValue = getMClassRegisterMask(Reg, Flags, false, Subtarget);
3747 if (SYSmValue == -1)
3748 return nullptr;
3749
3750 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
3751 N->getOperand(2), getAL(CurDAG, DL),
3752 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
3753 return CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops);
3754 }
3755
3756 // We then check to see if a valid mask can be constructed for one of the
3757 // register string values permitted for the A and R class cores. These values
3758 // are apsr, spsr and cpsr; these are also valid on older cores.
3759 int Mask = getARClassRegisterMask(Reg, Flags);
3760 if (Mask != -1) {
3761 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
3762 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3763 N->getOperand(0) };
3764 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
3765 DL, MVT::Other, Ops);
3766 }
3767
3768 return nullptr;
3769}
3770
Weiming Zhaoc5987002013-02-14 18:10:21 +00003771SDNode *ARMDAGToDAGISel::SelectInlineAsm(SDNode *N){
3772 std::vector<SDValue> AsmNodeOperands;
3773 unsigned Flag, Kind;
3774 bool Changed = false;
3775 unsigned NumOps = N->getNumOperands();
3776
Weiming Zhaoc5987002013-02-14 18:10:21 +00003777 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
3778 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
3779 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
3780 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003781 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
3782 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
3783 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00003784
Andrew Trickef9de2a2013-05-25 02:42:55 +00003785 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00003786 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
3787 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003788
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003789 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003790 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003791 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00003792 SDValue op = N->getOperand(i);
3793 AsmNodeOperands.push_back(op);
3794
3795 if (i < InlineAsm::Op_FirstOperand)
3796 continue;
3797
3798 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
3799 Flag = C->getZExtValue();
3800 Kind = InlineAsm::getKind(Flag);
3801 }
3802 else
3803 continue;
3804
Joey Gouly392cdad2013-07-08 19:52:51 +00003805 // Immediate operands to inline asm in the SelectionDAG are modeled with
3806 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
3807 // the second is a constant with the value of the immediate. If we get here
3808 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00003809 if (Kind == InlineAsm::Kind_Imm) {
3810 SDValue op = N->getOperand(++i);
3811 AsmNodeOperands.push_back(op);
3812 continue;
3813 }
3814
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003815 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
3816 if (NumRegs)
3817 OpChanged.push_back(false);
3818
3819 unsigned DefIdx = 0;
3820 bool IsTiedToChangedOp = false;
3821 // If it's a use that is tied with a previous def, it has no
3822 // reg class constraint.
3823 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
3824 IsTiedToChangedOp = OpChanged[DefIdx];
3825
Weiming Zhaoc5987002013-02-14 18:10:21 +00003826 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
3827 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
3828 continue;
3829
Weiming Zhaoc5987002013-02-14 18:10:21 +00003830 unsigned RC;
3831 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003832 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
3833 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00003834 continue;
3835
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003836 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00003837 SDValue V0 = N->getOperand(i+1);
3838 SDValue V1 = N->getOperand(i+2);
3839 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
3840 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
3841 SDValue PairedReg;
3842 MachineRegisterInfo &MRI = MF->getRegInfo();
3843
3844 if (Kind == InlineAsm::Kind_RegDef ||
3845 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
3846 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
3847 // the original GPRs.
3848
3849 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3850 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3851 SDValue Chain = SDValue(N,0);
3852
3853 SDNode *GU = N->getGluedUser();
3854 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
3855 Chain.getValue(1));
3856
3857 // Extract values from a GPRPair reg and copy to the original GPR reg.
3858 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
3859 RegCopy);
3860 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
3861 RegCopy);
3862 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
3863 RegCopy.getValue(1));
3864 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
3865
3866 // Update the original glue user.
3867 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
3868 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00003869 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003870 }
3871 else {
3872 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
3873 // GPRPair and then pass the GPRPair to the inline asm.
3874 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
3875
3876 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
3877 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
3878 Chain.getValue(1));
3879 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
3880 T0.getValue(1));
3881 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
3882
3883 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
3884 // i32 VRs of inline asm with it.
3885 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3886 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3887 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
3888
3889 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
3890 Glue = Chain.getValue(1);
3891 }
3892
3893 Changed = true;
3894
3895 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003896 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003897 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00003898 if (IsTiedToChangedOp)
3899 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
3900 else
3901 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003902 // Replace the current flag.
3903 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003904 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003905 // Add the new register node and skip the original two GPRs.
3906 AsmNodeOperands.push_back(PairedReg);
3907 // Skip the next two GPRs.
3908 i += 2;
3909 }
3910 }
3911
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003912 if (Glue.getNode())
3913 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003914 if (!Changed)
Craig Topper062a2ba2014-04-25 05:30:21 +00003915 return nullptr;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003916
Andrew Trickef9de2a2013-05-25 02:42:55 +00003917 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00003918 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003919 New->setNodeId(-1);
3920 return New.getNode();
3921}
3922
3923
Bob Wilsona2c462b2009-05-19 05:53:42 +00003924bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00003925SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00003926 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00003927 switch(ConstraintID) {
3928 default:
3929 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00003930 case InlineAsm::Constraint_i:
3931 // FIXME: It seems strange that 'i' is needed here since it's supposed to
3932 // be an immediate and not a memory constraint.
3933 // Fallthrough.
Daniel Sanders1f58ef72015-06-03 12:33:56 +00003934 case InlineAsm::Constraint_m:
James Molloy72222f52015-10-26 10:04:52 +00003935 case InlineAsm::Constraint_o:
Daniel Sanders1f58ef72015-06-03 12:33:56 +00003936 case InlineAsm::Constraint_Q:
3937 case InlineAsm::Constraint_Um:
3938 case InlineAsm::Constraint_Un:
3939 case InlineAsm::Constraint_Uq:
3940 case InlineAsm::Constraint_Us:
3941 case InlineAsm::Constraint_Ut:
3942 case InlineAsm::Constraint_Uv:
3943 case InlineAsm::Constraint_Uy:
3944 // Require the address to be in a register. That is safe for all ARM
3945 // variants and it is hard to do anything much smarter without knowing
3946 // how the operand is used.
3947 OutOps.push_back(Op);
3948 return false;
3949 }
3950 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00003951}
3952
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003953/// createARMISelDag - This pass converts a legalized DAG into a
3954/// ARM-specific DAG, ready for instruction scheduling.
3955///
Bob Wilson2dd957f2009-09-28 14:30:20 +00003956FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
3957 CodeGenOpt::Level OptLevel) {
3958 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003959}