blob: 50afb192b331d4ea05405cb6d28c487486aecdc6 [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 SelectThumbAddrModeRI(SDValue N, SDValue &Base, SDValue &Offset,
164 unsigned Scale);
165 bool SelectThumbAddrModeRI5S1(SDValue N, SDValue &Base, SDValue &Offset);
166 bool SelectThumbAddrModeRI5S2(SDValue N, SDValue &Base, SDValue &Offset);
167 bool SelectThumbAddrModeRI5S4(SDValue N, SDValue &Base, SDValue &Offset);
168 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
169 SDValue &OffImm);
170 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
171 SDValue &OffImm);
172 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
173 SDValue &OffImm);
174 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
175 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000176 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +0000177
Bill Wendling092a7bd2010-12-14 03:36:38 +0000178 // Thumb 2 Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000179 bool SelectT2ShifterOperandReg(SDValue N,
Evan Chengeab9ca72009-06-27 02:26:13 +0000180 SDValue &BaseReg, SDValue &Opc);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000181 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
182 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000183 SDValue &OffImm);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000184 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +0000185 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000186 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000187 SDValue &OffReg, SDValue &ShImm);
Tim Northovera7ecd242013-07-16 09:46:55 +0000188 bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Chengb23b50d2009-06-29 07:51:04 +0000189
Evan Cheng0fc80842010-11-12 22:42:47 +0000190 inline bool is_so_imm(unsigned Imm) const {
191 return ARM_AM::getSOImmVal(Imm) != -1;
192 }
193
194 inline bool is_so_imm_not(unsigned Imm) const {
195 return ARM_AM::getSOImmVal(~Imm) != -1;
196 }
197
198 inline bool is_t2_so_imm(unsigned Imm) const {
199 return ARM_AM::getT2SOImmVal(Imm) != -1;
200 }
201
202 inline bool is_t2_so_imm_not(unsigned Imm) const {
203 return ARM_AM::getT2SOImmVal(~Imm) != -1;
204 }
205
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000206 // Include the pieces autogenerated from the target description.
207#include "ARMGenDAGISel.inc"
Bob Wilsona2c462b2009-05-19 05:53:42 +0000208
209private:
Evan Cheng84c6cda2009-07-02 07:28:31 +0000210 /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
211 /// ARM.
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000212 SDNode *SelectARMIndexedLoad(SDNode *N);
213 SDNode *SelectT2IndexedLoad(SDNode *N);
Evan Cheng84c6cda2009-07-02 07:28:31 +0000214
Bob Wilson340861d2010-03-23 05:25:43 +0000215 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
216 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson12b47992009-10-14 17:28:52 +0000217 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson340861d2010-03-23 05:25:43 +0000218 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson06fce872011-02-07 17:43:21 +0000219 SDNode *SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000220 const uint16_t *DOpcodes,
221 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilson12b47992009-10-14 17:28:52 +0000222
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000223 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000224 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000225 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000226 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson06fce872011-02-07 17:43:21 +0000227 SDNode *SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000228 const uint16_t *DOpcodes,
229 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000230
Bob Wilson93117bc2009-10-14 16:46:45 +0000231 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilson4145e3a2009-10-14 16:19:03 +0000232 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsond5c57a52010-09-13 23:01:35 +0000233 /// load/store of D registers and Q registers.
Bob Wilson06fce872011-02-07 17:43:21 +0000234 SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad,
235 bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000236 const uint16_t *DOpcodes, const uint16_t *QOpcodes);
Bob Wilson4145e3a2009-10-14 16:19:03 +0000237
Bob Wilson2d790df2010-11-28 06:51:26 +0000238 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
239 /// should be 2, 3 or 4. The opcode array specifies the instructions used
240 /// for loading D registers. (Q registers are not supported.)
Bob Wilson06fce872011-02-07 17:43:21 +0000241 SDNode *SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000242 const uint16_t *Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +0000243
Bob Wilson5bc8a792010-07-07 00:08:54 +0000244 /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2,
245 /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be
246 /// generated to force the table registers to be consecutive.
247 SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc);
Bob Wilson3ed511b2010-07-06 23:36:25 +0000248
Sandeep Patel7460e082009-10-13 20:25:58 +0000249 /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
Jim Grosbach825cb292010-04-22 23:24:18 +0000250 SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000251
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000252 // Select special operations if node forms integer ABS pattern
253 SDNode *SelectABSOp(SDNode *N);
254
Luke Cheeseman85fd06d2015-06-01 12:02:47 +0000255 SDNode *SelectReadRegister(SDNode *N);
256 SDNode *SelectWriteRegister(SDNode *N);
257
Weiming Zhaoc5987002013-02-14 18:10:21 +0000258 SDNode *SelectInlineAsm(SDNode *N);
259
Evan Chengd85631e2010-05-05 18:28:36 +0000260 SDNode *SelectConcatVector(SDNode *N);
261
Evan Chengd9c55362009-07-02 01:23:32 +0000262 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
263 /// inline asm expressions.
Daniel Sanders60f1db02015-03-13 12:45:09 +0000264 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Craig Topper6bc27bf2014-03-10 02:09:33 +0000265 std::vector<SDValue> &OutOps) override;
Bob Wilsone6b778d2009-10-06 22:01:59 +0000266
Weiming Zhao95782222012-11-17 00:23:35 +0000267 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhao8f56f882012-11-16 21:55:34 +0000268 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao95782222012-11-17 00:23:35 +0000269 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
270 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
271 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Chengc2ae5f52010-05-10 17:34:18 +0000272
Bob Wilsond8a9a042010-06-04 00:04:02 +0000273 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +0000274 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
275 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
276 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000277
278 // Get the alignment operand for a NEON VLD or VST instruction.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000279 SDValue GetVLDSTAlign(SDValue Align, SDLoc dl, unsigned NumVecs,
280 bool is64BitVector);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000281};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000282}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000283
Sandeep Patel423e42b2009-10-13 18:59:48 +0000284/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
285/// operand. If so Imm will receive the 32-bit value.
286static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
287 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
288 Imm = cast<ConstantSDNode>(N)->getZExtValue();
289 return true;
290 }
291 return false;
292}
293
294// isInt32Immediate - This method tests to see if a constant operand.
295// If so Imm will receive the 32 bit value.
296static bool isInt32Immediate(SDValue N, unsigned &Imm) {
297 return isInt32Immediate(N.getNode(), Imm);
298}
299
300// isOpcWithIntImmediate - This method tests to see if the node is a specific
301// opcode and that it has a immediate integer right operand.
302// If so Imm will receive the 32 bit value.
303static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
304 return N->getOpcode() == Opc &&
305 isInt32Immediate(N->getOperand(1).getNode(), Imm);
306}
307
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000308/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000309/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000310///
311/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000312static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000313 int RangeMin, int RangeMax,
314 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000315 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000316
317 // Check that this is a constant.
318 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
319 if (!C)
320 return false;
321
322 ScaledConstant = (int) C->getZExtValue();
323 if ((ScaledConstant % Scale) != 0)
324 return false;
325
326 ScaledConstant /= Scale;
327 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
328}
329
Evan Chengeae6d2c2012-12-19 20:16:09 +0000330void ARMDAGToDAGISel::PreprocessISelDAG() {
331 if (!Subtarget->hasV6T2Ops())
332 return;
333
334 bool isThumb2 = Subtarget->isThumb();
335 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
336 E = CurDAG->allnodes_end(); I != E; ) {
337 SDNode *N = I++; // Preincrement iterator to avoid invalidation issues.
338
339 if (N->getOpcode() != ISD::ADD)
340 continue;
341
342 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
343 // leading zeros, followed by consecutive set bits, followed by 1 or 2
344 // trailing zeros, e.g. 1020.
345 // Transform the expression to
346 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
347 // of trailing zeros of c2. The left shift would be folded as an shifter
348 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
349 // node (UBFX).
350
351 SDValue N0 = N->getOperand(0);
352 SDValue N1 = N->getOperand(1);
353 unsigned And_imm = 0;
354 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
355 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
356 std::swap(N0, N1);
357 }
358 if (!And_imm)
359 continue;
360
361 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000362 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000363 if (TZ != 1 && TZ != 2)
364 // Be conservative here. Shifter operands aren't always free. e.g. On
365 // Swift, left shifter operand of 1 / 2 for free but others are not.
366 // e.g.
367 // ubfx r3, r1, #16, #8
368 // ldr.w r3, [r0, r3, lsl #2]
369 // vs.
370 // mov.w r9, #1020
371 // and.w r2, r9, r1, lsr #14
372 // ldr r2, [r0, r2]
373 continue;
374 And_imm >>= TZ;
375 if (And_imm & (And_imm + 1))
376 continue;
377
378 // Look for (and (srl X, c1), c2).
379 SDValue Srl = N1.getOperand(0);
380 unsigned Srl_imm = 0;
381 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
382 (Srl_imm <= 2))
383 continue;
384
385 // Make sure first operand is not a shifter operand which would prevent
386 // folding of the left shift.
387 SDValue CPTmp0;
388 SDValue CPTmp1;
389 SDValue CPTmp2;
390 if (isThumb2) {
391 if (SelectT2ShifterOperandReg(N0, CPTmp0, CPTmp1))
392 continue;
393 } else {
394 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
395 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
396 continue;
397 }
398
399 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000400 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000401 Srl.getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000402 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl),
403 MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000404 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000405 Srl,
406 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000407 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000408 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32));
Evan Chengeae6d2c2012-12-19 20:16:09 +0000409 CurDAG->UpdateNodeOperands(N, N0, N1);
Jim Grosbach1a597112014-04-03 23:43:18 +0000410 }
Evan Chengeae6d2c2012-12-19 20:16:09 +0000411}
412
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000413/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
414/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
415/// least on current ARM implementations) which should be avoidded.
416bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
417 if (OptLevel == CodeGenOpt::None)
418 return true;
419
420 if (!CheckVMLxHazard)
421 return true;
Bob Wilsone8a549c2012-09-29 21:43:49 +0000422
Tim Northover0feb91e2014-04-01 14:10:07 +0000423 if (!Subtarget->isCortexA7() && !Subtarget->isCortexA8() &&
424 !Subtarget->isCortexA9() && !Subtarget->isSwift())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000425 return true;
426
427 if (!N->hasOneUse())
428 return false;
429
430 SDNode *Use = *N->use_begin();
431 if (Use->getOpcode() == ISD::CopyToReg)
432 return true;
433 if (Use->isMachineOpcode()) {
Eric Christopher2f991c92014-07-03 22:24:49 +0000434 const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>(
Eric Christopherfc6de422014-08-05 02:39:49 +0000435 CurDAG->getSubtarget().getInstrInfo());
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000436
Evan Cheng6cc775f2011-06-28 19:10:37 +0000437 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
438 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000439 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000440 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000441 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
442 return true;
443 // vmlx feeding into another vmlx. We actually want to unfold
444 // the use later in the MLxExpansion pass. e.g.
445 // vmla
446 // vmla (stall 8 cycles)
447 //
448 // vmul (5 cycles)
449 // vadd (5 cycles)
450 // vmla
451 // This adds up to about 18 - 19 cycles.
452 //
453 // vmla
454 // vmul (stall 4 cycles)
455 // vadd adds up to about 14 cycles.
456 return TII->isFpMLxInstruction(Opcode);
457 }
458
459 return false;
460}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000461
Evan Cheng59bbc542010-10-27 23:41:30 +0000462bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
463 ARM_AM::ShiftOpc ShOpcVal,
464 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000465 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000466 return true;
467 if (Shift.hasOneUse())
468 return true;
469 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000470 return ShOpcVal == ARM_AM::lsl &&
471 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000472}
473
Owen Andersonb595ed02011-07-21 18:54:16 +0000474bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000475 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000476 SDValue &Opc,
477 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000478 if (DisableShifterOp)
479 return false;
480
Evan Chenga20cde32011-07-20 23:34:39 +0000481 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000482
483 // Don't match base register only case. That is matched to a separate
484 // lower complexity pattern with explicit register operand.
485 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000486
Evan Chengb23b50d2009-06-29 07:51:04 +0000487 BaseReg = N.getOperand(0);
488 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000489 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
490 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000491 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000492 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000493 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000494 return true;
495}
496
Owen Andersonb595ed02011-07-21 18:54:16 +0000497bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
498 SDValue &BaseReg,
499 SDValue &ShReg,
500 SDValue &Opc,
501 bool CheckProfitability) {
502 if (DisableShifterOp)
503 return false;
504
505 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
506
507 // Don't match base register only case. That is matched to a separate
508 // lower complexity pattern with explicit register operand.
509 if (ShOpcVal == ARM_AM::no_shift) return false;
510
511 BaseReg = N.getOperand(0);
512 unsigned ShImmVal = 0;
513 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
514 if (RHS) return false;
515
516 ShReg = N.getOperand(1);
517 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
518 return false;
519 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000520 SDLoc(N), MVT::i32);
Owen Andersonb595ed02011-07-21 18:54:16 +0000521 return true;
522}
523
524
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000525bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
526 SDValue &Base,
527 SDValue &OffImm) {
528 // Match simple R + imm12 operands.
529
530 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000531 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
532 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000533 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000534 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000535 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +0000536 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000537 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000538 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000539 }
Owen Anderson6d557452011-03-18 19:46:58 +0000540
Chris Lattner46c01a32011-02-13 22:25:43 +0000541 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northover72360d22013-12-02 10:35:41 +0000542 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000543 Base = N.getOperand(0);
544 } else
545 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000546 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000547 return true;
548 }
549
550 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Renato Golin63e27982014-09-09 09:57:59 +0000551 int RHSC = (int)RHS->getSExtValue();
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000552 if (N.getOpcode() == ISD::SUB)
553 RHSC = -RHSC;
554
Renato Golin63e27982014-09-09 09:57:59 +0000555 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000556 Base = N.getOperand(0);
557 if (Base.getOpcode() == ISD::FrameIndex) {
558 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +0000559 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000560 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000561 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000562 return true;
563 }
564 }
565
566 // Base only.
567 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000568 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000569 return true;
570}
571
572
573
574bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
575 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000576 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000577 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000578 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
579 // X * [3,5,9] -> X + X * [2,4,8] etc.
580 int RHSC = (int)RHS->getZExtValue();
581 if (RHSC & 1) {
582 RHSC = RHSC & ~1;
583 ARM_AM::AddrOpc AddSub = ARM_AM::add;
584 if (RHSC < 0) {
585 AddSub = ARM_AM::sub;
586 RHSC = - RHSC;
587 }
588 if (isPowerOf2_32(RHSC)) {
589 unsigned ShAmt = Log2_32(RHSC);
590 Base = Offset = N.getOperand(0);
591 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
592 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000593 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000594 return true;
595 }
596 }
597 }
598 }
599
Chris Lattner46c01a32011-02-13 22:25:43 +0000600 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
601 // ISD::OR that is equivalent to an ISD::ADD.
602 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000603 return false;
604
605 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000606 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000607 int RHSC;
608 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
609 -0x1000+1, 0x1000, RHSC)) // 12 bits.
610 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000611 }
612
613 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000614 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000615 ARM_AM::ShiftOpc ShOpcVal =
616 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000617 unsigned ShAmt = 0;
618
619 Base = N.getOperand(0);
620 Offset = N.getOperand(1);
621
622 if (ShOpcVal != ARM_AM::no_shift) {
623 // Check to see if the RHS of the shift is a constant, if not, we can't fold
624 // it.
625 if (ConstantSDNode *Sh =
626 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
627 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000628 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
629 Offset = N.getOperand(1).getOperand(0);
630 else {
631 ShAmt = 0;
632 ShOpcVal = ARM_AM::no_shift;
633 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000634 } else {
635 ShOpcVal = ARM_AM::no_shift;
636 }
637 }
638
639 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000640 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000641 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
642 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000643 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000644 if (ShOpcVal != ARM_AM::no_shift) {
645 // Check to see if the RHS of the shift is a constant, if not, we can't
646 // fold it.
647 if (ConstantSDNode *Sh =
648 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
649 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000650 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000651 Offset = N.getOperand(0).getOperand(0);
652 Base = N.getOperand(1);
653 } else {
654 ShAmt = 0;
655 ShOpcVal = ARM_AM::no_shift;
656 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000657 } else {
658 ShOpcVal = ARM_AM::no_shift;
659 }
660 }
661 }
662
663 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000664 SDLoc(N), MVT::i32);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000665 return true;
666}
667
668
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000669//-----
670
Jim Grosbach08605202010-09-29 19:03:54 +0000671AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
672 SDValue &Base,
673 SDValue &Offset,
674 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000675 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000676 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000677 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
678 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmaneffb8942008-09-12 16:56:44 +0000679 int RHSC = (int)RHS->getZExtValue();
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000680 if (RHSC & 1) {
681 RHSC = RHSC & ~1;
682 ARM_AM::AddrOpc AddSub = ARM_AM::add;
683 if (RHSC < 0) {
684 AddSub = ARM_AM::sub;
685 RHSC = - RHSC;
686 }
687 if (isPowerOf2_32(RHSC)) {
688 unsigned ShAmt = Log2_32(RHSC);
689 Base = Offset = N.getOperand(0);
690 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
691 ARM_AM::lsl),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000692 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000693 return AM2_SHOP;
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000694 }
695 }
696 }
697 }
698
Chris Lattner46c01a32011-02-13 22:25:43 +0000699 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
700 // ISD::OR that is equivalent to an ADD.
701 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000702 Base = N;
703 if (N.getOpcode() == ISD::FrameIndex) {
704 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +0000705 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Anton Korobeynikov25229082009-11-24 00:44:37 +0000706 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northover72360d22013-12-02 10:35:41 +0000707 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000708 Base = N.getOperand(0);
709 }
Owen Anderson9f944592009-08-11 20:47:22 +0000710 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000711 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
712 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000713 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000714 return AM2_BASE;
Rafael Espindola708cb602006-11-08 17:07:32 +0000715 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000716
Evan Cheng10043e22007-01-19 07:51:42 +0000717 // Match simple R +/- imm12 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +0000718 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000719 int RHSC;
720 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
721 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
722 Base = N.getOperand(0);
723 if (Base.getOpcode() == ISD::FrameIndex) {
724 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +0000725 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Rafael Espindola708cb602006-11-08 17:07:32 +0000726 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000727 Offset = CurDAG->getRegister(0, MVT::i32);
728
729 ARM_AM::AddrOpc AddSub = ARM_AM::add;
730 if (RHSC < 0) {
731 AddSub = ARM_AM::sub;
732 RHSC = - RHSC;
733 }
734 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
735 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000736 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000737 return AM2_BASE;
Evan Cheng10043e22007-01-19 07:51:42 +0000738 }
Jim Grosbachc7b10f32010-09-29 17:32:29 +0000739 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000740
Bob Wilsone8a549c2012-09-29 21:43:49 +0000741 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000742 // Compute R +/- (R << N) and reuse it.
743 Base = N;
744 Offset = CurDAG->getRegister(0, MVT::i32);
745 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
746 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000747 SDLoc(N), MVT::i32);
Evan Cheng59bbc542010-10-27 23:41:30 +0000748 return AM2_BASE;
749 }
750
Johnny Chenb678a562009-10-27 17:25:15 +0000751 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000752 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chenga20cde32011-07-20 23:34:39 +0000753 ARM_AM::ShiftOpc ShOpcVal =
754 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000755 unsigned ShAmt = 0;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000756
Evan Cheng10043e22007-01-19 07:51:42 +0000757 Base = N.getOperand(0);
758 Offset = N.getOperand(1);
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000759
Evan Cheng10043e22007-01-19 07:51:42 +0000760 if (ShOpcVal != ARM_AM::no_shift) {
761 // Check to see if the RHS of the shift is a constant, if not, we can't fold
762 // it.
763 if (ConstantSDNode *Sh =
764 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000765 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000766 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
767 Offset = N.getOperand(1).getOperand(0);
768 else {
769 ShAmt = 0;
770 ShOpcVal = ARM_AM::no_shift;
771 }
Evan Cheng10043e22007-01-19 07:51:42 +0000772 } else {
773 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola708cb602006-11-08 17:07:32 +0000774 }
775 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000776
Evan Cheng10043e22007-01-19 07:51:42 +0000777 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000778 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000779 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
780 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000781 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000782 if (ShOpcVal != ARM_AM::no_shift) {
783 // Check to see if the RHS of the shift is a constant, if not, we can't
784 // fold it.
785 if (ConstantSDNode *Sh =
786 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000787 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000788 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000789 Offset = N.getOperand(0).getOperand(0);
790 Base = N.getOperand(1);
791 } else {
792 ShAmt = 0;
793 ShOpcVal = ARM_AM::no_shift;
794 }
Evan Cheng10043e22007-01-19 07:51:42 +0000795 } else {
796 ShOpcVal = ARM_AM::no_shift;
797 }
798 }
799 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000800
Evan Cheng10043e22007-01-19 07:51:42 +0000801 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000802 SDLoc(N), MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000803 return AM2_SHOP;
Rafael Espindola708cb602006-11-08 17:07:32 +0000804}
805
Owen Anderson2aedba62011-07-26 20:54:26 +0000806bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000807 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000808 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000809 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
810 ? cast<LoadSDNode>(Op)->getAddressingMode()
811 : cast<StoreSDNode>(Op)->getAddressingMode();
812 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
813 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000814 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000815 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
816 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000817
818 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000819 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000820 unsigned ShAmt = 0;
821 if (ShOpcVal != ARM_AM::no_shift) {
822 // Check to see if the RHS of the shift is a constant, if not, we can't fold
823 // it.
824 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000825 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000826 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
827 Offset = N.getOperand(0);
828 else {
829 ShAmt = 0;
830 ShOpcVal = ARM_AM::no_shift;
831 }
Evan Cheng10043e22007-01-19 07:51:42 +0000832 } else {
833 ShOpcVal = ARM_AM::no_shift;
834 }
835 }
836
837 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000838 SDLoc(N), MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000839 return true;
840}
841
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000842bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
843 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000844 unsigned Opcode = Op->getOpcode();
845 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
846 ? cast<LoadSDNode>(Op)->getAddressingMode()
847 : cast<StoreSDNode>(Op)->getAddressingMode();
848 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
849 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000850 int Val;
851 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000852 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000853 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000854 Opc = CurDAG->getTargetConstant(Val, SDLoc(Op), MVT::i32);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000855 return true;
856 }
857
858 return false;
859}
860
861
Owen Anderson2aedba62011-07-26 20:54:26 +0000862bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
863 SDValue &Offset, SDValue &Opc) {
864 unsigned Opcode = Op->getOpcode();
865 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
866 ? cast<LoadSDNode>(Op)->getAddressingMode()
867 : cast<StoreSDNode>(Op)->getAddressingMode();
868 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
869 ? ARM_AM::add : ARM_AM::sub;
870 int Val;
871 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
872 Offset = CurDAG->getRegister(0, MVT::i32);
873 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
874 ARM_AM::no_shift),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000875 SDLoc(Op), MVT::i32);
Owen Anderson2aedba62011-07-26 20:54:26 +0000876 return true;
877 }
878
879 return false;
880}
881
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000882bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
883 Base = N;
884 return true;
885}
Evan Cheng10043e22007-01-19 07:51:42 +0000886
Chris Lattner0e023ea2010-09-21 20:31:19 +0000887bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000888 SDValue &Base, SDValue &Offset,
889 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000890 if (N.getOpcode() == ISD::SUB) {
891 // X - C is canonicalize to X + -C, no need to handle it here.
892 Base = N.getOperand(0);
893 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000894 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0), SDLoc(N),
895 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000896 return true;
897 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000898
Chris Lattner46c01a32011-02-13 22:25:43 +0000899 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000900 Base = N;
901 if (N.getOpcode() == ISD::FrameIndex) {
902 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +0000903 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Evan Cheng10043e22007-01-19 07:51:42 +0000904 }
Owen Anderson9f944592009-08-11 20:47:22 +0000905 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000906 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
907 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000908 return true;
909 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000910
Evan Cheng10043e22007-01-19 07:51:42 +0000911 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000912 int RHSC;
913 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
914 -256 + 1, 256, RHSC)) { // 8 bits.
915 Base = N.getOperand(0);
916 if (Base.getOpcode() == ISD::FrameIndex) {
917 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +0000918 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Evan Cheng10043e22007-01-19 07:51:42 +0000919 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000920 Offset = CurDAG->getRegister(0, MVT::i32);
921
922 ARM_AM::AddrOpc AddSub = ARM_AM::add;
923 if (RHSC < 0) {
924 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000925 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000926 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000927 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC), SDLoc(N),
928 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000929 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000930 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000931
Evan Cheng10043e22007-01-19 07:51:42 +0000932 Base = N.getOperand(0);
933 Offset = N.getOperand(1);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000934 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N),
935 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000936 return true;
937}
938
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000939bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000940 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000941 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000942 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
943 ? cast<LoadSDNode>(Op)->getAddressingMode()
944 : cast<StoreSDNode>(Op)->getAddressingMode();
945 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
946 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000947 int Val;
948 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
949 Offset = CurDAG->getRegister(0, MVT::i32);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000950 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), SDLoc(Op),
951 MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000952 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000953 }
954
955 Offset = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000956 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), SDLoc(Op),
957 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000958 return true;
959}
960
Jim Grosbachd37f0712010-10-21 19:38:40 +0000961bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000962 SDValue &Base, SDValue &Offset) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000963 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000964 Base = N;
965 if (N.getOpcode() == ISD::FrameIndex) {
966 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +0000967 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Anton Korobeynikov25229082009-11-24 00:44:37 +0000968 } else if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northover72360d22013-12-02 10:35:41 +0000969 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
Evan Cheng10043e22007-01-19 07:51:42 +0000970 Base = N.getOperand(0);
971 }
972 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000973 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000974 return true;
975 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000976
Evan Cheng10043e22007-01-19 07:51:42 +0000977 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000978 int RHSC;
979 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
980 -256 + 1, 256, RHSC)) {
981 Base = N.getOperand(0);
982 if (Base.getOpcode() == ISD::FrameIndex) {
983 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +0000984 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Evan Cheng10043e22007-01-19 07:51:42 +0000985 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000986
987 ARM_AM::AddrOpc AddSub = ARM_AM::add;
988 if (RHSC < 0) {
989 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000990 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000991 }
992 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000993 SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000994 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000995 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000996
Evan Cheng10043e22007-01-19 07:51:42 +0000997 Base = N;
998 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000999 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001000 return true;
1001}
1002
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001003bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
1004 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +00001005 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001006
1007 unsigned Alignment = 0;
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001008
1009 MemSDNode *MemN = cast<MemSDNode>(Parent);
1010
1011 if (isa<LSBaseSDNode>(MemN) ||
1012 ((MemN->getOpcode() == ARMISD::VST1_UPD ||
1013 MemN->getOpcode() == ARMISD::VLD1_UPD) &&
1014 MemN->getConstantOperandVal(MemN->getNumOperands() - 1) == 1)) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001015 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
1016 // The maximum alignment is equal to the memory size being referenced.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001017 unsigned MMOAlign = MemN->getAlignment();
1018 unsigned MemSize = MemN->getMemoryVT().getSizeInBits() / 8;
1019 if (MMOAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001020 Alignment = MemSize;
1021 } else {
1022 // All other uses of addrmode6 are for intrinsics. For now just record
1023 // the raw alignment value; it will be refined later based on the legal
1024 // alignment operands for the intrinsic.
Ahmed Bougachadb141ac2015-02-19 23:52:41 +00001025 Alignment = MemN->getAlignment();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001026 }
1027
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001028 Align = CurDAG->getTargetConstant(Alignment, SDLoc(N), MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001029 return true;
1030}
1031
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001032bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1033 SDValue &Offset) {
1034 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1035 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1036 if (AM != ISD::POST_INC)
1037 return false;
1038 Offset = N;
1039 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1040 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1041 Offset = CurDAG->getRegister(0, MVT::i32);
1042 }
1043 return true;
1044}
1045
Chris Lattner0e023ea2010-09-21 20:31:19 +00001046bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001047 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001048 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1049 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001050 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001051 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001052 SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001053 return true;
1054 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001055
Evan Cheng10043e22007-01-19 07:51:42 +00001056 return false;
1057}
1058
Bill Wendling092a7bd2010-12-14 03:36:38 +00001059
1060//===----------------------------------------------------------------------===//
1061// Thumb Addressing Modes
1062//===----------------------------------------------------------------------===//
1063
Chris Lattner0e023ea2010-09-21 20:31:19 +00001064bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001065 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001066 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001067 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001068 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001069 return false;
1070
1071 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001072 return true;
1073 }
1074
Evan Cheng10043e22007-01-19 07:51:42 +00001075 Base = N.getOperand(0);
1076 Offset = N.getOperand(1);
1077 return true;
1078}
1079
Evan Cheng139edae2007-01-24 02:21:22 +00001080bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001081ARMDAGToDAGISel::SelectThumbAddrModeRI(SDValue N, SDValue &Base,
1082 SDValue &Offset, unsigned Scale) {
Evan Cheng139edae2007-01-24 02:21:22 +00001083 if (Scale == 4) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001084 SDValue TmpBase, TmpOffImm;
Chris Lattner0e023ea2010-09-21 20:31:19 +00001085 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
Evan Cheng139edae2007-01-24 02:21:22 +00001086 return false; // We want to select tLDRspi / tSTRspi instead.
Bill Wendling092a7bd2010-12-14 03:36:38 +00001087
Evan Cheng1526ba52007-01-24 08:53:17 +00001088 if (N.getOpcode() == ARMISD::Wrapper &&
1089 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1090 return false; // We want to select tLDRpci instead.
Evan Cheng139edae2007-01-24 02:21:22 +00001091 }
1092
Chris Lattner46c01a32011-02-13 22:25:43 +00001093 if (!CurDAG->isBaseWithConstantOffset(N))
Bill Wendling832a5da2010-12-15 01:03:19 +00001094 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001095
Evan Cheng650d0672007-02-06 00:22:06 +00001096 // Thumb does not have [sp, r] address mode.
1097 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1098 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1099 if ((LHSR && LHSR->getReg() == ARM::SP) ||
Bill Wendling832a5da2010-12-15 01:03:19 +00001100 (RHSR && RHSR->getReg() == ARM::SP))
1101 return false;
Bill Wendling092a7bd2010-12-14 03:36:38 +00001102
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001103 // FIXME: Why do we explicitly check for a match here and then return false?
1104 // Presumably to allow something else to match, but shouldn't this be
1105 // documented?
1106 int RHSC;
1107 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC))
1108 return false;
Bill Wendling092a7bd2010-12-14 03:36:38 +00001109
1110 Base = N.getOperand(0);
1111 Offset = N.getOperand(1);
1112 return true;
1113}
1114
1115bool
1116ARMDAGToDAGISel::SelectThumbAddrModeRI5S1(SDValue N,
1117 SDValue &Base,
1118 SDValue &Offset) {
1119 return SelectThumbAddrModeRI(N, Base, Offset, 1);
1120}
1121
1122bool
1123ARMDAGToDAGISel::SelectThumbAddrModeRI5S2(SDValue N,
1124 SDValue &Base,
1125 SDValue &Offset) {
1126 return SelectThumbAddrModeRI(N, Base, Offset, 2);
1127}
1128
1129bool
1130ARMDAGToDAGISel::SelectThumbAddrModeRI5S4(SDValue N,
1131 SDValue &Base,
1132 SDValue &Offset) {
1133 return SelectThumbAddrModeRI(N, Base, Offset, 4);
1134}
1135
1136bool
1137ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1138 SDValue &Base, SDValue &OffImm) {
1139 if (Scale == 4) {
1140 SDValue TmpBase, TmpOffImm;
1141 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
1142 return false; // We want to select tLDRspi / tSTRspi instead.
1143
1144 if (N.getOpcode() == ARMISD::Wrapper &&
1145 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1146 return false; // We want to select tLDRpci instead.
1147 }
1148
Chris Lattner46c01a32011-02-13 22:25:43 +00001149 if (!CurDAG->isBaseWithConstantOffset(N)) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001150 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northover72360d22013-12-02 10:35:41 +00001151 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001152 Base = N.getOperand(0);
1153 } else {
1154 Base = N;
1155 }
1156
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001157 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001158 return true;
1159 }
1160
Bill Wendling832a5da2010-12-15 01:03:19 +00001161 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1162 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1163 if ((LHSR && LHSR->getReg() == ARM::SP) ||
1164 (RHSR && RHSR->getReg() == ARM::SP)) {
1165 ConstantSDNode *LHS = dyn_cast<ConstantSDNode>(N.getOperand(0));
1166 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1167 unsigned LHSC = LHS ? LHS->getZExtValue() : 0;
1168 unsigned RHSC = RHS ? RHS->getZExtValue() : 0;
1169
1170 // Thumb does not have [sp, #imm5] address mode for non-zero imm5.
1171 if (LHSC != 0 || RHSC != 0) return false;
1172
1173 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001174 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Bill Wendling832a5da2010-12-15 01:03:19 +00001175 return true;
1176 }
1177
Evan Cheng10043e22007-01-19 07:51:42 +00001178 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001179 int RHSC;
1180 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1181 Base = N.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001182 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001183 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001184 }
1185
Evan Chengc0b73662007-01-23 22:59:13 +00001186 Base = N.getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001187 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Chengc0b73662007-01-23 22:59:13 +00001188 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001189}
1190
Bill Wendling092a7bd2010-12-14 03:36:38 +00001191bool
1192ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1193 SDValue &OffImm) {
1194 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001195}
1196
Bill Wendling092a7bd2010-12-14 03:36:38 +00001197bool
1198ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1199 SDValue &OffImm) {
1200 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001201}
1202
Bill Wendling092a7bd2010-12-14 03:36:38 +00001203bool
1204ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1205 SDValue &OffImm) {
1206 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001207}
1208
Chris Lattner0e023ea2010-09-21 20:31:19 +00001209bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1210 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001211 if (N.getOpcode() == ISD::FrameIndex) {
1212 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001213 // Only multiples of 4 are allowed for the offset, so the frame object
1214 // alignment must be at least 4.
1215 MachineFrameInfo *MFI = MF->getFrameInfo();
1216 if (MFI->getObjectAlignment(FI) < 4)
1217 MFI->setObjectAlignment(FI, 4);
Eric Christopherb17140d2014-10-08 07:32:17 +00001218 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001219 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001220 return true;
1221 }
Evan Cheng139edae2007-01-24 02:21:22 +00001222
Chris Lattner46c01a32011-02-13 22:25:43 +00001223 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001224 return false;
1225
1226 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001227 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1228 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001229 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001230 int RHSC;
1231 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1232 Base = N.getOperand(0);
1233 if (Base.getOpcode() == ISD::FrameIndex) {
1234 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Renato Golinb9887ef2015-02-25 14:41:06 +00001235 // For LHS+RHS to result in an offset that's a multiple of 4 the object
1236 // indexed by the LHS must be 4-byte aligned.
1237 MachineFrameInfo *MFI = MF->getFrameInfo();
1238 if (MFI->getObjectAlignment(FI) < 4)
1239 MFI->setObjectAlignment(FI, 4);
Eric Christopherb17140d2014-10-08 07:32:17 +00001240 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Evan Cheng139edae2007-01-24 02:21:22 +00001241 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001242 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001243 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001244 }
1245 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001246
Evan Cheng10043e22007-01-19 07:51:42 +00001247 return false;
1248}
1249
Bill Wendling092a7bd2010-12-14 03:36:38 +00001250
1251//===----------------------------------------------------------------------===//
1252// Thumb 2 Addressing Modes
1253//===----------------------------------------------------------------------===//
1254
1255
Chris Lattner0e023ea2010-09-21 20:31:19 +00001256bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg,
Evan Chengeab9ca72009-06-27 02:26:13 +00001257 SDValue &Opc) {
Evan Cheng59069ec2010-07-30 23:33:54 +00001258 if (DisableShifterOp)
1259 return false;
1260
Evan Chenga20cde32011-07-20 23:34:39 +00001261 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengeab9ca72009-06-27 02:26:13 +00001262
1263 // Don't match base register only case. That is matched to a separate
1264 // lower complexity pattern with explicit register operand.
1265 if (ShOpcVal == ARM_AM::no_shift) return false;
1266
1267 BaseReg = N.getOperand(0);
1268 unsigned ShImmVal = 0;
1269 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1270 ShImmVal = RHS->getZExtValue() & 31;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001271 Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), SDLoc(N));
Evan Chengeab9ca72009-06-27 02:26:13 +00001272 return true;
1273 }
1274
1275 return false;
1276}
1277
Chris Lattner0e023ea2010-09-21 20:31:19 +00001278bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001279 SDValue &Base, SDValue &OffImm) {
1280 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001281
Evan Cheng36064672009-08-11 08:52:18 +00001282 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001283 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1284 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001285 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001286 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001287 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +00001288 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001289 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001290 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001291 }
Owen Anderson6d557452011-03-18 19:46:58 +00001292
Chris Lattner46c01a32011-02-13 22:25:43 +00001293 if (N.getOpcode() == ARMISD::Wrapper &&
Tim Northover72360d22013-12-02 10:35:41 +00001294 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
Evan Cheng36064672009-08-11 08:52:18 +00001295 Base = N.getOperand(0);
1296 if (Base.getOpcode() == ISD::TargetConstantPool)
1297 return false; // We want to select t2LDRpci instead.
1298 } else
1299 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001300 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001301 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001302 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001303
1304 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001305 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001306 // Let t2LDRi8 handle (R - imm8).
1307 return false;
1308
Evan Chengb23b50d2009-06-29 07:51:04 +00001309 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001310 if (N.getOpcode() == ISD::SUB)
1311 RHSC = -RHSC;
1312
1313 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001314 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001315 if (Base.getOpcode() == ISD::FrameIndex) {
1316 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +00001317 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
David Goodwin79c079b2009-07-30 18:56:48 +00001318 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001319 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001320 return true;
1321 }
1322 }
1323
Evan Cheng36064672009-08-11 08:52:18 +00001324 // Base only.
1325 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001326 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001327 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001328}
1329
Chris Lattner0e023ea2010-09-21 20:31:19 +00001330bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001331 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001332 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001333 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1334 !CurDAG->isBaseWithConstantOffset(N))
1335 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001336
Chris Lattner46c01a32011-02-13 22:25:43 +00001337 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1338 int RHSC = (int)RHS->getSExtValue();
1339 if (N.getOpcode() == ISD::SUB)
1340 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001341
Chris Lattner46c01a32011-02-13 22:25:43 +00001342 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1343 Base = N.getOperand(0);
1344 if (Base.getOpcode() == ISD::FrameIndex) {
1345 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +00001346 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Evan Chengb23b50d2009-06-29 07:51:04 +00001347 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001348 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32);
Chris Lattner46c01a32011-02-13 22:25:43 +00001349 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001350 }
1351 }
1352
1353 return false;
1354}
1355
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001356bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001357 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001358 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001359 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1360 ? cast<LoadSDNode>(Op)->getAddressingMode()
1361 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001362 int RHSC;
1363 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1364 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001365 ? CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32)
1366 : CurDAG->getTargetConstant(-RHSC, SDLoc(N), MVT::i32);
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001367 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001368 }
1369
1370 return false;
1371}
1372
Chris Lattner0e023ea2010-09-21 20:31:19 +00001373bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001374 SDValue &Base,
1375 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001376 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001377 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001378 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001379
Evan Cheng36064672009-08-11 08:52:18 +00001380 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1381 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1382 int RHSC = (int)RHS->getZExtValue();
1383 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1384 return false;
1385 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001386 return false;
1387 }
1388
Evan Chengb23b50d2009-06-29 07:51:04 +00001389 // Look for (R + R) or (R + (R << [1,2,3])).
1390 unsigned ShAmt = 0;
1391 Base = N.getOperand(0);
1392 OffReg = N.getOperand(1);
1393
1394 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001395 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001396 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001397 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001398 if (ShOpcVal == ARM_AM::lsl)
1399 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001400 }
1401
Evan Chengb23b50d2009-06-29 07:51:04 +00001402 if (ShOpcVal == ARM_AM::lsl) {
1403 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1404 // it.
1405 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1406 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001407 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1408 OffReg = OffReg.getOperand(0);
1409 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001410 ShAmt = 0;
Evan Cheng59bbc542010-10-27 23:41:30 +00001411 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001412 }
David Goodwinf3912052009-07-15 15:50:19 +00001413 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001414
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001415 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(N), MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001416
1417 return true;
1418}
1419
Tim Northovera7ecd242013-07-16 09:46:55 +00001420bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1421 SDValue &OffImm) {
Alp Tokercb402912014-01-24 17:20:08 +00001422 // This *must* succeed since it's used for the irreplaceable ldrex and strex
Tim Northovera7ecd242013-07-16 09:46:55 +00001423 // instructions.
1424 Base = N;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001425 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001426
1427 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1428 return true;
1429
1430 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1431 if (!RHS)
1432 return true;
1433
1434 uint32_t RHSC = (int)RHS->getZExtValue();
1435 if (RHSC > 1020 || RHSC % 4 != 0)
1436 return true;
1437
1438 Base = N.getOperand(0);
1439 if (Base.getOpcode() == ISD::FrameIndex) {
1440 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +00001441 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
Tim Northovera7ecd242013-07-16 09:46:55 +00001442 }
1443
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001444 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(N), MVT::i32);
Tim Northovera7ecd242013-07-16 09:46:55 +00001445 return true;
1446}
1447
Evan Chengb23b50d2009-06-29 07:51:04 +00001448//===--------------------------------------------------------------------===//
1449
Evan Cheng7e90b112007-07-05 07:15:27 +00001450/// getAL - Returns a ARMCC::AL immediate node.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001451static inline SDValue getAL(SelectionDAG *CurDAG, SDLoc dl) {
1452 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001453}
1454
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001455SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
1456 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001457 ISD::MemIndexedMode AM = LD->getAddressingMode();
1458 if (AM == ISD::UNINDEXED)
Craig Topper062a2ba2014-04-25 05:30:21 +00001459 return nullptr;
Evan Chengd9c55362009-07-02 01:23:32 +00001460
Owen Anderson53aa7a92009-08-10 22:56:29 +00001461 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001462 SDValue Offset, AMOpc;
1463 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1464 unsigned Opcode = 0;
1465 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001466 if (LoadedVT == MVT::i32 && isPre &&
1467 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1468 Opcode = ARM::LDR_PRE_IMM;
1469 Match = true;
1470 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001471 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001472 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001473 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001474 } else if (LoadedVT == MVT::i32 &&
1475 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001476 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001477 Match = true;
1478
Owen Anderson9f944592009-08-11 20:47:22 +00001479 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001480 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001481 Match = true;
1482 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1483 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1484 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001485 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001486 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001487 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001488 Match = true;
1489 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1490 }
1491 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001492 if (isPre &&
1493 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001494 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001495 Opcode = ARM::LDRB_PRE_IMM;
1496 } else if (!isPre &&
1497 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1498 Match = true;
1499 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001500 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1501 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001502 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001503 }
1504 }
1505 }
1506
1507 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001508 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1509 SDValue Chain = LD->getChain();
1510 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001511 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001512 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001513 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001514 MVT::i32, MVT::Other, Ops);
Owen Andersonfd60f602011-08-26 21:12:37 +00001515 } else {
1516 SDValue Chain = LD->getChain();
1517 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001518 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)),
Owen Andersonfd60f602011-08-26 21:12:37 +00001519 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001520 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001521 MVT::i32, MVT::Other, Ops);
Owen Andersonfd60f602011-08-26 21:12:37 +00001522 }
Evan Chengd9c55362009-07-02 01:23:32 +00001523 }
1524
Craig Topper062a2ba2014-04-25 05:30:21 +00001525 return nullptr;
Evan Chengd9c55362009-07-02 01:23:32 +00001526}
1527
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001528SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
1529 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001530 ISD::MemIndexedMode AM = LD->getAddressingMode();
1531 if (AM == ISD::UNINDEXED)
Craig Topper062a2ba2014-04-25 05:30:21 +00001532 return nullptr;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001533
Owen Anderson53aa7a92009-08-10 22:56:29 +00001534 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001535 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001536 SDValue Offset;
1537 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1538 unsigned Opcode = 0;
1539 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001540 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001541 switch (LoadedVT.getSimpleVT().SimpleTy) {
1542 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001543 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1544 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001545 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001546 if (isSExtLd)
1547 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1548 else
1549 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001550 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001551 case MVT::i8:
1552 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001553 if (isSExtLd)
1554 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1555 else
1556 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001557 break;
1558 default:
Craig Topper062a2ba2014-04-25 05:30:21 +00001559 return nullptr;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001560 }
1561 Match = true;
1562 }
1563
1564 if (Match) {
1565 SDValue Chain = LD->getChain();
1566 SDValue Base = LD->getBasePtr();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001567 SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)),
Owen Anderson9f944592009-08-11 20:47:22 +00001568 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001569 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001570 MVT::Other, Ops);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001571 }
1572
Craig Topper062a2ba2014-04-25 05:30:21 +00001573 return nullptr;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001574}
1575
Weiming Zhao8f56f882012-11-16 21:55:34 +00001576/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1577SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001578 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001579 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001580 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
1581 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
1582 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001583 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001584 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001585}
1586
Weiming Zhao95782222012-11-17 00:23:35 +00001587/// \brief Form a D register from a pair of S registers.
1588SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001589 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001590 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001591 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32);
1592 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1593 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001594 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001595 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001596}
1597
Weiming Zhao95782222012-11-17 00:23:35 +00001598/// \brief Form a quad register from a pair of D registers.
1599SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001600 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001601 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl,
1602 MVT::i32);
1603 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1604 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001605 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001606 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001607}
1608
Weiming Zhao95782222012-11-17 00:23:35 +00001609/// \brief Form 4 consecutive D registers from a pair of Q registers.
1610SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001611 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001612 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1613 MVT::i32);
1614 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1615 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001616 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001617 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001618}
1619
Weiming Zhao95782222012-11-17 00:23:35 +00001620/// \brief Form 4 consecutive S registers.
1621SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001622 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001623 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001624 SDValue RegClass =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001625 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32);
1626 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32);
1627 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32);
1628 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32);
1629 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001630 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1631 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001632 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001633}
1634
Weiming Zhao95782222012-11-17 00:23:35 +00001635/// \brief Form 4 consecutive D registers.
1636SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001637 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001638 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001639 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl,
1640 MVT::i32);
1641 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32);
1642 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32);
1643 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32);
1644 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001645 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1646 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001647 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001648}
1649
Weiming Zhao95782222012-11-17 00:23:35 +00001650/// \brief Form 4 consecutive Q registers.
1651SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001652 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001653 SDLoc dl(V0.getNode());
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001654 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl,
1655 MVT::i32);
1656 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32);
1657 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32);
1658 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32);
1659 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001660 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1661 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001662 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001663}
1664
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001665/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1666/// of a NEON VLD or VST instruction. The supported values depend on the
1667/// number of registers being loaded.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001668SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, SDLoc dl,
1669 unsigned NumVecs, bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001670 unsigned NumRegs = NumVecs;
1671 if (!is64BitVector && NumVecs < 3)
1672 NumRegs *= 2;
1673
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001674 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001675 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001676 Alignment = 32;
1677 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1678 Alignment = 16;
1679 else if (Alignment >= 8)
1680 Alignment = 8;
1681 else
1682 Alignment = 0;
1683
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001684 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001685}
1686
Jiangning Liu4df23632014-01-16 09:16:13 +00001687static bool isVLDfixed(unsigned Opc)
1688{
1689 switch (Opc) {
1690 default: return false;
1691 case ARM::VLD1d8wb_fixed : return true;
1692 case ARM::VLD1d16wb_fixed : return true;
1693 case ARM::VLD1d64Qwb_fixed : return true;
1694 case ARM::VLD1d32wb_fixed : return true;
1695 case ARM::VLD1d64wb_fixed : return true;
1696 case ARM::VLD1d64TPseudoWB_fixed : return true;
1697 case ARM::VLD1d64QPseudoWB_fixed : return true;
1698 case ARM::VLD1q8wb_fixed : return true;
1699 case ARM::VLD1q16wb_fixed : return true;
1700 case ARM::VLD1q32wb_fixed : return true;
1701 case ARM::VLD1q64wb_fixed : return true;
1702 case ARM::VLD2d8wb_fixed : return true;
1703 case ARM::VLD2d16wb_fixed : return true;
1704 case ARM::VLD2d32wb_fixed : return true;
1705 case ARM::VLD2q8PseudoWB_fixed : return true;
1706 case ARM::VLD2q16PseudoWB_fixed : return true;
1707 case ARM::VLD2q32PseudoWB_fixed : return true;
1708 case ARM::VLD2DUPd8wb_fixed : return true;
1709 case ARM::VLD2DUPd16wb_fixed : return true;
1710 case ARM::VLD2DUPd32wb_fixed : return true;
1711 }
1712}
1713
1714static bool isVSTfixed(unsigned Opc)
1715{
1716 switch (Opc) {
1717 default: return false;
1718 case ARM::VST1d8wb_fixed : return true;
1719 case ARM::VST1d16wb_fixed : return true;
1720 case ARM::VST1d32wb_fixed : return true;
1721 case ARM::VST1d64wb_fixed : return true;
Jim Grosbach1a597112014-04-03 23:43:18 +00001722 case ARM::VST1q8wb_fixed : return true;
1723 case ARM::VST1q16wb_fixed : return true;
1724 case ARM::VST1q32wb_fixed : return true;
1725 case ARM::VST1q64wb_fixed : return true;
Jiangning Liu4df23632014-01-16 09:16:13 +00001726 case ARM::VST1d64TPseudoWB_fixed : return true;
1727 case ARM::VST1d64QPseudoWB_fixed : return true;
1728 case ARM::VST2d8wb_fixed : return true;
1729 case ARM::VST2d16wb_fixed : return true;
1730 case ARM::VST2d32wb_fixed : return true;
1731 case ARM::VST2q8PseudoWB_fixed : return true;
1732 case ARM::VST2q16PseudoWB_fixed : return true;
1733 case ARM::VST2q32PseudoWB_fixed : return true;
1734 }
1735}
1736
Jim Grosbach2098cb12011-10-24 21:45:13 +00001737// Get the register stride update opcode of a VLD/VST instruction that
1738// is otherwise equivalent to the given fixed stride updating instruction.
1739static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
Jiangning Liu4df23632014-01-16 09:16:13 +00001740 assert((isVLDfixed(Opc) || isVSTfixed(Opc))
1741 && "Incorrect fixed stride updating instruction.");
Jim Grosbach2098cb12011-10-24 21:45:13 +00001742 switch (Opc) {
1743 default: break;
1744 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1745 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1746 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1747 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1748 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1749 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1750 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1751 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jiangning Liu4df23632014-01-16 09:16:13 +00001752 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register;
1753 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register;
1754 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register;
1755 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001756
1757 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1758 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1759 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1760 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1761 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1762 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1763 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1764 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001765 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001766 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001767
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001768 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1769 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1770 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001771 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1772 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1773 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1774
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001775 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1776 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1777 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001778 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1779 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1780 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001781
Jim Grosbach13a292c2012-03-06 22:01:44 +00001782 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1783 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1784 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001785 }
1786 return Opc; // If not one we handle, return it unchanged.
1787}
1788
Bob Wilson06fce872011-02-07 17:43:21 +00001789SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001790 const uint16_t *DOpcodes,
1791 const uint16_t *QOpcodes0,
1792 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001793 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001794 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001795
Bob Wilsonae08a732010-03-20 22:13:40 +00001796 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001797 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1798 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Craig Topper062a2ba2014-04-25 05:30:21 +00001799 return nullptr;
Bob Wilson12b47992009-10-14 17:28:52 +00001800
1801 SDValue Chain = N->getOperand(0);
1802 EVT VT = N->getValueType(0);
1803 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001804 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001805
Bob Wilson12b47992009-10-14 17:28:52 +00001806 unsigned OpcodeIndex;
1807 switch (VT.getSimpleVT().SimpleTy) {
1808 default: llvm_unreachable("unhandled vld type");
1809 // Double-register operations:
1810 case MVT::v8i8: OpcodeIndex = 0; break;
1811 case MVT::v4i16: OpcodeIndex = 1; break;
1812 case MVT::v2f32:
1813 case MVT::v2i32: OpcodeIndex = 2; break;
1814 case MVT::v1i64: OpcodeIndex = 3; break;
1815 // Quad-register operations:
1816 case MVT::v16i8: OpcodeIndex = 0; break;
1817 case MVT::v8i16: OpcodeIndex = 1; break;
1818 case MVT::v4f32:
1819 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001820 case MVT::v2f64:
Bob Wilson340861d2010-03-23 05:25:43 +00001821 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001822 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson340861d2010-03-23 05:25:43 +00001823 break;
Bob Wilson12b47992009-10-14 17:28:52 +00001824 }
1825
Bob Wilson35fafca2010-09-03 18:16:02 +00001826 EVT ResTy;
1827 if (NumVecs == 1)
1828 ResTy = VT;
1829 else {
1830 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1831 if (!is64BitVector)
1832 ResTyElts *= 2;
1833 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1834 }
Bob Wilson06fce872011-02-07 17:43:21 +00001835 std::vector<EVT> ResTys;
1836 ResTys.push_back(ResTy);
1837 if (isUpdating)
1838 ResTys.push_back(MVT::i32);
1839 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001840
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001841 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001842 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001843 SDNode *VLd;
1844 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001845
Bob Wilson06fce872011-02-07 17:43:21 +00001846 // Double registers and VLD1/VLD2 quad registers are directly supported.
1847 if (is64BitVector || NumVecs <= 2) {
1848 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1849 QOpcodes0[OpcodeIndex]);
1850 Ops.push_back(MemAddr);
1851 Ops.push_back(Align);
1852 if (isUpdating) {
1853 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachd146a022011-12-09 21:28:25 +00001854 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach2098cb12011-10-24 21:45:13 +00001855 // case entirely when the rest are updated to that form, too.
Jiangning Liu4df23632014-01-16 09:16:13 +00001856 if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001857 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00001858 // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001859 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00001860 if ((NumVecs > 2 && !isVLDfixed(Opc)) ||
Jim Grosbach05df4602011-10-31 21:50:31 +00001861 !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001862 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Evan Cheng630063a2010-05-10 21:26:24 +00001863 }
Bob Wilson06fce872011-02-07 17:43:21 +00001864 Ops.push_back(Pred);
1865 Ops.push_back(Reg0);
1866 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001867 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001868
Bob Wilson12b47992009-10-14 17:28:52 +00001869 } else {
1870 // Otherwise, quad registers are loaded with two separate instructions,
1871 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001872 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001873
Bob Wilson06fce872011-02-07 17:43:21 +00001874 // Load the even subregs. This is always an updating load, so that it
1875 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001876 SDValue ImplDef =
1877 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1878 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001879 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001880 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001881 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001882
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001883 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001884 Ops.push_back(SDValue(VLdA, 1));
1885 Ops.push_back(Align);
1886 if (isUpdating) {
1887 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1888 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1889 "only constant post-increment update allowed for VLD3/4");
1890 (void)Inc;
1891 Ops.push_back(Reg0);
1892 }
1893 Ops.push_back(SDValue(VLdA, 0));
1894 Ops.push_back(Pred);
1895 Ops.push_back(Reg0);
1896 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001897 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001898 }
Bob Wilson12b47992009-10-14 17:28:52 +00001899
Evan Cheng40791332011-04-19 00:04:03 +00001900 // Transfer memoperands.
1901 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1902 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1903 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1904
Bob Wilson06fce872011-02-07 17:43:21 +00001905 if (NumVecs == 1)
1906 return VLd;
1907
1908 // Extract out the subregisters.
1909 SDValue SuperReg = SDValue(VLd, 0);
1910 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
1911 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
1912 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1913 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1914 ReplaceUses(SDValue(N, Vec),
1915 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1916 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1917 if (isUpdating)
1918 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Craig Topper062a2ba2014-04-25 05:30:21 +00001919 return nullptr;
Bob Wilson12b47992009-10-14 17:28:52 +00001920}
1921
Bob Wilson06fce872011-02-07 17:43:21 +00001922SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001923 const uint16_t *DOpcodes,
1924 const uint16_t *QOpcodes0,
1925 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001926 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001927 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001928
Bob Wilsonae08a732010-03-20 22:13:40 +00001929 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001930 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1931 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1932 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Craig Topper062a2ba2014-04-25 05:30:21 +00001933 return nullptr;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001934
Evan Cheng40791332011-04-19 00:04:03 +00001935 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1936 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1937
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001938 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00001939 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001940 bool is64BitVector = VT.is64BitVector();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001941 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001942
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001943 unsigned OpcodeIndex;
1944 switch (VT.getSimpleVT().SimpleTy) {
1945 default: llvm_unreachable("unhandled vst type");
1946 // Double-register operations:
1947 case MVT::v8i8: OpcodeIndex = 0; break;
1948 case MVT::v4i16: OpcodeIndex = 1; break;
1949 case MVT::v2f32:
1950 case MVT::v2i32: OpcodeIndex = 2; break;
1951 case MVT::v1i64: OpcodeIndex = 3; break;
1952 // Quad-register operations:
1953 case MVT::v16i8: OpcodeIndex = 0; break;
1954 case MVT::v8i16: OpcodeIndex = 1; break;
1955 case MVT::v4f32:
1956 case MVT::v4i32: OpcodeIndex = 2; break;
Ahmed Bougachabe0b2272014-12-09 21:25:00 +00001957 case MVT::v2f64:
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001958 case MVT::v2i64: OpcodeIndex = 3;
1959 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
1960 break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001961 }
1962
Bob Wilson06fce872011-02-07 17:43:21 +00001963 std::vector<EVT> ResTys;
1964 if (isUpdating)
1965 ResTys.push_back(MVT::i32);
1966 ResTys.push_back(MVT::Other);
1967
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001968 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00001969 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001970 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00001971
Bob Wilson06fce872011-02-07 17:43:21 +00001972 // Double registers and VST1/VST2 quad registers are directly supported.
1973 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00001974 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00001975 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00001976 SrcReg = N->getOperand(Vec0Idx);
1977 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00001978 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00001979 SDValue V0 = N->getOperand(Vec0Idx + 0);
1980 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00001981 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00001982 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001983 else {
Bob Wilson06fce872011-02-07 17:43:21 +00001984 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00001985 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00001986 // an undef.
1987 SDValue V3 = (NumVecs == 3)
1988 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00001989 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00001990 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001991 }
Bob Wilson950882b2010-08-28 05:12:57 +00001992 } else {
1993 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00001994 SDValue Q0 = N->getOperand(Vec0Idx);
1995 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00001996 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001997 }
Bob Wilson06fce872011-02-07 17:43:21 +00001998
1999 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2000 QOpcodes0[OpcodeIndex]);
2001 Ops.push_back(MemAddr);
2002 Ops.push_back(Align);
2003 if (isUpdating) {
2004 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbach88ac7612011-12-14 21:32:11 +00002005 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach05df4602011-10-31 21:50:31 +00002006 // case entirely when the rest are updated to that form, too.
Jim Grosbach88ac7612011-12-14 21:32:11 +00002007 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach05df4602011-10-31 21:50:31 +00002008 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jiangning Liu4df23632014-01-16 09:16:13 +00002009 // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00002010 // check for that explicitly too. Horribly hacky, but temporary.
Jiangning Liu4df23632014-01-16 09:16:13 +00002011 if (!isa<ConstantSDNode>(Inc.getNode()))
2012 Ops.push_back(Inc);
2013 else if (NumVecs > 2 && !isVSTfixed(Opc))
2014 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002015 }
2016 Ops.push_back(SrcReg);
2017 Ops.push_back(Pred);
2018 Ops.push_back(Reg0);
2019 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00002020 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002021
2022 // Transfer memoperands.
2023 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
2024
2025 return VSt;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002026 }
2027
2028 // Otherwise, quad registers are stored with two separate instructions,
2029 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00002030
Bob Wilson01ac8f92010-06-16 21:34:01 +00002031 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00002032 SDValue V0 = N->getOperand(Vec0Idx + 0);
2033 SDValue V1 = N->getOperand(Vec0Idx + 1);
2034 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00002035 SDValue V3 = (NumVecs == 3)
2036 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00002037 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002038 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002039
Bob Wilson06fce872011-02-07 17:43:21 +00002040 // Store the even D registers. This is always an updating store, so that it
2041 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00002042 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
2043 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
2044 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00002045 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00002046 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00002047 Chain = SDValue(VStA, 1);
2048
2049 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00002050 Ops.push_back(SDValue(VStA, 0));
2051 Ops.push_back(Align);
2052 if (isUpdating) {
2053 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2054 assert(isa<ConstantSDNode>(Inc.getNode()) &&
2055 "only constant post-increment update allowed for VST3/4");
2056 (void)Inc;
2057 Ops.push_back(Reg0);
2058 }
2059 Ops.push_back(RegSeq);
2060 Ops.push_back(Pred);
2061 Ops.push_back(Reg0);
2062 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00002063 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00002064 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002065 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
2066 return VStB;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002067}
2068
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002069SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
Bob Wilson06fce872011-02-07 17:43:21 +00002070 bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00002071 const uint16_t *DOpcodes,
2072 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002073 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002074 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002075
Bob Wilsonae08a732010-03-20 22:13:40 +00002076 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00002077 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2078 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2079 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Craig Topper062a2ba2014-04-25 05:30:21 +00002080 return nullptr;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002081
Evan Cheng40791332011-04-19 00:04:03 +00002082 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2083 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2084
Bob Wilson4145e3a2009-10-14 16:19:03 +00002085 SDValue Chain = N->getOperand(0);
2086 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002087 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2088 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002089 bool is64BitVector = VT.is64BitVector();
2090
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002091 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002092 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002093 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002094 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2095 if (Alignment > NumBytes)
2096 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002097 if (Alignment < 8 && Alignment < NumBytes)
2098 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002099 // Alignment must be a power of two; make sure of that.
2100 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002101 if (Alignment == 1)
2102 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002103 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002104 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002105
Bob Wilson4145e3a2009-10-14 16:19:03 +00002106 unsigned OpcodeIndex;
2107 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002108 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002109 // Double-register operations:
2110 case MVT::v8i8: OpcodeIndex = 0; break;
2111 case MVT::v4i16: OpcodeIndex = 1; break;
2112 case MVT::v2f32:
2113 case MVT::v2i32: OpcodeIndex = 2; break;
2114 // Quad-register operations:
2115 case MVT::v8i16: OpcodeIndex = 0; break;
2116 case MVT::v4f32:
2117 case MVT::v4i32: OpcodeIndex = 1; break;
2118 }
2119
Bob Wilson06fce872011-02-07 17:43:21 +00002120 std::vector<EVT> ResTys;
2121 if (IsLoad) {
2122 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2123 if (!is64BitVector)
2124 ResTyElts *= 2;
2125 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2126 MVT::i64, ResTyElts));
2127 }
2128 if (isUpdating)
2129 ResTys.push_back(MVT::i32);
2130 ResTys.push_back(MVT::Other);
2131
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002132 SDValue Pred = getAL(CurDAG, dl);
Bob Wilsonae08a732010-03-20 22:13:40 +00002133 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002134
Bob Wilson06fce872011-02-07 17:43:21 +00002135 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002136 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002137 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002138 if (isUpdating) {
2139 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2140 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
2141 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002142
Bob Wilsond5c57a52010-09-13 23:01:35 +00002143 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002144 SDValue V0 = N->getOperand(Vec0Idx + 0);
2145 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002146 if (NumVecs == 2) {
2147 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002148 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002149 else
Weiming Zhao95782222012-11-17 00:23:35 +00002150 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002151 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002152 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002153 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002154 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2155 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002156 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002157 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002158 else
Weiming Zhao95782222012-11-17 00:23:35 +00002159 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002160 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002161 Ops.push_back(SuperReg);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002162 Ops.push_back(getI32Imm(Lane, dl));
Evan Chenga33fc862009-11-21 06:21:52 +00002163 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002164 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002165 Ops.push_back(Chain);
2166
Bob Wilson06fce872011-02-07 17:43:21 +00002167 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2168 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002169 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002170 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson93117bc2009-10-14 16:46:45 +00002171 if (!IsLoad)
Bob Wilson06fce872011-02-07 17:43:21 +00002172 return VLdLn;
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002173
Bob Wilsond5c57a52010-09-13 23:01:35 +00002174 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002175 SuperReg = SDValue(VLdLn, 0);
2176 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
2177 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
2178 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002179 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2180 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002181 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2182 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2183 if (isUpdating)
2184 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Craig Topper062a2ba2014-04-25 05:30:21 +00002185 return nullptr;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002186}
2187
Bob Wilson06fce872011-02-07 17:43:21 +00002188SDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating,
Craig Topper01736f82012-05-24 05:17:00 +00002189 unsigned NumVecs,
2190 const uint16_t *Opcodes) {
Bob Wilson2d790df2010-11-28 06:51:26 +00002191 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002192 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002193
2194 SDValue MemAddr, Align;
2195 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
Craig Topper062a2ba2014-04-25 05:30:21 +00002196 return nullptr;
Bob Wilson2d790df2010-11-28 06:51:26 +00002197
Evan Cheng40791332011-04-19 00:04:03 +00002198 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2199 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2200
Bob Wilson2d790df2010-11-28 06:51:26 +00002201 SDValue Chain = N->getOperand(0);
2202 EVT VT = N->getValueType(0);
2203
2204 unsigned Alignment = 0;
2205 if (NumVecs != 3) {
2206 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2207 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2208 if (Alignment > NumBytes)
2209 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002210 if (Alignment < 8 && Alignment < NumBytes)
2211 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002212 // Alignment must be a power of two; make sure of that.
2213 Alignment = (Alignment & -Alignment);
2214 if (Alignment == 1)
2215 Alignment = 0;
2216 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002217 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32);
Bob Wilson2d790df2010-11-28 06:51:26 +00002218
2219 unsigned OpcodeIndex;
2220 switch (VT.getSimpleVT().SimpleTy) {
2221 default: llvm_unreachable("unhandled vld-dup type");
2222 case MVT::v8i8: OpcodeIndex = 0; break;
2223 case MVT::v4i16: OpcodeIndex = 1; break;
2224 case MVT::v2f32:
2225 case MVT::v2i32: OpcodeIndex = 2; break;
2226 }
2227
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002228 SDValue Pred = getAL(CurDAG, dl);
Bob Wilson2d790df2010-11-28 06:51:26 +00002229 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2230 SDValue SuperReg;
2231 unsigned Opc = Opcodes[OpcodeIndex];
Bob Wilson06fce872011-02-07 17:43:21 +00002232 SmallVector<SDValue, 6> Ops;
2233 Ops.push_back(MemAddr);
2234 Ops.push_back(Align);
2235 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002236 // fixed-stride update instructions don't have an explicit writeback
2237 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002238 SDValue Inc = N->getOperand(2);
Jim Grosbachc80a2642011-12-21 19:40:55 +00002239 if (!isa<ConstantSDNode>(Inc.getNode()))
2240 Ops.push_back(Inc);
2241 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2242 else if (NumVecs > 2)
2243 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002244 }
2245 Ops.push_back(Pred);
2246 Ops.push_back(Reg0);
2247 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002248
2249 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002250 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002251 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002252 if (isUpdating)
2253 ResTys.push_back(MVT::i32);
2254 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002255 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002256 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002257 SuperReg = SDValue(VLdDup, 0);
Bob Wilson2d790df2010-11-28 06:51:26 +00002258
2259 // Extract the subregisters.
2260 assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
2261 unsigned SubIdx = ARM::dsub_0;
2262 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2263 ReplaceUses(SDValue(N, Vec),
2264 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Bob Wilson06fce872011-02-07 17:43:21 +00002265 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2266 if (isUpdating)
2267 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Craig Topper062a2ba2014-04-25 05:30:21 +00002268 return nullptr;
Bob Wilson2d790df2010-11-28 06:51:26 +00002269}
2270
Bob Wilson5bc8a792010-07-07 00:08:54 +00002271SDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2272 unsigned Opc) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00002273 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002274 SDLoc dl(N);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002275 EVT VT = N->getValueType(0);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002276 unsigned FirstTblReg = IsExt ? 2 : 1;
Bob Wilson3ed511b2010-07-06 23:36:25 +00002277
2278 // Form a REG_SEQUENCE to force register allocation.
2279 SDValue RegSeq;
Bob Wilson5bc8a792010-07-07 00:08:54 +00002280 SDValue V0 = N->getOperand(FirstTblReg + 0);
2281 SDValue V1 = N->getOperand(FirstTblReg + 1);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002282 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002283 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002284 else {
Bob Wilson5bc8a792010-07-07 00:08:54 +00002285 SDValue V2 = N->getOperand(FirstTblReg + 2);
Jim Grosbachd37f0712010-10-21 19:38:40 +00002286 // If it's a vtbl3, form a quad D-register and leave the last part as
Bob Wilson3ed511b2010-07-06 23:36:25 +00002287 // an undef.
2288 SDValue V3 = (NumVecs == 3)
2289 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson5bc8a792010-07-07 00:08:54 +00002290 : N->getOperand(FirstTblReg + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002291 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002292 }
2293
Bob Wilson5bc8a792010-07-07 00:08:54 +00002294 SmallVector<SDValue, 6> Ops;
2295 if (IsExt)
2296 Ops.push_back(N->getOperand(1));
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00002297 Ops.push_back(RegSeq);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002298 Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002299 Ops.push_back(getAL(CurDAG, dl)); // predicate
Bob Wilson3ed511b2010-07-06 23:36:25 +00002300 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
Michael Liaob53d8962013-04-19 22:22:57 +00002301 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002302}
2303
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002304SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
Jim Grosbach825cb292010-04-22 23:24:18 +00002305 bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002306 if (!Subtarget->hasV6T2Ops())
Craig Topper062a2ba2014-04-25 05:30:21 +00002307 return nullptr;
Bob Wilson93117bc2009-10-14 16:46:45 +00002308
Evan Chengeae6d2c2012-12-19 20:16:09 +00002309 unsigned Opc = isSigned
2310 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002311 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002312 SDLoc dl(N);
Jim Grosbach825cb292010-04-22 23:24:18 +00002313
Jim Grosbach825cb292010-04-22 23:24:18 +00002314 // For unsigned extracts, check for a shift right and mask
2315 unsigned And_imm = 0;
2316 if (N->getOpcode() == ISD::AND) {
2317 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2318
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002319 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002320 if (And_imm & (And_imm + 1))
Craig Topper062a2ba2014-04-25 05:30:21 +00002321 return nullptr;
Jim Grosbach825cb292010-04-22 23:24:18 +00002322
2323 unsigned Srl_imm = 0;
2324 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2325 Srl_imm)) {
2326 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2327
Jim Grosbach03f56d92011-07-27 21:09:25 +00002328 // Note: The width operand is encoded as width-1.
Benjamin Kramer5f6a9072015-02-12 15:35:40 +00002329 unsigned Width = countTrailingOnes(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002330 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002331
Jim Grosbach825cb292010-04-22 23:24:18 +00002332 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002333
2334 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2335 // It's cheaper to use a right shift to extract the top bits.
2336 if (Subtarget->isThumb()) {
2337 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2338 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002339 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2340 getAL(CurDAG, dl), Reg0, Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002341 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002342 }
2343
2344 // ARM models shift instructions as MOVsi with shifter operand.
2345 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2346 SDValue ShOpc =
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002347 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), dl,
Evan Chengeae6d2c2012-12-19 20:16:09 +00002348 MVT::i32);
2349 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002350 getAL(CurDAG, dl), Reg0, Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002351 return CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002352 }
2353
Jim Grosbach825cb292010-04-22 23:24:18 +00002354 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002355 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2356 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2357 getAL(CurDAG, dl), Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002358 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
Jim Grosbach825cb292010-04-22 23:24:18 +00002359 }
2360 }
Craig Topper062a2ba2014-04-25 05:30:21 +00002361 return nullptr;
Jim Grosbach825cb292010-04-22 23:24:18 +00002362 }
2363
2364 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002365 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002366 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002367 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2368 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002369 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002370 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002371 // Note: The width operand is encoded as width-1.
2372 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002373 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002374 if (LSB < 0)
Craig Topper062a2ba2014-04-25 05:30:21 +00002375 return nullptr;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002376 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002377 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002378 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2379 CurDAG->getTargetConstant(Width, dl, MVT::i32),
2380 getAL(CurDAG, dl), Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002381 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
Sandeep Patel423e42b2009-10-13 18:59:48 +00002382 }
2383 }
Tim Northover14ff2df2014-07-23 13:59:12 +00002384
2385 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
2386 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2387 unsigned LSB = 0;
2388 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) &&
2389 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB))
2390 return nullptr;
2391
2392 if (LSB + Width > 32)
2393 return nullptr;
2394
2395 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2396 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002397 CurDAG->getTargetConstant(LSB, dl, MVT::i32),
2398 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32),
2399 getAL(CurDAG, dl), Reg0 };
Tim Northover14ff2df2014-07-23 13:59:12 +00002400 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
2401 }
2402
Craig Topper062a2ba2014-04-25 05:30:21 +00002403 return nullptr;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002404}
2405
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002406/// Target-specific DAG combining for ISD::XOR.
2407/// Target-independent combining lowers SELECT_CC nodes of the form
2408/// select_cc setg[ge] X, 0, X, -X
2409/// select_cc setgt X, -1, X, -X
2410/// select_cc setl[te] X, 0, -X, X
2411/// select_cc setlt X, 1, -X, X
2412/// which represent Integer ABS into:
2413/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2414/// ARM instruction selection detects the latter and matches it to
2415/// ARM::ABS or ARM::t2ABS machine node.
2416SDNode *ARMDAGToDAGISel::SelectABSOp(SDNode *N){
2417 SDValue XORSrc0 = N->getOperand(0);
2418 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002419 EVT VT = N->getValueType(0);
2420
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002421 if (Subtarget->isThumb1Only())
Craig Topper062a2ba2014-04-25 05:30:21 +00002422 return nullptr;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002423
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002424 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Craig Topper062a2ba2014-04-25 05:30:21 +00002425 return nullptr;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002426
2427 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2428 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2429 SDValue SRASrc0 = XORSrc1.getOperand(0);
2430 SDValue SRASrc1 = XORSrc1.getOperand(1);
2431 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2432 EVT XType = SRASrc0.getValueType();
2433 unsigned Size = XType.getSizeInBits() - 1;
2434
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002435 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
Craig Topper062a2ba2014-04-25 05:30:21 +00002436 XType.isInteger() && SRAConstant != nullptr &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002437 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002438 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002439 return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2440 }
2441
Craig Topper062a2ba2014-04-25 05:30:21 +00002442 return nullptr;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002443}
2444
Evan Chengd85631e2010-05-05 18:28:36 +00002445SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
2446 // The only time a CONCAT_VECTORS operation can have legal types is when
2447 // two 64-bit vectors are concatenated to a 128-bit vector.
2448 EVT VT = N->getValueType(0);
2449 if (!VT.is128BitVector() || N->getNumOperands() != 2)
2450 llvm_unreachable("unexpected CONCAT_VECTORS");
Weiming Zhao95782222012-11-17 00:23:35 +00002451 return createDRegPairNode(VT, N->getOperand(0), N->getOperand(1));
Evan Chengd85631e2010-05-05 18:28:36 +00002452}
2453
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002454SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002455 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002456
Tim Northover31d093c2013-09-22 08:21:56 +00002457 if (N->isMachineOpcode()) {
2458 N->setNodeId(-1);
Craig Topper062a2ba2014-04-25 05:30:21 +00002459 return nullptr; // Already selected.
Tim Northover31d093c2013-09-22 08:21:56 +00002460 }
Rafael Espindola4e760152006-06-12 12:28:08 +00002461
2462 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002463 default: break;
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00002464 case ISD::WRITE_REGISTER: {
2465 SDNode *ResNode = SelectWriteRegister(N);
2466 if (ResNode)
2467 return ResNode;
2468 break;
2469 }
2470 case ISD::READ_REGISTER: {
2471 SDNode *ResNode = SelectReadRegister(N);
2472 if (ResNode)
2473 return ResNode;
2474 break;
2475 }
Weiming Zhaoc5987002013-02-14 18:10:21 +00002476 case ISD::INLINEASM: {
2477 SDNode *ResNode = SelectInlineAsm(N);
2478 if (ResNode)
2479 return ResNode;
2480 break;
2481 }
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002482 case ISD::XOR: {
2483 // Select special operations if XOR node forms integer ABS pattern
2484 SDNode *ResNode = SelectABSOp(N);
2485 if (ResNode)
2486 return ResNode;
2487 // Other cases are autogenerated.
2488 break;
2489 }
Evan Cheng10043e22007-01-19 07:51:42 +00002490 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002491 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002492 bool UseCP = true;
Eric Christopherc1058df2014-07-04 01:55:26 +00002493 if (Subtarget->useMovt(*MF))
Anton Korobeynikov7c2b1e72009-09-27 23:52:58 +00002494 // Thumb2-aware targets have the MOVT instruction, so all immediates can
2495 // be done with MOV + MOVT, at worst.
Tim Northover55c625f2014-01-23 13:43:47 +00002496 UseCP = false;
Anton Korobeynikov7c2b1e72009-09-27 23:52:58 +00002497 else {
2498 if (Subtarget->isThumb()) {
Tim Northover55c625f2014-01-23 13:43:47 +00002499 UseCP = (Val > 255 && // MOV
2500 ~Val > 255 && // MOV + MVN
2501 !ARM_AM::isThumbImmShiftedVal(Val) && // MOV + LSL
2502 !(Subtarget->hasV6T2Ops() && Val <= 0xffff)); // MOVW
Anton Korobeynikov7c2b1e72009-09-27 23:52:58 +00002503 } else
Tim Northover55c625f2014-01-23 13:43:47 +00002504 UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV
2505 ARM_AM::getSOImmVal(~Val) == -1 && // MVN
2506 !ARM_AM::isSOImmTwoPartVal(Val) && // two instrs.
2507 !(Subtarget->hasV6T2Ops() && Val <= 0xffff)); // MOVW
Anton Korobeynikov7c2b1e72009-09-27 23:52:58 +00002508 }
2509
Evan Cheng10043e22007-01-19 07:51:42 +00002510 if (UseCP) {
Eric Christopherb17140d2014-10-08 07:32:17 +00002511 SDValue CPIdx = CurDAG->getTargetConstantPool(
2512 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
2513 TLI->getPointerTy());
Evan Cheng1526ba52007-01-24 08:53:17 +00002514
2515 SDNode *ResNode;
Tim Northover55c625f2014-01-23 13:43:47 +00002516 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002517 SDValue Pred = getAL(CurDAG, dl);
Owen Anderson9f944592009-08-11 20:47:22 +00002518 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002519 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002520 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002521 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002522 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002523 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002524 CPIdx,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002525 CurDAG->getTargetConstant(0, dl, MVT::i32),
2526 getAL(CurDAG, dl),
Owen Anderson9f944592009-08-11 20:47:22 +00002527 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002528 CurDAG->getEntryNode()
2529 };
Dan Gohman32f71d72009-09-25 18:54:59 +00002530 ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002531 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002532 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002533 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
Craig Topper062a2ba2014-04-25 05:30:21 +00002534 return nullptr;
Evan Cheng10043e22007-01-19 07:51:42 +00002535 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002536
Evan Cheng10043e22007-01-19 07:51:42 +00002537 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002538 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002539 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002540 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002541 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002542 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Eric Christopherb17140d2014-10-08 07:32:17 +00002543 SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy());
David Goodwin22c2fba2009-07-08 23:10:31 +00002544 if (Subtarget->isThumb1Only()) {
Renato Golinb9887ef2015-02-25 14:41:06 +00002545 // Set the alignment of the frame object to 4, to avoid having to generate
2546 // more than one ADD
2547 MachineFrameInfo *MFI = MF->getFrameInfo();
2548 if (MFI->getObjectAlignment(FI) < 4)
2549 MFI->setObjectAlignment(FI, 4);
Tim Northover23075cc2014-10-20 21:28:41 +00002550 return CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002551 CurDAG->getTargetConstant(0, dl, MVT::i32));
Jim Grosbachfde21102009-04-07 20:34:09 +00002552 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002553 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2554 ARM::t2ADDri : ARM::ADDri);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002555 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32),
2556 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32),
Owen Anderson9f944592009-08-11 20:47:22 +00002557 CurDAG->getRegister(0, MVT::i32) };
Craig Topper481fb282014-04-27 19:21:11 +00002558 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops);
Evan Cheng7e90b112007-07-05 07:15:27 +00002559 }
Evan Cheng10043e22007-01-19 07:51:42 +00002560 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002561 case ISD::SRL:
Jim Grosbach825cb292010-04-22 23:24:18 +00002562 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
Sandeep Patel423e42b2009-10-13 18:59:48 +00002563 return I;
2564 break;
Tim Northover14ff2df2014-07-23 13:59:12 +00002565 case ISD::SIGN_EXTEND_INREG:
Sandeep Patel423e42b2009-10-13 18:59:48 +00002566 case ISD::SRA:
Jim Grosbach825cb292010-04-22 23:24:18 +00002567 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true))
Sandeep Patel423e42b2009-10-13 18:59:48 +00002568 return I;
2569 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002570 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002571 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002572 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002573 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002574 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002575 if (!RHSV) break;
2576 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002577 unsigned ShImm = Log2_32(RHSV-1);
2578 if (ShImm >= 32)
2579 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002580 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002581 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002582 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002583 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002584 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002585 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002586 return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002587 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002588 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2589 Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002590 return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002591 }
Evan Cheng10043e22007-01-19 07:51:42 +00002592 }
2593 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002594 unsigned ShImm = Log2_32(RHSV+1);
2595 if (ShImm >= 32)
2596 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002597 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002598 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002599 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32);
Owen Anderson9f944592009-08-11 20:47:22 +00002600 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002601 if (Subtarget->isThumb()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002602 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002603 return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002604 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002605 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0,
2606 Reg0 };
Craig Topper481fb282014-04-27 19:21:11 +00002607 return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002608 }
Evan Cheng10043e22007-01-19 07:51:42 +00002609 }
2610 }
2611 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002612 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002613 // Check for unsigned bitfield extract
2614 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
2615 return I;
2616
Evan Cheng786b15f2009-10-21 08:15:52 +00002617 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2618 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2619 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2620 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2621 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002622 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002623 if (VT != MVT::i32)
2624 break;
2625 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2626 ? ARM::t2MOVTi16
2627 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2628 if (!Opc)
2629 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002630 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002631 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
2632 if (!N1C)
2633 break;
2634 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2635 SDValue N2 = N0.getOperand(1);
2636 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2637 if (!N2C)
2638 break;
2639 unsigned N1CVal = N1C->getZExtValue();
2640 unsigned N2CVal = N2C->getZExtValue();
2641 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2642 (N1CVal & 0xffffU) == 0xffffU &&
2643 (N2CVal & 0xffffU) == 0x0U) {
2644 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002645 dl, MVT::i32);
Evan Cheng786b15f2009-10-21 08:15:52 +00002646 SDValue Ops[] = { N0.getOperand(0), Imm16,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002647 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002648 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
Evan Cheng786b15f2009-10-21 08:15:52 +00002649 }
2650 }
2651 break;
2652 }
Jim Grosbachd7cf55c2009-11-09 00:11:35 +00002653 case ARMISD::VMOVRRD:
2654 return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002655 N->getOperand(0), getAL(CurDAG, dl),
Dan Gohman32f71d72009-09-25 18:54:59 +00002656 CurDAG->getRegister(0, MVT::i32));
Dan Gohmana1603612007-10-08 18:33:35 +00002657 case ISD::UMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002658 if (Subtarget->isThumb1Only())
2659 break;
2660 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002661 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002662 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002663 return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002664 } else {
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),
Owen Anderson9f944592009-08-11 20:47:22 +00002667 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov62acecd2011-01-01 20:38:38 +00002668 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2669 ARM::UMULL : ARM::UMULLv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002670 dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002671 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002672 }
Dan Gohmana1603612007-10-08 18:33:35 +00002673 case ISD::SMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002674 if (Subtarget->isThumb1Only())
2675 break;
2676 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002677 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002678 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002679 return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002680 } else {
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),
Owen Anderson9f944592009-08-11 20:47:22 +00002683 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov62acecd2011-01-01 20:38:38 +00002684 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2685 ARM::SMULL : ARM::SMULLv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002686 dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002687 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002688 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002689 case ARMISD::UMLAL:{
2690 if (Subtarget->isThumb()) {
2691 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002692 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002693 CurDAG->getRegister(0, MVT::i32)};
Michael Liaob53d8962013-04-19 22:22:57 +00002694 return CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002695 }else{
2696 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002697 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002698 CurDAG->getRegister(0, MVT::i32),
2699 CurDAG->getRegister(0, MVT::i32) };
2700 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2701 ARM::UMLAL : ARM::UMLALv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002702 dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002703 }
2704 }
2705 case ARMISD::SMLAL:{
2706 if (Subtarget->isThumb()) {
2707 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002708 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002709 CurDAG->getRegister(0, MVT::i32)};
Michael Liaob53d8962013-04-19 22:22:57 +00002710 return CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002711 }else{
2712 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002713 N->getOperand(3), getAL(CurDAG, dl),
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002714 CurDAG->getRegister(0, MVT::i32),
2715 CurDAG->getRegister(0, MVT::i32) };
2716 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2717 ARM::SMLAL : ARM::SMLALv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002718 dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002719 }
2720 }
Evan Cheng10043e22007-01-19 07:51:42 +00002721 case ISD::LOAD: {
Craig Topper062a2ba2014-04-25 05:30:21 +00002722 SDNode *ResNode = nullptr;
Evan Chengb24e51e2009-07-07 01:17:28 +00002723 if (Subtarget->isThumb() && Subtarget->hasThumb2())
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002724 ResNode = SelectT2IndexedLoad(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00002725 else
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002726 ResNode = SelectARMIndexedLoad(N);
Evan Chengd9c55362009-07-02 01:23:32 +00002727 if (ResNode)
2728 return ResNode;
Evan Cheng10043e22007-01-19 07:51:42 +00002729 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002730 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00002731 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002732 case ARMISD::BRCOND: {
2733 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2734 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2735 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00002736
Evan Cheng7e90b112007-07-05 07:15:27 +00002737 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2738 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2739 // Pattern complexity = 6 cost = 1 size = 0
2740
David Goodwin27303cd2009-06-30 18:04:13 +00002741 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2742 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2743 // Pattern complexity = 6 cost = 1 size = 0
2744
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002745 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00002746 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002747 SDValue Chain = N->getOperand(0);
2748 SDValue N1 = N->getOperand(1);
2749 SDValue N2 = N->getOperand(2);
2750 SDValue N3 = N->getOperand(3);
2751 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00002752 assert(N1.getOpcode() == ISD::BasicBlock);
2753 assert(N2.getOpcode() == ISD::Constant);
2754 assert(N3.getOpcode() == ISD::Register);
2755
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002756 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002757 cast<ConstantSDNode>(N2)->getZExtValue()), dl,
Owen Anderson9f944592009-08-11 20:47:22 +00002758 MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002759 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00002760 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002761 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002762 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002763 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002764 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002765 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00002766 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002767 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00002768 SDValue(Chain.getNode(), Chain.getResNo()));
Craig Topper062a2ba2014-04-25 05:30:21 +00002769 return nullptr;
Evan Cheng7e90b112007-07-05 07:15:27 +00002770 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002771 case ARMISD::VZIP: {
2772 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002773 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002774 switch (VT.getSimpleVT().SimpleTy) {
Craig Topper062a2ba2014-04-25 05:30:21 +00002775 default: return nullptr;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002776 case MVT::v8i8: Opc = ARM::VZIPd8; break;
2777 case MVT::v4i16: Opc = ARM::VZIPd16; break;
2778 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00002779 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2780 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002781 case MVT::v16i8: Opc = ARM::VZIPq8; break;
2782 case MVT::v8i16: Opc = ARM::VZIPq16; break;
2783 case MVT::v4f32:
2784 case MVT::v4i32: Opc = ARM::VZIPq32; break;
2785 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002786 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002787 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2788 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002789 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002790 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002791 case ARMISD::VUZP: {
2792 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002793 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002794 switch (VT.getSimpleVT().SimpleTy) {
Craig Topper062a2ba2014-04-25 05:30:21 +00002795 default: return nullptr;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002796 case MVT::v8i8: Opc = ARM::VUZPd8; break;
2797 case MVT::v4i16: Opc = ARM::VUZPd16; break;
2798 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00002799 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2800 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002801 case MVT::v16i8: Opc = ARM::VUZPq8; break;
2802 case MVT::v8i16: Opc = ARM::VUZPq16; break;
2803 case MVT::v4f32:
2804 case MVT::v4i32: Opc = ARM::VUZPq32; break;
2805 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002806 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002807 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2808 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002809 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002810 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002811 case ARMISD::VTRN: {
2812 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002813 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002814 switch (VT.getSimpleVT().SimpleTy) {
Craig Topper062a2ba2014-04-25 05:30:21 +00002815 default: return nullptr;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002816 case MVT::v8i8: Opc = ARM::VTRNd8; break;
2817 case MVT::v4i16: Opc = ARM::VTRNd16; break;
2818 case MVT::v2f32:
2819 case MVT::v2i32: Opc = ARM::VTRNd32; break;
2820 case MVT::v16i8: Opc = ARM::VTRNq8; break;
2821 case MVT::v8i16: Opc = ARM::VTRNq16; break;
2822 case MVT::v4f32:
2823 case MVT::v4i32: Opc = ARM::VTRNq32; break;
2824 }
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002825 SDValue Pred = getAL(CurDAG, dl);
Evan Chenga33fc862009-11-21 06:21:52 +00002826 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2827 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002828 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002829 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00002830 case ARMISD::BUILD_VECTOR: {
2831 EVT VecVT = N->getValueType(0);
2832 EVT EltVT = VecVT.getVectorElementType();
2833 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00002834 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00002835 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Weiming Zhao95782222012-11-17 00:23:35 +00002836 return createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilsond8a9a042010-06-04 00:04:02 +00002837 }
Duncan Sands14627772010-11-03 12:17:33 +00002838 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Bob Wilsond8a9a042010-06-04 00:04:02 +00002839 if (NumElts == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002840 return createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilsond8a9a042010-06-04 00:04:02 +00002841 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Weiming Zhao95782222012-11-17 00:23:35 +00002842 return createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
Bob Wilsond8a9a042010-06-04 00:04:02 +00002843 N->getOperand(2), N->getOperand(3));
2844 }
Bob Wilsone0636a72009-08-26 17:39:53 +00002845
Bob Wilson2d790df2010-11-28 06:51:26 +00002846 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002847 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
2848 ARM::VLD2DUPd32 };
Bob Wilson06fce872011-02-07 17:43:21 +00002849 return SelectVLDDup(N, false, 2, Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +00002850 }
2851
Bob Wilson77ab1652010-11-29 19:35:29 +00002852 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002853 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
2854 ARM::VLD3DUPd16Pseudo,
2855 ARM::VLD3DUPd32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00002856 return SelectVLDDup(N, false, 3, Opcodes);
Bob Wilson77ab1652010-11-29 19:35:29 +00002857 }
2858
Bob Wilson431ac4ef2010-11-30 00:00:35 +00002859 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002860 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
2861 ARM::VLD4DUPd16Pseudo,
2862 ARM::VLD4DUPd32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00002863 return SelectVLDDup(N, false, 4, Opcodes);
2864 }
2865
2866 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002867 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
2868 ARM::VLD2DUPd16wb_fixed,
2869 ARM::VLD2DUPd32wb_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00002870 return SelectVLDDup(N, true, 2, Opcodes);
2871 }
2872
2873 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002874 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
2875 ARM::VLD3DUPd16Pseudo_UPD,
2876 ARM::VLD3DUPd32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002877 return SelectVLDDup(N, true, 3, Opcodes);
2878 }
2879
2880 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002881 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
2882 ARM::VLD4DUPd16Pseudo_UPD,
2883 ARM::VLD4DUPd32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002884 return SelectVLDDup(N, true, 4, Opcodes);
2885 }
2886
2887 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002888 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
2889 ARM::VLD1d16wb_fixed,
2890 ARM::VLD1d32wb_fixed,
2891 ARM::VLD1d64wb_fixed };
2892 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
2893 ARM::VLD1q16wb_fixed,
2894 ARM::VLD1q32wb_fixed,
2895 ARM::VLD1q64wb_fixed };
Craig Topper062a2ba2014-04-25 05:30:21 +00002896 return SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr);
Bob Wilson06fce872011-02-07 17:43:21 +00002897 }
2898
2899 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002900 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
2901 ARM::VLD2d16wb_fixed,
2902 ARM::VLD2d32wb_fixed,
2903 ARM::VLD1q64wb_fixed};
2904 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
2905 ARM::VLD2q16PseudoWB_fixed,
2906 ARM::VLD2q32PseudoWB_fixed };
Craig Topper062a2ba2014-04-25 05:30:21 +00002907 return SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr);
Bob Wilson06fce872011-02-07 17:43:21 +00002908 }
2909
2910 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002911 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
2912 ARM::VLD3d16Pseudo_UPD,
2913 ARM::VLD3d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00002914 ARM::VLD1d64TPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00002915 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
2916 ARM::VLD3q16Pseudo_UPD,
2917 ARM::VLD3q32Pseudo_UPD };
2918 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
2919 ARM::VLD3q16oddPseudo_UPD,
2920 ARM::VLD3q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002921 return SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
2922 }
2923
2924 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002925 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
2926 ARM::VLD4d16Pseudo_UPD,
2927 ARM::VLD4d32Pseudo_UPD,
Jiangning Liu4df23632014-01-16 09:16:13 +00002928 ARM::VLD1d64QPseudoWB_fixed};
Craig Topper01736f82012-05-24 05:17:00 +00002929 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
2930 ARM::VLD4q16Pseudo_UPD,
2931 ARM::VLD4q32Pseudo_UPD };
2932 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
2933 ARM::VLD4q16oddPseudo_UPD,
2934 ARM::VLD4q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002935 return SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
2936 }
2937
2938 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002939 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
2940 ARM::VLD2LNd16Pseudo_UPD,
2941 ARM::VLD2LNd32Pseudo_UPD };
2942 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
2943 ARM::VLD2LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002944 return SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
2945 }
2946
2947 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002948 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
2949 ARM::VLD3LNd16Pseudo_UPD,
2950 ARM::VLD3LNd32Pseudo_UPD };
2951 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
2952 ARM::VLD3LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002953 return SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
2954 }
2955
2956 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002957 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
2958 ARM::VLD4LNd16Pseudo_UPD,
2959 ARM::VLD4LNd32Pseudo_UPD };
2960 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
2961 ARM::VLD4LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002962 return SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
2963 }
2964
2965 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002966 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
2967 ARM::VST1d16wb_fixed,
2968 ARM::VST1d32wb_fixed,
2969 ARM::VST1d64wb_fixed };
2970 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
2971 ARM::VST1q16wb_fixed,
2972 ARM::VST1q32wb_fixed,
2973 ARM::VST1q64wb_fixed };
Craig Topper062a2ba2014-04-25 05:30:21 +00002974 return SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr);
Bob Wilson06fce872011-02-07 17:43:21 +00002975 }
2976
2977 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002978 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
2979 ARM::VST2d16wb_fixed,
2980 ARM::VST2d32wb_fixed,
2981 ARM::VST1q64wb_fixed};
2982 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
2983 ARM::VST2q16PseudoWB_fixed,
2984 ARM::VST2q32PseudoWB_fixed };
Craig Topper062a2ba2014-04-25 05:30:21 +00002985 return SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr);
Bob Wilson06fce872011-02-07 17:43:21 +00002986 }
2987
2988 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002989 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
2990 ARM::VST3d16Pseudo_UPD,
2991 ARM::VST3d32Pseudo_UPD,
2992 ARM::VST1d64TPseudoWB_fixed};
2993 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
2994 ARM::VST3q16Pseudo_UPD,
2995 ARM::VST3q32Pseudo_UPD };
2996 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
2997 ARM::VST3q16oddPseudo_UPD,
2998 ARM::VST3q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002999 return SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3000 }
3001
3002 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003003 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3004 ARM::VST4d16Pseudo_UPD,
3005 ARM::VST4d32Pseudo_UPD,
3006 ARM::VST1d64QPseudoWB_fixed};
3007 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3008 ARM::VST4q16Pseudo_UPD,
3009 ARM::VST4q32Pseudo_UPD };
3010 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3011 ARM::VST4q16oddPseudo_UPD,
3012 ARM::VST4q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003013 return SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3014 }
3015
3016 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003017 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3018 ARM::VST2LNd16Pseudo_UPD,
3019 ARM::VST2LNd32Pseudo_UPD };
3020 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3021 ARM::VST2LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003022 return SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3023 }
3024
3025 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003026 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3027 ARM::VST3LNd16Pseudo_UPD,
3028 ARM::VST3LNd32Pseudo_UPD };
3029 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3030 ARM::VST3LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003031 return SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3032 }
3033
3034 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003035 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3036 ARM::VST4LNd16Pseudo_UPD,
3037 ARM::VST4LNd32Pseudo_UPD };
3038 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3039 ARM::VST4LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003040 return SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003041 }
3042
Bob Wilsone0636a72009-08-26 17:39:53 +00003043 case ISD::INTRINSIC_VOID:
3044 case ISD::INTRINSIC_W_CHAIN: {
3045 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003046 switch (IntNo) {
3047 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003048 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003049
Tim Northover1ff5f292014-03-26 14:39:31 +00003050 case Intrinsic::arm_ldaexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003051 case Intrinsic::arm_ldrexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003052 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003053 SDValue Chain = N->getOperand(0);
Tim Northover1ff5f292014-03-26 14:39:31 +00003054 SDValue MemAddr = N->getOperand(2);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003055 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
Tim Northover1ff5f292014-03-26 14:39:31 +00003056
3057 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
3058 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)
3059 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003060
3061 // arm_ldrexd returns a i64 value in {i32, i32}
3062 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003063 if (isThumb) {
3064 ResTys.push_back(MVT::i32);
3065 ResTys.push_back(MVT::i32);
3066 } else
3067 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003068 ResTys.push_back(MVT::Other);
3069
Weiming Zhao8f56f882012-11-16 21:55:34 +00003070 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003071 SmallVector<SDValue, 7> Ops;
3072 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003073 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003074 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3075 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00003076 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003077 // Transfer memoperands.
3078 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3079 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3080 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3081
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003082 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003083 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003084 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003085 SDValue Result;
3086 if (isThumb)
3087 Result = SDValue(Ld, 0);
3088 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003089 SDValue SubRegIdx =
3090 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003091 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003092 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003093 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003094 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003095 ReplaceUses(SDValue(N, 0), Result);
3096 }
3097 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003098 SDValue Result;
3099 if (isThumb)
3100 Result = SDValue(Ld, 1);
3101 else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003102 SDValue SubRegIdx =
3103 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003104 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003105 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003106 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003107 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003108 ReplaceUses(SDValue(N, 1), Result);
3109 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003110 ReplaceUses(SDValue(N, 2), OutChain);
Craig Topper062a2ba2014-04-25 05:30:21 +00003111 return nullptr;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003112 }
Tim Northover1ff5f292014-03-26 14:39:31 +00003113 case Intrinsic::arm_stlexd:
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003114 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003115 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003116 SDValue Chain = N->getOperand(0);
3117 SDValue Val0 = N->getOperand(2);
3118 SDValue Val1 = N->getOperand(3);
3119 SDValue MemAddr = N->getOperand(4);
3120
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003121 // Store exclusive double return a i32 value which is the return status
3122 // of the issued store.
Benjamin Kramer867bfc52015-03-07 17:41:00 +00003123 const EVT ResTys[] = {MVT::i32, MVT::Other};
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003124
Weiming Zhao8f56f882012-11-16 21:55:34 +00003125 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3126 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003127 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003128 if (isThumb) {
3129 Ops.push_back(Val0);
3130 Ops.push_back(Val1);
3131 } else
3132 // arm_strexd uses GPRPair.
3133 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003134 Ops.push_back(MemAddr);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003135 Ops.push_back(getAL(CurDAG, dl));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003136 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3137 Ops.push_back(Chain);
3138
Tim Northover1ff5f292014-03-26 14:39:31 +00003139 bool IsRelease = IntNo == Intrinsic::arm_stlexd;
3140 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD)
3141 : (IsRelease ? ARM::STLEXD : ARM::STREXD);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003142
Michael Liaob53d8962013-04-19 22:22:57 +00003143 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003144 // Transfer memoperands.
3145 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3146 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3147 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3148
3149 return St;
3150 }
3151
Bob Wilson340861d2010-03-23 05:25:43 +00003152 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003153 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3154 ARM::VLD1d32, ARM::VLD1d64 };
3155 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3156 ARM::VLD1q32, ARM::VLD1q64};
Craig Topper062a2ba2014-04-25 05:30:21 +00003157 return SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr);
Bob Wilson340861d2010-03-23 05:25:43 +00003158 }
3159
Bob Wilsone0636a72009-08-26 17:39:53 +00003160 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003161 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3162 ARM::VLD2d32, ARM::VLD1q64 };
3163 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3164 ARM::VLD2q32Pseudo };
Craig Topper062a2ba2014-04-25 05:30:21 +00003165 return SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr);
Bob Wilsone0636a72009-08-26 17:39:53 +00003166 }
3167
3168 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003169 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3170 ARM::VLD3d16Pseudo,
3171 ARM::VLD3d32Pseudo,
3172 ARM::VLD1d64TPseudo };
3173 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3174 ARM::VLD3q16Pseudo_UPD,
3175 ARM::VLD3q32Pseudo_UPD };
3176 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3177 ARM::VLD3q16oddPseudo,
3178 ARM::VLD3q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003179 return SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003180 }
3181
3182 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003183 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3184 ARM::VLD4d16Pseudo,
3185 ARM::VLD4d32Pseudo,
3186 ARM::VLD1d64QPseudo };
3187 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3188 ARM::VLD4q16Pseudo_UPD,
3189 ARM::VLD4q32Pseudo_UPD };
3190 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3191 ARM::VLD4q16oddPseudo,
3192 ARM::VLD4q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003193 return SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003194 }
3195
Bob Wilsonda9817c2009-09-01 04:26:28 +00003196 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003197 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3198 ARM::VLD2LNd16Pseudo,
3199 ARM::VLD2LNd32Pseudo };
3200 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3201 ARM::VLD2LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003202 return SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003203 }
3204
3205 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003206 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3207 ARM::VLD3LNd16Pseudo,
3208 ARM::VLD3LNd32Pseudo };
3209 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3210 ARM::VLD3LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003211 return SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003212 }
3213
3214 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003215 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3216 ARM::VLD4LNd16Pseudo,
3217 ARM::VLD4LNd32Pseudo };
3218 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3219 ARM::VLD4LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003220 return SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003221 }
3222
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003223 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003224 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3225 ARM::VST1d32, ARM::VST1d64 };
3226 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3227 ARM::VST1q32, ARM::VST1q64 };
Craig Topper062a2ba2014-04-25 05:30:21 +00003228 return SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr);
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003229 }
3230
Bob Wilsone0636a72009-08-26 17:39:53 +00003231 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003232 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3233 ARM::VST2d32, ARM::VST1q64 };
3234 static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3235 ARM::VST2q32Pseudo };
Craig Topper062a2ba2014-04-25 05:30:21 +00003236 return SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr);
Bob Wilsone0636a72009-08-26 17:39:53 +00003237 }
3238
3239 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003240 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3241 ARM::VST3d16Pseudo,
3242 ARM::VST3d32Pseudo,
3243 ARM::VST1d64TPseudo };
3244 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3245 ARM::VST3q16Pseudo_UPD,
3246 ARM::VST3q32Pseudo_UPD };
3247 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3248 ARM::VST3q16oddPseudo,
3249 ARM::VST3q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003250 return SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003251 }
3252
3253 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003254 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3255 ARM::VST4d16Pseudo,
3256 ARM::VST4d32Pseudo,
3257 ARM::VST1d64QPseudo };
3258 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3259 ARM::VST4q16Pseudo_UPD,
3260 ARM::VST4q32Pseudo_UPD };
3261 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3262 ARM::VST4q16oddPseudo,
3263 ARM::VST4q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003264 return SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003265 }
Bob Wilsond7797752009-09-01 18:51:56 +00003266
3267 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003268 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3269 ARM::VST2LNd16Pseudo,
3270 ARM::VST2LNd32Pseudo };
3271 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3272 ARM::VST2LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003273 return SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003274 }
3275
3276 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003277 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3278 ARM::VST3LNd16Pseudo,
3279 ARM::VST3LNd32Pseudo };
3280 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3281 ARM::VST3LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003282 return SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003283 }
3284
3285 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003286 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3287 ARM::VST4LNd16Pseudo,
3288 ARM::VST4LNd32Pseudo };
3289 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3290 ARM::VST4LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003291 return SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003292 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003293 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003294 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003295 }
Evan Chengd85631e2010-05-05 18:28:36 +00003296
Bob Wilson3ed511b2010-07-06 23:36:25 +00003297 case ISD::INTRINSIC_WO_CHAIN: {
3298 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3299 switch (IntNo) {
3300 default:
3301 break;
3302
3303 case Intrinsic::arm_neon_vtbl2:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003304 return SelectVTBL(N, false, 2, ARM::VTBL2);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003305 case Intrinsic::arm_neon_vtbl3:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003306 return SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003307 case Intrinsic::arm_neon_vtbl4:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003308 return SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003309
3310 case Intrinsic::arm_neon_vtbx2:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003311 return SelectVTBL(N, true, 2, ARM::VTBX2);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003312 case Intrinsic::arm_neon_vtbx3:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003313 return SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003314 case Intrinsic::arm_neon_vtbx4:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003315 return SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003316 }
3317 break;
3318 }
3319
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003320 case ARMISD::VTBL1: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003321 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003322 EVT VT = N->getValueType(0);
3323 SmallVector<SDValue, 6> Ops;
3324
3325 Ops.push_back(N->getOperand(0));
3326 Ops.push_back(N->getOperand(1));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003327 Ops.push_back(getAL(CurDAG, dl)); // Predicate
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003328 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Michael Liaob53d8962013-04-19 22:22:57 +00003329 return CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003330 }
3331 case ARMISD::VTBL2: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003332 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003333 EVT VT = N->getValueType(0);
3334
3335 // Form a REG_SEQUENCE to force register allocation.
3336 SDValue V0 = N->getOperand(0);
3337 SDValue V1 = N->getOperand(1);
Weiming Zhao95782222012-11-17 00:23:35 +00003338 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003339
3340 SmallVector<SDValue, 6> Ops;
3341 Ops.push_back(RegSeq);
3342 Ops.push_back(N->getOperand(2));
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003343 Ops.push_back(getAL(CurDAG, dl)); // Predicate
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003344 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Michael Liaob53d8962013-04-19 22:22:57 +00003345 return CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003346 }
3347
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003348 case ISD::CONCAT_VECTORS:
Evan Chengd85631e2010-05-05 18:28:36 +00003349 return SelectConcatVector(N);
3350 }
Evan Chengd5021732008-12-10 21:54:21 +00003351
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003352 return SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003353}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003354
Luke Cheeseman85fd06d2015-06-01 12:02:47 +00003355// Inspect a register string of the form
3356// cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or
3357// cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string
3358// and obtain the integer operands from them, adding these operands to the
3359// provided vector.
3360static void getIntOperandsFromRegisterString(StringRef RegString,
3361 SelectionDAG *CurDAG, SDLoc DL,
3362 std::vector<SDValue>& Ops) {
3363 SmallVector<StringRef, 5> Fields;
3364 RegString.split(Fields, ":");
3365
3366 if (Fields.size() > 1) {
3367 bool AllIntFields = true;
3368
3369 for (StringRef Field : Fields) {
3370 // Need to trim out leading 'cp' characters and get the integer field.
3371 unsigned IntField;
3372 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField);
3373 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32));
3374 }
3375
3376 assert(AllIntFields &&
3377 "Unexpected non-integer value in special register string.");
3378 }
3379}
3380
3381// Maps a Banked Register string to its mask value. The mask value returned is
3382// for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register
3383// mask operand, which expresses which register is to be used, e.g. r8, and in
3384// which mode it is to be used, e.g. usr. Returns -1 to signify that the string
3385// was invalid.
3386static inline int getBankedRegisterMask(StringRef RegString) {
3387 return StringSwitch<int>(RegString.lower())
3388 .Case("r8_usr", 0x00)
3389 .Case("r9_usr", 0x01)
3390 .Case("r10_usr", 0x02)
3391 .Case("r11_usr", 0x03)
3392 .Case("r12_usr", 0x04)
3393 .Case("sp_usr", 0x05)
3394 .Case("lr_usr", 0x06)
3395 .Case("r8_fiq", 0x08)
3396 .Case("r9_fiq", 0x09)
3397 .Case("r10_fiq", 0x0a)
3398 .Case("r11_fiq", 0x0b)
3399 .Case("r12_fiq", 0x0c)
3400 .Case("sp_fiq", 0x0d)
3401 .Case("lr_fiq", 0x0e)
3402 .Case("lr_irq", 0x10)
3403 .Case("sp_irq", 0x11)
3404 .Case("lr_svc", 0x12)
3405 .Case("sp_svc", 0x13)
3406 .Case("lr_abt", 0x14)
3407 .Case("sp_abt", 0x15)
3408 .Case("lr_und", 0x16)
3409 .Case("sp_und", 0x17)
3410 .Case("lr_mon", 0x1c)
3411 .Case("sp_mon", 0x1d)
3412 .Case("elr_hyp", 0x1e)
3413 .Case("sp_hyp", 0x1f)
3414 .Case("spsr_fiq", 0x2e)
3415 .Case("spsr_irq", 0x30)
3416 .Case("spsr_svc", 0x32)
3417 .Case("spsr_abt", 0x34)
3418 .Case("spsr_und", 0x36)
3419 .Case("spsr_mon", 0x3c)
3420 .Case("spsr_hyp", 0x3e)
3421 .Default(-1);
3422}
3423
3424// Maps a MClass special register string to its value for use in the
3425// t2MRS_M / t2MSR_M instruction nodes as the SYSm value operand.
3426// Returns -1 to signify that the string was invalid.
3427static inline int getMClassRegisterSYSmValueMask(StringRef RegString) {
3428 return StringSwitch<int>(RegString.lower())
3429 .Case("apsr", 0x0)
3430 .Case("iapsr", 0x1)
3431 .Case("eapsr", 0x2)
3432 .Case("xpsr", 0x3)
3433 .Case("ipsr", 0x5)
3434 .Case("epsr", 0x6)
3435 .Case("iepsr", 0x7)
3436 .Case("msp", 0x8)
3437 .Case("psp", 0x9)
3438 .Case("primask", 0x10)
3439 .Case("basepri", 0x11)
3440 .Case("basepri_max", 0x12)
3441 .Case("faultmask", 0x13)
3442 .Case("control", 0x14)
3443 .Default(-1);
3444}
3445
3446// The flags here are common to those allowed for apsr in the A class cores and
3447// those allowed for the special registers in the M class cores. Returns a
3448// value representing which flags were present, -1 if invalid.
3449static inline int getMClassFlagsMask(StringRef Flags) {
3450 if (Flags.empty())
3451 return 0x3;
3452
3453 return StringSwitch<int>(Flags)
3454 .Case("g", 0x1)
3455 .Case("nzcvq", 0x2)
3456 .Case("nzcvqg", 0x3)
3457 .Default(-1);
3458}
3459
3460static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead,
3461 const ARMSubtarget *Subtarget) {
3462 // Ensure that the register (without flags) was a valid M Class special
3463 // register.
3464 int SYSmvalue = getMClassRegisterSYSmValueMask(Reg);
3465 if (SYSmvalue == -1)
3466 return -1;
3467
3468 // basepri, basepri_max and faultmask are only valid for V7m.
3469 if (!Subtarget->hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
3470 return -1;
3471
3472 // If it was a read then we won't be expecting flags and so at this point
3473 // we can return the mask.
3474 if (IsRead) {
3475 assert (Flags.empty() && "Unexpected flags for reading M class register.");
3476 return SYSmvalue;
3477 }
3478
3479 // We know we are now handling a write so need to get the mask for the flags.
3480 int Mask = getMClassFlagsMask(Flags);
3481
3482 // Only apsr, iapsr, eapsr, xpsr can have flags. The other register values
3483 // shouldn't have flags present.
3484 if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.empty()))
3485 return -1;
3486
3487 // The _g and _nzcvqg versions are only valid if the DSP extension is
3488 // available.
3489 if (!Subtarget->hasThumb2DSP() && (Mask & 0x2))
3490 return -1;
3491
3492 // The register was valid so need to put the mask in the correct place
3493 // (the flags need to be in bits 11-10) and combine with the SYSmvalue to
3494 // construct the operand for the instruction node.
3495 if (SYSmvalue < 0x4)
3496 return SYSmvalue | Mask << 10;
3497
3498 return SYSmvalue;
3499}
3500
3501static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
3502 // The mask operand contains the special register (R Bit) in bit 4, whether
3503 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and
3504 // bits 3-0 contains the fields to be accessed in the special register, set by
3505 // the flags provided with the register.
3506 int Mask = 0;
3507 if (Reg == "apsr") {
3508 // The flags permitted for apsr are the same flags that are allowed in
3509 // M class registers. We get the flag value and then shift the flags into
3510 // the correct place to combine with the mask.
3511 Mask = getMClassFlagsMask(Flags);
3512 if (Mask == -1)
3513 return -1;
3514 return Mask << 2;
3515 }
3516
3517 if (Reg != "cpsr" && Reg != "spsr") {
3518 return -1;
3519 }
3520
3521 // This is the same as if the flags were "fc"
3522 if (Flags.empty() || Flags == "all")
3523 return Mask | 0x9;
3524
3525 // Inspect the supplied flags string and set the bits in the mask for
3526 // the relevant and valid flags allowed for cpsr and spsr.
3527 for (char Flag : Flags) {
3528 int FlagVal;
3529 switch (Flag) {
3530 case 'c':
3531 FlagVal = 0x1;
3532 break;
3533 case 'x':
3534 FlagVal = 0x2;
3535 break;
3536 case 's':
3537 FlagVal = 0x4;
3538 break;
3539 case 'f':
3540 FlagVal = 0x8;
3541 break;
3542 default:
3543 FlagVal = 0;
3544 }
3545
3546 // This avoids allowing strings where the same flag bit appears twice.
3547 if (!FlagVal || (Mask & FlagVal))
3548 return -1;
3549 Mask |= FlagVal;
3550 }
3551
3552 // If the register is spsr then we need to set the R bit.
3553 if (Reg == "spsr")
3554 Mask |= 0x10;
3555
3556 return Mask;
3557}
3558
3559// Lower the read_register intrinsic to ARM specific DAG nodes
3560// using the supplied metadata string to select the instruction node to use
3561// and the registers/masks to construct as operands for the node.
3562SDNode *ARMDAGToDAGISel::SelectReadRegister(SDNode *N){
3563 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3564 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3565 bool IsThumb2 = Subtarget->isThumb2();
3566 SDLoc DL(N);
3567
3568 std::vector<SDValue> Ops;
3569 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3570
3571 if (!Ops.empty()) {
3572 // If the special register string was constructed of fields (as defined
3573 // in the ACLE) then need to lower to MRC node (32 bit) or
3574 // MRRC node(64 bit), we can make the distinction based on the number of
3575 // operands we have.
3576 unsigned Opcode;
3577 SmallVector<EVT, 3> ResTypes;
3578 if (Ops.size() == 5){
3579 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC;
3580 ResTypes.append({ MVT::i32, MVT::Other });
3581 } else {
3582 assert(Ops.size() == 3 &&
3583 "Invalid number of fields in special register string.");
3584 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC;
3585 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other });
3586 }
3587
3588 Ops.push_back(getAL(CurDAG, DL));
3589 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3590 Ops.push_back(N->getOperand(0));
3591 return CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops);
3592 }
3593
3594 std::string SpecialReg = RegString->getString().lower();
3595
3596 int BankedReg = getBankedRegisterMask(SpecialReg);
3597 if (BankedReg != -1) {
3598 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32),
3599 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3600 N->getOperand(0) };
3601 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked,
3602 DL, MVT::i32, MVT::Other, Ops);
3603 }
3604
3605 // The VFP registers are read by creating SelectionDAG nodes with opcodes
3606 // corresponding to the register that is being read from. So we switch on the
3607 // string to find which opcode we need to use.
3608 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3609 .Case("fpscr", ARM::VMRS)
3610 .Case("fpexc", ARM::VMRS_FPEXC)
3611 .Case("fpsid", ARM::VMRS_FPSID)
3612 .Case("mvfr0", ARM::VMRS_MVFR0)
3613 .Case("mvfr1", ARM::VMRS_MVFR1)
3614 .Case("mvfr2", ARM::VMRS_MVFR2)
3615 .Case("fpinst", ARM::VMRS_FPINST)
3616 .Case("fpinst2", ARM::VMRS_FPINST2)
3617 .Default(0);
3618
3619 // If an opcode was found then we can lower the read to a VFP instruction.
3620 if (Opcode) {
3621 if (!Subtarget->hasVFP2())
3622 return nullptr;
3623 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8())
3624 return nullptr;
3625
3626 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3627 N->getOperand(0) };
3628 return CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops);
3629 }
3630
3631 // If the target is M Class then need to validate that the register string
3632 // is an acceptable value, so check that a mask can be constructed from the
3633 // string.
3634 if (Subtarget->isMClass()) {
3635 int SYSmValue = getMClassRegisterMask(SpecialReg, "", true, Subtarget);
3636 if (SYSmValue == -1)
3637 return nullptr;
3638
3639 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
3640 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3641 N->getOperand(0) };
3642 return CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops);
3643 }
3644
3645 // Here we know the target is not M Class so we need to check if it is one
3646 // of the remaining possible values which are apsr, cpsr or spsr.
3647 if (SpecialReg == "apsr" || SpecialReg == "cpsr") {
3648 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3649 N->getOperand(0) };
3650 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS, DL,
3651 MVT::i32, MVT::Other, Ops);
3652 }
3653
3654 if (SpecialReg == "spsr") {
3655 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3656 N->getOperand(0) };
3657 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys,
3658 DL, MVT::i32, MVT::Other, Ops);
3659 }
3660
3661 return nullptr;
3662}
3663
3664// Lower the write_register intrinsic to ARM specific DAG nodes
3665// using the supplied metadata string to select the instruction node to use
3666// and the registers/masks to use in the nodes
3667SDNode *ARMDAGToDAGISel::SelectWriteRegister(SDNode *N){
3668 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
3669 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
3670 bool IsThumb2 = Subtarget->isThumb2();
3671 SDLoc DL(N);
3672
3673 std::vector<SDValue> Ops;
3674 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops);
3675
3676 if (!Ops.empty()) {
3677 // If the special register string was constructed of fields (as defined
3678 // in the ACLE) then need to lower to MCR node (32 bit) or
3679 // MCRR node(64 bit), we can make the distinction based on the number of
3680 // operands we have.
3681 unsigned Opcode;
3682 if (Ops.size() == 5) {
3683 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR;
3684 Ops.insert(Ops.begin()+2, N->getOperand(2));
3685 } else {
3686 assert(Ops.size() == 3 &&
3687 "Invalid number of fields in special register string.");
3688 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR;
3689 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) };
3690 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2);
3691 }
3692
3693 Ops.push_back(getAL(CurDAG, DL));
3694 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3695 Ops.push_back(N->getOperand(0));
3696
3697 return CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops);
3698 }
3699
3700 std::string SpecialReg = RegString->getString().lower();
3701 int BankedReg = getBankedRegisterMask(SpecialReg);
3702 if (BankedReg != -1) {
3703 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2),
3704 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3705 N->getOperand(0) };
3706 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked,
3707 DL, MVT::Other, Ops);
3708 }
3709
3710 // The VFP registers are written to by creating SelectionDAG nodes with
3711 // opcodes corresponding to the register that is being written. So we switch
3712 // on the string to find which opcode we need to use.
3713 unsigned Opcode = StringSwitch<unsigned>(SpecialReg)
3714 .Case("fpscr", ARM::VMSR)
3715 .Case("fpexc", ARM::VMSR_FPEXC)
3716 .Case("fpsid", ARM::VMSR_FPSID)
3717 .Case("fpinst", ARM::VMSR_FPINST)
3718 .Case("fpinst2", ARM::VMSR_FPINST2)
3719 .Default(0);
3720
3721 if (Opcode) {
3722 if (!Subtarget->hasVFP2())
3723 return nullptr;
3724 Ops = { N->getOperand(2), getAL(CurDAG, DL),
3725 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
3726 return CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops);
3727 }
3728
3729 SmallVector<StringRef, 5> Fields;
3730 StringRef(SpecialReg).split(Fields, "_", 1, false);
3731 std::string Reg = Fields[0].str();
3732 StringRef Flags = Fields.size() == 2 ? Fields[1] : "";
3733
3734 // If the target was M Class then need to validate the special register value
3735 // and retrieve the mask for use in the instruction node.
3736 if (Subtarget->isMClass()) {
3737 // basepri_max gets split so need to correct Reg and Flags.
3738 if (SpecialReg == "basepri_max") {
3739 Reg = SpecialReg;
3740 Flags = "";
3741 }
3742 int SYSmValue = getMClassRegisterMask(Reg, Flags, false, Subtarget);
3743 if (SYSmValue == -1)
3744 return nullptr;
3745
3746 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32),
3747 N->getOperand(2), getAL(CurDAG, DL),
3748 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) };
3749 return CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops);
3750 }
3751
3752 // We then check to see if a valid mask can be constructed for one of the
3753 // register string values permitted for the A and R class cores. These values
3754 // are apsr, spsr and cpsr; these are also valid on older cores.
3755 int Mask = getARClassRegisterMask(Reg, Flags);
3756 if (Mask != -1) {
3757 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2),
3758 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32),
3759 N->getOperand(0) };
3760 return CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR,
3761 DL, MVT::Other, Ops);
3762 }
3763
3764 return nullptr;
3765}
3766
Weiming Zhaoc5987002013-02-14 18:10:21 +00003767SDNode *ARMDAGToDAGISel::SelectInlineAsm(SDNode *N){
3768 std::vector<SDValue> AsmNodeOperands;
3769 unsigned Flag, Kind;
3770 bool Changed = false;
3771 unsigned NumOps = N->getNumOperands();
3772
Weiming Zhaoc5987002013-02-14 18:10:21 +00003773 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
3774 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
3775 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
3776 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003777 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
3778 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
3779 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00003780
Andrew Trickef9de2a2013-05-25 02:42:55 +00003781 SDLoc dl(N);
Craig Topper062a2ba2014-04-25 05:30:21 +00003782 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1)
3783 : SDValue(nullptr,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003784
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003785 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003786 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003787 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00003788 SDValue op = N->getOperand(i);
3789 AsmNodeOperands.push_back(op);
3790
3791 if (i < InlineAsm::Op_FirstOperand)
3792 continue;
3793
3794 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
3795 Flag = C->getZExtValue();
3796 Kind = InlineAsm::getKind(Flag);
3797 }
3798 else
3799 continue;
3800
Joey Gouly392cdad2013-07-08 19:52:51 +00003801 // Immediate operands to inline asm in the SelectionDAG are modeled with
3802 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
3803 // the second is a constant with the value of the immediate. If we get here
3804 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00003805 if (Kind == InlineAsm::Kind_Imm) {
3806 SDValue op = N->getOperand(++i);
3807 AsmNodeOperands.push_back(op);
3808 continue;
3809 }
3810
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003811 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
3812 if (NumRegs)
3813 OpChanged.push_back(false);
3814
3815 unsigned DefIdx = 0;
3816 bool IsTiedToChangedOp = false;
3817 // If it's a use that is tied with a previous def, it has no
3818 // reg class constraint.
3819 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
3820 IsTiedToChangedOp = OpChanged[DefIdx];
3821
Weiming Zhaoc5987002013-02-14 18:10:21 +00003822 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
3823 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
3824 continue;
3825
Weiming Zhaoc5987002013-02-14 18:10:21 +00003826 unsigned RC;
3827 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003828 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
3829 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00003830 continue;
3831
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003832 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00003833 SDValue V0 = N->getOperand(i+1);
3834 SDValue V1 = N->getOperand(i+2);
3835 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
3836 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
3837 SDValue PairedReg;
3838 MachineRegisterInfo &MRI = MF->getRegInfo();
3839
3840 if (Kind == InlineAsm::Kind_RegDef ||
3841 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
3842 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
3843 // the original GPRs.
3844
3845 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3846 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3847 SDValue Chain = SDValue(N,0);
3848
3849 SDNode *GU = N->getGluedUser();
3850 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
3851 Chain.getValue(1));
3852
3853 // Extract values from a GPRPair reg and copy to the original GPR reg.
3854 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
3855 RegCopy);
3856 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
3857 RegCopy);
3858 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
3859 RegCopy.getValue(1));
3860 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
3861
3862 // Update the original glue user.
3863 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
3864 Ops.push_back(T1.getValue(1));
Craig Topper8c0b4d02014-04-28 05:57:50 +00003865 CurDAG->UpdateNodeOperands(GU, Ops);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003866 }
3867 else {
3868 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
3869 // GPRPair and then pass the GPRPair to the inline asm.
3870 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
3871
3872 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
3873 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
3874 Chain.getValue(1));
3875 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
3876 T0.getValue(1));
3877 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
3878
3879 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
3880 // i32 VRs of inline asm with it.
3881 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3882 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3883 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
3884
3885 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
3886 Glue = Chain.getValue(1);
3887 }
3888
3889 Changed = true;
3890
3891 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003892 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003893 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00003894 if (IsTiedToChangedOp)
3895 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
3896 else
3897 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003898 // Replace the current flag.
3899 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00003900 Flag, dl, MVT::i32);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003901 // Add the new register node and skip the original two GPRs.
3902 AsmNodeOperands.push_back(PairedReg);
3903 // Skip the next two GPRs.
3904 i += 2;
3905 }
3906 }
3907
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003908 if (Glue.getNode())
3909 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003910 if (!Changed)
Craig Topper062a2ba2014-04-25 05:30:21 +00003911 return nullptr;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003912
Andrew Trickef9de2a2013-05-25 02:42:55 +00003913 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Craig Topper48d114b2014-04-26 18:35:24 +00003914 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003915 New->setNodeId(-1);
3916 return New.getNode();
3917}
3918
3919
Bob Wilsona2c462b2009-05-19 05:53:42 +00003920bool ARMDAGToDAGISel::
Daniel Sanders60f1db02015-03-13 12:45:09 +00003921SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
Bob Wilsona2c462b2009-05-19 05:53:42 +00003922 std::vector<SDValue> &OutOps) {
Daniel Sanders1f58ef72015-06-03 12:33:56 +00003923 switch(ConstraintID) {
3924 default:
3925 llvm_unreachable("Unexpected asm memory constraint");
Daniel Sanders43a79bf2015-06-03 14:17:18 +00003926 case InlineAsm::Constraint_i:
3927 // FIXME: It seems strange that 'i' is needed here since it's supposed to
3928 // be an immediate and not a memory constraint.
3929 // Fallthrough.
Daniel Sanders1f58ef72015-06-03 12:33:56 +00003930 case InlineAsm::Constraint_m:
3931 case InlineAsm::Constraint_Q:
3932 case InlineAsm::Constraint_Um:
3933 case InlineAsm::Constraint_Un:
3934 case InlineAsm::Constraint_Uq:
3935 case InlineAsm::Constraint_Us:
3936 case InlineAsm::Constraint_Ut:
3937 case InlineAsm::Constraint_Uv:
3938 case InlineAsm::Constraint_Uy:
3939 // Require the address to be in a register. That is safe for all ARM
3940 // variants and it is hard to do anything much smarter without knowing
3941 // how the operand is used.
3942 OutOps.push_back(Op);
3943 return false;
3944 }
3945 return true;
Bob Wilsona2c462b2009-05-19 05:53:42 +00003946}
3947
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003948/// createARMISelDag - This pass converts a legalized DAG into a
3949/// ARM-specific DAG, ready for instruction scheduling.
3950///
Bob Wilson2dd957f2009-09-28 14:30:20 +00003951FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
3952 CodeGenOpt::Level OptLevel) {
3953 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003954}