blob: 3298b73dad2cadfa3492daf02be9647297986126 [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
Dale Johannesend679ff72010-06-03 21:09:53 +000014#define DEBUG_TYPE "arm-isel"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000015#include "ARM.h"
Evan Cheng62c7b5b2010-12-05 22:04:16 +000016#include "ARMBaseInstrInfo.h"
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000017#include "ARMTargetMachine.h"
Evan Chenga20cde32011-07-20 23:34:39 +000018#include "MCTargetDesc/ARMAddressingModes.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"
35#include "llvm/Support/raw_ostream.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000036#include "llvm/Target/TargetLowering.h"
37#include "llvm/Target/TargetOptions.h"
Torok Edwinfb8d6d52009-07-08 20:53:28 +000038
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000039using namespace llvm;
40
Evan Cheng59069ec2010-07-30 23:33:54 +000041static cl::opt<bool>
42DisableShifterOp("disable-shifter-op", cl::Hidden,
43 cl::desc("Disable isel of shifter-op"),
44 cl::init(false));
45
Evan Cheng62c7b5b2010-12-05 22:04:16 +000046static cl::opt<bool>
47CheckVMLxHazard("check-vmlx-hazard", cl::Hidden,
48 cl::desc("Check fp vmla / vmls hazard at isel time"),
Bob Wilson0858c3a2011-04-19 18:11:57 +000049 cl::init(true));
Evan Cheng62c7b5b2010-12-05 22:04:16 +000050
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000051//===--------------------------------------------------------------------===//
52/// ARMDAGToDAGISel - ARM specific code to select ARM machine
53/// instructions for SelectionDAG operations.
54///
55namespace {
Jim Grosbach08605202010-09-29 19:03:54 +000056
57enum AddrMode2Type {
58 AM2_BASE, // Simple AM2 (+-imm12)
59 AM2_SHOP // Shifter-op AM2
60};
61
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000062class ARMDAGToDAGISel : public SelectionDAGISel {
Anton Korobeynikov99152f32009-06-26 21:28:53 +000063 ARMBaseTargetMachine &TM;
Evan Chengbc0d0ec2008-09-18 07:24:33 +000064
Evan Cheng10043e22007-01-19 07:51:42 +000065 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
66 /// make the right decision when generating code for different targets.
67 const ARMSubtarget *Subtarget;
68
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000069public:
Bob Wilson2dd957f2009-09-28 14:30:20 +000070 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm,
71 CodeGenOpt::Level OptLevel)
72 : SelectionDAGISel(tm, OptLevel), TM(tm),
Evan Cheng62c7b5b2010-12-05 22:04:16 +000073 Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
Rafael Espindolaffdc24b2006-05-14 22:18:28 +000074 }
75
Evan Cheng10043e22007-01-19 07:51:42 +000076 virtual const char *getPassName() const {
77 return "ARM Instruction Selection";
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000078 }
79
Evan Chengeae6d2c2012-12-19 20:16:09 +000080 virtual void PreprocessISelDAG();
81
Bob Wilson4facd962009-10-08 18:51:31 +000082 /// getI32Imm - Return a target constant of type i32 with the specified
83 /// value.
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000084 inline SDValue getI32Imm(unsigned Imm) {
Owen Anderson9f944592009-08-11 20:47:22 +000085 return CurDAG->getTargetConstant(Imm, MVT::i32);
Anton Korobeynikov02bb33c2009-06-17 18:13:58 +000086 }
87
Dan Gohmanea6f91f2010-01-05 01:24:18 +000088 SDNode *Select(SDNode *N);
Evan Cheng5e73ff22010-02-15 19:41:07 +000089
Evan Cheng62c7b5b2010-12-05 22:04:16 +000090
91 bool hasNoVMLxHazardUse(SDNode *N) const;
Evan Cheng59bbc542010-10-27 23:41:30 +000092 bool isShifterOpProfitable(const SDValue &Shift,
93 ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt);
Owen Andersonb595ed02011-07-21 18:54:16 +000094 bool SelectRegShifterOperand(SDValue N, SDValue &A,
95 SDValue &B, SDValue &C,
96 bool CheckProfitability = true);
97 bool SelectImmShifterOperand(SDValue N, SDValue &A,
Owen Anderson04912702011-07-21 23:38:37 +000098 SDValue &B, bool CheckProfitability = true);
99 bool SelectShiftRegShifterOperand(SDValue N, SDValue &A,
Owen Anderson6d557452011-03-18 19:46:58 +0000100 SDValue &B, SDValue &C) {
101 // Don't apply the profitability check
Owen Anderson04912702011-07-21 23:38:37 +0000102 return SelectRegShifterOperand(N, A, B, C, false);
103 }
104 bool SelectShiftImmShifterOperand(SDValue N, SDValue &A,
105 SDValue &B) {
106 // Don't apply the profitability check
107 return SelectImmShifterOperand(N, A, B, false);
Owen Anderson6d557452011-03-18 19:46:58 +0000108 }
109
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000110 bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
111 bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);
112
Jim Grosbach08605202010-09-29 19:03:54 +0000113 AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base,
114 SDValue &Offset, SDValue &Opc);
115 bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset,
116 SDValue &Opc) {
117 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE;
118 }
119
120 bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset,
121 SDValue &Opc) {
122 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP;
123 }
124
125 bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset,
126 SDValue &Opc) {
127 SelectAddrMode2Worker(N, Base, Offset, Opc);
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000128// return SelectAddrMode2ShOp(N, Base, Offset, Opc);
Jim Grosbach08605202010-09-29 19:03:54 +0000129 // This always matches one way or another.
130 return true;
131 }
132
Owen Anderson2aedba62011-07-26 20:54:26 +0000133 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
134 SDValue &Offset, SDValue &Opc);
135 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000136 SDValue &Offset, SDValue &Opc);
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000137 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
138 SDValue &Offset, SDValue &Opc);
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000139 bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000140 bool SelectAddrMode3(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000141 SDValue &Offset, SDValue &Opc);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000142 bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000143 SDValue &Offset, SDValue &Opc);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000144 bool SelectAddrMode5(SDValue N, SDValue &Base,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000145 SDValue &Offset);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000146 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
Bob Wilsone3ecd5f2011-02-25 06:42:42 +0000147 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000148
Evan Chengdfce83c2011-01-17 08:03:18 +0000149 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
Evan Cheng10043e22007-01-19 07:51:42 +0000150
Bill Wendling092a7bd2010-12-14 03:36:38 +0000151 // Thumb Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000152 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
Bill Wendling092a7bd2010-12-14 03:36:38 +0000153 bool SelectThumbAddrModeRI(SDValue N, SDValue &Base, SDValue &Offset,
154 unsigned Scale);
155 bool SelectThumbAddrModeRI5S1(SDValue N, SDValue &Base, SDValue &Offset);
156 bool SelectThumbAddrModeRI5S2(SDValue N, SDValue &Base, SDValue &Offset);
157 bool SelectThumbAddrModeRI5S4(SDValue N, SDValue &Base, SDValue &Offset);
158 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
159 SDValue &OffImm);
160 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
161 SDValue &OffImm);
162 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
163 SDValue &OffImm);
164 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
165 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000166 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +0000167
Bill Wendling092a7bd2010-12-14 03:36:38 +0000168 // Thumb 2 Addressing Modes:
Chris Lattner0e023ea2010-09-21 20:31:19 +0000169 bool SelectT2ShifterOperandReg(SDValue N,
Evan Chengeab9ca72009-06-27 02:26:13 +0000170 SDValue &BaseReg, SDValue &Opc);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000171 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
172 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000173 SDValue &OffImm);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000174 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +0000175 SDValue &OffImm);
Chris Lattner0e023ea2010-09-21 20:31:19 +0000176 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base,
Evan Chengb23b50d2009-06-29 07:51:04 +0000177 SDValue &OffReg, SDValue &ShImm);
Tim Northovera7ecd242013-07-16 09:46:55 +0000178 bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm);
Evan Chengb23b50d2009-06-29 07:51:04 +0000179
Evan Cheng0fc80842010-11-12 22:42:47 +0000180 inline bool is_so_imm(unsigned Imm) const {
181 return ARM_AM::getSOImmVal(Imm) != -1;
182 }
183
184 inline bool is_so_imm_not(unsigned Imm) const {
185 return ARM_AM::getSOImmVal(~Imm) != -1;
186 }
187
188 inline bool is_t2_so_imm(unsigned Imm) const {
189 return ARM_AM::getT2SOImmVal(Imm) != -1;
190 }
191
192 inline bool is_t2_so_imm_not(unsigned Imm) const {
193 return ARM_AM::getT2SOImmVal(~Imm) != -1;
194 }
195
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000196 // Include the pieces autogenerated from the target description.
197#include "ARMGenDAGISel.inc"
Bob Wilsona2c462b2009-05-19 05:53:42 +0000198
199private:
Evan Cheng84c6cda2009-07-02 07:28:31 +0000200 /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
201 /// ARM.
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000202 SDNode *SelectARMIndexedLoad(SDNode *N);
203 SDNode *SelectT2IndexedLoad(SDNode *N);
Evan Cheng84c6cda2009-07-02 07:28:31 +0000204
Bob Wilson340861d2010-03-23 05:25:43 +0000205 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
206 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson12b47992009-10-14 17:28:52 +0000207 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson340861d2010-03-23 05:25:43 +0000208 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson06fce872011-02-07 17:43:21 +0000209 SDNode *SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000210 const uint16_t *DOpcodes,
211 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilson12b47992009-10-14 17:28:52 +0000212
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000213 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000214 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000215 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000216 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson06fce872011-02-07 17:43:21 +0000217 SDNode *SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000218 const uint16_t *DOpcodes,
219 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000220
Bob Wilson93117bc2009-10-14 16:46:45 +0000221 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilson4145e3a2009-10-14 16:19:03 +0000222 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsond5c57a52010-09-13 23:01:35 +0000223 /// load/store of D registers and Q registers.
Bob Wilson06fce872011-02-07 17:43:21 +0000224 SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad,
225 bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000226 const uint16_t *DOpcodes, const uint16_t *QOpcodes);
Bob Wilson4145e3a2009-10-14 16:19:03 +0000227
Bob Wilson2d790df2010-11-28 06:51:26 +0000228 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
229 /// should be 2, 3 or 4. The opcode array specifies the instructions used
230 /// for loading D registers. (Q registers are not supported.)
Bob Wilson06fce872011-02-07 17:43:21 +0000231 SDNode *SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000232 const uint16_t *Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +0000233
Bob Wilson5bc8a792010-07-07 00:08:54 +0000234 /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2,
235 /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be
236 /// generated to force the table registers to be consecutive.
237 SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc);
Bob Wilson3ed511b2010-07-06 23:36:25 +0000238
Sandeep Patel7460e082009-10-13 20:25:58 +0000239 /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
Jim Grosbach825cb292010-04-22 23:24:18 +0000240 SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000241
Evan Chengb6c77042009-11-19 21:45:22 +0000242 /// SelectCMOVOp - Select CMOV instructions for ARM.
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000243 SDNode *SelectCMOVOp(SDNode *N);
244 SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +0000245 ARMCC::CondCodes CCVal, SDValue CCR,
246 SDValue InFlag);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000247 SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +0000248 ARMCC::CondCodes CCVal, SDValue CCR,
249 SDValue InFlag);
Jim Grosbach5b255c22010-10-07 00:53:56 +0000250 SDNode *SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +0000251 ARMCC::CondCodes CCVal, SDValue CCR,
252 SDValue InFlag);
Jim Grosbach742adc32010-10-07 00:42:42 +0000253 SDNode *SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +0000254 ARMCC::CondCodes CCVal, SDValue CCR,
255 SDValue InFlag);
Evan Chengb6c77042009-11-19 21:45:22 +0000256
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000257 // Select special operations if node forms integer ABS pattern
258 SDNode *SelectABSOp(SDNode *N);
259
Weiming Zhaoc5987002013-02-14 18:10:21 +0000260 SDNode *SelectInlineAsm(SDNode *N);
261
Evan Chengd85631e2010-05-05 18:28:36 +0000262 SDNode *SelectConcatVector(SDNode *N);
263
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +0000264 SDNode *SelectAtomic64(SDNode *Node, unsigned Opc);
265
Evan Chengd9c55362009-07-02 01:23:32 +0000266 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
267 /// inline asm expressions.
268 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
269 char ConstraintCode,
270 std::vector<SDValue> &OutOps);
Bob Wilsone6b778d2009-10-06 22:01:59 +0000271
Weiming Zhao95782222012-11-17 00:23:35 +0000272 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhao8f56f882012-11-16 21:55:34 +0000273 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao95782222012-11-17 00:23:35 +0000274 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
275 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
276 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Chengc2ae5f52010-05-10 17:34:18 +0000277
Bob Wilsond8a9a042010-06-04 00:04:02 +0000278 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +0000279 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
280 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
281 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000282
283 // Get the alignment operand for a NEON VLD or VST instruction.
284 SDValue GetVLDSTAlign(SDValue Align, unsigned NumVecs, bool is64BitVector);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000285};
Evan Cheng10043e22007-01-19 07:51:42 +0000286}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000287
Sandeep Patel423e42b2009-10-13 18:59:48 +0000288/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
289/// operand. If so Imm will receive the 32-bit value.
290static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
291 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
292 Imm = cast<ConstantSDNode>(N)->getZExtValue();
293 return true;
294 }
295 return false;
296}
297
298// isInt32Immediate - This method tests to see if a constant operand.
299// If so Imm will receive the 32 bit value.
300static bool isInt32Immediate(SDValue N, unsigned &Imm) {
301 return isInt32Immediate(N.getNode(), Imm);
302}
303
304// isOpcWithIntImmediate - This method tests to see if the node is a specific
305// opcode and that it has a immediate integer right operand.
306// If so Imm will receive the 32 bit value.
307static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
308 return N->getOpcode() == Opc &&
309 isInt32Immediate(N->getOperand(1).getNode(), Imm);
310}
311
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000312/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000313/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000314///
315/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000316static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000317 int RangeMin, int RangeMax,
318 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000319 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000320
321 // Check that this is a constant.
322 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
323 if (!C)
324 return false;
325
326 ScaledConstant = (int) C->getZExtValue();
327 if ((ScaledConstant % Scale) != 0)
328 return false;
329
330 ScaledConstant /= Scale;
331 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
332}
333
Evan Chengeae6d2c2012-12-19 20:16:09 +0000334void ARMDAGToDAGISel::PreprocessISelDAG() {
335 if (!Subtarget->hasV6T2Ops())
336 return;
337
338 bool isThumb2 = Subtarget->isThumb();
339 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
340 E = CurDAG->allnodes_end(); I != E; ) {
341 SDNode *N = I++; // Preincrement iterator to avoid invalidation issues.
342
343 if (N->getOpcode() != ISD::ADD)
344 continue;
345
346 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
347 // leading zeros, followed by consecutive set bits, followed by 1 or 2
348 // trailing zeros, e.g. 1020.
349 // Transform the expression to
350 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
351 // of trailing zeros of c2. The left shift would be folded as an shifter
352 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
353 // node (UBFX).
354
355 SDValue N0 = N->getOperand(0);
356 SDValue N1 = N->getOperand(1);
357 unsigned And_imm = 0;
358 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
359 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
360 std::swap(N0, N1);
361 }
362 if (!And_imm)
363 continue;
364
365 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000366 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000367 if (TZ != 1 && TZ != 2)
368 // Be conservative here. Shifter operands aren't always free. e.g. On
369 // Swift, left shifter operand of 1 / 2 for free but others are not.
370 // e.g.
371 // ubfx r3, r1, #16, #8
372 // ldr.w r3, [r0, r3, lsl #2]
373 // vs.
374 // mov.w r9, #1020
375 // and.w r2, r9, r1, lsr #14
376 // ldr r2, [r0, r2]
377 continue;
378 And_imm >>= TZ;
379 if (And_imm & (And_imm + 1))
380 continue;
381
382 // Look for (and (srl X, c1), c2).
383 SDValue Srl = N1.getOperand(0);
384 unsigned Srl_imm = 0;
385 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
386 (Srl_imm <= 2))
387 continue;
388
389 // Make sure first operand is not a shifter operand which would prevent
390 // folding of the left shift.
391 SDValue CPTmp0;
392 SDValue CPTmp1;
393 SDValue CPTmp2;
394 if (isThumb2) {
395 if (SelectT2ShifterOperandReg(N0, CPTmp0, CPTmp1))
396 continue;
397 } else {
398 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
399 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
400 continue;
401 }
402
403 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000404 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000405 Srl.getOperand(0),
406 CurDAG->getConstant(Srl_imm+TZ, MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000407 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000408 Srl, CurDAG->getConstant(And_imm, MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000409 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000410 N1, CurDAG->getConstant(TZ, MVT::i32));
411 CurDAG->UpdateNodeOperands(N, N0, N1);
412 }
413}
414
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000415/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
416/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
417/// least on current ARM implementations) which should be avoidded.
418bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
419 if (OptLevel == CodeGenOpt::None)
420 return true;
421
422 if (!CheckVMLxHazard)
423 return true;
Bob Wilsone8a549c2012-09-29 21:43:49 +0000424
Silviu Baranga91ddaa12013-07-29 09:25:50 +0000425 if (!Subtarget->isCortexA8() && !Subtarget->isCortexA9() &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000426 !Subtarget->isSwift())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000427 return true;
428
429 if (!N->hasOneUse())
430 return false;
431
432 SDNode *Use = *N->use_begin();
433 if (Use->getOpcode() == ISD::CopyToReg)
434 return true;
435 if (Use->isMachineOpcode()) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000436 const ARMBaseInstrInfo *TII =
437 static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo());
438
Evan Cheng6cc775f2011-06-28 19:10:37 +0000439 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
440 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000441 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000442 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000443 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
444 return true;
445 // vmlx feeding into another vmlx. We actually want to unfold
446 // the use later in the MLxExpansion pass. e.g.
447 // vmla
448 // vmla (stall 8 cycles)
449 //
450 // vmul (5 cycles)
451 // vadd (5 cycles)
452 // vmla
453 // This adds up to about 18 - 19 cycles.
454 //
455 // vmla
456 // vmul (stall 4 cycles)
457 // vadd adds up to about 14 cycles.
458 return TII->isFpMLxInstruction(Opcode);
459 }
460
461 return false;
462}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000463
Evan Cheng59bbc542010-10-27 23:41:30 +0000464bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
465 ARM_AM::ShiftOpc ShOpcVal,
466 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000467 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000468 return true;
469 if (Shift.hasOneUse())
470 return true;
471 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000472 return ShOpcVal == ARM_AM::lsl &&
473 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000474}
475
Owen Andersonb595ed02011-07-21 18:54:16 +0000476bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000477 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000478 SDValue &Opc,
479 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000480 if (DisableShifterOp)
481 return false;
482
Evan Chenga20cde32011-07-20 23:34:39 +0000483 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000484
485 // Don't match base register only case. That is matched to a separate
486 // lower complexity pattern with explicit register operand.
487 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000488
Evan Chengb23b50d2009-06-29 07:51:04 +0000489 BaseReg = N.getOperand(0);
490 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000491 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
492 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000493 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000494 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
495 MVT::i32);
496 return true;
497}
498
Owen Andersonb595ed02011-07-21 18:54:16 +0000499bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
500 SDValue &BaseReg,
501 SDValue &ShReg,
502 SDValue &Opc,
503 bool CheckProfitability) {
504 if (DisableShifterOp)
505 return false;
506
507 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
508
509 // Don't match base register only case. That is matched to a separate
510 // lower complexity pattern with explicit register operand.
511 if (ShOpcVal == ARM_AM::no_shift) return false;
512
513 BaseReg = N.getOperand(0);
514 unsigned ShImmVal = 0;
515 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
516 if (RHS) return false;
517
518 ShReg = N.getOperand(1);
519 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
520 return false;
521 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
522 MVT::i32);
523 return true;
524}
525
526
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000527bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
528 SDValue &Base,
529 SDValue &OffImm) {
530 // Match simple R + imm12 operands.
531
532 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000533 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
534 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000535 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000536 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000537 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000538 Base = CurDAG->getTargetFrameIndex(FI,
539 getTargetLowering()->getPointerTy());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000540 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
541 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000542 }
Owen Anderson6d557452011-03-18 19:46:58 +0000543
Chris Lattner46c01a32011-02-13 22:25:43 +0000544 if (N.getOpcode() == ARMISD::Wrapper &&
545 !(Subtarget->useMovt() &&
546 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000547 Base = N.getOperand(0);
548 } else
549 Base = N;
550 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
551 return true;
552 }
553
554 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
555 int RHSC = (int)RHS->getZExtValue();
556 if (N.getOpcode() == ISD::SUB)
557 RHSC = -RHSC;
558
559 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
560 Base = N.getOperand(0);
561 if (Base.getOpcode() == ISD::FrameIndex) {
562 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000563 Base = CurDAG->getTargetFrameIndex(FI,
564 getTargetLowering()->getPointerTy());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000565 }
566 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
567 return true;
568 }
569 }
570
571 // Base only.
572 Base = N;
573 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
574 return true;
575}
576
577
578
579bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
580 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000581 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000582 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000583 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
584 // X * [3,5,9] -> X + X * [2,4,8] etc.
585 int RHSC = (int)RHS->getZExtValue();
586 if (RHSC & 1) {
587 RHSC = RHSC & ~1;
588 ARM_AM::AddrOpc AddSub = ARM_AM::add;
589 if (RHSC < 0) {
590 AddSub = ARM_AM::sub;
591 RHSC = - RHSC;
592 }
593 if (isPowerOf2_32(RHSC)) {
594 unsigned ShAmt = Log2_32(RHSC);
595 Base = Offset = N.getOperand(0);
596 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
597 ARM_AM::lsl),
598 MVT::i32);
599 return true;
600 }
601 }
602 }
603 }
604
Chris Lattner46c01a32011-02-13 22:25:43 +0000605 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
606 // ISD::OR that is equivalent to an ISD::ADD.
607 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000608 return false;
609
610 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000611 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000612 int RHSC;
613 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
614 -0x1000+1, 0x1000, RHSC)) // 12 bits.
615 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000616 }
617
618 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000619 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000620 ARM_AM::ShiftOpc ShOpcVal =
621 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000622 unsigned ShAmt = 0;
623
624 Base = N.getOperand(0);
625 Offset = N.getOperand(1);
626
627 if (ShOpcVal != ARM_AM::no_shift) {
628 // Check to see if the RHS of the shift is a constant, if not, we can't fold
629 // it.
630 if (ConstantSDNode *Sh =
631 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
632 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000633 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
634 Offset = N.getOperand(1).getOperand(0);
635 else {
636 ShAmt = 0;
637 ShOpcVal = ARM_AM::no_shift;
638 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000639 } else {
640 ShOpcVal = ARM_AM::no_shift;
641 }
642 }
643
644 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000645 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000646 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
647 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000648 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000649 if (ShOpcVal != ARM_AM::no_shift) {
650 // Check to see if the RHS of the shift is a constant, if not, we can't
651 // fold it.
652 if (ConstantSDNode *Sh =
653 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
654 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000655 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000656 Offset = N.getOperand(0).getOperand(0);
657 Base = N.getOperand(1);
658 } else {
659 ShAmt = 0;
660 ShOpcVal = ARM_AM::no_shift;
661 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000662 } else {
663 ShOpcVal = ARM_AM::no_shift;
664 }
665 }
666 }
667
668 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
669 MVT::i32);
670 return true;
671}
672
673
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000674//-----
675
Jim Grosbach08605202010-09-29 19:03:54 +0000676AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
677 SDValue &Base,
678 SDValue &Offset,
679 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000680 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000681 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000682 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
683 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmaneffb8942008-09-12 16:56:44 +0000684 int RHSC = (int)RHS->getZExtValue();
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000685 if (RHSC & 1) {
686 RHSC = RHSC & ~1;
687 ARM_AM::AddrOpc AddSub = ARM_AM::add;
688 if (RHSC < 0) {
689 AddSub = ARM_AM::sub;
690 RHSC = - RHSC;
691 }
692 if (isPowerOf2_32(RHSC)) {
693 unsigned ShAmt = Log2_32(RHSC);
694 Base = Offset = N.getOperand(0);
695 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
696 ARM_AM::lsl),
Owen Anderson9f944592009-08-11 20:47:22 +0000697 MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000698 return AM2_SHOP;
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000699 }
700 }
701 }
702 }
703
Chris Lattner46c01a32011-02-13 22:25:43 +0000704 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
705 // ISD::OR that is equivalent to an ADD.
706 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000707 Base = N;
708 if (N.getOpcode() == ISD::FrameIndex) {
709 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000710 Base = CurDAG->getTargetFrameIndex(FI,
711 getTargetLowering()->getPointerTy());
Anton Korobeynikov25229082009-11-24 00:44:37 +0000712 } else if (N.getOpcode() == ARMISD::Wrapper &&
713 !(Subtarget->useMovt() &&
714 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000715 Base = N.getOperand(0);
716 }
Owen Anderson9f944592009-08-11 20:47:22 +0000717 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000718 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
719 ARM_AM::no_shift),
Owen Anderson9f944592009-08-11 20:47:22 +0000720 MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000721 return AM2_BASE;
Rafael Espindola708cb602006-11-08 17:07:32 +0000722 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000723
Evan Cheng10043e22007-01-19 07:51:42 +0000724 // Match simple R +/- imm12 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +0000725 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000726 int RHSC;
727 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
728 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
729 Base = N.getOperand(0);
730 if (Base.getOpcode() == ISD::FrameIndex) {
731 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000732 Base = CurDAG->getTargetFrameIndex(FI,
733 getTargetLowering()->getPointerTy());
Rafael Espindola708cb602006-11-08 17:07:32 +0000734 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000735 Offset = CurDAG->getRegister(0, MVT::i32);
736
737 ARM_AM::AddrOpc AddSub = ARM_AM::add;
738 if (RHSC < 0) {
739 AddSub = ARM_AM::sub;
740 RHSC = - RHSC;
741 }
742 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
743 ARM_AM::no_shift),
744 MVT::i32);
745 return AM2_BASE;
Evan Cheng10043e22007-01-19 07:51:42 +0000746 }
Jim Grosbachc7b10f32010-09-29 17:32:29 +0000747 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000748
Bob Wilsone8a549c2012-09-29 21:43:49 +0000749 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000750 // Compute R +/- (R << N) and reuse it.
751 Base = N;
752 Offset = CurDAG->getRegister(0, MVT::i32);
753 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
754 ARM_AM::no_shift),
755 MVT::i32);
756 return AM2_BASE;
757 }
758
Johnny Chenb678a562009-10-27 17:25:15 +0000759 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000760 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chenga20cde32011-07-20 23:34:39 +0000761 ARM_AM::ShiftOpc ShOpcVal =
762 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000763 unsigned ShAmt = 0;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000764
Evan Cheng10043e22007-01-19 07:51:42 +0000765 Base = N.getOperand(0);
766 Offset = N.getOperand(1);
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000767
Evan Cheng10043e22007-01-19 07:51:42 +0000768 if (ShOpcVal != ARM_AM::no_shift) {
769 // Check to see if the RHS of the shift is a constant, if not, we can't fold
770 // it.
771 if (ConstantSDNode *Sh =
772 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000773 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000774 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
775 Offset = N.getOperand(1).getOperand(0);
776 else {
777 ShAmt = 0;
778 ShOpcVal = ARM_AM::no_shift;
779 }
Evan Cheng10043e22007-01-19 07:51:42 +0000780 } else {
781 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola708cb602006-11-08 17:07:32 +0000782 }
783 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000784
Evan Cheng10043e22007-01-19 07:51:42 +0000785 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000786 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000787 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
788 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000789 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000790 if (ShOpcVal != ARM_AM::no_shift) {
791 // Check to see if the RHS of the shift is a constant, if not, we can't
792 // fold it.
793 if (ConstantSDNode *Sh =
794 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000795 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000796 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000797 Offset = N.getOperand(0).getOperand(0);
798 Base = N.getOperand(1);
799 } else {
800 ShAmt = 0;
801 ShOpcVal = ARM_AM::no_shift;
802 }
Evan Cheng10043e22007-01-19 07:51:42 +0000803 } else {
804 ShOpcVal = ARM_AM::no_shift;
805 }
806 }
807 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000808
Evan Cheng10043e22007-01-19 07:51:42 +0000809 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson9f944592009-08-11 20:47:22 +0000810 MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000811 return AM2_SHOP;
Rafael Espindola708cb602006-11-08 17:07:32 +0000812}
813
Owen Anderson2aedba62011-07-26 20:54:26 +0000814bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000815 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000816 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000817 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
818 ? cast<LoadSDNode>(Op)->getAddressingMode()
819 : cast<StoreSDNode>(Op)->getAddressingMode();
820 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
821 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000822 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000823 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
824 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000825
826 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000827 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000828 unsigned ShAmt = 0;
829 if (ShOpcVal != ARM_AM::no_shift) {
830 // Check to see if the RHS of the shift is a constant, if not, we can't fold
831 // it.
832 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000833 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000834 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
835 Offset = N.getOperand(0);
836 else {
837 ShAmt = 0;
838 ShOpcVal = ARM_AM::no_shift;
839 }
Evan Cheng10043e22007-01-19 07:51:42 +0000840 } else {
841 ShOpcVal = ARM_AM::no_shift;
842 }
843 }
844
845 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson9f944592009-08-11 20:47:22 +0000846 MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000847 return true;
848}
849
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000850bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
851 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000852 unsigned Opcode = Op->getOpcode();
853 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
854 ? cast<LoadSDNode>(Op)->getAddressingMode()
855 : cast<StoreSDNode>(Op)->getAddressingMode();
856 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
857 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000858 int Val;
859 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000860 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000861 Offset = CurDAG->getRegister(0, MVT::i32);
862 Opc = CurDAG->getTargetConstant(Val, MVT::i32);
863 return true;
864 }
865
866 return false;
867}
868
869
Owen Anderson2aedba62011-07-26 20:54:26 +0000870bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
871 SDValue &Offset, SDValue &Opc) {
872 unsigned Opcode = Op->getOpcode();
873 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
874 ? cast<LoadSDNode>(Op)->getAddressingMode()
875 : cast<StoreSDNode>(Op)->getAddressingMode();
876 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
877 ? ARM_AM::add : ARM_AM::sub;
878 int Val;
879 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
880 Offset = CurDAG->getRegister(0, MVT::i32);
881 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
882 ARM_AM::no_shift),
883 MVT::i32);
884 return true;
885 }
886
887 return false;
888}
889
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000890bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
891 Base = N;
892 return true;
893}
Evan Cheng10043e22007-01-19 07:51:42 +0000894
Chris Lattner0e023ea2010-09-21 20:31:19 +0000895bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000896 SDValue &Base, SDValue &Offset,
897 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000898 if (N.getOpcode() == ISD::SUB) {
899 // X - C is canonicalize to X + -C, no need to handle it here.
900 Base = N.getOperand(0);
901 Offset = N.getOperand(1);
Owen Anderson9f944592009-08-11 20:47:22 +0000902 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000903 return true;
904 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000905
Chris Lattner46c01a32011-02-13 22:25:43 +0000906 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000907 Base = N;
908 if (N.getOpcode() == ISD::FrameIndex) {
909 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000910 Base = CurDAG->getTargetFrameIndex(FI,
911 getTargetLowering()->getPointerTy());
Evan Cheng10043e22007-01-19 07:51:42 +0000912 }
Owen Anderson9f944592009-08-11 20:47:22 +0000913 Offset = CurDAG->getRegister(0, MVT::i32);
914 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000915 return true;
916 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000917
Evan Cheng10043e22007-01-19 07:51:42 +0000918 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000919 int RHSC;
920 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
921 -256 + 1, 256, RHSC)) { // 8 bits.
922 Base = N.getOperand(0);
923 if (Base.getOpcode() == ISD::FrameIndex) {
924 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000925 Base = CurDAG->getTargetFrameIndex(FI,
926 getTargetLowering()->getPointerTy());
Evan Cheng10043e22007-01-19 07:51:42 +0000927 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000928 Offset = CurDAG->getRegister(0, MVT::i32);
929
930 ARM_AM::AddrOpc AddSub = ARM_AM::add;
931 if (RHSC < 0) {
932 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000933 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000934 }
935 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32);
936 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000937 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000938
Evan Cheng10043e22007-01-19 07:51:42 +0000939 Base = N.getOperand(0);
940 Offset = N.getOperand(1);
Owen Anderson9f944592009-08-11 20:47:22 +0000941 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000942 return true;
943}
944
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000945bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000946 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000947 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000948 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
949 ? cast<LoadSDNode>(Op)->getAddressingMode()
950 : cast<StoreSDNode>(Op)->getAddressingMode();
951 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
952 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000953 int Val;
954 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
955 Offset = CurDAG->getRegister(0, MVT::i32);
956 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32);
957 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000958 }
959
960 Offset = N;
Owen Anderson9f944592009-08-11 20:47:22 +0000961 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000962 return true;
963}
964
Jim Grosbachd37f0712010-10-21 19:38:40 +0000965bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000966 SDValue &Base, SDValue &Offset) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000967 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000968 Base = N;
969 if (N.getOpcode() == ISD::FrameIndex) {
970 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000971 Base = CurDAG->getTargetFrameIndex(FI,
972 getTargetLowering()->getPointerTy());
Anton Korobeynikov25229082009-11-24 00:44:37 +0000973 } else if (N.getOpcode() == ARMISD::Wrapper &&
974 !(Subtarget->useMovt() &&
975 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000976 Base = N.getOperand(0);
977 }
978 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson9f944592009-08-11 20:47:22 +0000979 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000980 return true;
981 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000982
Evan Cheng10043e22007-01-19 07:51:42 +0000983 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000984 int RHSC;
985 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
986 -256 + 1, 256, RHSC)) {
987 Base = N.getOperand(0);
988 if (Base.getOpcode() == ISD::FrameIndex) {
989 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000990 Base = CurDAG->getTargetFrameIndex(FI,
991 getTargetLowering()->getPointerTy());
Evan Cheng10043e22007-01-19 07:51:42 +0000992 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000993
994 ARM_AM::AddrOpc AddSub = ARM_AM::add;
995 if (RHSC < 0) {
996 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000997 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000998 }
999 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
1000 MVT::i32);
1001 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001002 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001003
Evan Cheng10043e22007-01-19 07:51:42 +00001004 Base = N;
1005 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson9f944592009-08-11 20:47:22 +00001006 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001007 return true;
1008}
1009
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001010bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
1011 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +00001012 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001013
1014 unsigned Alignment = 0;
1015 if (LSBaseSDNode *LSN = dyn_cast<LSBaseSDNode>(Parent)) {
1016 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
1017 // The maximum alignment is equal to the memory size being referenced.
1018 unsigned LSNAlign = LSN->getAlignment();
1019 unsigned MemSize = LSN->getMemoryVT().getSizeInBits() / 8;
Jakob Stoklund Olesene5a6adc2011-10-27 22:39:16 +00001020 if (LSNAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001021 Alignment = MemSize;
1022 } else {
1023 // All other uses of addrmode6 are for intrinsics. For now just record
1024 // the raw alignment value; it will be refined later based on the legal
1025 // alignment operands for the intrinsic.
1026 Alignment = cast<MemIntrinsicSDNode>(Parent)->getAlignment();
1027 }
1028
1029 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001030 return true;
1031}
1032
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001033bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1034 SDValue &Offset) {
1035 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1036 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1037 if (AM != ISD::POST_INC)
1038 return false;
1039 Offset = N;
1040 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1041 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1042 Offset = CurDAG->getRegister(0, MVT::i32);
1043 }
1044 return true;
1045}
1046
Chris Lattner0e023ea2010-09-21 20:31:19 +00001047bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001048 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001049 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1050 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001051 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001052 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
1053 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001054 return true;
1055 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001056
Evan Cheng10043e22007-01-19 07:51:42 +00001057 return false;
1058}
1059
Bill Wendling092a7bd2010-12-14 03:36:38 +00001060
1061//===----------------------------------------------------------------------===//
1062// Thumb Addressing Modes
1063//===----------------------------------------------------------------------===//
1064
Chris Lattner0e023ea2010-09-21 20:31:19 +00001065bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001066 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001067 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001068 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001069 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001070 return false;
1071
1072 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001073 return true;
1074 }
1075
Evan Cheng10043e22007-01-19 07:51:42 +00001076 Base = N.getOperand(0);
1077 Offset = N.getOperand(1);
1078 return true;
1079}
1080
Evan Cheng139edae2007-01-24 02:21:22 +00001081bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001082ARMDAGToDAGISel::SelectThumbAddrModeRI(SDValue N, SDValue &Base,
1083 SDValue &Offset, unsigned Scale) {
Evan Cheng139edae2007-01-24 02:21:22 +00001084 if (Scale == 4) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001085 SDValue TmpBase, TmpOffImm;
Chris Lattner0e023ea2010-09-21 20:31:19 +00001086 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
Evan Cheng139edae2007-01-24 02:21:22 +00001087 return false; // We want to select tLDRspi / tSTRspi instead.
Bill Wendling092a7bd2010-12-14 03:36:38 +00001088
Evan Cheng1526ba52007-01-24 08:53:17 +00001089 if (N.getOpcode() == ARMISD::Wrapper &&
1090 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1091 return false; // We want to select tLDRpci instead.
Evan Cheng139edae2007-01-24 02:21:22 +00001092 }
1093
Chris Lattner46c01a32011-02-13 22:25:43 +00001094 if (!CurDAG->isBaseWithConstantOffset(N))
Bill Wendling832a5da2010-12-15 01:03:19 +00001095 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001096
Evan Cheng650d0672007-02-06 00:22:06 +00001097 // Thumb does not have [sp, r] address mode.
1098 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1099 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1100 if ((LHSR && LHSR->getReg() == ARM::SP) ||
Bill Wendling832a5da2010-12-15 01:03:19 +00001101 (RHSR && RHSR->getReg() == ARM::SP))
1102 return false;
Bill Wendling092a7bd2010-12-14 03:36:38 +00001103
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001104 // FIXME: Why do we explicitly check for a match here and then return false?
1105 // Presumably to allow something else to match, but shouldn't this be
1106 // documented?
1107 int RHSC;
1108 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC))
1109 return false;
Bill Wendling092a7bd2010-12-14 03:36:38 +00001110
1111 Base = N.getOperand(0);
1112 Offset = N.getOperand(1);
1113 return true;
1114}
1115
1116bool
1117ARMDAGToDAGISel::SelectThumbAddrModeRI5S1(SDValue N,
1118 SDValue &Base,
1119 SDValue &Offset) {
1120 return SelectThumbAddrModeRI(N, Base, Offset, 1);
1121}
1122
1123bool
1124ARMDAGToDAGISel::SelectThumbAddrModeRI5S2(SDValue N,
1125 SDValue &Base,
1126 SDValue &Offset) {
1127 return SelectThumbAddrModeRI(N, Base, Offset, 2);
1128}
1129
1130bool
1131ARMDAGToDAGISel::SelectThumbAddrModeRI5S4(SDValue N,
1132 SDValue &Base,
1133 SDValue &Offset) {
1134 return SelectThumbAddrModeRI(N, Base, Offset, 4);
1135}
1136
1137bool
1138ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1139 SDValue &Base, SDValue &OffImm) {
1140 if (Scale == 4) {
1141 SDValue TmpBase, TmpOffImm;
1142 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
1143 return false; // We want to select tLDRspi / tSTRspi instead.
1144
1145 if (N.getOpcode() == ARMISD::Wrapper &&
1146 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1147 return false; // We want to select tLDRpci instead.
1148 }
1149
Chris Lattner46c01a32011-02-13 22:25:43 +00001150 if (!CurDAG->isBaseWithConstantOffset(N)) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001151 if (N.getOpcode() == ARMISD::Wrapper &&
1152 !(Subtarget->useMovt() &&
1153 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
1154 Base = N.getOperand(0);
1155 } else {
1156 Base = N;
1157 }
1158
Owen Anderson9f944592009-08-11 20:47:22 +00001159 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001160 return true;
1161 }
1162
Bill Wendling832a5da2010-12-15 01:03:19 +00001163 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1164 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1165 if ((LHSR && LHSR->getReg() == ARM::SP) ||
1166 (RHSR && RHSR->getReg() == ARM::SP)) {
1167 ConstantSDNode *LHS = dyn_cast<ConstantSDNode>(N.getOperand(0));
1168 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1169 unsigned LHSC = LHS ? LHS->getZExtValue() : 0;
1170 unsigned RHSC = RHS ? RHS->getZExtValue() : 0;
1171
1172 // Thumb does not have [sp, #imm5] address mode for non-zero imm5.
1173 if (LHSC != 0 || RHSC != 0) return false;
1174
1175 Base = N;
1176 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
1177 return true;
1178 }
1179
Evan Cheng10043e22007-01-19 07:51:42 +00001180 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001181 int RHSC;
1182 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1183 Base = N.getOperand(0);
1184 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1185 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001186 }
1187
Evan Chengc0b73662007-01-23 22:59:13 +00001188 Base = N.getOperand(0);
Owen Anderson9f944592009-08-11 20:47:22 +00001189 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chengc0b73662007-01-23 22:59:13 +00001190 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001191}
1192
Bill Wendling092a7bd2010-12-14 03:36:38 +00001193bool
1194ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1195 SDValue &OffImm) {
1196 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001197}
1198
Bill Wendling092a7bd2010-12-14 03:36:38 +00001199bool
1200ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1201 SDValue &OffImm) {
1202 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001203}
1204
Bill Wendling092a7bd2010-12-14 03:36:38 +00001205bool
1206ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1207 SDValue &OffImm) {
1208 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001209}
1210
Chris Lattner0e023ea2010-09-21 20:31:19 +00001211bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1212 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001213 if (N.getOpcode() == ISD::FrameIndex) {
1214 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001215 Base = CurDAG->getTargetFrameIndex(FI,
1216 getTargetLowering()->getPointerTy());
Owen Anderson9f944592009-08-11 20:47:22 +00001217 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001218 return true;
1219 }
Evan Cheng139edae2007-01-24 02:21:22 +00001220
Chris Lattner46c01a32011-02-13 22:25:43 +00001221 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001222 return false;
1223
1224 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001225 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1226 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001227 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001228 int RHSC;
1229 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1230 Base = N.getOperand(0);
1231 if (Base.getOpcode() == ISD::FrameIndex) {
1232 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001233 Base = CurDAG->getTargetFrameIndex(FI,
1234 getTargetLowering()->getPointerTy());
Evan Cheng139edae2007-01-24 02:21:22 +00001235 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001236 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1237 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001238 }
1239 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001240
Evan Cheng10043e22007-01-19 07:51:42 +00001241 return false;
1242}
1243
Bill Wendling092a7bd2010-12-14 03:36:38 +00001244
1245//===----------------------------------------------------------------------===//
1246// Thumb 2 Addressing Modes
1247//===----------------------------------------------------------------------===//
1248
1249
Chris Lattner0e023ea2010-09-21 20:31:19 +00001250bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg,
Evan Chengeab9ca72009-06-27 02:26:13 +00001251 SDValue &Opc) {
Evan Cheng59069ec2010-07-30 23:33:54 +00001252 if (DisableShifterOp)
1253 return false;
1254
Evan Chenga20cde32011-07-20 23:34:39 +00001255 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengeab9ca72009-06-27 02:26:13 +00001256
1257 // Don't match base register only case. That is matched to a separate
1258 // lower complexity pattern with explicit register operand.
1259 if (ShOpcVal == ARM_AM::no_shift) return false;
1260
1261 BaseReg = N.getOperand(0);
1262 unsigned ShImmVal = 0;
1263 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1264 ShImmVal = RHS->getZExtValue() & 31;
1265 Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
1266 return true;
1267 }
1268
1269 return false;
1270}
1271
Chris Lattner0e023ea2010-09-21 20:31:19 +00001272bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001273 SDValue &Base, SDValue &OffImm) {
1274 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001275
Evan Cheng36064672009-08-11 08:52:18 +00001276 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001277 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1278 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001279 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001280 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001281 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001282 Base = CurDAG->getTargetFrameIndex(FI,
1283 getTargetLowering()->getPointerTy());
Owen Anderson9f944592009-08-11 20:47:22 +00001284 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001285 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001286 }
Owen Anderson6d557452011-03-18 19:46:58 +00001287
Chris Lattner46c01a32011-02-13 22:25:43 +00001288 if (N.getOpcode() == ARMISD::Wrapper &&
Anton Korobeynikov25229082009-11-24 00:44:37 +00001289 !(Subtarget->useMovt() &&
1290 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Cheng36064672009-08-11 08:52:18 +00001291 Base = N.getOperand(0);
1292 if (Base.getOpcode() == ISD::TargetConstantPool)
1293 return false; // We want to select t2LDRpci instead.
1294 } else
1295 Base = N;
Owen Anderson9f944592009-08-11 20:47:22 +00001296 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001297 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001298 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001299
1300 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001301 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001302 // Let t2LDRi8 handle (R - imm8).
1303 return false;
1304
Evan Chengb23b50d2009-06-29 07:51:04 +00001305 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001306 if (N.getOpcode() == ISD::SUB)
1307 RHSC = -RHSC;
1308
1309 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001310 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001311 if (Base.getOpcode() == ISD::FrameIndex) {
1312 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001313 Base = CurDAG->getTargetFrameIndex(FI,
1314 getTargetLowering()->getPointerTy());
David Goodwin79c079b2009-07-30 18:56:48 +00001315 }
Owen Anderson9f944592009-08-11 20:47:22 +00001316 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001317 return true;
1318 }
1319 }
1320
Evan Cheng36064672009-08-11 08:52:18 +00001321 // Base only.
1322 Base = N;
Owen Anderson9f944592009-08-11 20:47:22 +00001323 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001324 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001325}
1326
Chris Lattner0e023ea2010-09-21 20:31:19 +00001327bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001328 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001329 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001330 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1331 !CurDAG->isBaseWithConstantOffset(N))
1332 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001333
Chris Lattner46c01a32011-02-13 22:25:43 +00001334 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1335 int RHSC = (int)RHS->getSExtValue();
1336 if (N.getOpcode() == ISD::SUB)
1337 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001338
Chris Lattner46c01a32011-02-13 22:25:43 +00001339 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1340 Base = N.getOperand(0);
1341 if (Base.getOpcode() == ISD::FrameIndex) {
1342 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001343 Base = CurDAG->getTargetFrameIndex(FI,
1344 getTargetLowering()->getPointerTy());
Evan Chengb23b50d2009-06-29 07:51:04 +00001345 }
Chris Lattner46c01a32011-02-13 22:25:43 +00001346 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1347 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001348 }
1349 }
1350
1351 return false;
1352}
1353
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001354bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001355 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001356 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001357 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1358 ? cast<LoadSDNode>(Op)->getAddressingMode()
1359 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001360 int RHSC;
1361 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1362 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
1363 ? CurDAG->getTargetConstant(RHSC, MVT::i32)
1364 : CurDAG->getTargetConstant(-RHSC, MVT::i32);
1365 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001366 }
1367
1368 return false;
1369}
1370
Chris Lattner0e023ea2010-09-21 20:31:19 +00001371bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001372 SDValue &Base,
1373 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001374 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001375 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001376 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001377
Evan Cheng36064672009-08-11 08:52:18 +00001378 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1379 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1380 int RHSC = (int)RHS->getZExtValue();
1381 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1382 return false;
1383 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001384 return false;
1385 }
1386
Evan Chengb23b50d2009-06-29 07:51:04 +00001387 // Look for (R + R) or (R + (R << [1,2,3])).
1388 unsigned ShAmt = 0;
1389 Base = N.getOperand(0);
1390 OffReg = N.getOperand(1);
1391
1392 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001393 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001394 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001395 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001396 if (ShOpcVal == ARM_AM::lsl)
1397 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001398 }
1399
Evan Chengb23b50d2009-06-29 07:51:04 +00001400 if (ShOpcVal == ARM_AM::lsl) {
1401 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1402 // it.
1403 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1404 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001405 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1406 OffReg = OffReg.getOperand(0);
1407 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001408 ShAmt = 0;
1409 ShOpcVal = ARM_AM::no_shift;
Evan Cheng59bbc542010-10-27 23:41:30 +00001410 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001411 } else {
1412 ShOpcVal = ARM_AM::no_shift;
1413 }
David Goodwinf3912052009-07-15 15:50:19 +00001414 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001415
Owen Anderson9f944592009-08-11 20:47:22 +00001416 ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001417
1418 return true;
1419}
1420
Tim Northovera7ecd242013-07-16 09:46:55 +00001421bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
1422 SDValue &OffImm) {
1423 // This *must* succeed since it's used for the irreplacable ldrex and strex
1424 // instructions.
1425 Base = N;
1426 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
1427
1428 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N))
1429 return true;
1430
1431 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1432 if (!RHS)
1433 return true;
1434
1435 uint32_t RHSC = (int)RHS->getZExtValue();
1436 if (RHSC > 1020 || RHSC % 4 != 0)
1437 return true;
1438
1439 Base = N.getOperand(0);
1440 if (Base.getOpcode() == ISD::FrameIndex) {
1441 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1442 Base = CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy());
1443 }
1444
1445 OffImm = CurDAG->getTargetConstant(RHSC / 4, MVT::i32);
1446 return true;
1447}
1448
Evan Chengb23b50d2009-06-29 07:51:04 +00001449//===--------------------------------------------------------------------===//
1450
Evan Cheng7e90b112007-07-05 07:15:27 +00001451/// getAL - Returns a ARMCC::AL immediate node.
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001452static inline SDValue getAL(SelectionDAG *CurDAG) {
Owen Anderson9f944592009-08-11 20:47:22 +00001453 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001454}
1455
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001456SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
1457 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001458 ISD::MemIndexedMode AM = LD->getAddressingMode();
1459 if (AM == ISD::UNINDEXED)
1460 return NULL;
1461
Owen Anderson53aa7a92009-08-10 22:56:29 +00001462 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001463 SDValue Offset, AMOpc;
1464 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1465 unsigned Opcode = 0;
1466 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001467 if (LoadedVT == MVT::i32 && isPre &&
1468 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1469 Opcode = ARM::LDR_PRE_IMM;
1470 Match = true;
1471 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001472 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001473 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001474 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001475 } else if (LoadedVT == MVT::i32 &&
1476 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001477 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001478 Match = true;
1479
Owen Anderson9f944592009-08-11 20:47:22 +00001480 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001481 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001482 Match = true;
1483 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1484 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1485 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001486 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001487 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001488 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001489 Match = true;
1490 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1491 }
1492 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001493 if (isPre &&
1494 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001495 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001496 Opcode = ARM::LDRB_PRE_IMM;
1497 } else if (!isPre &&
1498 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1499 Match = true;
1500 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001501 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1502 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001503 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001504 }
1505 }
1506 }
1507
1508 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001509 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1510 SDValue Chain = LD->getChain();
1511 SDValue Base = LD->getBasePtr();
1512 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG),
1513 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001514 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001515 MVT::i32, MVT::Other, Ops);
Owen Andersonfd60f602011-08-26 21:12:37 +00001516 } else {
1517 SDValue Chain = LD->getChain();
1518 SDValue Base = LD->getBasePtr();
1519 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG),
1520 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001521 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001522 MVT::i32, MVT::Other, Ops);
Owen Andersonfd60f602011-08-26 21:12:37 +00001523 }
Evan Chengd9c55362009-07-02 01:23:32 +00001524 }
1525
1526 return NULL;
1527}
1528
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001529SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
1530 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001531 ISD::MemIndexedMode AM = LD->getAddressingMode();
1532 if (AM == ISD::UNINDEXED)
1533 return NULL;
1534
Owen Anderson53aa7a92009-08-10 22:56:29 +00001535 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001536 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001537 SDValue Offset;
1538 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1539 unsigned Opcode = 0;
1540 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001541 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001542 switch (LoadedVT.getSimpleVT().SimpleTy) {
1543 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001544 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1545 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001546 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001547 if (isSExtLd)
1548 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1549 else
1550 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001551 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001552 case MVT::i8:
1553 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001554 if (isSExtLd)
1555 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1556 else
1557 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001558 break;
1559 default:
1560 return NULL;
1561 }
1562 Match = true;
1563 }
1564
1565 if (Match) {
1566 SDValue Chain = LD->getChain();
1567 SDValue Base = LD->getBasePtr();
1568 SDValue Ops[]= { Base, Offset, getAL(CurDAG),
Owen Anderson9f944592009-08-11 20:47:22 +00001569 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001570 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001571 MVT::Other, Ops);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001572 }
1573
1574 return NULL;
1575}
1576
Weiming Zhao8f56f882012-11-16 21:55:34 +00001577/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1578SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001579 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001580 SDValue RegClass =
1581 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, MVT::i32);
1582 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32);
1583 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32);
1584 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001585 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001586}
1587
Weiming Zhao95782222012-11-17 00:23:35 +00001588/// \brief Form a D register from a pair of S registers.
1589SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001590 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001591 SDValue RegClass =
1592 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, MVT::i32);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001593 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1594 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001595 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001596 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001597}
1598
Weiming Zhao95782222012-11-17 00:23:35 +00001599/// \brief Form a quad register from a pair of D registers.
1600SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001601 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001602 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, MVT::i32);
Jakob Stoklund Olesen6c47d642010-05-24 16:54:32 +00001603 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1604 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, 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());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001612 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen6c47d642010-05-24 16:54:32 +00001613 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1614 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001615 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001616 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001617}
1618
Weiming Zhao95782222012-11-17 00:23:35 +00001619/// \brief Form 4 consecutive S registers.
1620SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001621 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001622 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001623 SDValue RegClass =
1624 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, MVT::i32);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001625 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1626 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
1627 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, MVT::i32);
1628 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001629 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1630 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001631 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001632}
1633
Weiming Zhao95782222012-11-17 00:23:35 +00001634/// \brief Form 4 consecutive D registers.
1635SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001636 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001637 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001638 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen6c47d642010-05-24 16:54:32 +00001639 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1640 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
1641 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32);
1642 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001643 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1644 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001645 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001646}
1647
Weiming Zhao95782222012-11-17 00:23:35 +00001648/// \brief Form 4 consecutive Q registers.
1649SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +00001650 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001651 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001652 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen6c47d642010-05-24 16:54:32 +00001653 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1654 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
1655 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32);
1656 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001657 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1658 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001659 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001660}
1661
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001662/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1663/// of a NEON VLD or VST instruction. The supported values depend on the
1664/// number of registers being loaded.
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001665SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, unsigned NumVecs,
1666 bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001667 unsigned NumRegs = NumVecs;
1668 if (!is64BitVector && NumVecs < 3)
1669 NumRegs *= 2;
1670
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001671 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001672 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001673 Alignment = 32;
1674 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1675 Alignment = 16;
1676 else if (Alignment >= 8)
1677 Alignment = 8;
1678 else
1679 Alignment = 0;
1680
1681 return CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001682}
1683
Jim Grosbach2098cb12011-10-24 21:45:13 +00001684// Get the register stride update opcode of a VLD/VST instruction that
1685// is otherwise equivalent to the given fixed stride updating instruction.
1686static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
1687 switch (Opc) {
1688 default: break;
1689 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1690 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1691 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1692 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1693 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1694 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1695 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1696 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001697
1698 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1699 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1700 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1701 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1702 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1703 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1704 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1705 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001706 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001707 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001708
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001709 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1710 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1711 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001712 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1713 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1714 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1715
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001716 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1717 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1718 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001719 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1720 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1721 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001722
Jim Grosbach13a292c2012-03-06 22:01:44 +00001723 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1724 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1725 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001726 }
1727 return Opc; // If not one we handle, return it unchanged.
1728}
1729
Bob Wilson06fce872011-02-07 17:43:21 +00001730SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001731 const uint16_t *DOpcodes,
1732 const uint16_t *QOpcodes0,
1733 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001734 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001735 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001736
Bob Wilsonae08a732010-03-20 22:13:40 +00001737 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001738 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1739 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilson12b47992009-10-14 17:28:52 +00001740 return NULL;
1741
1742 SDValue Chain = N->getOperand(0);
1743 EVT VT = N->getValueType(0);
1744 bool is64BitVector = VT.is64BitVector();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001745 Align = GetVLDSTAlign(Align, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001746
Bob Wilson12b47992009-10-14 17:28:52 +00001747 unsigned OpcodeIndex;
1748 switch (VT.getSimpleVT().SimpleTy) {
1749 default: llvm_unreachable("unhandled vld type");
1750 // Double-register operations:
1751 case MVT::v8i8: OpcodeIndex = 0; break;
1752 case MVT::v4i16: OpcodeIndex = 1; break;
1753 case MVT::v2f32:
1754 case MVT::v2i32: OpcodeIndex = 2; break;
1755 case MVT::v1i64: OpcodeIndex = 3; break;
1756 // Quad-register operations:
1757 case MVT::v16i8: OpcodeIndex = 0; break;
1758 case MVT::v8i16: OpcodeIndex = 1; break;
1759 case MVT::v4f32:
1760 case MVT::v4i32: OpcodeIndex = 2; break;
Bob Wilson340861d2010-03-23 05:25:43 +00001761 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001762 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson340861d2010-03-23 05:25:43 +00001763 break;
Bob Wilson12b47992009-10-14 17:28:52 +00001764 }
1765
Bob Wilson35fafca2010-09-03 18:16:02 +00001766 EVT ResTy;
1767 if (NumVecs == 1)
1768 ResTy = VT;
1769 else {
1770 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1771 if (!is64BitVector)
1772 ResTyElts *= 2;
1773 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1774 }
Bob Wilson06fce872011-02-07 17:43:21 +00001775 std::vector<EVT> ResTys;
1776 ResTys.push_back(ResTy);
1777 if (isUpdating)
1778 ResTys.push_back(MVT::i32);
1779 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001780
Evan Cheng3da64f762010-04-16 05:46:06 +00001781 SDValue Pred = getAL(CurDAG);
Bob Wilsonae08a732010-03-20 22:13:40 +00001782 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001783 SDNode *VLd;
1784 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001785
Bob Wilson06fce872011-02-07 17:43:21 +00001786 // Double registers and VLD1/VLD2 quad registers are directly supported.
1787 if (is64BitVector || NumVecs <= 2) {
1788 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1789 QOpcodes0[OpcodeIndex]);
1790 Ops.push_back(MemAddr);
1791 Ops.push_back(Align);
1792 if (isUpdating) {
1793 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachd146a022011-12-09 21:28:25 +00001794 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach2098cb12011-10-24 21:45:13 +00001795 // case entirely when the rest are updated to that form, too.
Jim Grosbachd146a022011-12-09 21:28:25 +00001796 if ((NumVecs == 1 || NumVecs == 2) && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001797 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jim Grosbachd146a022011-12-09 21:28:25 +00001798 // We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001799 // check for that explicitly too. Horribly hacky, but temporary.
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001800 if ((NumVecs != 1 && NumVecs != 2 && Opc != ARM::VLD1q64wb_fixed) ||
Jim Grosbach05df4602011-10-31 21:50:31 +00001801 !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001802 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Evan Cheng630063a2010-05-10 21:26:24 +00001803 }
Bob Wilson06fce872011-02-07 17:43:21 +00001804 Ops.push_back(Pred);
1805 Ops.push_back(Reg0);
1806 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001807 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001808
Bob Wilson12b47992009-10-14 17:28:52 +00001809 } else {
1810 // Otherwise, quad registers are loaded with two separate instructions,
1811 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001812 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001813
Bob Wilson06fce872011-02-07 17:43:21 +00001814 // Load the even subregs. This is always an updating load, so that it
1815 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001816 SDValue ImplDef =
1817 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1818 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001819 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001820 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001821 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001822
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001823 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001824 Ops.push_back(SDValue(VLdA, 1));
1825 Ops.push_back(Align);
1826 if (isUpdating) {
1827 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1828 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1829 "only constant post-increment update allowed for VLD3/4");
1830 (void)Inc;
1831 Ops.push_back(Reg0);
1832 }
1833 Ops.push_back(SDValue(VLdA, 0));
1834 Ops.push_back(Pred);
1835 Ops.push_back(Reg0);
1836 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001837 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001838 }
Bob Wilson12b47992009-10-14 17:28:52 +00001839
Evan Cheng40791332011-04-19 00:04:03 +00001840 // Transfer memoperands.
1841 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1842 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1843 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1844
Bob Wilson06fce872011-02-07 17:43:21 +00001845 if (NumVecs == 1)
1846 return VLd;
1847
1848 // Extract out the subregisters.
1849 SDValue SuperReg = SDValue(VLd, 0);
1850 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
1851 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
1852 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1853 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1854 ReplaceUses(SDValue(N, Vec),
1855 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1856 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1857 if (isUpdating)
1858 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Bob Wilson12b47992009-10-14 17:28:52 +00001859 return NULL;
1860}
1861
Bob Wilson06fce872011-02-07 17:43:21 +00001862SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001863 const uint16_t *DOpcodes,
1864 const uint16_t *QOpcodes0,
1865 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001866 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001867 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001868
Bob Wilsonae08a732010-03-20 22:13:40 +00001869 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001870 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1871 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1872 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001873 return NULL;
1874
Evan Cheng40791332011-04-19 00:04:03 +00001875 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1876 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1877
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001878 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00001879 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001880 bool is64BitVector = VT.is64BitVector();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001881 Align = GetVLDSTAlign(Align, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001882
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001883 unsigned OpcodeIndex;
1884 switch (VT.getSimpleVT().SimpleTy) {
1885 default: llvm_unreachable("unhandled vst type");
1886 // Double-register operations:
1887 case MVT::v8i8: OpcodeIndex = 0; break;
1888 case MVT::v4i16: OpcodeIndex = 1; break;
1889 case MVT::v2f32:
1890 case MVT::v2i32: OpcodeIndex = 2; break;
1891 case MVT::v1i64: OpcodeIndex = 3; break;
1892 // Quad-register operations:
1893 case MVT::v16i8: OpcodeIndex = 0; break;
1894 case MVT::v8i16: OpcodeIndex = 1; break;
1895 case MVT::v4f32:
1896 case MVT::v4i32: OpcodeIndex = 2; break;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001897 case MVT::v2i64: OpcodeIndex = 3;
1898 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
1899 break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001900 }
1901
Bob Wilson06fce872011-02-07 17:43:21 +00001902 std::vector<EVT> ResTys;
1903 if (isUpdating)
1904 ResTys.push_back(MVT::i32);
1905 ResTys.push_back(MVT::Other);
1906
Evan Cheng3da64f762010-04-16 05:46:06 +00001907 SDValue Pred = getAL(CurDAG);
Bob Wilsonae08a732010-03-20 22:13:40 +00001908 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001909 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00001910
Bob Wilson06fce872011-02-07 17:43:21 +00001911 // Double registers and VST1/VST2 quad registers are directly supported.
1912 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00001913 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00001914 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00001915 SrcReg = N->getOperand(Vec0Idx);
1916 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00001917 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00001918 SDValue V0 = N->getOperand(Vec0Idx + 0);
1919 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00001920 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00001921 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001922 else {
Bob Wilson06fce872011-02-07 17:43:21 +00001923 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00001924 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00001925 // an undef.
1926 SDValue V3 = (NumVecs == 3)
1927 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00001928 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00001929 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001930 }
Bob Wilson950882b2010-08-28 05:12:57 +00001931 } else {
1932 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00001933 SDValue Q0 = N->getOperand(Vec0Idx);
1934 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00001935 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001936 }
Bob Wilson06fce872011-02-07 17:43:21 +00001937
1938 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1939 QOpcodes0[OpcodeIndex]);
1940 Ops.push_back(MemAddr);
1941 Ops.push_back(Align);
1942 if (isUpdating) {
1943 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbach88ac7612011-12-14 21:32:11 +00001944 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach05df4602011-10-31 21:50:31 +00001945 // case entirely when the rest are updated to that form, too.
Jim Grosbach88ac7612011-12-14 21:32:11 +00001946 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach05df4602011-10-31 21:50:31 +00001947 Opc = getVLDSTRegisterUpdateOpcode(Opc);
1948 // We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
1949 // check for that explicitly too. Horribly hacky, but temporary.
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001950 if ((NumVecs > 2 && Opc != ARM::VST1q64wb_fixed) ||
Jim Grosbach05df4602011-10-31 21:50:31 +00001951 !isa<ConstantSDNode>(Inc.getNode()))
1952 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Bob Wilson06fce872011-02-07 17:43:21 +00001953 }
1954 Ops.push_back(SrcReg);
1955 Ops.push_back(Pred);
1956 Ops.push_back(Reg0);
1957 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001958 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00001959
1960 // Transfer memoperands.
1961 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
1962
1963 return VSt;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001964 }
1965
1966 // Otherwise, quad registers are stored with two separate instructions,
1967 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00001968
Bob Wilson01ac8f92010-06-16 21:34:01 +00001969 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00001970 SDValue V0 = N->getOperand(Vec0Idx + 0);
1971 SDValue V1 = N->getOperand(Vec0Idx + 1);
1972 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00001973 SDValue V3 = (NumVecs == 3)
1974 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00001975 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00001976 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00001977
Bob Wilson06fce872011-02-07 17:43:21 +00001978 // Store the even D registers. This is always an updating store, so that it
1979 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00001980 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
1981 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
1982 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00001983 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00001984 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00001985 Chain = SDValue(VStA, 1);
1986
1987 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00001988 Ops.push_back(SDValue(VStA, 0));
1989 Ops.push_back(Align);
1990 if (isUpdating) {
1991 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1992 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1993 "only constant post-increment update allowed for VST3/4");
1994 (void)Inc;
1995 Ops.push_back(Reg0);
1996 }
1997 Ops.push_back(RegSeq);
1998 Ops.push_back(Pred);
1999 Ops.push_back(Reg0);
2000 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00002001 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00002002 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002003 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
2004 return VStB;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00002005}
2006
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002007SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
Bob Wilson06fce872011-02-07 17:43:21 +00002008 bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00002009 const uint16_t *DOpcodes,
2010 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002011 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002012 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002013
Bob Wilsonae08a732010-03-20 22:13:40 +00002014 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00002015 unsigned AddrOpIdx = isUpdating ? 1 : 2;
2016 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
2017 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilson4145e3a2009-10-14 16:19:03 +00002018 return NULL;
2019
Evan Cheng40791332011-04-19 00:04:03 +00002020 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2021 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2022
Bob Wilson4145e3a2009-10-14 16:19:03 +00002023 SDValue Chain = N->getOperand(0);
2024 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00002025 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
2026 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00002027 bool is64BitVector = VT.is64BitVector();
2028
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002029 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002030 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002031 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002032 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2033 if (Alignment > NumBytes)
2034 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002035 if (Alignment < 8 && Alignment < NumBytes)
2036 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002037 // Alignment must be a power of two; make sure of that.
2038 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002039 if (Alignment == 1)
2040 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002041 }
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002042 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002043
Bob Wilson4145e3a2009-10-14 16:19:03 +00002044 unsigned OpcodeIndex;
2045 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002046 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002047 // Double-register operations:
2048 case MVT::v8i8: OpcodeIndex = 0; break;
2049 case MVT::v4i16: OpcodeIndex = 1; break;
2050 case MVT::v2f32:
2051 case MVT::v2i32: OpcodeIndex = 2; break;
2052 // Quad-register operations:
2053 case MVT::v8i16: OpcodeIndex = 0; break;
2054 case MVT::v4f32:
2055 case MVT::v4i32: OpcodeIndex = 1; break;
2056 }
2057
Bob Wilson06fce872011-02-07 17:43:21 +00002058 std::vector<EVT> ResTys;
2059 if (IsLoad) {
2060 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2061 if (!is64BitVector)
2062 ResTyElts *= 2;
2063 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2064 MVT::i64, ResTyElts));
2065 }
2066 if (isUpdating)
2067 ResTys.push_back(MVT::i32);
2068 ResTys.push_back(MVT::Other);
2069
Evan Cheng3da64f762010-04-16 05:46:06 +00002070 SDValue Pred = getAL(CurDAG);
Bob Wilsonae08a732010-03-20 22:13:40 +00002071 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002072
Bob Wilson06fce872011-02-07 17:43:21 +00002073 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002074 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002075 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002076 if (isUpdating) {
2077 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2078 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
2079 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002080
Bob Wilsond5c57a52010-09-13 23:01:35 +00002081 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002082 SDValue V0 = N->getOperand(Vec0Idx + 0);
2083 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002084 if (NumVecs == 2) {
2085 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002086 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002087 else
Weiming Zhao95782222012-11-17 00:23:35 +00002088 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002089 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002090 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002091 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002092 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2093 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002094 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002095 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002096 else
Weiming Zhao95782222012-11-17 00:23:35 +00002097 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002098 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002099 Ops.push_back(SuperReg);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002100 Ops.push_back(getI32Imm(Lane));
Evan Chenga33fc862009-11-21 06:21:52 +00002101 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002102 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002103 Ops.push_back(Chain);
2104
Bob Wilson06fce872011-02-07 17:43:21 +00002105 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2106 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002107 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002108 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson93117bc2009-10-14 16:46:45 +00002109 if (!IsLoad)
Bob Wilson06fce872011-02-07 17:43:21 +00002110 return VLdLn;
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002111
Bob Wilsond5c57a52010-09-13 23:01:35 +00002112 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002113 SuperReg = SDValue(VLdLn, 0);
2114 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
2115 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
2116 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002117 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2118 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002119 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2120 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2121 if (isUpdating)
2122 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Bob Wilson4145e3a2009-10-14 16:19:03 +00002123 return NULL;
2124}
2125
Bob Wilson06fce872011-02-07 17:43:21 +00002126SDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating,
Craig Topper01736f82012-05-24 05:17:00 +00002127 unsigned NumVecs,
2128 const uint16_t *Opcodes) {
Bob Wilson2d790df2010-11-28 06:51:26 +00002129 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002130 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002131
2132 SDValue MemAddr, Align;
2133 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
2134 return NULL;
2135
Evan Cheng40791332011-04-19 00:04:03 +00002136 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2137 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2138
Bob Wilson2d790df2010-11-28 06:51:26 +00002139 SDValue Chain = N->getOperand(0);
2140 EVT VT = N->getValueType(0);
2141
2142 unsigned Alignment = 0;
2143 if (NumVecs != 3) {
2144 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2145 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2146 if (Alignment > NumBytes)
2147 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002148 if (Alignment < 8 && Alignment < NumBytes)
2149 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002150 // Alignment must be a power of two; make sure of that.
2151 Alignment = (Alignment & -Alignment);
2152 if (Alignment == 1)
2153 Alignment = 0;
2154 }
2155 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
2156
2157 unsigned OpcodeIndex;
2158 switch (VT.getSimpleVT().SimpleTy) {
2159 default: llvm_unreachable("unhandled vld-dup type");
2160 case MVT::v8i8: OpcodeIndex = 0; break;
2161 case MVT::v4i16: OpcodeIndex = 1; break;
2162 case MVT::v2f32:
2163 case MVT::v2i32: OpcodeIndex = 2; break;
2164 }
2165
2166 SDValue Pred = getAL(CurDAG);
2167 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2168 SDValue SuperReg;
2169 unsigned Opc = Opcodes[OpcodeIndex];
Bob Wilson06fce872011-02-07 17:43:21 +00002170 SmallVector<SDValue, 6> Ops;
2171 Ops.push_back(MemAddr);
2172 Ops.push_back(Align);
2173 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002174 // fixed-stride update instructions don't have an explicit writeback
2175 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002176 SDValue Inc = N->getOperand(2);
Jim Grosbachc80a2642011-12-21 19:40:55 +00002177 if (!isa<ConstantSDNode>(Inc.getNode()))
2178 Ops.push_back(Inc);
2179 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2180 else if (NumVecs > 2)
2181 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002182 }
2183 Ops.push_back(Pred);
2184 Ops.push_back(Reg0);
2185 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002186
2187 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002188 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002189 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002190 if (isUpdating)
2191 ResTys.push_back(MVT::i32);
2192 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002193 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002194 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002195 SuperReg = SDValue(VLdDup, 0);
Bob Wilson2d790df2010-11-28 06:51:26 +00002196
2197 // Extract the subregisters.
2198 assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
2199 unsigned SubIdx = ARM::dsub_0;
2200 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2201 ReplaceUses(SDValue(N, Vec),
2202 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Bob Wilson06fce872011-02-07 17:43:21 +00002203 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2204 if (isUpdating)
2205 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Bob Wilson2d790df2010-11-28 06:51:26 +00002206 return NULL;
2207}
2208
Bob Wilson5bc8a792010-07-07 00:08:54 +00002209SDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2210 unsigned Opc) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00002211 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002212 SDLoc dl(N);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002213 EVT VT = N->getValueType(0);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002214 unsigned FirstTblReg = IsExt ? 2 : 1;
Bob Wilson3ed511b2010-07-06 23:36:25 +00002215
2216 // Form a REG_SEQUENCE to force register allocation.
2217 SDValue RegSeq;
Bob Wilson5bc8a792010-07-07 00:08:54 +00002218 SDValue V0 = N->getOperand(FirstTblReg + 0);
2219 SDValue V1 = N->getOperand(FirstTblReg + 1);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002220 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002221 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002222 else {
Bob Wilson5bc8a792010-07-07 00:08:54 +00002223 SDValue V2 = N->getOperand(FirstTblReg + 2);
Jim Grosbachd37f0712010-10-21 19:38:40 +00002224 // If it's a vtbl3, form a quad D-register and leave the last part as
Bob Wilson3ed511b2010-07-06 23:36:25 +00002225 // an undef.
2226 SDValue V3 = (NumVecs == 3)
2227 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson5bc8a792010-07-07 00:08:54 +00002228 : N->getOperand(FirstTblReg + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002229 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002230 }
2231
Bob Wilson5bc8a792010-07-07 00:08:54 +00002232 SmallVector<SDValue, 6> Ops;
2233 if (IsExt)
2234 Ops.push_back(N->getOperand(1));
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00002235 Ops.push_back(RegSeq);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002236 Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
Bob Wilson3ed511b2010-07-06 23:36:25 +00002237 Ops.push_back(getAL(CurDAG)); // predicate
2238 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
Michael Liaob53d8962013-04-19 22:22:57 +00002239 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002240}
2241
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002242SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
Jim Grosbach825cb292010-04-22 23:24:18 +00002243 bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002244 if (!Subtarget->hasV6T2Ops())
2245 return NULL;
Bob Wilson93117bc2009-10-14 16:46:45 +00002246
Evan Chengeae6d2c2012-12-19 20:16:09 +00002247 unsigned Opc = isSigned
2248 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002249 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
2250
Jim Grosbach825cb292010-04-22 23:24:18 +00002251 // For unsigned extracts, check for a shift right and mask
2252 unsigned And_imm = 0;
2253 if (N->getOpcode() == ISD::AND) {
2254 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2255
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002256 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002257 if (And_imm & (And_imm + 1))
2258 return NULL;
2259
2260 unsigned Srl_imm = 0;
2261 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2262 Srl_imm)) {
2263 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2264
Jim Grosbach03f56d92011-07-27 21:09:25 +00002265 // Note: The width operand is encoded as width-1.
2266 unsigned Width = CountTrailingOnes_32(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002267 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002268
Jim Grosbach825cb292010-04-22 23:24:18 +00002269 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002270
2271 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2272 // It's cheaper to use a right shift to extract the top bits.
2273 if (Subtarget->isThumb()) {
2274 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2275 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2276 CurDAG->getTargetConstant(LSB, MVT::i32),
2277 getAL(CurDAG), Reg0, Reg0 };
2278 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
2279 }
2280
2281 // ARM models shift instructions as MOVsi with shifter operand.
2282 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2283 SDValue ShOpc =
2284 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB),
2285 MVT::i32);
2286 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
2287 getAL(CurDAG), Reg0, Reg0 };
2288 return CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops, 5);
2289 }
2290
Jim Grosbach825cb292010-04-22 23:24:18 +00002291 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2292 CurDAG->getTargetConstant(LSB, MVT::i32),
2293 CurDAG->getTargetConstant(Width, MVT::i32),
2294 getAL(CurDAG), Reg0 };
2295 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
2296 }
2297 }
2298 return NULL;
2299 }
2300
2301 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002302 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002303 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002304 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2305 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002306 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002307 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002308 // Note: The width operand is encoded as width-1.
2309 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002310 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002311 if (LSB < 0)
Sandeep Patel423e42b2009-10-13 18:59:48 +00002312 return NULL;
2313 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002314 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sandeep Patel423e42b2009-10-13 18:59:48 +00002315 CurDAG->getTargetConstant(LSB, MVT::i32),
2316 CurDAG->getTargetConstant(Width, MVT::i32),
2317 getAL(CurDAG), Reg0 };
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002318 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Sandeep Patel423e42b2009-10-13 18:59:48 +00002319 }
2320 }
2321 return NULL;
2322}
2323
Evan Cheng81a28512009-11-20 00:54:03 +00002324SDNode *ARMDAGToDAGISel::
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002325SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002326 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
2327 SDValue CPTmp0;
2328 SDValue CPTmp1;
Chris Lattner0e023ea2010-09-21 20:31:19 +00002329 if (SelectT2ShifterOperandReg(TrueVal, CPTmp0, CPTmp1)) {
Evan Cheng81a28512009-11-20 00:54:03 +00002330 unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue();
2331 unsigned SOShOp = ARM_AM::getSORegShOp(SOVal);
2332 unsigned Opc = 0;
2333 switch (SOShOp) {
2334 case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break;
2335 case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break;
2336 case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break;
2337 case ARM_AM::ror: Opc = ARM::t2MOVCCror; break;
2338 default:
2339 llvm_unreachable("Unknown so_reg opcode!");
Evan Cheng81a28512009-11-20 00:54:03 +00002340 }
2341 SDValue SOShImm =
2342 CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32);
2343 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2344 SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag };
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002345 return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6);
Evan Cheng81a28512009-11-20 00:54:03 +00002346 }
2347 return 0;
2348}
2349
2350SDNode *ARMDAGToDAGISel::
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002351SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002352 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
2353 SDValue CPTmp0;
2354 SDValue CPTmp1;
2355 SDValue CPTmp2;
Owen Anderson04912702011-07-21 23:38:37 +00002356 if (SelectImmShifterOperand(TrueVal, CPTmp0, CPTmp2)) {
Evan Cheng81a28512009-11-20 00:54:03 +00002357 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
Owen Anderson3fa7ca82011-07-22 18:30:30 +00002358 SDValue Ops[] = { FalseVal, CPTmp0, CPTmp2, CC, CCR, InFlag };
2359 return CurDAG->SelectNodeTo(N, ARM::MOVCCsi, MVT::i32, Ops, 6);
Owen Andersonb595ed02011-07-21 18:54:16 +00002360 }
2361
2362 if (SelectRegShifterOperand(TrueVal, CPTmp0, CPTmp1, CPTmp2)) {
2363 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2364 SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag };
2365 return CurDAG->SelectNodeTo(N, ARM::MOVCCsr, MVT::i32, Ops, 7);
Evan Cheng81a28512009-11-20 00:54:03 +00002366 }
2367 return 0;
2368}
2369
2370SDNode *ARMDAGToDAGISel::
Jim Grosbach5b255c22010-10-07 00:53:56 +00002371SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng39c81c02010-11-17 20:56:30 +00002372 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
Evan Cheng81a28512009-11-20 00:54:03 +00002373 ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal);
Evan Chenga5f04842010-11-19 23:01:16 +00002374 if (!T)
Evan Cheng81a28512009-11-20 00:54:03 +00002375 return 0;
2376
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002377 unsigned Opc = 0;
Jim Grosbach5b255c22010-10-07 00:53:56 +00002378 unsigned TrueImm = T->getZExtValue();
Evan Cheng39c81c02010-11-17 20:56:30 +00002379 if (is_t2_so_imm(TrueImm)) {
2380 Opc = ARM::t2MOVCCi;
2381 } else if (TrueImm <= 0xffff) {
2382 Opc = ARM::t2MOVCCi16;
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002383 } else if (is_t2_so_imm_not(TrueImm)) {
2384 TrueImm = ~TrueImm;
2385 Opc = ARM::t2MVNCCi;
Evan Cheng39c81c02010-11-17 20:56:30 +00002386 } else if (TrueVal.getNode()->hasOneUse() && Subtarget->hasV6T2Ops()) {
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002387 // Large immediate.
2388 Opc = ARM::t2MOVCCi32imm;
2389 }
2390
2391 if (Opc) {
Evan Cheng0fc80842010-11-12 22:42:47 +00002392 SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32);
Evan Cheng81a28512009-11-20 00:54:03 +00002393 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2394 SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002395 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Cheng81a28512009-11-20 00:54:03 +00002396 }
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002397
Evan Cheng81a28512009-11-20 00:54:03 +00002398 return 0;
2399}
2400
2401SDNode *ARMDAGToDAGISel::
Jim Grosbach742adc32010-10-07 00:42:42 +00002402SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng39c81c02010-11-17 20:56:30 +00002403 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
Evan Cheng81a28512009-11-20 00:54:03 +00002404 ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal);
2405 if (!T)
2406 return 0;
2407
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002408 unsigned Opc = 0;
Jim Grosbach742adc32010-10-07 00:42:42 +00002409 unsigned TrueImm = T->getZExtValue();
Evan Cheng0fc80842010-11-12 22:42:47 +00002410 bool isSoImm = is_so_imm(TrueImm);
Evan Cheng39c81c02010-11-17 20:56:30 +00002411 if (isSoImm) {
2412 Opc = ARM::MOVCCi;
2413 } else if (Subtarget->hasV6T2Ops() && TrueImm <= 0xffff) {
2414 Opc = ARM::MOVCCi16;
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002415 } else if (is_so_imm_not(TrueImm)) {
2416 TrueImm = ~TrueImm;
2417 Opc = ARM::MVNCCi;
Evan Cheng39c81c02010-11-17 20:56:30 +00002418 } else if (TrueVal.getNode()->hasOneUse() &&
2419 (Subtarget->hasV6T2Ops() || ARM_AM::isSOImmTwoPartVal(TrueImm))) {
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002420 // Large immediate.
2421 Opc = ARM::MOVCCi32imm;
2422 }
2423
2424 if (Opc) {
Jim Grosbach742adc32010-10-07 00:42:42 +00002425 SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32);
Evan Cheng81a28512009-11-20 00:54:03 +00002426 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2427 SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002428 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Cheng81a28512009-11-20 00:54:03 +00002429 }
Andrew Trickc416ba62010-12-24 04:28:06 +00002430
Evan Cheng81a28512009-11-20 00:54:03 +00002431 return 0;
2432}
2433
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002434SDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) {
2435 EVT VT = N->getValueType(0);
2436 SDValue FalseVal = N->getOperand(0);
2437 SDValue TrueVal = N->getOperand(1);
2438 SDValue CC = N->getOperand(2);
2439 SDValue CCR = N->getOperand(3);
2440 SDValue InFlag = N->getOperand(4);
Evan Cheng81a28512009-11-20 00:54:03 +00002441 assert(CC.getOpcode() == ISD::Constant);
2442 assert(CCR.getOpcode() == ISD::Register);
2443 ARMCC::CondCodes CCVal =
2444 (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue();
Evan Chengb6c77042009-11-19 21:45:22 +00002445
2446 if (!Subtarget->isThumb1Only() && VT == MVT::i32) {
2447 // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
2448 // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
2449 // Pattern complexity = 18 cost = 1 size = 0
Evan Chengb6c77042009-11-19 21:45:22 +00002450 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002451 SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002452 CCVal, CCR, InFlag);
2453 if (!Res)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002454 Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002455 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2456 if (Res)
2457 return Res;
Evan Chengb6c77042009-11-19 21:45:22 +00002458 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002459 SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002460 CCVal, CCR, InFlag);
2461 if (!Res)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002462 Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002463 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2464 if (Res)
2465 return Res;
Evan Chengb6c77042009-11-19 21:45:22 +00002466 }
2467
2468 // Pattern: (ARMcmov:i32 GPR:i32:$false,
Jakob Stoklund Olesene2cbaf62010-08-17 20:39:04 +00002469 // (imm:i32)<<P:Pred_so_imm>>:$true,
Evan Chengb6c77042009-11-19 21:45:22 +00002470 // (imm:i32):$cc)
2471 // Emits: (MOVCCi:i32 GPR:i32:$false,
2472 // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc)
2473 // Pattern complexity = 10 cost = 1 size = 0
Evan Cheng81a28512009-11-20 00:54:03 +00002474 if (Subtarget->isThumb()) {
Jim Grosbach5b255c22010-10-07 00:53:56 +00002475 SDNode *Res = SelectT2CMOVImmOp(N, FalseVal, TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002476 CCVal, CCR, InFlag);
2477 if (!Res)
Jim Grosbach5b255c22010-10-07 00:53:56 +00002478 Res = SelectT2CMOVImmOp(N, TrueVal, FalseVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002479 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2480 if (Res)
2481 return Res;
2482 } else {
Jim Grosbach742adc32010-10-07 00:42:42 +00002483 SDNode *Res = SelectARMCMOVImmOp(N, FalseVal, TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002484 CCVal, CCR, InFlag);
2485 if (!Res)
Jim Grosbach742adc32010-10-07 00:42:42 +00002486 Res = SelectARMCMOVImmOp(N, TrueVal, FalseVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002487 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2488 if (Res)
2489 return Res;
Evan Chengb6c77042009-11-19 21:45:22 +00002490 }
2491 }
2492
2493 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2494 // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2495 // Pattern complexity = 6 cost = 1 size = 0
2496 //
2497 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2498 // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2499 // Pattern complexity = 6 cost = 11 size = 0
2500 //
Jim Grosbach2fee5322011-03-11 23:15:02 +00002501 // Also VMOVScc and VMOVDcc.
Evan Cheng81a28512009-11-20 00:54:03 +00002502 SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32);
2503 SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag };
Evan Chengb6c77042009-11-19 21:45:22 +00002504 unsigned Opc = 0;
2505 switch (VT.getSimpleVT().SimpleTy) {
Craig Toppere55c5562012-02-07 02:50:20 +00002506 default: llvm_unreachable("Illegal conditional move type!");
Evan Chengb6c77042009-11-19 21:45:22 +00002507 case MVT::i32:
2508 Opc = Subtarget->isThumb()
2509 ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo)
2510 : ARM::MOVCCr;
2511 break;
2512 case MVT::f32:
2513 Opc = ARM::VMOVScc;
2514 break;
2515 case MVT::f64:
2516 Opc = ARM::VMOVDcc;
2517 break;
2518 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002519 return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5);
Evan Chengb6c77042009-11-19 21:45:22 +00002520}
2521
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002522/// Target-specific DAG combining for ISD::XOR.
2523/// Target-independent combining lowers SELECT_CC nodes of the form
2524/// select_cc setg[ge] X, 0, X, -X
2525/// select_cc setgt X, -1, X, -X
2526/// select_cc setl[te] X, 0, -X, X
2527/// select_cc setlt X, 1, -X, X
2528/// which represent Integer ABS into:
2529/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2530/// ARM instruction selection detects the latter and matches it to
2531/// ARM::ABS or ARM::t2ABS machine node.
2532SDNode *ARMDAGToDAGISel::SelectABSOp(SDNode *N){
2533 SDValue XORSrc0 = N->getOperand(0);
2534 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002535 EVT VT = N->getValueType(0);
2536
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002537 if (Subtarget->isThumb1Only())
2538 return NULL;
2539
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002540 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002541 return NULL;
2542
2543 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2544 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2545 SDValue SRASrc0 = XORSrc1.getOperand(0);
2546 SDValue SRASrc1 = XORSrc1.getOperand(1);
2547 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2548 EVT XType = SRASrc0.getValueType();
2549 unsigned Size = XType.getSizeInBits() - 1;
2550
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002551 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
2552 XType.isInteger() && SRAConstant != NULL &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002553 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002554 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002555 return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2556 }
2557
2558 return NULL;
2559}
2560
Evan Chengd85631e2010-05-05 18:28:36 +00002561SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
2562 // The only time a CONCAT_VECTORS operation can have legal types is when
2563 // two 64-bit vectors are concatenated to a 128-bit vector.
2564 EVT VT = N->getValueType(0);
2565 if (!VT.is128BitVector() || N->getNumOperands() != 2)
2566 llvm_unreachable("unexpected CONCAT_VECTORS");
Weiming Zhao95782222012-11-17 00:23:35 +00002567 return createDRegPairNode(VT, N->getOperand(0), N->getOperand(1));
Evan Chengd85631e2010-05-05 18:28:36 +00002568}
2569
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +00002570SDNode *ARMDAGToDAGISel::SelectAtomic64(SDNode *Node, unsigned Opc) {
Eli Friedman1ccecbb2011-08-31 17:52:22 +00002571 SmallVector<SDValue, 6> Ops;
2572 Ops.push_back(Node->getOperand(1)); // Ptr
2573 Ops.push_back(Node->getOperand(2)); // Low part of Val1
2574 Ops.push_back(Node->getOperand(3)); // High part of Val1
Owen Anderson939cd212011-08-31 20:00:11 +00002575 if (Opc == ARM::ATOMCMPXCHG6432) {
Eli Friedman1ccecbb2011-08-31 17:52:22 +00002576 Ops.push_back(Node->getOperand(4)); // Low part of Val2
2577 Ops.push_back(Node->getOperand(5)); // High part of Val2
2578 }
2579 Ops.push_back(Node->getOperand(0)); // Chain
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +00002580 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2581 MemOp[0] = cast<MemSDNode>(Node)->getMemOperand();
Andrew Trickef9de2a2013-05-25 02:42:55 +00002582 SDNode *ResNode = CurDAG->getMachineNode(Opc, SDLoc(Node),
Eli Friedman1ccecbb2011-08-31 17:52:22 +00002583 MVT::i32, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002584 Ops);
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +00002585 cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp + 1);
2586 return ResNode;
2587}
2588
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002589SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002590 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002591
Dan Gohman17059682008-07-17 19:10:17 +00002592 if (N->isMachineOpcode())
Evan Cheng10043e22007-01-19 07:51:42 +00002593 return NULL; // Already selected.
Rafael Espindola4e760152006-06-12 12:28:08 +00002594
2595 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002596 default: break;
Weiming Zhaoc5987002013-02-14 18:10:21 +00002597 case ISD::INLINEASM: {
2598 SDNode *ResNode = SelectInlineAsm(N);
2599 if (ResNode)
2600 return ResNode;
2601 break;
2602 }
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002603 case ISD::XOR: {
2604 // Select special operations if XOR node forms integer ABS pattern
2605 SDNode *ResNode = SelectABSOp(N);
2606 if (ResNode)
2607 return ResNode;
2608 // Other cases are autogenerated.
2609 break;
2610 }
Evan Cheng10043e22007-01-19 07:51:42 +00002611 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002612 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002613 bool UseCP = true;
Anton Korobeynikov7c2b1e72009-09-27 23:52:58 +00002614 if (Subtarget->hasThumb2())
2615 // Thumb2-aware targets have the MOVT instruction, so all immediates can
2616 // be done with MOV + MOVT, at worst.
2617 UseCP = 0;
2618 else {
2619 if (Subtarget->isThumb()) {
Bob Wilson360eef02009-06-22 17:29:13 +00002620 UseCP = (Val > 255 && // MOV
2621 ~Val > 255 && // MOV + MVN
2622 !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL
Anton Korobeynikov7c2b1e72009-09-27 23:52:58 +00002623 } else
2624 UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV
2625 ARM_AM::getSOImmVal(~Val) == -1 && // MVN
2626 !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs.
2627 }
2628
Evan Cheng10043e22007-01-19 07:51:42 +00002629 if (UseCP) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002630 SDValue CPIdx =
Owen Anderson55f1c092009-08-13 21:58:54 +00002631 CurDAG->getTargetConstantPool(ConstantInt::get(
2632 Type::getInt32Ty(*CurDAG->getContext()), Val),
Bill Wendlinga3cd3502013-06-19 21:36:55 +00002633 getTargetLowering()->getPointerTy());
Evan Cheng1526ba52007-01-24 08:53:17 +00002634
2635 SDNode *ResNode;
Evan Chengcd4cdd12009-07-11 06:43:01 +00002636 if (Subtarget->isThumb1Only()) {
Evan Cheng3da64f762010-04-16 05:46:06 +00002637 SDValue Pred = getAL(CurDAG);
Owen Anderson9f944592009-08-11 20:47:22 +00002638 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002639 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002640 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002641 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002642 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002643 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002644 CPIdx,
Owen Anderson9f944592009-08-11 20:47:22 +00002645 CurDAG->getTargetConstant(0, MVT::i32),
Evan Cheng7e90b112007-07-05 07:15:27 +00002646 getAL(CurDAG),
Owen Anderson9f944592009-08-11 20:47:22 +00002647 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002648 CurDAG->getEntryNode()
2649 };
Dan Gohman32f71d72009-09-25 18:54:59 +00002650 ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002651 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002652 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002653 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
Evan Cheng10043e22007-01-19 07:51:42 +00002654 return NULL;
2655 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002656
Evan Cheng10043e22007-01-19 07:51:42 +00002657 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002658 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002659 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002660 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002661 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002662 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00002663 SDValue TFI = CurDAG->getTargetFrameIndex(FI,
2664 getTargetLowering()->getPointerTy());
David Goodwin22c2fba2009-07-08 23:10:31 +00002665 if (Subtarget->isThumb1Only()) {
Jim Grosbach1b8457a2011-08-24 17:46:13 +00002666 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
2667 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2668 return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, Ops, 4);
Jim Grosbachfde21102009-04-07 20:34:09 +00002669 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002670 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2671 ARM::t2ADDri : ARM::ADDri);
Owen Anderson9f944592009-08-11 20:47:22 +00002672 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
2673 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2674 CurDAG->getRegister(0, MVT::i32) };
2675 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Cheng7e90b112007-07-05 07:15:27 +00002676 }
Evan Cheng10043e22007-01-19 07:51:42 +00002677 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002678 case ISD::SRL:
Jim Grosbach825cb292010-04-22 23:24:18 +00002679 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
Sandeep Patel423e42b2009-10-13 18:59:48 +00002680 return I;
2681 break;
2682 case ISD::SRA:
Jim Grosbach825cb292010-04-22 23:24:18 +00002683 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true))
Sandeep Patel423e42b2009-10-13 18:59:48 +00002684 return I;
2685 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002686 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002687 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002688 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002689 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002690 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002691 if (!RHSV) break;
2692 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002693 unsigned ShImm = Log2_32(RHSV-1);
2694 if (ShImm >= 32)
2695 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002696 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002697 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson9f944592009-08-11 20:47:22 +00002698 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
2699 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002700 if (Subtarget->isThumb()) {
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002701 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson9f944592009-08-11 20:47:22 +00002702 return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002703 } else {
2704 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Andersonb595ed02011-07-21 18:54:16 +00002705 return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops, 7);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002706 }
Evan Cheng10043e22007-01-19 07:51:42 +00002707 }
2708 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002709 unsigned ShImm = Log2_32(RHSV+1);
2710 if (ShImm >= 32)
2711 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002712 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002713 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson9f944592009-08-11 20:47:22 +00002714 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
2715 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002716 if (Subtarget->isThumb()) {
Bob Wilsonb6112e82010-05-28 00:27:15 +00002717 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
2718 return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 6);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002719 } else {
2720 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Andersonb595ed02011-07-21 18:54:16 +00002721 return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops, 7);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002722 }
Evan Cheng10043e22007-01-19 07:51:42 +00002723 }
2724 }
2725 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002726 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002727 // Check for unsigned bitfield extract
2728 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
2729 return I;
2730
Evan Cheng786b15f2009-10-21 08:15:52 +00002731 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2732 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2733 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2734 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2735 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002736 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002737 if (VT != MVT::i32)
2738 break;
2739 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2740 ? ARM::t2MOVTi16
2741 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2742 if (!Opc)
2743 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002744 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002745 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
2746 if (!N1C)
2747 break;
2748 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2749 SDValue N2 = N0.getOperand(1);
2750 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2751 if (!N2C)
2752 break;
2753 unsigned N1CVal = N1C->getZExtValue();
2754 unsigned N2CVal = N2C->getZExtValue();
2755 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2756 (N1CVal & 0xffffU) == 0xffffU &&
2757 (N2CVal & 0xffffU) == 0x0U) {
2758 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
2759 MVT::i32);
2760 SDValue Ops[] = { N0.getOperand(0), Imm16,
2761 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002762 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
Evan Cheng786b15f2009-10-21 08:15:52 +00002763 }
2764 }
2765 break;
2766 }
Jim Grosbachd7cf55c2009-11-09 00:11:35 +00002767 case ARMISD::VMOVRRD:
2768 return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002769 N->getOperand(0), getAL(CurDAG),
Dan Gohman32f71d72009-09-25 18:54:59 +00002770 CurDAG->getRegister(0, MVT::i32));
Dan Gohmana1603612007-10-08 18:33:35 +00002771 case ISD::UMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002772 if (Subtarget->isThumb1Only())
2773 break;
2774 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002775 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Michael Liaob53d8962013-04-19 22:22:57 +00002776 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2777 return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002778 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002779 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson9f944592009-08-11 20:47:22 +00002780 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2781 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov62acecd2011-01-01 20:38:38 +00002782 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2783 ARM::UMULL : ARM::UMULLv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002784 dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002785 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002786 }
Dan Gohmana1603612007-10-08 18:33:35 +00002787 case ISD::SMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002788 if (Subtarget->isThumb1Only())
2789 break;
2790 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002791 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson9f944592009-08-11 20:47:22 +00002792 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002793 return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002794 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002795 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson9f944592009-08-11 20:47:22 +00002796 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2797 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov62acecd2011-01-01 20:38:38 +00002798 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2799 ARM::SMULL : ARM::SMULLv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002800 dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002801 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002802 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002803 case ARMISD::UMLAL:{
2804 if (Subtarget->isThumb()) {
2805 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2806 N->getOperand(3), getAL(CurDAG),
2807 CurDAG->getRegister(0, MVT::i32)};
Michael Liaob53d8962013-04-19 22:22:57 +00002808 return CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002809 }else{
2810 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2811 N->getOperand(3), getAL(CurDAG),
2812 CurDAG->getRegister(0, MVT::i32),
2813 CurDAG->getRegister(0, MVT::i32) };
2814 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2815 ARM::UMLAL : ARM::UMLALv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002816 dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002817 }
2818 }
2819 case ARMISD::SMLAL:{
2820 if (Subtarget->isThumb()) {
2821 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2822 N->getOperand(3), getAL(CurDAG),
2823 CurDAG->getRegister(0, MVT::i32)};
Michael Liaob53d8962013-04-19 22:22:57 +00002824 return CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002825 }else{
2826 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2827 N->getOperand(3), getAL(CurDAG),
2828 CurDAG->getRegister(0, MVT::i32),
2829 CurDAG->getRegister(0, MVT::i32) };
2830 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2831 ARM::SMLAL : ARM::SMLALv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002832 dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002833 }
2834 }
Evan Cheng10043e22007-01-19 07:51:42 +00002835 case ISD::LOAD: {
Evan Cheng84c6cda2009-07-02 07:28:31 +00002836 SDNode *ResNode = 0;
Evan Chengb24e51e2009-07-07 01:17:28 +00002837 if (Subtarget->isThumb() && Subtarget->hasThumb2())
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002838 ResNode = SelectT2IndexedLoad(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00002839 else
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002840 ResNode = SelectARMIndexedLoad(N);
Evan Chengd9c55362009-07-02 01:23:32 +00002841 if (ResNode)
2842 return ResNode;
Evan Cheng10043e22007-01-19 07:51:42 +00002843 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002844 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00002845 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002846 case ARMISD::BRCOND: {
2847 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2848 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2849 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00002850
Evan Cheng7e90b112007-07-05 07:15:27 +00002851 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2852 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2853 // Pattern complexity = 6 cost = 1 size = 0
2854
David Goodwin27303cd2009-06-30 18:04:13 +00002855 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2856 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2857 // Pattern complexity = 6 cost = 1 size = 0
2858
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002859 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00002860 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002861 SDValue Chain = N->getOperand(0);
2862 SDValue N1 = N->getOperand(1);
2863 SDValue N2 = N->getOperand(2);
2864 SDValue N3 = N->getOperand(3);
2865 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00002866 assert(N1.getOpcode() == ISD::BasicBlock);
2867 assert(N2.getOpcode() == ISD::Constant);
2868 assert(N3.getOpcode() == ISD::Register);
2869
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002870 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Dan Gohmaneffb8942008-09-12 16:56:44 +00002871 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson9f944592009-08-11 20:47:22 +00002872 MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002873 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00002874 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002875 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002876 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002877 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002878 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002879 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00002880 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002881 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00002882 SDValue(Chain.getNode(), Chain.getResNo()));
Evan Cheng7e90b112007-07-05 07:15:27 +00002883 return NULL;
2884 }
Evan Chengb6c77042009-11-19 21:45:22 +00002885 case ARMISD::CMOV:
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002886 return SelectCMOVOp(N);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002887 case ARMISD::VZIP: {
2888 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002889 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002890 switch (VT.getSimpleVT().SimpleTy) {
2891 default: return NULL;
2892 case MVT::v8i8: Opc = ARM::VZIPd8; break;
2893 case MVT::v4i16: Opc = ARM::VZIPd16; break;
2894 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00002895 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2896 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002897 case MVT::v16i8: Opc = ARM::VZIPq8; break;
2898 case MVT::v8i16: Opc = ARM::VZIPq16; break;
2899 case MVT::v4f32:
2900 case MVT::v4i32: Opc = ARM::VZIPq32; break;
2901 }
Evan Cheng3da64f762010-04-16 05:46:06 +00002902 SDValue Pred = getAL(CurDAG);
Evan Chenga33fc862009-11-21 06:21:52 +00002903 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2904 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002905 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002906 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002907 case ARMISD::VUZP: {
2908 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002909 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002910 switch (VT.getSimpleVT().SimpleTy) {
2911 default: return NULL;
2912 case MVT::v8i8: Opc = ARM::VUZPd8; break;
2913 case MVT::v4i16: Opc = ARM::VUZPd16; break;
2914 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00002915 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2916 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002917 case MVT::v16i8: Opc = ARM::VUZPq8; break;
2918 case MVT::v8i16: Opc = ARM::VUZPq16; break;
2919 case MVT::v4f32:
2920 case MVT::v4i32: Opc = ARM::VUZPq32; break;
2921 }
Evan Cheng3da64f762010-04-16 05:46:06 +00002922 SDValue Pred = getAL(CurDAG);
Evan Chenga33fc862009-11-21 06:21:52 +00002923 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2924 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002925 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002926 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002927 case ARMISD::VTRN: {
2928 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002929 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002930 switch (VT.getSimpleVT().SimpleTy) {
2931 default: return NULL;
2932 case MVT::v8i8: Opc = ARM::VTRNd8; break;
2933 case MVT::v4i16: Opc = ARM::VTRNd16; break;
2934 case MVT::v2f32:
2935 case MVT::v2i32: Opc = ARM::VTRNd32; break;
2936 case MVT::v16i8: Opc = ARM::VTRNq8; break;
2937 case MVT::v8i16: Opc = ARM::VTRNq16; break;
2938 case MVT::v4f32:
2939 case MVT::v4i32: Opc = ARM::VTRNq32; break;
2940 }
Evan Cheng3da64f762010-04-16 05:46:06 +00002941 SDValue Pred = getAL(CurDAG);
Evan Chenga33fc862009-11-21 06:21:52 +00002942 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2943 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002944 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002945 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00002946 case ARMISD::BUILD_VECTOR: {
2947 EVT VecVT = N->getValueType(0);
2948 EVT EltVT = VecVT.getVectorElementType();
2949 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00002950 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00002951 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Weiming Zhao95782222012-11-17 00:23:35 +00002952 return createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilsond8a9a042010-06-04 00:04:02 +00002953 }
Duncan Sands14627772010-11-03 12:17:33 +00002954 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Bob Wilsond8a9a042010-06-04 00:04:02 +00002955 if (NumElts == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002956 return createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilsond8a9a042010-06-04 00:04:02 +00002957 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Weiming Zhao95782222012-11-17 00:23:35 +00002958 return createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
Bob Wilsond8a9a042010-06-04 00:04:02 +00002959 N->getOperand(2), N->getOperand(3));
2960 }
Bob Wilsone0636a72009-08-26 17:39:53 +00002961
Bob Wilson2d790df2010-11-28 06:51:26 +00002962 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002963 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
2964 ARM::VLD2DUPd32 };
Bob Wilson06fce872011-02-07 17:43:21 +00002965 return SelectVLDDup(N, false, 2, Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +00002966 }
2967
Bob Wilson77ab1652010-11-29 19:35:29 +00002968 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002969 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
2970 ARM::VLD3DUPd16Pseudo,
2971 ARM::VLD3DUPd32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00002972 return SelectVLDDup(N, false, 3, Opcodes);
Bob Wilson77ab1652010-11-29 19:35:29 +00002973 }
2974
Bob Wilson431ac4ef2010-11-30 00:00:35 +00002975 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002976 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
2977 ARM::VLD4DUPd16Pseudo,
2978 ARM::VLD4DUPd32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00002979 return SelectVLDDup(N, false, 4, Opcodes);
2980 }
2981
2982 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002983 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
2984 ARM::VLD2DUPd16wb_fixed,
2985 ARM::VLD2DUPd32wb_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00002986 return SelectVLDDup(N, true, 2, Opcodes);
2987 }
2988
2989 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002990 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
2991 ARM::VLD3DUPd16Pseudo_UPD,
2992 ARM::VLD3DUPd32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002993 return SelectVLDDup(N, true, 3, Opcodes);
2994 }
2995
2996 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002997 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
2998 ARM::VLD4DUPd16Pseudo_UPD,
2999 ARM::VLD4DUPd32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003000 return SelectVLDDup(N, true, 4, Opcodes);
3001 }
3002
3003 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003004 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
3005 ARM::VLD1d16wb_fixed,
3006 ARM::VLD1d32wb_fixed,
3007 ARM::VLD1d64wb_fixed };
3008 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
3009 ARM::VLD1q16wb_fixed,
3010 ARM::VLD1q32wb_fixed,
3011 ARM::VLD1q64wb_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00003012 return SelectVLD(N, true, 1, DOpcodes, QOpcodes, 0);
3013 }
3014
3015 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003016 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
3017 ARM::VLD2d16wb_fixed,
3018 ARM::VLD2d32wb_fixed,
3019 ARM::VLD1q64wb_fixed};
3020 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
3021 ARM::VLD2q16PseudoWB_fixed,
3022 ARM::VLD2q32PseudoWB_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00003023 return SelectVLD(N, true, 2, DOpcodes, QOpcodes, 0);
3024 }
3025
3026 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003027 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
3028 ARM::VLD3d16Pseudo_UPD,
3029 ARM::VLD3d32Pseudo_UPD,
3030 ARM::VLD1q64wb_fixed};
3031 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3032 ARM::VLD3q16Pseudo_UPD,
3033 ARM::VLD3q32Pseudo_UPD };
3034 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3035 ARM::VLD3q16oddPseudo_UPD,
3036 ARM::VLD3q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003037 return SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3038 }
3039
3040 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003041 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3042 ARM::VLD4d16Pseudo_UPD,
3043 ARM::VLD4d32Pseudo_UPD,
3044 ARM::VLD1q64wb_fixed};
3045 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3046 ARM::VLD4q16Pseudo_UPD,
3047 ARM::VLD4q32Pseudo_UPD };
3048 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3049 ARM::VLD4q16oddPseudo_UPD,
3050 ARM::VLD4q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003051 return SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3052 }
3053
3054 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003055 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3056 ARM::VLD2LNd16Pseudo_UPD,
3057 ARM::VLD2LNd32Pseudo_UPD };
3058 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3059 ARM::VLD2LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003060 return SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3061 }
3062
3063 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003064 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3065 ARM::VLD3LNd16Pseudo_UPD,
3066 ARM::VLD3LNd32Pseudo_UPD };
3067 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3068 ARM::VLD3LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003069 return SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3070 }
3071
3072 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003073 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3074 ARM::VLD4LNd16Pseudo_UPD,
3075 ARM::VLD4LNd32Pseudo_UPD };
3076 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3077 ARM::VLD4LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003078 return SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3079 }
3080
3081 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003082 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3083 ARM::VST1d16wb_fixed,
3084 ARM::VST1d32wb_fixed,
3085 ARM::VST1d64wb_fixed };
3086 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3087 ARM::VST1q16wb_fixed,
3088 ARM::VST1q32wb_fixed,
3089 ARM::VST1q64wb_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00003090 return SelectVST(N, true, 1, DOpcodes, QOpcodes, 0);
3091 }
3092
3093 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003094 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3095 ARM::VST2d16wb_fixed,
3096 ARM::VST2d32wb_fixed,
3097 ARM::VST1q64wb_fixed};
3098 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3099 ARM::VST2q16PseudoWB_fixed,
3100 ARM::VST2q32PseudoWB_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00003101 return SelectVST(N, true, 2, DOpcodes, QOpcodes, 0);
3102 }
3103
3104 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003105 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3106 ARM::VST3d16Pseudo_UPD,
3107 ARM::VST3d32Pseudo_UPD,
3108 ARM::VST1d64TPseudoWB_fixed};
3109 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3110 ARM::VST3q16Pseudo_UPD,
3111 ARM::VST3q32Pseudo_UPD };
3112 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3113 ARM::VST3q16oddPseudo_UPD,
3114 ARM::VST3q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003115 return SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3116 }
3117
3118 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003119 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3120 ARM::VST4d16Pseudo_UPD,
3121 ARM::VST4d32Pseudo_UPD,
3122 ARM::VST1d64QPseudoWB_fixed};
3123 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3124 ARM::VST4q16Pseudo_UPD,
3125 ARM::VST4q32Pseudo_UPD };
3126 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3127 ARM::VST4q16oddPseudo_UPD,
3128 ARM::VST4q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003129 return SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3130 }
3131
3132 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003133 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3134 ARM::VST2LNd16Pseudo_UPD,
3135 ARM::VST2LNd32Pseudo_UPD };
3136 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3137 ARM::VST2LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003138 return SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3139 }
3140
3141 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003142 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3143 ARM::VST3LNd16Pseudo_UPD,
3144 ARM::VST3LNd32Pseudo_UPD };
3145 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3146 ARM::VST3LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003147 return SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3148 }
3149
3150 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003151 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3152 ARM::VST4LNd16Pseudo_UPD,
3153 ARM::VST4LNd32Pseudo_UPD };
3154 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3155 ARM::VST4LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003156 return SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003157 }
3158
Bob Wilsone0636a72009-08-26 17:39:53 +00003159 case ISD::INTRINSIC_VOID:
3160 case ISD::INTRINSIC_W_CHAIN: {
3161 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003162 switch (IntNo) {
3163 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003164 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003165
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003166 case Intrinsic::arm_ldrexd: {
3167 SDValue MemAddr = N->getOperand(2);
Andrew Trickef9de2a2013-05-25 02:42:55 +00003168 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003169 SDValue Chain = N->getOperand(0);
3170
Weiming Zhao8f56f882012-11-16 21:55:34 +00003171 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3172 unsigned NewOpc = isThumb ? ARM::t2LDREXD :ARM::LDREXD;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003173
3174 // arm_ldrexd returns a i64 value in {i32, i32}
3175 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003176 if (isThumb) {
3177 ResTys.push_back(MVT::i32);
3178 ResTys.push_back(MVT::i32);
3179 } else
3180 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003181 ResTys.push_back(MVT::Other);
3182
Weiming Zhao8f56f882012-11-16 21:55:34 +00003183 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003184 SmallVector<SDValue, 7> Ops;
3185 Ops.push_back(MemAddr);
3186 Ops.push_back(getAL(CurDAG));
3187 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3188 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00003189 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003190 // Transfer memoperands.
3191 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3192 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3193 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3194
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003195 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003196 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003197 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003198 SDValue Result;
3199 if (isThumb)
3200 Result = SDValue(Ld, 0);
3201 else {
3202 SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32);
3203 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003204 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003205 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003206 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003207 ReplaceUses(SDValue(N, 0), Result);
3208 }
3209 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003210 SDValue Result;
3211 if (isThumb)
3212 Result = SDValue(Ld, 1);
3213 else {
3214 SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32);
3215 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003216 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003217 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003218 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003219 ReplaceUses(SDValue(N, 1), Result);
3220 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003221 ReplaceUses(SDValue(N, 2), OutChain);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003222 return NULL;
3223 }
3224
3225 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003226 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003227 SDValue Chain = N->getOperand(0);
3228 SDValue Val0 = N->getOperand(2);
3229 SDValue Val1 = N->getOperand(3);
3230 SDValue MemAddr = N->getOperand(4);
3231
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003232 // Store exclusive double return a i32 value which is the return status
3233 // of the issued store.
Benjamin Kramerfdf362b2013-03-07 20:33:29 +00003234 EVT ResTys[] = { MVT::i32, MVT::Other };
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003235
Weiming Zhao8f56f882012-11-16 21:55:34 +00003236 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3237 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003238 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003239 if (isThumb) {
3240 Ops.push_back(Val0);
3241 Ops.push_back(Val1);
3242 } else
3243 // arm_strexd uses GPRPair.
3244 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003245 Ops.push_back(MemAddr);
3246 Ops.push_back(getAL(CurDAG));
3247 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3248 Ops.push_back(Chain);
3249
Weiming Zhao8f56f882012-11-16 21:55:34 +00003250 unsigned NewOpc = isThumb ? ARM::t2STREXD : ARM::STREXD;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003251
Michael Liaob53d8962013-04-19 22:22:57 +00003252 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003253 // Transfer memoperands.
3254 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3255 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3256 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3257
3258 return St;
3259 }
3260
Bob Wilson340861d2010-03-23 05:25:43 +00003261 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003262 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3263 ARM::VLD1d32, ARM::VLD1d64 };
3264 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3265 ARM::VLD1q32, ARM::VLD1q64};
Bob Wilson06fce872011-02-07 17:43:21 +00003266 return SelectVLD(N, false, 1, DOpcodes, QOpcodes, 0);
Bob Wilson340861d2010-03-23 05:25:43 +00003267 }
3268
Bob Wilsone0636a72009-08-26 17:39:53 +00003269 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003270 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3271 ARM::VLD2d32, ARM::VLD1q64 };
3272 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3273 ARM::VLD2q32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003274 return SelectVLD(N, false, 2, DOpcodes, QOpcodes, 0);
Bob Wilsone0636a72009-08-26 17:39:53 +00003275 }
3276
3277 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003278 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3279 ARM::VLD3d16Pseudo,
3280 ARM::VLD3d32Pseudo,
3281 ARM::VLD1d64TPseudo };
3282 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3283 ARM::VLD3q16Pseudo_UPD,
3284 ARM::VLD3q32Pseudo_UPD };
3285 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3286 ARM::VLD3q16oddPseudo,
3287 ARM::VLD3q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003288 return SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003289 }
3290
3291 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003292 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3293 ARM::VLD4d16Pseudo,
3294 ARM::VLD4d32Pseudo,
3295 ARM::VLD1d64QPseudo };
3296 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3297 ARM::VLD4q16Pseudo_UPD,
3298 ARM::VLD4q32Pseudo_UPD };
3299 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3300 ARM::VLD4q16oddPseudo,
3301 ARM::VLD4q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003302 return SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003303 }
3304
Bob Wilsonda9817c2009-09-01 04:26:28 +00003305 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003306 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3307 ARM::VLD2LNd16Pseudo,
3308 ARM::VLD2LNd32Pseudo };
3309 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3310 ARM::VLD2LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003311 return SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003312 }
3313
3314 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003315 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3316 ARM::VLD3LNd16Pseudo,
3317 ARM::VLD3LNd32Pseudo };
3318 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3319 ARM::VLD3LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003320 return SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003321 }
3322
3323 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003324 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3325 ARM::VLD4LNd16Pseudo,
3326 ARM::VLD4LNd32Pseudo };
3327 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3328 ARM::VLD4LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003329 return SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003330 }
3331
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003332 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003333 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3334 ARM::VST1d32, ARM::VST1d64 };
3335 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3336 ARM::VST1q32, ARM::VST1q64 };
Bob Wilson06fce872011-02-07 17:43:21 +00003337 return SelectVST(N, false, 1, DOpcodes, QOpcodes, 0);
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003338 }
3339
Bob Wilsone0636a72009-08-26 17:39:53 +00003340 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003341 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3342 ARM::VST2d32, ARM::VST1q64 };
3343 static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3344 ARM::VST2q32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003345 return SelectVST(N, false, 2, DOpcodes, QOpcodes, 0);
Bob Wilsone0636a72009-08-26 17:39:53 +00003346 }
3347
3348 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003349 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3350 ARM::VST3d16Pseudo,
3351 ARM::VST3d32Pseudo,
3352 ARM::VST1d64TPseudo };
3353 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3354 ARM::VST3q16Pseudo_UPD,
3355 ARM::VST3q32Pseudo_UPD };
3356 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3357 ARM::VST3q16oddPseudo,
3358 ARM::VST3q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003359 return SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003360 }
3361
3362 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003363 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3364 ARM::VST4d16Pseudo,
3365 ARM::VST4d32Pseudo,
3366 ARM::VST1d64QPseudo };
3367 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3368 ARM::VST4q16Pseudo_UPD,
3369 ARM::VST4q32Pseudo_UPD };
3370 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3371 ARM::VST4q16oddPseudo,
3372 ARM::VST4q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003373 return SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003374 }
Bob Wilsond7797752009-09-01 18:51:56 +00003375
3376 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003377 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3378 ARM::VST2LNd16Pseudo,
3379 ARM::VST2LNd32Pseudo };
3380 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3381 ARM::VST2LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003382 return SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003383 }
3384
3385 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003386 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3387 ARM::VST3LNd16Pseudo,
3388 ARM::VST3LNd32Pseudo };
3389 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3390 ARM::VST3LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003391 return SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003392 }
3393
3394 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003395 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3396 ARM::VST4LNd16Pseudo,
3397 ARM::VST4LNd32Pseudo };
3398 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3399 ARM::VST4LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003400 return SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003401 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003402 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003403 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003404 }
Evan Chengd85631e2010-05-05 18:28:36 +00003405
Bob Wilson3ed511b2010-07-06 23:36:25 +00003406 case ISD::INTRINSIC_WO_CHAIN: {
3407 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3408 switch (IntNo) {
3409 default:
3410 break;
3411
3412 case Intrinsic::arm_neon_vtbl2:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003413 return SelectVTBL(N, false, 2, ARM::VTBL2);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003414 case Intrinsic::arm_neon_vtbl3:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003415 return SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003416 case Intrinsic::arm_neon_vtbl4:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003417 return SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003418
3419 case Intrinsic::arm_neon_vtbx2:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003420 return SelectVTBL(N, true, 2, ARM::VTBX2);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003421 case Intrinsic::arm_neon_vtbx3:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003422 return SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003423 case Intrinsic::arm_neon_vtbx4:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003424 return SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003425 }
3426 break;
3427 }
3428
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003429 case ARMISD::VTBL1: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003430 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003431 EVT VT = N->getValueType(0);
3432 SmallVector<SDValue, 6> Ops;
3433
3434 Ops.push_back(N->getOperand(0));
3435 Ops.push_back(N->getOperand(1));
3436 Ops.push_back(getAL(CurDAG)); // Predicate
3437 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Michael Liaob53d8962013-04-19 22:22:57 +00003438 return CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003439 }
3440 case ARMISD::VTBL2: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003441 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003442 EVT VT = N->getValueType(0);
3443
3444 // Form a REG_SEQUENCE to force register allocation.
3445 SDValue V0 = N->getOperand(0);
3446 SDValue V1 = N->getOperand(1);
Weiming Zhao95782222012-11-17 00:23:35 +00003447 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003448
3449 SmallVector<SDValue, 6> Ops;
3450 Ops.push_back(RegSeq);
3451 Ops.push_back(N->getOperand(2));
3452 Ops.push_back(getAL(CurDAG)); // Predicate
3453 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Michael Liaob53d8962013-04-19 22:22:57 +00003454 return CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003455 }
3456
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003457 case ISD::CONCAT_VECTORS:
Evan Chengd85631e2010-05-05 18:28:36 +00003458 return SelectConcatVector(N);
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +00003459
3460 case ARMISD::ATOMOR64_DAG:
3461 return SelectAtomic64(N, ARM::ATOMOR6432);
3462 case ARMISD::ATOMXOR64_DAG:
3463 return SelectAtomic64(N, ARM::ATOMXOR6432);
3464 case ARMISD::ATOMADD64_DAG:
3465 return SelectAtomic64(N, ARM::ATOMADD6432);
3466 case ARMISD::ATOMSUB64_DAG:
3467 return SelectAtomic64(N, ARM::ATOMSUB6432);
3468 case ARMISD::ATOMNAND64_DAG:
3469 return SelectAtomic64(N, ARM::ATOMNAND6432);
3470 case ARMISD::ATOMAND64_DAG:
3471 return SelectAtomic64(N, ARM::ATOMAND6432);
3472 case ARMISD::ATOMSWAP64_DAG:
3473 return SelectAtomic64(N, ARM::ATOMSWAP6432);
Eli Friedman1ccecbb2011-08-31 17:52:22 +00003474 case ARMISD::ATOMCMPXCHG64_DAG:
3475 return SelectAtomic64(N, ARM::ATOMCMPXCHG6432);
Silviu Baranga93aefa52012-11-29 14:41:25 +00003476
3477 case ARMISD::ATOMMIN64_DAG:
3478 return SelectAtomic64(N, ARM::ATOMMIN6432);
3479 case ARMISD::ATOMUMIN64_DAG:
3480 return SelectAtomic64(N, ARM::ATOMUMIN6432);
3481 case ARMISD::ATOMMAX64_DAG:
3482 return SelectAtomic64(N, ARM::ATOMMAX6432);
3483 case ARMISD::ATOMUMAX64_DAG:
3484 return SelectAtomic64(N, ARM::ATOMUMAX6432);
Evan Chengd85631e2010-05-05 18:28:36 +00003485 }
Evan Chengd5021732008-12-10 21:54:21 +00003486
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003487 return SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003488}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003489
Weiming Zhaoc5987002013-02-14 18:10:21 +00003490SDNode *ARMDAGToDAGISel::SelectInlineAsm(SDNode *N){
3491 std::vector<SDValue> AsmNodeOperands;
3492 unsigned Flag, Kind;
3493 bool Changed = false;
3494 unsigned NumOps = N->getNumOperands();
3495
Weiming Zhaoc5987002013-02-14 18:10:21 +00003496 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
3497 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
3498 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
3499 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003500 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
3501 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
3502 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00003503
Andrew Trickef9de2a2013-05-25 02:42:55 +00003504 SDLoc dl(N);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003505 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1) : SDValue(0,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003506
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003507 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003508 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003509 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00003510 SDValue op = N->getOperand(i);
3511 AsmNodeOperands.push_back(op);
3512
3513 if (i < InlineAsm::Op_FirstOperand)
3514 continue;
3515
3516 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
3517 Flag = C->getZExtValue();
3518 Kind = InlineAsm::getKind(Flag);
3519 }
3520 else
3521 continue;
3522
Joey Gouly392cdad2013-07-08 19:52:51 +00003523 // Immediate operands to inline asm in the SelectionDAG are modeled with
3524 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and
3525 // the second is a constant with the value of the immediate. If we get here
3526 // and we have a Kind_Imm, skip the next operand, and continue.
Joey Gouly606f3fb2013-07-05 10:19:40 +00003527 if (Kind == InlineAsm::Kind_Imm) {
3528 SDValue op = N->getOperand(++i);
3529 AsmNodeOperands.push_back(op);
3530 continue;
3531 }
3532
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003533 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
3534 if (NumRegs)
3535 OpChanged.push_back(false);
3536
3537 unsigned DefIdx = 0;
3538 bool IsTiedToChangedOp = false;
3539 // If it's a use that is tied with a previous def, it has no
3540 // reg class constraint.
3541 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
3542 IsTiedToChangedOp = OpChanged[DefIdx];
3543
Weiming Zhaoc5987002013-02-14 18:10:21 +00003544 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
3545 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
3546 continue;
3547
Weiming Zhaoc5987002013-02-14 18:10:21 +00003548 unsigned RC;
3549 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003550 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
3551 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00003552 continue;
3553
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003554 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00003555 SDValue V0 = N->getOperand(i+1);
3556 SDValue V1 = N->getOperand(i+2);
3557 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
3558 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
3559 SDValue PairedReg;
3560 MachineRegisterInfo &MRI = MF->getRegInfo();
3561
3562 if (Kind == InlineAsm::Kind_RegDef ||
3563 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
3564 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
3565 // the original GPRs.
3566
3567 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3568 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3569 SDValue Chain = SDValue(N,0);
3570
3571 SDNode *GU = N->getGluedUser();
3572 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
3573 Chain.getValue(1));
3574
3575 // Extract values from a GPRPair reg and copy to the original GPR reg.
3576 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
3577 RegCopy);
3578 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
3579 RegCopy);
3580 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
3581 RegCopy.getValue(1));
3582 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
3583
3584 // Update the original glue user.
3585 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
3586 Ops.push_back(T1.getValue(1));
3587 CurDAG->UpdateNodeOperands(GU, &Ops[0], Ops.size());
3588 GU = T1.getNode();
3589 }
3590 else {
3591 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
3592 // GPRPair and then pass the GPRPair to the inline asm.
3593 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
3594
3595 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
3596 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
3597 Chain.getValue(1));
3598 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
3599 T0.getValue(1));
3600 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
3601
3602 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
3603 // i32 VRs of inline asm with it.
3604 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3605 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3606 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
3607
3608 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
3609 Glue = Chain.getValue(1);
3610 }
3611
3612 Changed = true;
3613
3614 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003615 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003616 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
Tim Northover55349a22013-08-18 18:06:03 +00003617 if (IsTiedToChangedOp)
3618 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx);
3619 else
3620 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003621 // Replace the current flag.
3622 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
3623 Flag, MVT::i32);
3624 // Add the new register node and skip the original two GPRs.
3625 AsmNodeOperands.push_back(PairedReg);
3626 // Skip the next two GPRs.
3627 i += 2;
3628 }
3629 }
3630
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003631 if (Glue.getNode())
3632 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003633 if (!Changed)
3634 return NULL;
3635
Andrew Trickef9de2a2013-05-25 02:42:55 +00003636 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Weiming Zhaoc5987002013-02-14 18:10:21 +00003637 CurDAG->getVTList(MVT::Other, MVT::Glue), &AsmNodeOperands[0],
3638 AsmNodeOperands.size());
3639 New->setNodeId(-1);
3640 return New.getNode();
3641}
3642
3643
Bob Wilsona2c462b2009-05-19 05:53:42 +00003644bool ARMDAGToDAGISel::
3645SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
3646 std::vector<SDValue> &OutOps) {
3647 assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
Bob Wilson3b515602009-10-13 20:50:28 +00003648 // Require the address to be in a register. That is safe for all ARM
3649 // variants and it is hard to do anything much smarter without knowing
3650 // how the operand is used.
3651 OutOps.push_back(Op);
Bob Wilsona2c462b2009-05-19 05:53:42 +00003652 return false;
3653}
3654
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003655/// createARMISelDag - This pass converts a legalized DAG into a
3656/// ARM-specific DAG, ready for instruction scheduling.
3657///
Bob Wilson2dd957f2009-09-28 14:30:20 +00003658FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
3659 CodeGenOpt::Level OptLevel) {
3660 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003661}