blob: da0fe2cf7d41b4a6a3ad7580771cca15c6e2deaf [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);
178
Evan Cheng0fc80842010-11-12 22:42:47 +0000179 inline bool is_so_imm(unsigned Imm) const {
180 return ARM_AM::getSOImmVal(Imm) != -1;
181 }
182
183 inline bool is_so_imm_not(unsigned Imm) const {
184 return ARM_AM::getSOImmVal(~Imm) != -1;
185 }
186
187 inline bool is_t2_so_imm(unsigned Imm) const {
188 return ARM_AM::getT2SOImmVal(Imm) != -1;
189 }
190
191 inline bool is_t2_so_imm_not(unsigned Imm) const {
192 return ARM_AM::getT2SOImmVal(~Imm) != -1;
193 }
194
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000195 // Include the pieces autogenerated from the target description.
196#include "ARMGenDAGISel.inc"
Bob Wilsona2c462b2009-05-19 05:53:42 +0000197
198private:
Evan Cheng84c6cda2009-07-02 07:28:31 +0000199 /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
200 /// ARM.
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000201 SDNode *SelectARMIndexedLoad(SDNode *N);
202 SDNode *SelectT2IndexedLoad(SDNode *N);
Evan Cheng84c6cda2009-07-02 07:28:31 +0000203
Bob Wilson340861d2010-03-23 05:25:43 +0000204 /// SelectVLD - Select NEON load intrinsics. NumVecs should be
205 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilson12b47992009-10-14 17:28:52 +0000206 /// loads of D registers and even subregs and odd subregs of Q registers.
Bob Wilson340861d2010-03-23 05:25:43 +0000207 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson06fce872011-02-07 17:43:21 +0000208 SDNode *SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000209 const uint16_t *DOpcodes,
210 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilson12b47992009-10-14 17:28:52 +0000211
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000212 /// SelectVST - Select NEON store intrinsics. NumVecs should
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000213 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000214 /// stores of D registers and even subregs and odd subregs of Q registers.
Bob Wilsoncc0a2a72010-03-23 06:20:33 +0000215 /// For NumVecs <= 2, QOpcodes1 is not used.
Bob Wilson06fce872011-02-07 17:43:21 +0000216 SDNode *SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000217 const uint16_t *DOpcodes,
218 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1);
Bob Wilsonc350cdf2009-10-14 18:32:29 +0000219
Bob Wilson93117bc2009-10-14 16:46:45 +0000220 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should
Bob Wilson4145e3a2009-10-14 16:19:03 +0000221 /// be 2, 3 or 4. The opcode arrays specify the instructions used for
Bob Wilsond5c57a52010-09-13 23:01:35 +0000222 /// load/store of D registers and Q registers.
Bob Wilson06fce872011-02-07 17:43:21 +0000223 SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad,
224 bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000225 const uint16_t *DOpcodes, const uint16_t *QOpcodes);
Bob Wilson4145e3a2009-10-14 16:19:03 +0000226
Bob Wilson2d790df2010-11-28 06:51:26 +0000227 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs
228 /// should be 2, 3 or 4. The opcode array specifies the instructions used
229 /// for loading D registers. (Q registers are not supported.)
Bob Wilson06fce872011-02-07 17:43:21 +0000230 SDNode *SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +0000231 const uint16_t *Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +0000232
Bob Wilson5bc8a792010-07-07 00:08:54 +0000233 /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2,
234 /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be
235 /// generated to force the table registers to be consecutive.
236 SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc);
Bob Wilson3ed511b2010-07-06 23:36:25 +0000237
Sandeep Patel7460e082009-10-13 20:25:58 +0000238 /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
Jim Grosbach825cb292010-04-22 23:24:18 +0000239 SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
Sandeep Patel423e42b2009-10-13 18:59:48 +0000240
Evan Chengb6c77042009-11-19 21:45:22 +0000241 /// SelectCMOVOp - Select CMOV instructions for ARM.
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000242 SDNode *SelectCMOVOp(SDNode *N);
243 SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +0000244 ARMCC::CondCodes CCVal, SDValue CCR,
245 SDValue InFlag);
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000246 SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +0000247 ARMCC::CondCodes CCVal, SDValue CCR,
248 SDValue InFlag);
Jim Grosbach5b255c22010-10-07 00:53:56 +0000249 SDNode *SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +0000250 ARMCC::CondCodes CCVal, SDValue CCR,
251 SDValue InFlag);
Jim Grosbach742adc32010-10-07 00:42:42 +0000252 SDNode *SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +0000253 ARMCC::CondCodes CCVal, SDValue CCR,
254 SDValue InFlag);
Evan Chengb6c77042009-11-19 21:45:22 +0000255
Bill Wendlinga7d697e2011-10-10 22:59:55 +0000256 // Select special operations if node forms integer ABS pattern
257 SDNode *SelectABSOp(SDNode *N);
258
Weiming Zhaoc5987002013-02-14 18:10:21 +0000259 SDNode *SelectInlineAsm(SDNode *N);
260
Evan Chengd85631e2010-05-05 18:28:36 +0000261 SDNode *SelectConcatVector(SDNode *N);
262
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +0000263 SDNode *SelectAtomic64(SDNode *Node, unsigned Opc);
264
Evan Chengd9c55362009-07-02 01:23:32 +0000265 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
266 /// inline asm expressions.
267 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
268 char ConstraintCode,
269 std::vector<SDValue> &OutOps);
Bob Wilsone6b778d2009-10-06 22:01:59 +0000270
Weiming Zhao95782222012-11-17 00:23:35 +0000271 // Form pairs of consecutive R, S, D, or Q registers.
Weiming Zhao8f56f882012-11-16 21:55:34 +0000272 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1);
Weiming Zhao95782222012-11-17 00:23:35 +0000273 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1);
274 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1);
275 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1);
Evan Chengc2ae5f52010-05-10 17:34:18 +0000276
Bob Wilsond8a9a042010-06-04 00:04:02 +0000277 // Form sequences of 4 consecutive S, D, or Q registers.
Weiming Zhao95782222012-11-17 00:23:35 +0000278 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
279 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
280 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +0000281
282 // Get the alignment operand for a NEON VLD or VST instruction.
283 SDValue GetVLDSTAlign(SDValue Align, unsigned NumVecs, bool is64BitVector);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000284};
Evan Cheng10043e22007-01-19 07:51:42 +0000285}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +0000286
Sandeep Patel423e42b2009-10-13 18:59:48 +0000287/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
288/// operand. If so Imm will receive the 32-bit value.
289static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
290 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
291 Imm = cast<ConstantSDNode>(N)->getZExtValue();
292 return true;
293 }
294 return false;
295}
296
297// isInt32Immediate - This method tests to see if a constant operand.
298// If so Imm will receive the 32 bit value.
299static bool isInt32Immediate(SDValue N, unsigned &Imm) {
300 return isInt32Immediate(N.getNode(), Imm);
301}
302
303// isOpcWithIntImmediate - This method tests to see if the node is a specific
304// opcode and that it has a immediate integer right operand.
305// If so Imm will receive the 32 bit value.
306static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
307 return N->getOpcode() == Opc &&
308 isInt32Immediate(N->getOperand(1).getNode(), Imm);
309}
310
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000311/// \brief Check whether a particular node is a constant value representable as
Dmitri Gribenko5485acd2012-09-14 14:57:36 +0000312/// (N * Scale) where (N in [\p RangeMin, \p RangeMax).
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000313///
314/// \param ScaledConstant [out] - On success, the pre-scaled constant value.
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000315static bool isScaledConstantInRange(SDValue Node, int Scale,
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000316 int RangeMin, int RangeMax,
317 int &ScaledConstant) {
Jakob Stoklund Olesen2056d152011-09-23 22:10:33 +0000318 assert(Scale > 0 && "Invalid scale!");
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000319
320 // Check that this is a constant.
321 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node);
322 if (!C)
323 return false;
324
325 ScaledConstant = (int) C->getZExtValue();
326 if ((ScaledConstant % Scale) != 0)
327 return false;
328
329 ScaledConstant /= Scale;
330 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax;
331}
332
Evan Chengeae6d2c2012-12-19 20:16:09 +0000333void ARMDAGToDAGISel::PreprocessISelDAG() {
334 if (!Subtarget->hasV6T2Ops())
335 return;
336
337 bool isThumb2 = Subtarget->isThumb();
338 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
339 E = CurDAG->allnodes_end(); I != E; ) {
340 SDNode *N = I++; // Preincrement iterator to avoid invalidation issues.
341
342 if (N->getOpcode() != ISD::ADD)
343 continue;
344
345 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with
346 // leading zeros, followed by consecutive set bits, followed by 1 or 2
347 // trailing zeros, e.g. 1020.
348 // Transform the expression to
349 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number
350 // of trailing zeros of c2. The left shift would be folded as an shifter
351 // operand of 'add' and the 'and' and 'srl' would become a bits extraction
352 // node (UBFX).
353
354 SDValue N0 = N->getOperand(0);
355 SDValue N1 = N->getOperand(1);
356 unsigned And_imm = 0;
357 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) {
358 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm))
359 std::swap(N0, N1);
360 }
361 if (!And_imm)
362 continue;
363
364 // Check if the AND mask is an immediate of the form: 000.....1111111100
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000365 unsigned TZ = countTrailingZeros(And_imm);
Evan Chengeae6d2c2012-12-19 20:16:09 +0000366 if (TZ != 1 && TZ != 2)
367 // Be conservative here. Shifter operands aren't always free. e.g. On
368 // Swift, left shifter operand of 1 / 2 for free but others are not.
369 // e.g.
370 // ubfx r3, r1, #16, #8
371 // ldr.w r3, [r0, r3, lsl #2]
372 // vs.
373 // mov.w r9, #1020
374 // and.w r2, r9, r1, lsr #14
375 // ldr r2, [r0, r2]
376 continue;
377 And_imm >>= TZ;
378 if (And_imm & (And_imm + 1))
379 continue;
380
381 // Look for (and (srl X, c1), c2).
382 SDValue Srl = N1.getOperand(0);
383 unsigned Srl_imm = 0;
384 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) ||
385 (Srl_imm <= 2))
386 continue;
387
388 // Make sure first operand is not a shifter operand which would prevent
389 // folding of the left shift.
390 SDValue CPTmp0;
391 SDValue CPTmp1;
392 SDValue CPTmp2;
393 if (isThumb2) {
394 if (SelectT2ShifterOperandReg(N0, CPTmp0, CPTmp1))
395 continue;
396 } else {
397 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) ||
398 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2))
399 continue;
400 }
401
402 // Now make the transformation.
Andrew Trickef9de2a2013-05-25 02:42:55 +0000403 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000404 Srl.getOperand(0),
405 CurDAG->getConstant(Srl_imm+TZ, MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000406 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000407 Srl, CurDAG->getConstant(And_imm, MVT::i32));
Andrew Trickef9de2a2013-05-25 02:42:55 +0000408 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32,
Evan Chengeae6d2c2012-12-19 20:16:09 +0000409 N1, CurDAG->getConstant(TZ, MVT::i32));
410 CurDAG->UpdateNodeOperands(N, N0, N1);
411 }
412}
413
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000414/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS
415/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at
416/// least on current ARM implementations) which should be avoidded.
417bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
418 if (OptLevel == CodeGenOpt::None)
419 return true;
420
421 if (!CheckVMLxHazard)
422 return true;
Bob Wilsone8a549c2012-09-29 21:43:49 +0000423
424 if (!Subtarget->isCortexA8() && !Subtarget->isLikeA9() &&
425 !Subtarget->isSwift())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000426 return true;
427
428 if (!N->hasOneUse())
429 return false;
430
431 SDNode *Use = *N->use_begin();
432 if (Use->getOpcode() == ISD::CopyToReg)
433 return true;
434 if (Use->isMachineOpcode()) {
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000435 const ARMBaseInstrInfo *TII =
436 static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo());
437
Evan Cheng6cc775f2011-06-28 19:10:37 +0000438 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
439 if (MCID.mayStore())
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000440 return true;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000441 unsigned Opcode = MCID.getOpcode();
Evan Cheng62c7b5b2010-12-05 22:04:16 +0000442 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
443 return true;
444 // vmlx feeding into another vmlx. We actually want to unfold
445 // the use later in the MLxExpansion pass. e.g.
446 // vmla
447 // vmla (stall 8 cycles)
448 //
449 // vmul (5 cycles)
450 // vadd (5 cycles)
451 // vmla
452 // This adds up to about 18 - 19 cycles.
453 //
454 // vmla
455 // vmul (stall 4 cycles)
456 // vadd adds up to about 14 cycles.
457 return TII->isFpMLxInstruction(Opcode);
458 }
459
460 return false;
461}
Sandeep Patel423e42b2009-10-13 18:59:48 +0000462
Evan Cheng59bbc542010-10-27 23:41:30 +0000463bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
464 ARM_AM::ShiftOpc ShOpcVal,
465 unsigned ShAmt) {
Bob Wilsone8a549c2012-09-29 21:43:49 +0000466 if (!Subtarget->isLikeA9() && !Subtarget->isSwift())
Evan Cheng59bbc542010-10-27 23:41:30 +0000467 return true;
468 if (Shift.hasOneUse())
469 return true;
470 // R << 2 is free.
Bob Wilsone8a549c2012-09-29 21:43:49 +0000471 return ShOpcVal == ARM_AM::lsl &&
472 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1));
Evan Cheng59bbc542010-10-27 23:41:30 +0000473}
474
Owen Andersonb595ed02011-07-21 18:54:16 +0000475bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +0000476 SDValue &BaseReg,
Owen Anderson6d557452011-03-18 19:46:58 +0000477 SDValue &Opc,
478 bool CheckProfitability) {
Evan Cheng59069ec2010-07-30 23:33:54 +0000479 if (DisableShifterOp)
480 return false;
481
Evan Chenga20cde32011-07-20 23:34:39 +0000482 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +0000483
484 // Don't match base register only case. That is matched to a separate
485 // lower complexity pattern with explicit register operand.
486 if (ShOpcVal == ARM_AM::no_shift) return false;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000487
Evan Chengb23b50d2009-06-29 07:51:04 +0000488 BaseReg = N.getOperand(0);
489 unsigned ShImmVal = 0;
Owen Andersonb595ed02011-07-21 18:54:16 +0000490 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
491 if (!RHS) return false;
Owen Andersonb595ed02011-07-21 18:54:16 +0000492 ShImmVal = RHS->getZExtValue() & 31;
Evan Cheng59bbc542010-10-27 23:41:30 +0000493 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
494 MVT::i32);
495 return true;
496}
497
Owen Andersonb595ed02011-07-21 18:54:16 +0000498bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
499 SDValue &BaseReg,
500 SDValue &ShReg,
501 SDValue &Opc,
502 bool CheckProfitability) {
503 if (DisableShifterOp)
504 return false;
505
506 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
507
508 // Don't match base register only case. That is matched to a separate
509 // lower complexity pattern with explicit register operand.
510 if (ShOpcVal == ARM_AM::no_shift) return false;
511
512 BaseReg = N.getOperand(0);
513 unsigned ShImmVal = 0;
514 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
515 if (RHS) return false;
516
517 ShReg = N.getOperand(1);
518 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
519 return false;
520 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
521 MVT::i32);
522 return true;
523}
524
525
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000526bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
527 SDValue &Base,
528 SDValue &OffImm) {
529 // Match simple R + imm12 operands.
530
531 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +0000532 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
533 !CurDAG->isBaseWithConstantOffset(N)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000534 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000535 // Match frame index.
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000536 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000537 Base = CurDAG->getTargetFrameIndex(FI,
538 getTargetLowering()->getPointerTy());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000539 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
540 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +0000541 }
Owen Anderson6d557452011-03-18 19:46:58 +0000542
Chris Lattner46c01a32011-02-13 22:25:43 +0000543 if (N.getOpcode() == ARMISD::Wrapper &&
544 !(Subtarget->useMovt() &&
545 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000546 Base = N.getOperand(0);
547 } else
548 Base = N;
549 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
550 return true;
551 }
552
553 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
554 int RHSC = (int)RHS->getZExtValue();
555 if (N.getOpcode() == ISD::SUB)
556 RHSC = -RHSC;
557
558 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
559 Base = N.getOperand(0);
560 if (Base.getOpcode() == ISD::FrameIndex) {
561 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000562 Base = CurDAG->getTargetFrameIndex(FI,
563 getTargetLowering()->getPointerTy());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000564 }
565 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
566 return true;
567 }
568 }
569
570 // Base only.
571 Base = N;
572 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
573 return true;
574}
575
576
577
578bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
579 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000580 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000581 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000582 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
583 // X * [3,5,9] -> X + X * [2,4,8] etc.
584 int RHSC = (int)RHS->getZExtValue();
585 if (RHSC & 1) {
586 RHSC = RHSC & ~1;
587 ARM_AM::AddrOpc AddSub = ARM_AM::add;
588 if (RHSC < 0) {
589 AddSub = ARM_AM::sub;
590 RHSC = - RHSC;
591 }
592 if (isPowerOf2_32(RHSC)) {
593 unsigned ShAmt = Log2_32(RHSC);
594 Base = Offset = N.getOperand(0);
595 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
596 ARM_AM::lsl),
597 MVT::i32);
598 return true;
599 }
600 }
601 }
602 }
603
Chris Lattner46c01a32011-02-13 22:25:43 +0000604 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
605 // ISD::OR that is equivalent to an ISD::ADD.
606 !CurDAG->isBaseWithConstantOffset(N))
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000607 return false;
608
609 // Leave simple R +/- imm12 operands for LDRi12
Chris Lattner46c01a32011-02-13 22:25:43 +0000610 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000611 int RHSC;
612 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
613 -0x1000+1, 0x1000, RHSC)) // 12 bits.
614 return false;
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000615 }
616
617 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000618 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add;
Evan Chenga20cde32011-07-20 23:34:39 +0000619 ARM_AM::ShiftOpc ShOpcVal =
620 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000621 unsigned ShAmt = 0;
622
623 Base = N.getOperand(0);
624 Offset = N.getOperand(1);
625
626 if (ShOpcVal != ARM_AM::no_shift) {
627 // Check to see if the RHS of the shift is a constant, if not, we can't fold
628 // it.
629 if (ConstantSDNode *Sh =
630 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
631 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000632 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
633 Offset = N.getOperand(1).getOperand(0);
634 else {
635 ShAmt = 0;
636 ShOpcVal = ARM_AM::no_shift;
637 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000638 } else {
639 ShOpcVal = ARM_AM::no_shift;
640 }
641 }
642
643 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000644 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000645 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
646 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000647 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000648 if (ShOpcVal != ARM_AM::no_shift) {
649 // Check to see if the RHS of the shift is a constant, if not, we can't
650 // fold it.
651 if (ConstantSDNode *Sh =
652 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
653 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000654 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000655 Offset = N.getOperand(0).getOperand(0);
656 Base = N.getOperand(1);
657 } else {
658 ShAmt = 0;
659 ShOpcVal = ARM_AM::no_shift;
660 }
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000661 } else {
662 ShOpcVal = ARM_AM::no_shift;
663 }
664 }
665 }
666
667 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
668 MVT::i32);
669 return true;
670}
671
672
Jim Grosbach1e4d9a12010-10-26 22:37:02 +0000673//-----
674
Jim Grosbach08605202010-09-29 19:03:54 +0000675AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
676 SDValue &Base,
677 SDValue &Offset,
678 SDValue &Opc) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000679 if (N.getOpcode() == ISD::MUL &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000680 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000681 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
682 // X * [3,5,9] -> X + X * [2,4,8] etc.
Dan Gohmaneffb8942008-09-12 16:56:44 +0000683 int RHSC = (int)RHS->getZExtValue();
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000684 if (RHSC & 1) {
685 RHSC = RHSC & ~1;
686 ARM_AM::AddrOpc AddSub = ARM_AM::add;
687 if (RHSC < 0) {
688 AddSub = ARM_AM::sub;
689 RHSC = - RHSC;
690 }
691 if (isPowerOf2_32(RHSC)) {
692 unsigned ShAmt = Log2_32(RHSC);
693 Base = Offset = N.getOperand(0);
694 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt,
695 ARM_AM::lsl),
Owen Anderson9f944592009-08-11 20:47:22 +0000696 MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000697 return AM2_SHOP;
Evan Cheng72a8bcf2007-03-13 21:05:54 +0000698 }
699 }
700 }
701 }
702
Chris Lattner46c01a32011-02-13 22:25:43 +0000703 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
704 // ISD::OR that is equivalent to an ADD.
705 !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000706 Base = N;
707 if (N.getOpcode() == ISD::FrameIndex) {
708 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000709 Base = CurDAG->getTargetFrameIndex(FI,
710 getTargetLowering()->getPointerTy());
Anton Korobeynikov25229082009-11-24 00:44:37 +0000711 } else if (N.getOpcode() == ARMISD::Wrapper &&
712 !(Subtarget->useMovt() &&
713 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000714 Base = N.getOperand(0);
715 }
Owen Anderson9f944592009-08-11 20:47:22 +0000716 Offset = CurDAG->getRegister(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000717 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
718 ARM_AM::no_shift),
Owen Anderson9f944592009-08-11 20:47:22 +0000719 MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000720 return AM2_BASE;
Rafael Espindola708cb602006-11-08 17:07:32 +0000721 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000722
Evan Cheng10043e22007-01-19 07:51:42 +0000723 // Match simple R +/- imm12 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +0000724 if (N.getOpcode() != ISD::SUB) {
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000725 int RHSC;
726 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
727 -0x1000+1, 0x1000, RHSC)) { // 12 bits.
728 Base = N.getOperand(0);
729 if (Base.getOpcode() == ISD::FrameIndex) {
730 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000731 Base = CurDAG->getTargetFrameIndex(FI,
732 getTargetLowering()->getPointerTy());
Rafael Espindola708cb602006-11-08 17:07:32 +0000733 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000734 Offset = CurDAG->getRegister(0, MVT::i32);
735
736 ARM_AM::AddrOpc AddSub = ARM_AM::add;
737 if (RHSC < 0) {
738 AddSub = ARM_AM::sub;
739 RHSC = - RHSC;
740 }
741 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC,
742 ARM_AM::no_shift),
743 MVT::i32);
744 return AM2_BASE;
Evan Cheng10043e22007-01-19 07:51:42 +0000745 }
Jim Grosbachc7b10f32010-09-29 17:32:29 +0000746 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000747
Bob Wilsone8a549c2012-09-29 21:43:49 +0000748 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000749 // Compute R +/- (R << N) and reuse it.
750 Base = N;
751 Offset = CurDAG->getRegister(0, MVT::i32);
752 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
753 ARM_AM::no_shift),
754 MVT::i32);
755 return AM2_BASE;
756 }
757
Johnny Chenb678a562009-10-27 17:25:15 +0000758 // Otherwise this is R +/- [possibly shifted] R.
Chris Lattner46c01a32011-02-13 22:25:43 +0000759 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
Evan Chenga20cde32011-07-20 23:34:39 +0000760 ARM_AM::ShiftOpc ShOpcVal =
761 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000762 unsigned ShAmt = 0;
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000763
Evan Cheng10043e22007-01-19 07:51:42 +0000764 Base = N.getOperand(0);
765 Offset = N.getOperand(1);
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000766
Evan Cheng10043e22007-01-19 07:51:42 +0000767 if (ShOpcVal != ARM_AM::no_shift) {
768 // Check to see if the RHS of the shift is a constant, if not, we can't fold
769 // it.
770 if (ConstantSDNode *Sh =
771 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000772 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000773 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt))
774 Offset = N.getOperand(1).getOperand(0);
775 else {
776 ShAmt = 0;
777 ShOpcVal = ARM_AM::no_shift;
778 }
Evan Cheng10043e22007-01-19 07:51:42 +0000779 } else {
780 ShOpcVal = ARM_AM::no_shift;
Rafael Espindola708cb602006-11-08 17:07:32 +0000781 }
782 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000783
Evan Cheng10043e22007-01-19 07:51:42 +0000784 // Try matching (R shl C) + (R).
Chris Lattner46c01a32011-02-13 22:25:43 +0000785 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift &&
Bob Wilsone8a549c2012-09-29 21:43:49 +0000786 !(Subtarget->isLikeA9() || Subtarget->isSwift() ||
787 N.getOperand(0).hasOneUse())) {
Evan Chenga20cde32011-07-20 23:34:39 +0000788 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000789 if (ShOpcVal != ARM_AM::no_shift) {
790 // Check to see if the RHS of the shift is a constant, if not, we can't
791 // fold it.
792 if (ConstantSDNode *Sh =
793 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000794 ShAmt = Sh->getZExtValue();
Cameron Zwarich842f99a2011-10-05 23:39:02 +0000795 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) {
Evan Cheng59bbc542010-10-27 23:41:30 +0000796 Offset = N.getOperand(0).getOperand(0);
797 Base = N.getOperand(1);
798 } else {
799 ShAmt = 0;
800 ShOpcVal = ARM_AM::no_shift;
801 }
Evan Cheng10043e22007-01-19 07:51:42 +0000802 } else {
803 ShOpcVal = ARM_AM::no_shift;
804 }
805 }
806 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000807
Evan Cheng10043e22007-01-19 07:51:42 +0000808 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson9f944592009-08-11 20:47:22 +0000809 MVT::i32);
Jim Grosbach08605202010-09-29 19:03:54 +0000810 return AM2_SHOP;
Rafael Espindola708cb602006-11-08 17:07:32 +0000811}
812
Owen Anderson2aedba62011-07-26 20:54:26 +0000813bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000814 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000815 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000816 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
817 ? cast<LoadSDNode>(Op)->getAddressingMode()
818 : cast<StoreSDNode>(Op)->getAddressingMode();
819 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
820 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000821 int Val;
Owen Anderson2aedba62011-07-26 20:54:26 +0000822 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
823 return false;
Evan Cheng10043e22007-01-19 07:51:42 +0000824
825 Offset = N;
Evan Chenga20cde32011-07-20 23:34:39 +0000826 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Cheng10043e22007-01-19 07:51:42 +0000827 unsigned ShAmt = 0;
828 if (ShOpcVal != ARM_AM::no_shift) {
829 // Check to see if the RHS of the shift is a constant, if not, we can't fold
830 // it.
831 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +0000832 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +0000833 if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
834 Offset = N.getOperand(0);
835 else {
836 ShAmt = 0;
837 ShOpcVal = ARM_AM::no_shift;
838 }
Evan Cheng10043e22007-01-19 07:51:42 +0000839 } else {
840 ShOpcVal = ARM_AM::no_shift;
841 }
842 }
843
844 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal),
Owen Anderson9f944592009-08-11 20:47:22 +0000845 MVT::i32);
Rafael Espindola19398ec2006-10-17 18:04:53 +0000846 return true;
847}
848
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000849bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
850 SDValue &Offset, SDValue &Opc) {
Owen Anderson939cd212011-08-31 20:00:11 +0000851 unsigned Opcode = Op->getOpcode();
852 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
853 ? cast<LoadSDNode>(Op)->getAddressingMode()
854 : cast<StoreSDNode>(Op)->getAddressingMode();
855 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
856 ? ARM_AM::add : ARM_AM::sub;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000857 int Val;
858 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
Owen Anderson939cd212011-08-31 20:00:11 +0000859 if (AddSub == ARM_AM::sub) Val *= -1;
Owen Anderson4d5c8f82011-08-29 20:16:50 +0000860 Offset = CurDAG->getRegister(0, MVT::i32);
861 Opc = CurDAG->getTargetConstant(Val, MVT::i32);
862 return true;
863 }
864
865 return false;
866}
867
868
Owen Anderson2aedba62011-07-26 20:54:26 +0000869bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
870 SDValue &Offset, SDValue &Opc) {
871 unsigned Opcode = Op->getOpcode();
872 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
873 ? cast<LoadSDNode>(Op)->getAddressingMode()
874 : cast<StoreSDNode>(Op)->getAddressingMode();
875 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
876 ? ARM_AM::add : ARM_AM::sub;
877 int Val;
878 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits.
879 Offset = CurDAG->getRegister(0, MVT::i32);
880 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val,
881 ARM_AM::no_shift),
882 MVT::i32);
883 return true;
884 }
885
886 return false;
887}
888
Jim Grosbachf0c95ca2011-08-05 20:35:44 +0000889bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
890 Base = N;
891 return true;
892}
Evan Cheng10043e22007-01-19 07:51:42 +0000893
Chris Lattner0e023ea2010-09-21 20:31:19 +0000894bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000895 SDValue &Base, SDValue &Offset,
896 SDValue &Opc) {
Evan Cheng10043e22007-01-19 07:51:42 +0000897 if (N.getOpcode() == ISD::SUB) {
898 // X - C is canonicalize to X + -C, no need to handle it here.
899 Base = N.getOperand(0);
900 Offset = N.getOperand(1);
Owen Anderson9f944592009-08-11 20:47:22 +0000901 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000902 return true;
903 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000904
Chris Lattner46c01a32011-02-13 22:25:43 +0000905 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000906 Base = N;
907 if (N.getOpcode() == ISD::FrameIndex) {
908 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000909 Base = CurDAG->getTargetFrameIndex(FI,
910 getTargetLowering()->getPointerTy());
Evan Cheng10043e22007-01-19 07:51:42 +0000911 }
Owen Anderson9f944592009-08-11 20:47:22 +0000912 Offset = CurDAG->getRegister(0, MVT::i32);
913 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000914 return true;
915 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000916
Evan Cheng10043e22007-01-19 07:51:42 +0000917 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000918 int RHSC;
919 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1,
920 -256 + 1, 256, RHSC)) { // 8 bits.
921 Base = N.getOperand(0);
922 if (Base.getOpcode() == ISD::FrameIndex) {
923 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000924 Base = CurDAG->getTargetFrameIndex(FI,
925 getTargetLowering()->getPointerTy());
Evan Cheng10043e22007-01-19 07:51:42 +0000926 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000927 Offset = CurDAG->getRegister(0, MVT::i32);
928
929 ARM_AM::AddrOpc AddSub = ARM_AM::add;
930 if (RHSC < 0) {
931 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000932 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000933 }
934 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32);
935 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000936 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000937
Evan Cheng10043e22007-01-19 07:51:42 +0000938 Base = N.getOperand(0);
939 Offset = N.getOperand(1);
Owen Anderson9f944592009-08-11 20:47:22 +0000940 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000941 return true;
942}
943
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000944bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000945 SDValue &Offset, SDValue &Opc) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +0000946 unsigned Opcode = Op->getOpcode();
Evan Cheng10043e22007-01-19 07:51:42 +0000947 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
948 ? cast<LoadSDNode>(Op)->getAddressingMode()
949 : cast<StoreSDNode>(Op)->getAddressingMode();
950 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC)
951 ? ARM_AM::add : ARM_AM::sub;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000952 int Val;
953 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits.
954 Offset = CurDAG->getRegister(0, MVT::i32);
955 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32);
956 return true;
Evan Cheng10043e22007-01-19 07:51:42 +0000957 }
958
959 Offset = N;
Owen Anderson9f944592009-08-11 20:47:22 +0000960 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000961 return true;
962}
963
Jim Grosbachd37f0712010-10-21 19:38:40 +0000964bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +0000965 SDValue &Base, SDValue &Offset) {
Chris Lattner46c01a32011-02-13 22:25:43 +0000966 if (!CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000967 Base = N;
968 if (N.getOpcode() == ISD::FrameIndex) {
969 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000970 Base = CurDAG->getTargetFrameIndex(FI,
971 getTargetLowering()->getPointerTy());
Anton Korobeynikov25229082009-11-24 00:44:37 +0000972 } else if (N.getOpcode() == ARMISD::Wrapper &&
973 !(Subtarget->useMovt() &&
974 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Cheng10043e22007-01-19 07:51:42 +0000975 Base = N.getOperand(0);
976 }
977 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson9f944592009-08-11 20:47:22 +0000978 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +0000979 return true;
980 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +0000981
Evan Cheng10043e22007-01-19 07:51:42 +0000982 // If the RHS is +/- imm8, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000983 int RHSC;
984 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4,
985 -256 + 1, 256, RHSC)) {
986 Base = N.getOperand(0);
987 if (Base.getOpcode() == ISD::FrameIndex) {
988 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +0000989 Base = CurDAG->getTargetFrameIndex(FI,
990 getTargetLowering()->getPointerTy());
Evan Cheng10043e22007-01-19 07:51:42 +0000991 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000992
993 ARM_AM::AddrOpc AddSub = ARM_AM::add;
994 if (RHSC < 0) {
995 AddSub = ARM_AM::sub;
Chris Lattner46c01a32011-02-13 22:25:43 +0000996 RHSC = -RHSC;
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +0000997 }
998 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC),
999 MVT::i32);
1000 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001001 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001002
Evan Cheng10043e22007-01-19 07:51:42 +00001003 Base = N;
1004 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
Owen Anderson9f944592009-08-11 20:47:22 +00001005 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001006 return true;
1007}
1008
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001009bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
1010 SDValue &Align) {
Bob Wilsondeb35af2009-07-01 23:16:05 +00001011 Addr = N;
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001012
1013 unsigned Alignment = 0;
1014 if (LSBaseSDNode *LSN = dyn_cast<LSBaseSDNode>(Parent)) {
1015 // This case occurs only for VLD1-lane/dup and VST1-lane instructions.
1016 // The maximum alignment is equal to the memory size being referenced.
1017 unsigned LSNAlign = LSN->getAlignment();
1018 unsigned MemSize = LSN->getMemoryVT().getSizeInBits() / 8;
Jakob Stoklund Olesene5a6adc2011-10-27 22:39:16 +00001019 if (LSNAlign >= MemSize && MemSize > 1)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001020 Alignment = MemSize;
1021 } else {
1022 // All other uses of addrmode6 are for intrinsics. For now just record
1023 // the raw alignment value; it will be refined later based on the legal
1024 // alignment operands for the intrinsic.
1025 Alignment = cast<MemIntrinsicSDNode>(Parent)->getAlignment();
1026 }
1027
1028 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilsondeb35af2009-07-01 23:16:05 +00001029 return true;
1030}
1031
Bob Wilsone3ecd5f2011-02-25 06:42:42 +00001032bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
1033 SDValue &Offset) {
1034 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
1035 ISD::MemIndexedMode AM = LdSt->getAddressingMode();
1036 if (AM != ISD::POST_INC)
1037 return false;
1038 Offset = N;
1039 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
1040 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
1041 Offset = CurDAG->getRegister(0, MVT::i32);
1042 }
1043 return true;
1044}
1045
Chris Lattner0e023ea2010-09-21 20:31:19 +00001046bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
Evan Cheng9a58aff2009-08-14 19:01:37 +00001047 SDValue &Offset, SDValue &Label) {
Evan Cheng10043e22007-01-19 07:51:42 +00001048 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
1049 Offset = N.getOperand(0);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001050 SDValue N1 = N.getOperand(1);
Evan Chengb8b0ad82011-01-20 08:34:58 +00001051 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
1052 MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001053 return true;
1054 }
Bill Wendling092a7bd2010-12-14 03:36:38 +00001055
Evan Cheng10043e22007-01-19 07:51:42 +00001056 return false;
1057}
1058
Bill Wendling092a7bd2010-12-14 03:36:38 +00001059
1060//===----------------------------------------------------------------------===//
1061// Thumb Addressing Modes
1062//===----------------------------------------------------------------------===//
1063
Chris Lattner0e023ea2010-09-21 20:31:19 +00001064bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001065 SDValue &Base, SDValue &Offset){
Chris Lattner46c01a32011-02-13 22:25:43 +00001066 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
Evan Cheng0794c6a2009-07-11 07:08:13 +00001067 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
Dan Gohmanf1d83042010-06-18 14:22:04 +00001068 if (!NC || !NC->isNullValue())
Evan Cheng0794c6a2009-07-11 07:08:13 +00001069 return false;
1070
1071 Base = Offset = N;
Evan Chengc0b73662007-01-23 22:59:13 +00001072 return true;
1073 }
1074
Evan Cheng10043e22007-01-19 07:51:42 +00001075 Base = N.getOperand(0);
1076 Offset = N.getOperand(1);
1077 return true;
1078}
1079
Evan Cheng139edae2007-01-24 02:21:22 +00001080bool
Bill Wendling092a7bd2010-12-14 03:36:38 +00001081ARMDAGToDAGISel::SelectThumbAddrModeRI(SDValue N, SDValue &Base,
1082 SDValue &Offset, unsigned Scale) {
Evan Cheng139edae2007-01-24 02:21:22 +00001083 if (Scale == 4) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001084 SDValue TmpBase, TmpOffImm;
Chris Lattner0e023ea2010-09-21 20:31:19 +00001085 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
Evan Cheng139edae2007-01-24 02:21:22 +00001086 return false; // We want to select tLDRspi / tSTRspi instead.
Bill Wendling092a7bd2010-12-14 03:36:38 +00001087
Evan Cheng1526ba52007-01-24 08:53:17 +00001088 if (N.getOpcode() == ARMISD::Wrapper &&
1089 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1090 return false; // We want to select tLDRpci instead.
Evan Cheng139edae2007-01-24 02:21:22 +00001091 }
1092
Chris Lattner46c01a32011-02-13 22:25:43 +00001093 if (!CurDAG->isBaseWithConstantOffset(N))
Bill Wendling832a5da2010-12-15 01:03:19 +00001094 return false;
Evan Cheng10043e22007-01-19 07:51:42 +00001095
Evan Cheng650d0672007-02-06 00:22:06 +00001096 // Thumb does not have [sp, r] address mode.
1097 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1098 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1099 if ((LHSR && LHSR->getReg() == ARM::SP) ||
Bill Wendling832a5da2010-12-15 01:03:19 +00001100 (RHSR && RHSR->getReg() == ARM::SP))
1101 return false;
Bill Wendling092a7bd2010-12-14 03:36:38 +00001102
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001103 // FIXME: Why do we explicitly check for a match here and then return false?
1104 // Presumably to allow something else to match, but shouldn't this be
1105 // documented?
1106 int RHSC;
1107 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC))
1108 return false;
Bill Wendling092a7bd2010-12-14 03:36:38 +00001109
1110 Base = N.getOperand(0);
1111 Offset = N.getOperand(1);
1112 return true;
1113}
1114
1115bool
1116ARMDAGToDAGISel::SelectThumbAddrModeRI5S1(SDValue N,
1117 SDValue &Base,
1118 SDValue &Offset) {
1119 return SelectThumbAddrModeRI(N, Base, Offset, 1);
1120}
1121
1122bool
1123ARMDAGToDAGISel::SelectThumbAddrModeRI5S2(SDValue N,
1124 SDValue &Base,
1125 SDValue &Offset) {
1126 return SelectThumbAddrModeRI(N, Base, Offset, 2);
1127}
1128
1129bool
1130ARMDAGToDAGISel::SelectThumbAddrModeRI5S4(SDValue N,
1131 SDValue &Base,
1132 SDValue &Offset) {
1133 return SelectThumbAddrModeRI(N, Base, Offset, 4);
1134}
1135
1136bool
1137ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
1138 SDValue &Base, SDValue &OffImm) {
1139 if (Scale == 4) {
1140 SDValue TmpBase, TmpOffImm;
1141 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
1142 return false; // We want to select tLDRspi / tSTRspi instead.
1143
1144 if (N.getOpcode() == ARMISD::Wrapper &&
1145 N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
1146 return false; // We want to select tLDRpci instead.
1147 }
1148
Chris Lattner46c01a32011-02-13 22:25:43 +00001149 if (!CurDAG->isBaseWithConstantOffset(N)) {
Bill Wendling092a7bd2010-12-14 03:36:38 +00001150 if (N.getOpcode() == ARMISD::Wrapper &&
1151 !(Subtarget->useMovt() &&
1152 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
1153 Base = N.getOperand(0);
1154 } else {
1155 Base = N;
1156 }
1157
Owen Anderson9f944592009-08-11 20:47:22 +00001158 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng650d0672007-02-06 00:22:06 +00001159 return true;
1160 }
1161
Bill Wendling832a5da2010-12-15 01:03:19 +00001162 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
1163 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1));
1164 if ((LHSR && LHSR->getReg() == ARM::SP) ||
1165 (RHSR && RHSR->getReg() == ARM::SP)) {
1166 ConstantSDNode *LHS = dyn_cast<ConstantSDNode>(N.getOperand(0));
1167 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
1168 unsigned LHSC = LHS ? LHS->getZExtValue() : 0;
1169 unsigned RHSC = RHS ? RHS->getZExtValue() : 0;
1170
1171 // Thumb does not have [sp, #imm5] address mode for non-zero imm5.
1172 if (LHSC != 0 || RHSC != 0) return false;
1173
1174 Base = N;
1175 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
1176 return true;
1177 }
1178
Evan Cheng10043e22007-01-19 07:51:42 +00001179 // If the RHS is + imm5 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001180 int RHSC;
1181 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) {
1182 Base = N.getOperand(0);
1183 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1184 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001185 }
1186
Evan Chengc0b73662007-01-23 22:59:13 +00001187 Base = N.getOperand(0);
Owen Anderson9f944592009-08-11 20:47:22 +00001188 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Chengc0b73662007-01-23 22:59:13 +00001189 return true;
Evan Cheng10043e22007-01-19 07:51:42 +00001190}
1191
Bill Wendling092a7bd2010-12-14 03:36:38 +00001192bool
1193ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
1194 SDValue &OffImm) {
1195 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001196}
1197
Bill Wendling092a7bd2010-12-14 03:36:38 +00001198bool
1199ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
1200 SDValue &OffImm) {
1201 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001202}
1203
Bill Wendling092a7bd2010-12-14 03:36:38 +00001204bool
1205ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
1206 SDValue &OffImm) {
1207 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
Evan Cheng10043e22007-01-19 07:51:42 +00001208}
1209
Chris Lattner0e023ea2010-09-21 20:31:19 +00001210bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
1211 SDValue &Base, SDValue &OffImm) {
Evan Cheng10043e22007-01-19 07:51:42 +00001212 if (N.getOpcode() == ISD::FrameIndex) {
1213 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001214 Base = CurDAG->getTargetFrameIndex(FI,
1215 getTargetLowering()->getPointerTy());
Owen Anderson9f944592009-08-11 20:47:22 +00001216 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng10043e22007-01-19 07:51:42 +00001217 return true;
1218 }
Evan Cheng139edae2007-01-24 02:21:22 +00001219
Chris Lattner46c01a32011-02-13 22:25:43 +00001220 if (!CurDAG->isBaseWithConstantOffset(N))
Evan Cheng650d0672007-02-06 00:22:06 +00001221 return false;
1222
1223 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0));
Evan Chenga9740312007-02-06 09:11:20 +00001224 if (N.getOperand(0).getOpcode() == ISD::FrameIndex ||
1225 (LHSR && LHSR->getReg() == ARM::SP)) {
Evan Cheng139edae2007-01-24 02:21:22 +00001226 // If the RHS is + imm8 * scale, fold into addr mode.
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001227 int RHSC;
1228 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) {
1229 Base = N.getOperand(0);
1230 if (Base.getOpcode() == ISD::FrameIndex) {
1231 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001232 Base = CurDAG->getTargetFrameIndex(FI,
1233 getTargetLowering()->getPointerTy());
Evan Cheng139edae2007-01-24 02:21:22 +00001234 }
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001235 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1236 return true;
Evan Cheng139edae2007-01-24 02:21:22 +00001237 }
1238 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001239
Evan Cheng10043e22007-01-19 07:51:42 +00001240 return false;
1241}
1242
Bill Wendling092a7bd2010-12-14 03:36:38 +00001243
1244//===----------------------------------------------------------------------===//
1245// Thumb 2 Addressing Modes
1246//===----------------------------------------------------------------------===//
1247
1248
Chris Lattner0e023ea2010-09-21 20:31:19 +00001249bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg,
Evan Chengeab9ca72009-06-27 02:26:13 +00001250 SDValue &Opc) {
Evan Cheng59069ec2010-07-30 23:33:54 +00001251 if (DisableShifterOp)
1252 return false;
1253
Evan Chenga20cde32011-07-20 23:34:39 +00001254 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
Evan Chengeab9ca72009-06-27 02:26:13 +00001255
1256 // Don't match base register only case. That is matched to a separate
1257 // lower complexity pattern with explicit register operand.
1258 if (ShOpcVal == ARM_AM::no_shift) return false;
1259
1260 BaseReg = N.getOperand(0);
1261 unsigned ShImmVal = 0;
1262 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1263 ShImmVal = RHS->getZExtValue() & 31;
1264 Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
1265 return true;
1266 }
1267
1268 return false;
1269}
1270
Chris Lattner0e023ea2010-09-21 20:31:19 +00001271bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001272 SDValue &Base, SDValue &OffImm) {
1273 // Match simple R + imm12 operands.
David Goodwin802a0b52009-07-20 15:55:39 +00001274
Evan Cheng36064672009-08-11 08:52:18 +00001275 // Base only.
Chris Lattner46c01a32011-02-13 22:25:43 +00001276 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1277 !CurDAG->isBaseWithConstantOffset(N)) {
David Goodwin802a0b52009-07-20 15:55:39 +00001278 if (N.getOpcode() == ISD::FrameIndex) {
Chris Lattner46c01a32011-02-13 22:25:43 +00001279 // Match frame index.
David Goodwin802a0b52009-07-20 15:55:39 +00001280 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001281 Base = CurDAG->getTargetFrameIndex(FI,
1282 getTargetLowering()->getPointerTy());
Owen Anderson9f944592009-08-11 20:47:22 +00001283 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
David Goodwin802a0b52009-07-20 15:55:39 +00001284 return true;
Chris Lattner46c01a32011-02-13 22:25:43 +00001285 }
Owen Anderson6d557452011-03-18 19:46:58 +00001286
Chris Lattner46c01a32011-02-13 22:25:43 +00001287 if (N.getOpcode() == ARMISD::Wrapper &&
Anton Korobeynikov25229082009-11-24 00:44:37 +00001288 !(Subtarget->useMovt() &&
1289 N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
Evan Cheng36064672009-08-11 08:52:18 +00001290 Base = N.getOperand(0);
1291 if (Base.getOpcode() == ISD::TargetConstantPool)
1292 return false; // We want to select t2LDRpci instead.
1293 } else
1294 Base = N;
Owen Anderson9f944592009-08-11 20:47:22 +00001295 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001296 return true;
David Goodwin802a0b52009-07-20 15:55:39 +00001297 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001298
1299 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
Chris Lattner0e023ea2010-09-21 20:31:19 +00001300 if (SelectT2AddrModeImm8(N, Base, OffImm))
Evan Cheng36064672009-08-11 08:52:18 +00001301 // Let t2LDRi8 handle (R - imm8).
1302 return false;
1303
Evan Chengb23b50d2009-06-29 07:51:04 +00001304 int RHSC = (int)RHS->getZExtValue();
David Goodwin79c079b2009-07-30 18:56:48 +00001305 if (N.getOpcode() == ISD::SUB)
1306 RHSC = -RHSC;
1307
1308 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned)
Evan Chengb23b50d2009-06-29 07:51:04 +00001309 Base = N.getOperand(0);
David Goodwin79c079b2009-07-30 18:56:48 +00001310 if (Base.getOpcode() == ISD::FrameIndex) {
1311 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001312 Base = CurDAG->getTargetFrameIndex(FI,
1313 getTargetLowering()->getPointerTy());
David Goodwin79c079b2009-07-30 18:56:48 +00001314 }
Owen Anderson9f944592009-08-11 20:47:22 +00001315 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001316 return true;
1317 }
1318 }
1319
Evan Cheng36064672009-08-11 08:52:18 +00001320 // Base only.
1321 Base = N;
Owen Anderson9f944592009-08-11 20:47:22 +00001322 OffImm = CurDAG->getTargetConstant(0, MVT::i32);
Evan Cheng36064672009-08-11 08:52:18 +00001323 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001324}
1325
Chris Lattner0e023ea2010-09-21 20:31:19 +00001326bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001327 SDValue &Base, SDValue &OffImm) {
David Goodwin79c079b2009-07-30 18:56:48 +00001328 // Match simple R - imm8 operands.
Chris Lattner46c01a32011-02-13 22:25:43 +00001329 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
1330 !CurDAG->isBaseWithConstantOffset(N))
1331 return false;
Owen Anderson6d557452011-03-18 19:46:58 +00001332
Chris Lattner46c01a32011-02-13 22:25:43 +00001333 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1334 int RHSC = (int)RHS->getSExtValue();
1335 if (N.getOpcode() == ISD::SUB)
1336 RHSC = -RHSC;
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001337
Chris Lattner46c01a32011-02-13 22:25:43 +00001338 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
1339 Base = N.getOperand(0);
1340 if (Base.getOpcode() == ISD::FrameIndex) {
1341 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00001342 Base = CurDAG->getTargetFrameIndex(FI,
1343 getTargetLowering()->getPointerTy());
Evan Chengb23b50d2009-06-29 07:51:04 +00001344 }
Chris Lattner46c01a32011-02-13 22:25:43 +00001345 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
1346 return true;
Evan Chengb23b50d2009-06-29 07:51:04 +00001347 }
1348 }
1349
1350 return false;
1351}
1352
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001353bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
Evan Cheng84c6cda2009-07-02 07:28:31 +00001354 SDValue &OffImm){
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001355 unsigned Opcode = Op->getOpcode();
Evan Cheng84c6cda2009-07-02 07:28:31 +00001356 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
1357 ? cast<LoadSDNode>(Op)->getAddressingMode()
1358 : cast<StoreSDNode>(Op)->getAddressingMode();
Daniel Dunbare0cd9ac2011-01-19 15:12:16 +00001359 int RHSC;
1360 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits.
1361 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC))
1362 ? CurDAG->getTargetConstant(RHSC, MVT::i32)
1363 : CurDAG->getTargetConstant(-RHSC, MVT::i32);
1364 return true;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001365 }
1366
1367 return false;
1368}
1369
Chris Lattner0e023ea2010-09-21 20:31:19 +00001370bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
Evan Chengb23b50d2009-06-29 07:51:04 +00001371 SDValue &Base,
1372 SDValue &OffReg, SDValue &ShImm) {
Evan Cheng36064672009-08-11 08:52:18 +00001373 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
Chris Lattner46c01a32011-02-13 22:25:43 +00001374 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N))
Evan Cheng36064672009-08-11 08:52:18 +00001375 return false;
Evan Chengb23b50d2009-06-29 07:51:04 +00001376
Evan Cheng36064672009-08-11 08:52:18 +00001377 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
1378 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1379 int RHSC = (int)RHS->getZExtValue();
1380 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
1381 return false;
1382 else if (RHSC < 0 && RHSC >= -255) // 8 bits
David Goodwin79c079b2009-07-30 18:56:48 +00001383 return false;
1384 }
1385
Evan Chengb23b50d2009-06-29 07:51:04 +00001386 // Look for (R + R) or (R + (R << [1,2,3])).
1387 unsigned ShAmt = 0;
1388 Base = N.getOperand(0);
1389 OffReg = N.getOperand(1);
1390
1391 // Swap if it is ((R << c) + R).
Evan Chenga20cde32011-07-20 23:34:39 +00001392 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001393 if (ShOpcVal != ARM_AM::lsl) {
Evan Chenga20cde32011-07-20 23:34:39 +00001394 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode());
Evan Chengb23b50d2009-06-29 07:51:04 +00001395 if (ShOpcVal == ARM_AM::lsl)
1396 std::swap(Base, OffReg);
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001397 }
1398
Evan Chengb23b50d2009-06-29 07:51:04 +00001399 if (ShOpcVal == ARM_AM::lsl) {
1400 // Check to see if the RHS of the shift is a constant, if not, we can't fold
1401 // it.
1402 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
1403 ShAmt = Sh->getZExtValue();
Evan Cheng59bbc542010-10-27 23:41:30 +00001404 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt))
1405 OffReg = OffReg.getOperand(0);
1406 else {
Evan Chengb23b50d2009-06-29 07:51:04 +00001407 ShAmt = 0;
1408 ShOpcVal = ARM_AM::no_shift;
Evan Cheng59bbc542010-10-27 23:41:30 +00001409 }
Evan Chengb23b50d2009-06-29 07:51:04 +00001410 } else {
1411 ShOpcVal = ARM_AM::no_shift;
1412 }
David Goodwinf3912052009-07-15 15:50:19 +00001413 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00001414
Owen Anderson9f944592009-08-11 20:47:22 +00001415 ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32);
Evan Chengb23b50d2009-06-29 07:51:04 +00001416
1417 return true;
1418}
1419
1420//===--------------------------------------------------------------------===//
1421
Evan Cheng7e90b112007-07-05 07:15:27 +00001422/// getAL - Returns a ARMCC::AL immediate node.
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00001423static inline SDValue getAL(SelectionDAG *CurDAG) {
Owen Anderson9f944592009-08-11 20:47:22 +00001424 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);
Evan Cheng0f7cbe82007-05-15 01:29:07 +00001425}
1426
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001427SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
1428 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Chengd9c55362009-07-02 01:23:32 +00001429 ISD::MemIndexedMode AM = LD->getAddressingMode();
1430 if (AM == ISD::UNINDEXED)
1431 return NULL;
1432
Owen Anderson53aa7a92009-08-10 22:56:29 +00001433 EVT LoadedVT = LD->getMemoryVT();
Evan Chengd9c55362009-07-02 01:23:32 +00001434 SDValue Offset, AMOpc;
1435 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1436 unsigned Opcode = 0;
1437 bool Match = false;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001438 if (LoadedVT == MVT::i32 && isPre &&
1439 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
1440 Opcode = ARM::LDR_PRE_IMM;
1441 Match = true;
1442 } else if (LoadedVT == MVT::i32 && !isPre &&
Owen Anderson2aedba62011-07-26 20:54:26 +00001443 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001444 Opcode = ARM::LDR_POST_IMM;
Evan Chengd9c55362009-07-02 01:23:32 +00001445 Match = true;
Owen Anderson2aedba62011-07-26 20:54:26 +00001446 } else if (LoadedVT == MVT::i32 &&
1447 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Owen Anderson16d33f32011-08-26 20:43:14 +00001448 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Owen Anderson2aedba62011-07-26 20:54:26 +00001449 Match = true;
1450
Owen Anderson9f944592009-08-11 20:47:22 +00001451 } else if (LoadedVT == MVT::i16 &&
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001452 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001453 Match = true;
1454 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD)
1455 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST)
1456 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST);
Owen Anderson9f944592009-08-11 20:47:22 +00001457 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) {
Evan Chengd9c55362009-07-02 01:23:32 +00001458 if (LD->getExtensionType() == ISD::SEXTLOAD) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001459 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001460 Match = true;
1461 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST;
1462 }
1463 } else {
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001464 if (isPre &&
1465 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) {
Evan Chengd9c55362009-07-02 01:23:32 +00001466 Match = true;
Owen Anderson4d5c8f82011-08-29 20:16:50 +00001467 Opcode = ARM::LDRB_PRE_IMM;
1468 } else if (!isPre &&
1469 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
1470 Match = true;
1471 Opcode = ARM::LDRB_POST_IMM;
Owen Anderson2aedba62011-07-26 20:54:26 +00001472 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
1473 Match = true;
Owen Anderson16d33f32011-08-26 20:43:14 +00001474 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
Evan Chengd9c55362009-07-02 01:23:32 +00001475 }
1476 }
1477 }
1478
1479 if (Match) {
Owen Andersonfd60f602011-08-26 21:12:37 +00001480 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) {
1481 SDValue Chain = LD->getChain();
1482 SDValue Base = LD->getBasePtr();
1483 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG),
1484 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001485 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001486 MVT::i32, MVT::Other, Ops);
Owen Andersonfd60f602011-08-26 21:12:37 +00001487 } else {
1488 SDValue Chain = LD->getChain();
1489 SDValue Base = LD->getBasePtr();
1490 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG),
1491 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001492 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001493 MVT::i32, MVT::Other, Ops);
Owen Andersonfd60f602011-08-26 21:12:37 +00001494 }
Evan Chengd9c55362009-07-02 01:23:32 +00001495 }
1496
1497 return NULL;
1498}
1499
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001500SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
1501 LoadSDNode *LD = cast<LoadSDNode>(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001502 ISD::MemIndexedMode AM = LD->getAddressingMode();
1503 if (AM == ISD::UNINDEXED)
1504 return NULL;
1505
Owen Anderson53aa7a92009-08-10 22:56:29 +00001506 EVT LoadedVT = LD->getMemoryVT();
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001507 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001508 SDValue Offset;
1509 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
1510 unsigned Opcode = 0;
1511 bool Match = false;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001512 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) {
Owen Anderson9f944592009-08-11 20:47:22 +00001513 switch (LoadedVT.getSimpleVT().SimpleTy) {
1514 case MVT::i32:
Evan Cheng84c6cda2009-07-02 07:28:31 +00001515 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
1516 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001517 case MVT::i16:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001518 if (isSExtLd)
1519 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST;
1520 else
1521 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001522 break;
Owen Anderson9f944592009-08-11 20:47:22 +00001523 case MVT::i8:
1524 case MVT::i1:
Evan Cheng8ecd7eb2009-07-02 23:16:11 +00001525 if (isSExtLd)
1526 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST;
1527 else
1528 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
Evan Cheng84c6cda2009-07-02 07:28:31 +00001529 break;
1530 default:
1531 return NULL;
1532 }
1533 Match = true;
1534 }
1535
1536 if (Match) {
1537 SDValue Chain = LD->getChain();
1538 SDValue Base = LD->getBasePtr();
1539 SDValue Ops[]= { Base, Offset, getAL(CurDAG),
Owen Anderson9f944592009-08-11 20:47:22 +00001540 CurDAG->getRegister(0, MVT::i32), Chain };
Andrew Trickef9de2a2013-05-25 02:42:55 +00001541 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32,
Michael Liaob53d8962013-04-19 22:22:57 +00001542 MVT::Other, Ops);
Evan Cheng84c6cda2009-07-02 07:28:31 +00001543 }
1544
1545 return NULL;
1546}
1547
Weiming Zhao8f56f882012-11-16 21:55:34 +00001548/// \brief Form a GPRPair pseudo register from a pair of GPR regs.
1549SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001550 SDLoc dl(V0.getNode());
Weiming Zhao8f56f882012-11-16 21:55:34 +00001551 SDValue RegClass =
1552 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, MVT::i32);
1553 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32);
1554 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32);
1555 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001556 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Weiming Zhao8f56f882012-11-16 21:55:34 +00001557}
1558
Weiming Zhao95782222012-11-17 00:23:35 +00001559/// \brief Form a D register from a pair of S registers.
1560SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001561 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001562 SDValue RegClass =
1563 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, MVT::i32);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001564 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1565 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001566 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001567 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001568}
1569
Weiming Zhao95782222012-11-17 00:23:35 +00001570/// \brief Form a quad register from a pair of D registers.
1571SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001572 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001573 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, MVT::i32);
Jakob Stoklund Olesen6c47d642010-05-24 16:54:32 +00001574 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1575 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001576 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001577 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsone6b778d2009-10-06 22:01:59 +00001578}
1579
Weiming Zhao95782222012-11-17 00:23:35 +00001580/// \brief Form 4 consecutive D registers from a pair of Q registers.
1581SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001582 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001583 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen6c47d642010-05-24 16:54:32 +00001584 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1585 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001586 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 };
Michael Liaob53d8962013-04-19 22:22:57 +00001587 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Chengc2ae5f52010-05-10 17:34:18 +00001588}
1589
Weiming Zhao95782222012-11-17 00:23:35 +00001590/// \brief Form 4 consecutive S registers.
1591SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
Bob Wilsond8a9a042010-06-04 00:04:02 +00001592 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001593 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001594 SDValue RegClass =
1595 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, MVT::i32);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001596 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32);
1597 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32);
1598 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, MVT::i32);
1599 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001600 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1601 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001602 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Bob Wilsond8a9a042010-06-04 00:04:02 +00001603}
1604
Weiming Zhao95782222012-11-17 00:23:35 +00001605/// \brief Form 4 consecutive D registers.
1606SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Chengc2ae5f52010-05-10 17:34:18 +00001607 SDValue V2, SDValue V3) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001608 SDLoc dl(V0.getNode());
Owen Anderson5fc8b772011-06-16 18:17:13 +00001609 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen6c47d642010-05-24 16:54:32 +00001610 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32);
1611 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32);
1612 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32);
1613 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001614 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1615 V2, SubReg2, V3, SubReg3 };
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 Q registers.
1620SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
Evan Cheng298e6b82010-05-16 03:27:48 +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 = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, MVT::i32);
Jakob Stoklund Olesen6c47d642010-05-24 16:54:32 +00001624 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32);
1625 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32);
1626 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32);
1627 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32);
Owen Anderson5fc8b772011-06-16 18:17:13 +00001628 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1,
1629 V2, SubReg2, V3, SubReg3 };
Michael Liaob53d8962013-04-19 22:22:57 +00001630 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops);
Evan Cheng298e6b82010-05-16 03:27:48 +00001631}
1632
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001633/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand
1634/// of a NEON VLD or VST instruction. The supported values depend on the
1635/// number of registers being loaded.
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001636SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, unsigned NumVecs,
1637 bool is64BitVector) {
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001638 unsigned NumRegs = NumVecs;
1639 if (!is64BitVector && NumVecs < 3)
1640 NumRegs *= 2;
1641
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001642 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001643 if (Alignment >= 32 && NumRegs == 4)
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001644 Alignment = 32;
1645 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4))
1646 Alignment = 16;
1647 else if (Alignment >= 8)
1648 Alignment = 8;
1649 else
1650 Alignment = 0;
1651
1652 return CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001653}
1654
Jim Grosbach2098cb12011-10-24 21:45:13 +00001655// Get the register stride update opcode of a VLD/VST instruction that
1656// is otherwise equivalent to the given fixed stride updating instruction.
1657static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) {
1658 switch (Opc) {
1659 default: break;
1660 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register;
1661 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register;
1662 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register;
1663 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register;
1664 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register;
1665 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register;
1666 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register;
1667 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register;
Jim Grosbach05df4602011-10-31 21:50:31 +00001668
1669 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register;
1670 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register;
1671 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register;
1672 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register;
1673 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register;
1674 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register;
1675 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register;
1676 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register;
Jim Grosbach98d032f2011-11-29 22:38:04 +00001677 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register;
Jim Grosbach5ee209c2011-11-29 22:58:48 +00001678 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001679
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001680 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register;
1681 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register;
1682 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register;
Jim Grosbachd146a022011-12-09 21:28:25 +00001683 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register;
1684 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register;
1685 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register;
1686
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001687 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register;
1688 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register;
1689 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register;
Jim Grosbach88ac7612011-12-14 21:32:11 +00001690 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register;
1691 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register;
1692 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register;
Jim Grosbachc80a2642011-12-21 19:40:55 +00001693
Jim Grosbach13a292c2012-03-06 22:01:44 +00001694 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register;
1695 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register;
1696 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register;
Jim Grosbach2098cb12011-10-24 21:45:13 +00001697 }
1698 return Opc; // If not one we handle, return it unchanged.
1699}
1700
Bob Wilson06fce872011-02-07 17:43:21 +00001701SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001702 const uint16_t *DOpcodes,
1703 const uint16_t *QOpcodes0,
1704 const uint16_t *QOpcodes1) {
Bob Wilson340861d2010-03-23 05:25:43 +00001705 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001706 SDLoc dl(N);
Bob Wilson12b47992009-10-14 17:28:52 +00001707
Bob Wilsonae08a732010-03-20 22:13:40 +00001708 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001709 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1710 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilson12b47992009-10-14 17:28:52 +00001711 return NULL;
1712
1713 SDValue Chain = N->getOperand(0);
1714 EVT VT = N->getValueType(0);
1715 bool is64BitVector = VT.is64BitVector();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001716 Align = GetVLDSTAlign(Align, NumVecs, is64BitVector);
Bob Wilson9eeb8902010-09-23 21:43:54 +00001717
Bob Wilson12b47992009-10-14 17:28:52 +00001718 unsigned OpcodeIndex;
1719 switch (VT.getSimpleVT().SimpleTy) {
1720 default: llvm_unreachable("unhandled vld type");
1721 // Double-register operations:
1722 case MVT::v8i8: OpcodeIndex = 0; break;
1723 case MVT::v4i16: OpcodeIndex = 1; break;
1724 case MVT::v2f32:
1725 case MVT::v2i32: OpcodeIndex = 2; break;
1726 case MVT::v1i64: OpcodeIndex = 3; break;
1727 // Quad-register operations:
1728 case MVT::v16i8: OpcodeIndex = 0; break;
1729 case MVT::v8i16: OpcodeIndex = 1; break;
1730 case MVT::v4f32:
1731 case MVT::v4i32: OpcodeIndex = 2; break;
Bob Wilson340861d2010-03-23 05:25:43 +00001732 case MVT::v2i64: OpcodeIndex = 3;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001733 assert(NumVecs == 1 && "v2i64 type only supported for VLD1");
Bob Wilson340861d2010-03-23 05:25:43 +00001734 break;
Bob Wilson12b47992009-10-14 17:28:52 +00001735 }
1736
Bob Wilson35fafca2010-09-03 18:16:02 +00001737 EVT ResTy;
1738 if (NumVecs == 1)
1739 ResTy = VT;
1740 else {
1741 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
1742 if (!is64BitVector)
1743 ResTyElts *= 2;
1744 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts);
1745 }
Bob Wilson06fce872011-02-07 17:43:21 +00001746 std::vector<EVT> ResTys;
1747 ResTys.push_back(ResTy);
1748 if (isUpdating)
1749 ResTys.push_back(MVT::i32);
1750 ResTys.push_back(MVT::Other);
Bob Wilson35fafca2010-09-03 18:16:02 +00001751
Evan Cheng3da64f762010-04-16 05:46:06 +00001752 SDValue Pred = getAL(CurDAG);
Bob Wilsonae08a732010-03-20 22:13:40 +00001753 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001754 SDNode *VLd;
1755 SmallVector<SDValue, 7> Ops;
Evan Cheng630063a2010-05-10 21:26:24 +00001756
Bob Wilson06fce872011-02-07 17:43:21 +00001757 // Double registers and VLD1/VLD2 quad registers are directly supported.
1758 if (is64BitVector || NumVecs <= 2) {
1759 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1760 QOpcodes0[OpcodeIndex]);
1761 Ops.push_back(MemAddr);
1762 Ops.push_back(Align);
1763 if (isUpdating) {
1764 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbachd146a022011-12-09 21:28:25 +00001765 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach2098cb12011-10-24 21:45:13 +00001766 // case entirely when the rest are updated to that form, too.
Jim Grosbachd146a022011-12-09 21:28:25 +00001767 if ((NumVecs == 1 || NumVecs == 2) && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001768 Opc = getVLDSTRegisterUpdateOpcode(Opc);
Jim Grosbachd146a022011-12-09 21:28:25 +00001769 // We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so
Jim Grosbach05df4602011-10-31 21:50:31 +00001770 // check for that explicitly too. Horribly hacky, but temporary.
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001771 if ((NumVecs != 1 && NumVecs != 2 && Opc != ARM::VLD1q64wb_fixed) ||
Jim Grosbach05df4602011-10-31 21:50:31 +00001772 !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach2098cb12011-10-24 21:45:13 +00001773 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Evan Cheng630063a2010-05-10 21:26:24 +00001774 }
Bob Wilson06fce872011-02-07 17:43:21 +00001775 Ops.push_back(Pred);
1776 Ops.push_back(Reg0);
1777 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001778 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Bob Wilson75a64082010-09-02 16:00:54 +00001779
Bob Wilson12b47992009-10-14 17:28:52 +00001780 } else {
1781 // Otherwise, quad registers are loaded with two separate instructions,
1782 // where one loads the even registers and the other loads the odd registers.
Bob Wilson35fafca2010-09-03 18:16:02 +00001783 EVT AddrTy = MemAddr.getValueType();
Bob Wilson12b47992009-10-14 17:28:52 +00001784
Bob Wilson06fce872011-02-07 17:43:21 +00001785 // Load the even subregs. This is always an updating load, so that it
1786 // provides the address to the second load for the odd subregs.
Bob Wilson35fafca2010-09-03 18:16:02 +00001787 SDValue ImplDef =
1788 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0);
1789 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain };
Bob Wilsona609b892011-02-07 17:43:15 +00001790 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
Michael Liaob53d8962013-04-19 22:22:57 +00001791 ResTy, AddrTy, MVT::Other, OpsA);
Bob Wilson35fafca2010-09-03 18:16:02 +00001792 Chain = SDValue(VLdA, 2);
Bob Wilson12b47992009-10-14 17:28:52 +00001793
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001794 // Load the odd subregs.
Bob Wilson06fce872011-02-07 17:43:21 +00001795 Ops.push_back(SDValue(VLdA, 1));
1796 Ops.push_back(Align);
1797 if (isUpdating) {
1798 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1799 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1800 "only constant post-increment update allowed for VLD3/4");
1801 (void)Inc;
1802 Ops.push_back(Reg0);
1803 }
1804 Ops.push_back(SDValue(VLdA, 0));
1805 Ops.push_back(Pred);
1806 Ops.push_back(Reg0);
1807 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001808 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops);
Bob Wilson35fafca2010-09-03 18:16:02 +00001809 }
Bob Wilson12b47992009-10-14 17:28:52 +00001810
Evan Cheng40791332011-04-19 00:04:03 +00001811 // Transfer memoperands.
1812 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1813 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1814 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);
1815
Bob Wilson06fce872011-02-07 17:43:21 +00001816 if (NumVecs == 1)
1817 return VLd;
1818
1819 // Extract out the subregisters.
1820 SDValue SuperReg = SDValue(VLd, 0);
1821 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
1822 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
1823 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0);
1824 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
1825 ReplaceUses(SDValue(N, Vec),
1826 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
1827 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
1828 if (isUpdating)
1829 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));
Bob Wilson12b47992009-10-14 17:28:52 +00001830 return NULL;
1831}
1832
Bob Wilson06fce872011-02-07 17:43:21 +00001833SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001834 const uint16_t *DOpcodes,
1835 const uint16_t *QOpcodes0,
1836 const uint16_t *QOpcodes1) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00001837 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001838 SDLoc dl(N);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001839
Bob Wilsonae08a732010-03-20 22:13:40 +00001840 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001841 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1842 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1843 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001844 return NULL;
1845
Evan Cheng40791332011-04-19 00:04:03 +00001846 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1847 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1848
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001849 SDValue Chain = N->getOperand(0);
Bob Wilson06fce872011-02-07 17:43:21 +00001850 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001851 bool is64BitVector = VT.is64BitVector();
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00001852 Align = GetVLDSTAlign(Align, NumVecs, is64BitVector);
Bob Wilson7fbbe9a2010-09-23 23:42:37 +00001853
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001854 unsigned OpcodeIndex;
1855 switch (VT.getSimpleVT().SimpleTy) {
1856 default: llvm_unreachable("unhandled vst type");
1857 // Double-register operations:
1858 case MVT::v8i8: OpcodeIndex = 0; break;
1859 case MVT::v4i16: OpcodeIndex = 1; break;
1860 case MVT::v2f32:
1861 case MVT::v2i32: OpcodeIndex = 2; break;
1862 case MVT::v1i64: OpcodeIndex = 3; break;
1863 // Quad-register operations:
1864 case MVT::v16i8: OpcodeIndex = 0; break;
1865 case MVT::v8i16: OpcodeIndex = 1; break;
1866 case MVT::v4f32:
1867 case MVT::v4i32: OpcodeIndex = 2; break;
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00001868 case MVT::v2i64: OpcodeIndex = 3;
1869 assert(NumVecs == 1 && "v2i64 type only supported for VST1");
1870 break;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001871 }
1872
Bob Wilson06fce872011-02-07 17:43:21 +00001873 std::vector<EVT> ResTys;
1874 if (isUpdating)
1875 ResTys.push_back(MVT::i32);
1876 ResTys.push_back(MVT::Other);
1877
Evan Cheng3da64f762010-04-16 05:46:06 +00001878 SDValue Pred = getAL(CurDAG);
Bob Wilsonae08a732010-03-20 22:13:40 +00001879 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Bob Wilson06fce872011-02-07 17:43:21 +00001880 SmallVector<SDValue, 7> Ops;
Evan Chenga33fc862009-11-21 06:21:52 +00001881
Bob Wilson06fce872011-02-07 17:43:21 +00001882 // Double registers and VST1/VST2 quad registers are directly supported.
1883 if (is64BitVector || NumVecs <= 2) {
Bob Wilsona609b892011-02-07 17:43:15 +00001884 SDValue SrcReg;
Bob Wilson950882b2010-08-28 05:12:57 +00001885 if (NumVecs == 1) {
Bob Wilson06fce872011-02-07 17:43:21 +00001886 SrcReg = N->getOperand(Vec0Idx);
1887 } else if (is64BitVector) {
Evan Chenge276c182010-05-11 01:19:40 +00001888 // Form a REG_SEQUENCE to force register allocation.
Bob Wilson06fce872011-02-07 17:43:21 +00001889 SDValue V0 = N->getOperand(Vec0Idx + 0);
1890 SDValue V1 = N->getOperand(Vec0Idx + 1);
Evan Chenge276c182010-05-11 01:19:40 +00001891 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00001892 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001893 else {
Bob Wilson06fce872011-02-07 17:43:21 +00001894 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsona609b892011-02-07 17:43:15 +00001895 // If it's a vst3, form a quad D-register and leave the last part as
Evan Chenge276c182010-05-11 01:19:40 +00001896 // an undef.
1897 SDValue V3 = (NumVecs == 3)
1898 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00001899 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00001900 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Evan Chenge276c182010-05-11 01:19:40 +00001901 }
Bob Wilson950882b2010-08-28 05:12:57 +00001902 } else {
1903 // Form a QQ register.
Bob Wilson06fce872011-02-07 17:43:21 +00001904 SDValue Q0 = N->getOperand(Vec0Idx);
1905 SDValue Q1 = N->getOperand(Vec0Idx + 1);
Weiming Zhao95782222012-11-17 00:23:35 +00001906 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0);
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001907 }
Bob Wilson06fce872011-02-07 17:43:21 +00001908
1909 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
1910 QOpcodes0[OpcodeIndex]);
1911 Ops.push_back(MemAddr);
1912 Ops.push_back(Align);
1913 if (isUpdating) {
1914 SDValue Inc = N->getOperand(AddrOpIdx + 1);
Jim Grosbach88ac7612011-12-14 21:32:11 +00001915 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0
Jim Grosbach05df4602011-10-31 21:50:31 +00001916 // case entirely when the rest are updated to that form, too.
Jim Grosbach88ac7612011-12-14 21:32:11 +00001917 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode()))
Jim Grosbach05df4602011-10-31 21:50:31 +00001918 Opc = getVLDSTRegisterUpdateOpcode(Opc);
1919 // We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so
1920 // check for that explicitly too. Horribly hacky, but temporary.
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001921 if ((NumVecs > 2 && Opc != ARM::VST1q64wb_fixed) ||
Jim Grosbach05df4602011-10-31 21:50:31 +00001922 !isa<ConstantSDNode>(Inc.getNode()))
1923 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
Bob Wilson06fce872011-02-07 17:43:21 +00001924 }
1925 Ops.push_back(SrcReg);
1926 Ops.push_back(Pred);
1927 Ops.push_back(Reg0);
1928 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00001929 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00001930
1931 // Transfer memoperands.
1932 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);
1933
1934 return VSt;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001935 }
1936
1937 // Otherwise, quad registers are stored with two separate instructions,
1938 // where one stores the even registers and the other stores the odd registers.
Evan Cheng9e688cb2010-05-15 07:53:37 +00001939
Bob Wilson01ac8f92010-06-16 21:34:01 +00001940 // Form the QQQQ REG_SEQUENCE.
Bob Wilson06fce872011-02-07 17:43:21 +00001941 SDValue V0 = N->getOperand(Vec0Idx + 0);
1942 SDValue V1 = N->getOperand(Vec0Idx + 1);
1943 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilson950882b2010-08-28 05:12:57 +00001944 SDValue V3 = (NumVecs == 3)
1945 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson06fce872011-02-07 17:43:21 +00001946 : N->getOperand(Vec0Idx + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00001947 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson01ac8f92010-06-16 21:34:01 +00001948
Bob Wilson06fce872011-02-07 17:43:21 +00001949 // Store the even D registers. This is always an updating store, so that it
1950 // provides the address to the second store for the odd subregs.
Bob Wilsona609b892011-02-07 17:43:15 +00001951 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain };
1952 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl,
1953 MemAddr.getValueType(),
Michael Liaob53d8962013-04-19 22:22:57 +00001954 MVT::Other, OpsA);
Evan Cheng40791332011-04-19 00:04:03 +00001955 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson01ac8f92010-06-16 21:34:01 +00001956 Chain = SDValue(VStA, 1);
1957
1958 // Store the odd D registers.
Bob Wilson06fce872011-02-07 17:43:21 +00001959 Ops.push_back(SDValue(VStA, 0));
1960 Ops.push_back(Align);
1961 if (isUpdating) {
1962 SDValue Inc = N->getOperand(AddrOpIdx + 1);
1963 assert(isa<ConstantSDNode>(Inc.getNode()) &&
1964 "only constant post-increment update allowed for VST3/4");
1965 (void)Inc;
1966 Ops.push_back(Reg0);
1967 }
1968 Ops.push_back(RegSeq);
1969 Ops.push_back(Pred);
1970 Ops.push_back(Reg0);
1971 Ops.push_back(Chain);
Evan Cheng40791332011-04-19 00:04:03 +00001972 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys,
Michael Liaob53d8962013-04-19 22:22:57 +00001973 Ops);
Evan Cheng40791332011-04-19 00:04:03 +00001974 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1);
1975 return VStB;
Bob Wilsonc350cdf2009-10-14 18:32:29 +00001976}
1977
Dan Gohmanea6f91f2010-01-05 01:24:18 +00001978SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
Bob Wilson06fce872011-02-07 17:43:21 +00001979 bool isUpdating, unsigned NumVecs,
Craig Topper01736f82012-05-24 05:17:00 +00001980 const uint16_t *DOpcodes,
1981 const uint16_t *QOpcodes) {
Bob Wilson93117bc2009-10-14 16:46:45 +00001982 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00001983 SDLoc dl(N);
Bob Wilson4145e3a2009-10-14 16:19:03 +00001984
Bob Wilsonae08a732010-03-20 22:13:40 +00001985 SDValue MemAddr, Align;
Bob Wilson06fce872011-02-07 17:43:21 +00001986 unsigned AddrOpIdx = isUpdating ? 1 : 2;
1987 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
1988 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align))
Bob Wilson4145e3a2009-10-14 16:19:03 +00001989 return NULL;
1990
Evan Cheng40791332011-04-19 00:04:03 +00001991 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
1992 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
1993
Bob Wilson4145e3a2009-10-14 16:19:03 +00001994 SDValue Chain = N->getOperand(0);
1995 unsigned Lane =
Bob Wilson06fce872011-02-07 17:43:21 +00001996 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue();
1997 EVT VT = N->getOperand(Vec0Idx).getValueType();
Bob Wilson4145e3a2009-10-14 16:19:03 +00001998 bool is64BitVector = VT.is64BitVector();
1999
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002000 unsigned Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002001 if (NumVecs != 3) {
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002002 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002003 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2004 if (Alignment > NumBytes)
2005 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002006 if (Alignment < 8 && Alignment < NumBytes)
2007 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002008 // Alignment must be a power of two; make sure of that.
2009 Alignment = (Alignment & -Alignment);
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002010 if (Alignment == 1)
2011 Alignment = 0;
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002012 }
Bob Wilsondd9fbaa2010-11-01 23:40:51 +00002013 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
Bob Wilsonb6d61dc2010-10-19 00:16:32 +00002014
Bob Wilson4145e3a2009-10-14 16:19:03 +00002015 unsigned OpcodeIndex;
2016 switch (VT.getSimpleVT().SimpleTy) {
Bob Wilson93117bc2009-10-14 16:46:45 +00002017 default: llvm_unreachable("unhandled vld/vst lane type");
Bob Wilson4145e3a2009-10-14 16:19:03 +00002018 // Double-register operations:
2019 case MVT::v8i8: OpcodeIndex = 0; break;
2020 case MVT::v4i16: OpcodeIndex = 1; break;
2021 case MVT::v2f32:
2022 case MVT::v2i32: OpcodeIndex = 2; break;
2023 // Quad-register operations:
2024 case MVT::v8i16: OpcodeIndex = 0; break;
2025 case MVT::v4f32:
2026 case MVT::v4i32: OpcodeIndex = 1; break;
2027 }
2028
Bob Wilson06fce872011-02-07 17:43:21 +00002029 std::vector<EVT> ResTys;
2030 if (IsLoad) {
2031 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
2032 if (!is64BitVector)
2033 ResTyElts *= 2;
2034 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(),
2035 MVT::i64, ResTyElts));
2036 }
2037 if (isUpdating)
2038 ResTys.push_back(MVT::i32);
2039 ResTys.push_back(MVT::Other);
2040
Evan Cheng3da64f762010-04-16 05:46:06 +00002041 SDValue Pred = getAL(CurDAG);
Bob Wilsonae08a732010-03-20 22:13:40 +00002042 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chenga33fc862009-11-21 06:21:52 +00002043
Bob Wilson06fce872011-02-07 17:43:21 +00002044 SmallVector<SDValue, 8> Ops;
Bob Wilson4145e3a2009-10-14 16:19:03 +00002045 Ops.push_back(MemAddr);
Jim Grosbachd1d002a2009-11-07 21:25:39 +00002046 Ops.push_back(Align);
Bob Wilson06fce872011-02-07 17:43:21 +00002047 if (isUpdating) {
2048 SDValue Inc = N->getOperand(AddrOpIdx + 1);
2049 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc);
2050 }
Bob Wilson01ac8f92010-06-16 21:34:01 +00002051
Bob Wilsond5c57a52010-09-13 23:01:35 +00002052 SDValue SuperReg;
Bob Wilson06fce872011-02-07 17:43:21 +00002053 SDValue V0 = N->getOperand(Vec0Idx + 0);
2054 SDValue V1 = N->getOperand(Vec0Idx + 1);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002055 if (NumVecs == 2) {
2056 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002057 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002058 else
Weiming Zhao95782222012-11-17 00:23:35 +00002059 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002060 } else {
Bob Wilson06fce872011-02-07 17:43:21 +00002061 SDValue V2 = N->getOperand(Vec0Idx + 2);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002062 SDValue V3 = (NumVecs == 3)
Bob Wilson06fce872011-02-07 17:43:21 +00002063 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
2064 : N->getOperand(Vec0Idx + 3);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002065 if (is64BitVector)
Weiming Zhao95782222012-11-17 00:23:35 +00002066 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilsond5c57a52010-09-13 23:01:35 +00002067 else
Weiming Zhao95782222012-11-17 00:23:35 +00002068 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002069 }
Bob Wilsond5c57a52010-09-13 23:01:35 +00002070 Ops.push_back(SuperReg);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002071 Ops.push_back(getI32Imm(Lane));
Evan Chenga33fc862009-11-21 06:21:52 +00002072 Ops.push_back(Pred);
Bob Wilsonae08a732010-03-20 22:13:40 +00002073 Ops.push_back(Reg0);
Bob Wilson4145e3a2009-10-14 16:19:03 +00002074 Ops.push_back(Chain);
2075
Bob Wilson06fce872011-02-07 17:43:21 +00002076 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] :
2077 QOpcodes[OpcodeIndex]);
Michael Liaob53d8962013-04-19 22:22:57 +00002078 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002079 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson93117bc2009-10-14 16:46:45 +00002080 if (!IsLoad)
Bob Wilson06fce872011-02-07 17:43:21 +00002081 return VLdLn;
Evan Cheng0cbd11d2010-05-15 01:36:29 +00002082
Bob Wilsond5c57a52010-09-13 23:01:35 +00002083 // Extract the subregisters.
Bob Wilson06fce872011-02-07 17:43:21 +00002084 SuperReg = SDValue(VLdLn, 0);
2085 assert(ARM::dsub_7 == ARM::dsub_0+7 &&
2086 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering");
2087 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0;
Bob Wilson01ac8f92010-06-16 21:34:01 +00002088 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2089 ReplaceUses(SDValue(N, Vec),
Bob Wilson06fce872011-02-07 17:43:21 +00002090 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
2091 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1));
2092 if (isUpdating)
2093 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2));
Bob Wilson4145e3a2009-10-14 16:19:03 +00002094 return NULL;
2095}
2096
Bob Wilson06fce872011-02-07 17:43:21 +00002097SDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating,
Craig Topper01736f82012-05-24 05:17:00 +00002098 unsigned NumVecs,
2099 const uint16_t *Opcodes) {
Bob Wilson2d790df2010-11-28 06:51:26 +00002100 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002101 SDLoc dl(N);
Bob Wilson2d790df2010-11-28 06:51:26 +00002102
2103 SDValue MemAddr, Align;
2104 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align))
2105 return NULL;
2106
Evan Cheng40791332011-04-19 00:04:03 +00002107 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2108 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2109
Bob Wilson2d790df2010-11-28 06:51:26 +00002110 SDValue Chain = N->getOperand(0);
2111 EVT VT = N->getValueType(0);
2112
2113 unsigned Alignment = 0;
2114 if (NumVecs != 3) {
2115 Alignment = cast<ConstantSDNode>(Align)->getZExtValue();
2116 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8;
2117 if (Alignment > NumBytes)
2118 Alignment = NumBytes;
Bob Wilsond29b38c2010-12-10 19:37:42 +00002119 if (Alignment < 8 && Alignment < NumBytes)
2120 Alignment = 0;
Bob Wilson2d790df2010-11-28 06:51:26 +00002121 // Alignment must be a power of two; make sure of that.
2122 Alignment = (Alignment & -Alignment);
2123 if (Alignment == 1)
2124 Alignment = 0;
2125 }
2126 Align = CurDAG->getTargetConstant(Alignment, MVT::i32);
2127
2128 unsigned OpcodeIndex;
2129 switch (VT.getSimpleVT().SimpleTy) {
2130 default: llvm_unreachable("unhandled vld-dup type");
2131 case MVT::v8i8: OpcodeIndex = 0; break;
2132 case MVT::v4i16: OpcodeIndex = 1; break;
2133 case MVT::v2f32:
2134 case MVT::v2i32: OpcodeIndex = 2; break;
2135 }
2136
2137 SDValue Pred = getAL(CurDAG);
2138 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
2139 SDValue SuperReg;
2140 unsigned Opc = Opcodes[OpcodeIndex];
Bob Wilson06fce872011-02-07 17:43:21 +00002141 SmallVector<SDValue, 6> Ops;
2142 Ops.push_back(MemAddr);
2143 Ops.push_back(Align);
2144 if (isUpdating) {
Jim Grosbachc80a2642011-12-21 19:40:55 +00002145 // fixed-stride update instructions don't have an explicit writeback
2146 // operand. It's implicit in the opcode itself.
Bob Wilson06fce872011-02-07 17:43:21 +00002147 SDValue Inc = N->getOperand(2);
Jim Grosbachc80a2642011-12-21 19:40:55 +00002148 if (!isa<ConstantSDNode>(Inc.getNode()))
2149 Ops.push_back(Inc);
2150 // FIXME: VLD3 and VLD4 haven't been updated to that form yet.
2151 else if (NumVecs > 2)
2152 Ops.push_back(Reg0);
Bob Wilson06fce872011-02-07 17:43:21 +00002153 }
2154 Ops.push_back(Pred);
2155 Ops.push_back(Reg0);
2156 Ops.push_back(Chain);
Bob Wilson2d790df2010-11-28 06:51:26 +00002157
2158 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs;
Bob Wilson06fce872011-02-07 17:43:21 +00002159 std::vector<EVT> ResTys;
Evan Cheng40791332011-04-19 00:04:03 +00002160 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts));
Bob Wilson06fce872011-02-07 17:43:21 +00002161 if (isUpdating)
2162 ResTys.push_back(MVT::i32);
2163 ResTys.push_back(MVT::Other);
Michael Liaob53d8962013-04-19 22:22:57 +00002164 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
Evan Cheng40791332011-04-19 00:04:03 +00002165 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1);
Bob Wilson2d790df2010-11-28 06:51:26 +00002166 SuperReg = SDValue(VLdDup, 0);
Bob Wilson2d790df2010-11-28 06:51:26 +00002167
2168 // Extract the subregisters.
2169 assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
2170 unsigned SubIdx = ARM::dsub_0;
2171 for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
2172 ReplaceUses(SDValue(N, Vec),
2173 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg));
Bob Wilson06fce872011-02-07 17:43:21 +00002174 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1));
2175 if (isUpdating)
2176 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2));
Bob Wilson2d790df2010-11-28 06:51:26 +00002177 return NULL;
2178}
2179
Bob Wilson5bc8a792010-07-07 00:08:54 +00002180SDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs,
2181 unsigned Opc) {
Bob Wilson3ed511b2010-07-06 23:36:25 +00002182 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range");
Andrew Trickef9de2a2013-05-25 02:42:55 +00002183 SDLoc dl(N);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002184 EVT VT = N->getValueType(0);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002185 unsigned FirstTblReg = IsExt ? 2 : 1;
Bob Wilson3ed511b2010-07-06 23:36:25 +00002186
2187 // Form a REG_SEQUENCE to force register allocation.
2188 SDValue RegSeq;
Bob Wilson5bc8a792010-07-07 00:08:54 +00002189 SDValue V0 = N->getOperand(FirstTblReg + 0);
2190 SDValue V1 = N->getOperand(FirstTblReg + 1);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002191 if (NumVecs == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002192 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002193 else {
Bob Wilson5bc8a792010-07-07 00:08:54 +00002194 SDValue V2 = N->getOperand(FirstTblReg + 2);
Jim Grosbachd37f0712010-10-21 19:38:40 +00002195 // If it's a vtbl3, form a quad D-register and leave the last part as
Bob Wilson3ed511b2010-07-06 23:36:25 +00002196 // an undef.
2197 SDValue V3 = (NumVecs == 3)
2198 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0)
Bob Wilson5bc8a792010-07-07 00:08:54 +00002199 : N->getOperand(FirstTblReg + 3);
Weiming Zhao95782222012-11-17 00:23:35 +00002200 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002201 }
2202
Bob Wilson5bc8a792010-07-07 00:08:54 +00002203 SmallVector<SDValue, 6> Ops;
2204 if (IsExt)
2205 Ops.push_back(N->getOperand(1));
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00002206 Ops.push_back(RegSeq);
Bob Wilson5bc8a792010-07-07 00:08:54 +00002207 Ops.push_back(N->getOperand(FirstTblReg + NumVecs));
Bob Wilson3ed511b2010-07-06 23:36:25 +00002208 Ops.push_back(getAL(CurDAG)); // predicate
2209 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register
Michael Liaob53d8962013-04-19 22:22:57 +00002210 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
Bob Wilson3ed511b2010-07-06 23:36:25 +00002211}
2212
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002213SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
Jim Grosbach825cb292010-04-22 23:24:18 +00002214 bool isSigned) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002215 if (!Subtarget->hasV6T2Ops())
2216 return NULL;
Bob Wilson93117bc2009-10-14 16:46:45 +00002217
Evan Chengeae6d2c2012-12-19 20:16:09 +00002218 unsigned Opc = isSigned
2219 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
Jim Grosbach825cb292010-04-22 23:24:18 +00002220 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
2221
Jim Grosbach825cb292010-04-22 23:24:18 +00002222 // For unsigned extracts, check for a shift right and mask
2223 unsigned And_imm = 0;
2224 if (N->getOpcode() == ISD::AND) {
2225 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
2226
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00002227 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
Jim Grosbach825cb292010-04-22 23:24:18 +00002228 if (And_imm & (And_imm + 1))
2229 return NULL;
2230
2231 unsigned Srl_imm = 0;
2232 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
2233 Srl_imm)) {
2234 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
2235
Jim Grosbach03f56d92011-07-27 21:09:25 +00002236 // Note: The width operand is encoded as width-1.
2237 unsigned Width = CountTrailingOnes_32(And_imm) - 1;
Jim Grosbach825cb292010-04-22 23:24:18 +00002238 unsigned LSB = Srl_imm;
Evan Chengeae6d2c2012-12-19 20:16:09 +00002239
Jim Grosbach825cb292010-04-22 23:24:18 +00002240 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Chengeae6d2c2012-12-19 20:16:09 +00002241
2242 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) {
2243 // It's cheaper to use a right shift to extract the top bits.
2244 if (Subtarget->isThumb()) {
2245 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri;
2246 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2247 CurDAG->getTargetConstant(LSB, MVT::i32),
2248 getAL(CurDAG), Reg0, Reg0 };
2249 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
2250 }
2251
2252 // ARM models shift instructions as MOVsi with shifter operand.
2253 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL);
2254 SDValue ShOpc =
2255 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB),
2256 MVT::i32);
2257 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc,
2258 getAL(CurDAG), Reg0, Reg0 };
2259 return CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops, 5);
2260 }
2261
Jim Grosbach825cb292010-04-22 23:24:18 +00002262 SDValue Ops[] = { N->getOperand(0).getOperand(0),
2263 CurDAG->getTargetConstant(LSB, MVT::i32),
2264 CurDAG->getTargetConstant(Width, MVT::i32),
2265 getAL(CurDAG), Reg0 };
2266 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
2267 }
2268 }
2269 return NULL;
2270 }
2271
2272 // Otherwise, we're looking for a shift of a shift
Sandeep Patel423e42b2009-10-13 18:59:48 +00002273 unsigned Shl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002274 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002275 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
2276 unsigned Srl_imm = 0;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002277 if (isInt32Immediate(N->getOperand(1), Srl_imm)) {
Sandeep Patel423e42b2009-10-13 18:59:48 +00002278 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
Jim Grosbach03f56d92011-07-27 21:09:25 +00002279 // Note: The width operand is encoded as width-1.
2280 unsigned Width = 32 - Srl_imm - 1;
Sandeep Patel423e42b2009-10-13 18:59:48 +00002281 int LSB = Srl_imm - Shl_imm;
Evan Cheng0f55e9c2009-10-22 00:40:00 +00002282 if (LSB < 0)
Sandeep Patel423e42b2009-10-13 18:59:48 +00002283 return NULL;
2284 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002285 SDValue Ops[] = { N->getOperand(0).getOperand(0),
Sandeep Patel423e42b2009-10-13 18:59:48 +00002286 CurDAG->getTargetConstant(LSB, MVT::i32),
2287 CurDAG->getTargetConstant(Width, MVT::i32),
2288 getAL(CurDAG), Reg0 };
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002289 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Sandeep Patel423e42b2009-10-13 18:59:48 +00002290 }
2291 }
2292 return NULL;
2293}
2294
Evan Cheng81a28512009-11-20 00:54:03 +00002295SDNode *ARMDAGToDAGISel::
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002296SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002297 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
2298 SDValue CPTmp0;
2299 SDValue CPTmp1;
Chris Lattner0e023ea2010-09-21 20:31:19 +00002300 if (SelectT2ShifterOperandReg(TrueVal, CPTmp0, CPTmp1)) {
Evan Cheng81a28512009-11-20 00:54:03 +00002301 unsigned SOVal = cast<ConstantSDNode>(CPTmp1)->getZExtValue();
2302 unsigned SOShOp = ARM_AM::getSORegShOp(SOVal);
2303 unsigned Opc = 0;
2304 switch (SOShOp) {
2305 case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break;
2306 case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break;
2307 case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break;
2308 case ARM_AM::ror: Opc = ARM::t2MOVCCror; break;
2309 default:
2310 llvm_unreachable("Unknown so_reg opcode!");
Evan Cheng81a28512009-11-20 00:54:03 +00002311 }
2312 SDValue SOShImm =
2313 CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32);
2314 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2315 SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag };
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002316 return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6);
Evan Cheng81a28512009-11-20 00:54:03 +00002317 }
2318 return 0;
2319}
2320
2321SDNode *ARMDAGToDAGISel::
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002322SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002323 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
2324 SDValue CPTmp0;
2325 SDValue CPTmp1;
2326 SDValue CPTmp2;
Owen Anderson04912702011-07-21 23:38:37 +00002327 if (SelectImmShifterOperand(TrueVal, CPTmp0, CPTmp2)) {
Evan Cheng81a28512009-11-20 00:54:03 +00002328 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
Owen Anderson3fa7ca82011-07-22 18:30:30 +00002329 SDValue Ops[] = { FalseVal, CPTmp0, CPTmp2, CC, CCR, InFlag };
2330 return CurDAG->SelectNodeTo(N, ARM::MOVCCsi, MVT::i32, Ops, 6);
Owen Andersonb595ed02011-07-21 18:54:16 +00002331 }
2332
2333 if (SelectRegShifterOperand(TrueVal, CPTmp0, CPTmp1, CPTmp2)) {
2334 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2335 SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag };
2336 return CurDAG->SelectNodeTo(N, ARM::MOVCCsr, MVT::i32, Ops, 7);
Evan Cheng81a28512009-11-20 00:54:03 +00002337 }
2338 return 0;
2339}
2340
2341SDNode *ARMDAGToDAGISel::
Jim Grosbach5b255c22010-10-07 00:53:56 +00002342SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng39c81c02010-11-17 20:56:30 +00002343 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
Evan Cheng81a28512009-11-20 00:54:03 +00002344 ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal);
Evan Chenga5f04842010-11-19 23:01:16 +00002345 if (!T)
Evan Cheng81a28512009-11-20 00:54:03 +00002346 return 0;
2347
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002348 unsigned Opc = 0;
Jim Grosbach5b255c22010-10-07 00:53:56 +00002349 unsigned TrueImm = T->getZExtValue();
Evan Cheng39c81c02010-11-17 20:56:30 +00002350 if (is_t2_so_imm(TrueImm)) {
2351 Opc = ARM::t2MOVCCi;
2352 } else if (TrueImm <= 0xffff) {
2353 Opc = ARM::t2MOVCCi16;
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002354 } else if (is_t2_so_imm_not(TrueImm)) {
2355 TrueImm = ~TrueImm;
2356 Opc = ARM::t2MVNCCi;
Evan Cheng39c81c02010-11-17 20:56:30 +00002357 } else if (TrueVal.getNode()->hasOneUse() && Subtarget->hasV6T2Ops()) {
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002358 // Large immediate.
2359 Opc = ARM::t2MOVCCi32imm;
2360 }
2361
2362 if (Opc) {
Evan Cheng0fc80842010-11-12 22:42:47 +00002363 SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32);
Evan Cheng81a28512009-11-20 00:54:03 +00002364 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2365 SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002366 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Cheng81a28512009-11-20 00:54:03 +00002367 }
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002368
Evan Cheng81a28512009-11-20 00:54:03 +00002369 return 0;
2370}
2371
2372SDNode *ARMDAGToDAGISel::
Jim Grosbach742adc32010-10-07 00:42:42 +00002373SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
Evan Cheng39c81c02010-11-17 20:56:30 +00002374 ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) {
Evan Cheng81a28512009-11-20 00:54:03 +00002375 ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal);
2376 if (!T)
2377 return 0;
2378
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002379 unsigned Opc = 0;
Jim Grosbach742adc32010-10-07 00:42:42 +00002380 unsigned TrueImm = T->getZExtValue();
Evan Cheng0fc80842010-11-12 22:42:47 +00002381 bool isSoImm = is_so_imm(TrueImm);
Evan Cheng39c81c02010-11-17 20:56:30 +00002382 if (isSoImm) {
2383 Opc = ARM::MOVCCi;
2384 } else if (Subtarget->hasV6T2Ops() && TrueImm <= 0xffff) {
2385 Opc = ARM::MOVCCi16;
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002386 } else if (is_so_imm_not(TrueImm)) {
2387 TrueImm = ~TrueImm;
2388 Opc = ARM::MVNCCi;
Evan Cheng39c81c02010-11-17 20:56:30 +00002389 } else if (TrueVal.getNode()->hasOneUse() &&
2390 (Subtarget->hasV6T2Ops() || ARM_AM::isSOImmTwoPartVal(TrueImm))) {
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002391 // Large immediate.
2392 Opc = ARM::MOVCCi32imm;
2393 }
2394
2395 if (Opc) {
Jim Grosbach742adc32010-10-07 00:42:42 +00002396 SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32);
Evan Cheng81a28512009-11-20 00:54:03 +00002397 SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
2398 SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag };
Evan Cheng2bcb8da2010-11-13 02:25:14 +00002399 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Cheng81a28512009-11-20 00:54:03 +00002400 }
Andrew Trickc416ba62010-12-24 04:28:06 +00002401
Evan Cheng81a28512009-11-20 00:54:03 +00002402 return 0;
2403}
2404
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002405SDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) {
2406 EVT VT = N->getValueType(0);
2407 SDValue FalseVal = N->getOperand(0);
2408 SDValue TrueVal = N->getOperand(1);
2409 SDValue CC = N->getOperand(2);
2410 SDValue CCR = N->getOperand(3);
2411 SDValue InFlag = N->getOperand(4);
Evan Cheng81a28512009-11-20 00:54:03 +00002412 assert(CC.getOpcode() == ISD::Constant);
2413 assert(CCR.getOpcode() == ISD::Register);
2414 ARMCC::CondCodes CCVal =
2415 (ARMCC::CondCodes)cast<ConstantSDNode>(CC)->getZExtValue();
Evan Chengb6c77042009-11-19 21:45:22 +00002416
2417 if (!Subtarget->isThumb1Only() && VT == MVT::i32) {
2418 // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
2419 // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc)
2420 // Pattern complexity = 18 cost = 1 size = 0
Evan Chengb6c77042009-11-19 21:45:22 +00002421 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002422 SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002423 CCVal, CCR, InFlag);
2424 if (!Res)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002425 Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002426 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2427 if (Res)
2428 return Res;
Evan Chengb6c77042009-11-19 21:45:22 +00002429 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002430 SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002431 CCVal, CCR, InFlag);
2432 if (!Res)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002433 Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002434 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2435 if (Res)
2436 return Res;
Evan Chengb6c77042009-11-19 21:45:22 +00002437 }
2438
2439 // Pattern: (ARMcmov:i32 GPR:i32:$false,
Jakob Stoklund Olesene2cbaf62010-08-17 20:39:04 +00002440 // (imm:i32)<<P:Pred_so_imm>>:$true,
Evan Chengb6c77042009-11-19 21:45:22 +00002441 // (imm:i32):$cc)
2442 // Emits: (MOVCCi:i32 GPR:i32:$false,
2443 // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc)
2444 // Pattern complexity = 10 cost = 1 size = 0
Evan Cheng81a28512009-11-20 00:54:03 +00002445 if (Subtarget->isThumb()) {
Jim Grosbach5b255c22010-10-07 00:53:56 +00002446 SDNode *Res = SelectT2CMOVImmOp(N, FalseVal, TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002447 CCVal, CCR, InFlag);
2448 if (!Res)
Jim Grosbach5b255c22010-10-07 00:53:56 +00002449 Res = SelectT2CMOVImmOp(N, TrueVal, FalseVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002450 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2451 if (Res)
2452 return Res;
2453 } else {
Jim Grosbach742adc32010-10-07 00:42:42 +00002454 SDNode *Res = SelectARMCMOVImmOp(N, FalseVal, TrueVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002455 CCVal, CCR, InFlag);
2456 if (!Res)
Jim Grosbach742adc32010-10-07 00:42:42 +00002457 Res = SelectARMCMOVImmOp(N, TrueVal, FalseVal,
Evan Cheng81a28512009-11-20 00:54:03 +00002458 ARMCC::getOppositeCondition(CCVal), CCR, InFlag);
2459 if (Res)
2460 return Res;
Evan Chengb6c77042009-11-19 21:45:22 +00002461 }
2462 }
2463
2464 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2465 // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2466 // Pattern complexity = 6 cost = 1 size = 0
2467 //
2468 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2469 // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc)
2470 // Pattern complexity = 6 cost = 11 size = 0
2471 //
Jim Grosbach2fee5322011-03-11 23:15:02 +00002472 // Also VMOVScc and VMOVDcc.
Evan Cheng81a28512009-11-20 00:54:03 +00002473 SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32);
2474 SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag };
Evan Chengb6c77042009-11-19 21:45:22 +00002475 unsigned Opc = 0;
2476 switch (VT.getSimpleVT().SimpleTy) {
Craig Toppere55c5562012-02-07 02:50:20 +00002477 default: llvm_unreachable("Illegal conditional move type!");
Evan Chengb6c77042009-11-19 21:45:22 +00002478 case MVT::i32:
2479 Opc = Subtarget->isThumb()
2480 ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo)
2481 : ARM::MOVCCr;
2482 break;
2483 case MVT::f32:
2484 Opc = ARM::VMOVScc;
2485 break;
2486 case MVT::f64:
2487 Opc = ARM::VMOVDcc;
2488 break;
2489 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002490 return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5);
Evan Chengb6c77042009-11-19 21:45:22 +00002491}
2492
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002493/// Target-specific DAG combining for ISD::XOR.
2494/// Target-independent combining lowers SELECT_CC nodes of the form
2495/// select_cc setg[ge] X, 0, X, -X
2496/// select_cc setgt X, -1, X, -X
2497/// select_cc setl[te] X, 0, -X, X
2498/// select_cc setlt X, 1, -X, X
2499/// which represent Integer ABS into:
2500/// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
2501/// ARM instruction selection detects the latter and matches it to
2502/// ARM::ABS or ARM::t2ABS machine node.
2503SDNode *ARMDAGToDAGISel::SelectABSOp(SDNode *N){
2504 SDValue XORSrc0 = N->getOperand(0);
2505 SDValue XORSrc1 = N->getOperand(1);
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002506 EVT VT = N->getValueType(0);
2507
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002508 if (Subtarget->isThumb1Only())
2509 return NULL;
2510
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002511 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA)
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002512 return NULL;
2513
2514 SDValue ADDSrc0 = XORSrc0.getOperand(0);
2515 SDValue ADDSrc1 = XORSrc0.getOperand(1);
2516 SDValue SRASrc0 = XORSrc1.getOperand(0);
2517 SDValue SRASrc1 = XORSrc1.getOperand(1);
2518 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1);
2519 EVT XType = SRASrc0.getValueType();
2520 unsigned Size = XType.getSizeInBits() - 1;
2521
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002522 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 &&
2523 XType.isInteger() && SRAConstant != NULL &&
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002524 Size == SRAConstant->getZExtValue()) {
Jim Grosbachb437a8c2012-08-01 20:33:00 +00002525 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS;
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002526 return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0);
2527 }
2528
2529 return NULL;
2530}
2531
Evan Chengd85631e2010-05-05 18:28:36 +00002532SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
2533 // The only time a CONCAT_VECTORS operation can have legal types is when
2534 // two 64-bit vectors are concatenated to a 128-bit vector.
2535 EVT VT = N->getValueType(0);
2536 if (!VT.is128BitVector() || N->getNumOperands() != 2)
2537 llvm_unreachable("unexpected CONCAT_VECTORS");
Weiming Zhao95782222012-11-17 00:23:35 +00002538 return createDRegPairNode(VT, N->getOperand(0), N->getOperand(1));
Evan Chengd85631e2010-05-05 18:28:36 +00002539}
2540
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +00002541SDNode *ARMDAGToDAGISel::SelectAtomic64(SDNode *Node, unsigned Opc) {
Eli Friedman1ccecbb2011-08-31 17:52:22 +00002542 SmallVector<SDValue, 6> Ops;
2543 Ops.push_back(Node->getOperand(1)); // Ptr
2544 Ops.push_back(Node->getOperand(2)); // Low part of Val1
2545 Ops.push_back(Node->getOperand(3)); // High part of Val1
Owen Anderson939cd212011-08-31 20:00:11 +00002546 if (Opc == ARM::ATOMCMPXCHG6432) {
Eli Friedman1ccecbb2011-08-31 17:52:22 +00002547 Ops.push_back(Node->getOperand(4)); // Low part of Val2
2548 Ops.push_back(Node->getOperand(5)); // High part of Val2
2549 }
2550 Ops.push_back(Node->getOperand(0)); // Chain
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +00002551 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
2552 MemOp[0] = cast<MemSDNode>(Node)->getMemOperand();
Andrew Trickef9de2a2013-05-25 02:42:55 +00002553 SDNode *ResNode = CurDAG->getMachineNode(Opc, SDLoc(Node),
Eli Friedman1ccecbb2011-08-31 17:52:22 +00002554 MVT::i32, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002555 Ops);
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +00002556 cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp + 1);
2557 return ResNode;
2558}
2559
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002560SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00002561 SDLoc dl(N);
Evan Cheng10043e22007-01-19 07:51:42 +00002562
Dan Gohman17059682008-07-17 19:10:17 +00002563 if (N->isMachineOpcode())
Evan Cheng10043e22007-01-19 07:51:42 +00002564 return NULL; // Already selected.
Rafael Espindola4e760152006-06-12 12:28:08 +00002565
2566 switch (N->getOpcode()) {
Evan Cheng10043e22007-01-19 07:51:42 +00002567 default: break;
Weiming Zhaoc5987002013-02-14 18:10:21 +00002568 case ISD::INLINEASM: {
2569 SDNode *ResNode = SelectInlineAsm(N);
2570 if (ResNode)
2571 return ResNode;
2572 break;
2573 }
Bill Wendlinga7d697e2011-10-10 22:59:55 +00002574 case ISD::XOR: {
2575 // Select special operations if XOR node forms integer ABS pattern
2576 SDNode *ResNode = SelectABSOp(N);
2577 if (ResNode)
2578 return ResNode;
2579 // Other cases are autogenerated.
2580 break;
2581 }
Evan Cheng10043e22007-01-19 07:51:42 +00002582 case ISD::Constant: {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002583 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002584 bool UseCP = true;
Anton Korobeynikov7c2b1e72009-09-27 23:52:58 +00002585 if (Subtarget->hasThumb2())
2586 // Thumb2-aware targets have the MOVT instruction, so all immediates can
2587 // be done with MOV + MOVT, at worst.
2588 UseCP = 0;
2589 else {
2590 if (Subtarget->isThumb()) {
Bob Wilson360eef02009-06-22 17:29:13 +00002591 UseCP = (Val > 255 && // MOV
2592 ~Val > 255 && // MOV + MVN
2593 !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL
Anton Korobeynikov7c2b1e72009-09-27 23:52:58 +00002594 } else
2595 UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV
2596 ARM_AM::getSOImmVal(~Val) == -1 && // MVN
2597 !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs.
2598 }
2599
Evan Cheng10043e22007-01-19 07:51:42 +00002600 if (UseCP) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002601 SDValue CPIdx =
Owen Anderson55f1c092009-08-13 21:58:54 +00002602 CurDAG->getTargetConstantPool(ConstantInt::get(
2603 Type::getInt32Ty(*CurDAG->getContext()), Val),
Bill Wendlinga3cd3502013-06-19 21:36:55 +00002604 getTargetLowering()->getPointerTy());
Evan Cheng1526ba52007-01-24 08:53:17 +00002605
2606 SDNode *ResNode;
Evan Chengcd4cdd12009-07-11 06:43:01 +00002607 if (Subtarget->isThumb1Only()) {
Evan Cheng3da64f762010-04-16 05:46:06 +00002608 SDValue Pred = getAL(CurDAG);
Owen Anderson9f944592009-08-11 20:47:22 +00002609 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002610 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
Jim Grosbachbfef3092010-12-15 23:52:36 +00002611 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002612 Ops);
Evan Chengcd4cdd12009-07-11 06:43:01 +00002613 } else {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002614 SDValue Ops[] = {
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002615 CPIdx,
Owen Anderson9f944592009-08-11 20:47:22 +00002616 CurDAG->getTargetConstant(0, MVT::i32),
Evan Cheng7e90b112007-07-05 07:15:27 +00002617 getAL(CurDAG),
Owen Anderson9f944592009-08-11 20:47:22 +00002618 CurDAG->getRegister(0, MVT::i32),
Evan Cheng1526ba52007-01-24 08:53:17 +00002619 CurDAG->getEntryNode()
2620 };
Dan Gohman32f71d72009-09-25 18:54:59 +00002621 ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002622 Ops);
Evan Cheng1526ba52007-01-24 08:53:17 +00002623 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002624 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
Evan Cheng10043e22007-01-19 07:51:42 +00002625 return NULL;
2626 }
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002627
Evan Cheng10043e22007-01-19 07:51:42 +00002628 // Other cases are autogenerated.
Rafael Espindola4e760152006-06-12 12:28:08 +00002629 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002630 }
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002631 case ISD::FrameIndex: {
Evan Cheng10043e22007-01-19 07:51:42 +00002632 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002633 int FI = cast<FrameIndexSDNode>(N)->getIndex();
Bill Wendlinga3cd3502013-06-19 21:36:55 +00002634 SDValue TFI = CurDAG->getTargetFrameIndex(FI,
2635 getTargetLowering()->getPointerTy());
David Goodwin22c2fba2009-07-08 23:10:31 +00002636 if (Subtarget->isThumb1Only()) {
Jim Grosbach1b8457a2011-08-24 17:46:13 +00002637 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
2638 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2639 return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, Ops, 4);
Jim Grosbachfde21102009-04-07 20:34:09 +00002640 } else {
David Goodwin4ad77972009-07-14 18:48:51 +00002641 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
2642 ARM::t2ADDri : ARM::ADDri);
Owen Anderson9f944592009-08-11 20:47:22 +00002643 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
2644 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2645 CurDAG->getRegister(0, MVT::i32) };
2646 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
Evan Cheng7e90b112007-07-05 07:15:27 +00002647 }
Evan Cheng10043e22007-01-19 07:51:42 +00002648 }
Sandeep Patel423e42b2009-10-13 18:59:48 +00002649 case ISD::SRL:
Jim Grosbach825cb292010-04-22 23:24:18 +00002650 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
Sandeep Patel423e42b2009-10-13 18:59:48 +00002651 return I;
2652 break;
2653 case ISD::SRA:
Jim Grosbach825cb292010-04-22 23:24:18 +00002654 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true))
Sandeep Patel423e42b2009-10-13 18:59:48 +00002655 return I;
2656 break;
Evan Cheng10043e22007-01-19 07:51:42 +00002657 case ISD::MUL:
Evan Chengb24e51e2009-07-07 01:17:28 +00002658 if (Subtarget->isThumb1Only())
Evan Cheng139edae2007-01-24 02:21:22 +00002659 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002660 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
Dan Gohmaneffb8942008-09-12 16:56:44 +00002661 unsigned RHSV = C->getZExtValue();
Evan Cheng10043e22007-01-19 07:51:42 +00002662 if (!RHSV) break;
2663 if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002664 unsigned ShImm = Log2_32(RHSV-1);
2665 if (ShImm >= 32)
2666 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002667 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002668 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson9f944592009-08-11 20:47:22 +00002669 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
2670 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002671 if (Subtarget->isThumb()) {
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002672 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Anderson9f944592009-08-11 20:47:22 +00002673 return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002674 } else {
2675 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Andersonb595ed02011-07-21 18:54:16 +00002676 return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops, 7);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002677 }
Evan Cheng10043e22007-01-19 07:51:42 +00002678 }
2679 if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002680 unsigned ShImm = Log2_32(RHSV+1);
2681 if (ShImm >= 32)
2682 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002683 SDValue V = N->getOperand(0);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002684 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
Owen Anderson9f944592009-08-11 20:47:22 +00002685 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32);
2686 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
Evan Cheng1ec43962009-07-22 18:08:05 +00002687 if (Subtarget->isThumb()) {
Bob Wilsonb6112e82010-05-28 00:27:15 +00002688 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
2689 return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 6);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002690 } else {
2691 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
Owen Andersonb595ed02011-07-21 18:54:16 +00002692 return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops, 7);
Evan Cheng0d8b0cf2009-07-21 00:31:12 +00002693 }
Evan Cheng10043e22007-01-19 07:51:42 +00002694 }
2695 }
2696 break;
Evan Cheng786b15f2009-10-21 08:15:52 +00002697 case ISD::AND: {
Jim Grosbach825cb292010-04-22 23:24:18 +00002698 // Check for unsigned bitfield extract
2699 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
2700 return I;
2701
Evan Cheng786b15f2009-10-21 08:15:52 +00002702 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
2703 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
2704 // are entirely contributed by c2 and lower 16-bits are entirely contributed
2705 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)).
2706 // Select it to: "movt x, ((c1 & 0xffff) >> 16)
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002707 EVT VT = N->getValueType(0);
Evan Cheng786b15f2009-10-21 08:15:52 +00002708 if (VT != MVT::i32)
2709 break;
2710 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2())
2711 ? ARM::t2MOVTi16
2712 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0);
2713 if (!Opc)
2714 break;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002715 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
Evan Cheng786b15f2009-10-21 08:15:52 +00002716 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
2717 if (!N1C)
2718 break;
2719 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {
2720 SDValue N2 = N0.getOperand(1);
2721 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
2722 if (!N2C)
2723 break;
2724 unsigned N1CVal = N1C->getZExtValue();
2725 unsigned N2CVal = N2C->getZExtValue();
2726 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) &&
2727 (N1CVal & 0xffffU) == 0xffffU &&
2728 (N2CVal & 0xffffU) == 0x0U) {
2729 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16,
2730 MVT::i32);
2731 SDValue Ops[] = { N0.getOperand(0), Imm16,
2732 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002733 return CurDAG->getMachineNode(Opc, dl, VT, Ops);
Evan Cheng786b15f2009-10-21 08:15:52 +00002734 }
2735 }
2736 break;
2737 }
Jim Grosbachd7cf55c2009-11-09 00:11:35 +00002738 case ARMISD::VMOVRRD:
2739 return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002740 N->getOperand(0), getAL(CurDAG),
Dan Gohman32f71d72009-09-25 18:54:59 +00002741 CurDAG->getRegister(0, MVT::i32));
Dan Gohmana1603612007-10-08 18:33:35 +00002742 case ISD::UMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002743 if (Subtarget->isThumb1Only())
2744 break;
2745 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002746 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Michael Liaob53d8962013-04-19 22:22:57 +00002747 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
2748 return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002749 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002750 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson9f944592009-08-11 20:47:22 +00002751 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2752 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov62acecd2011-01-01 20:38:38 +00002753 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2754 ARM::UMULL : ARM::UMULLv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002755 dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002756 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002757 }
Dan Gohmana1603612007-10-08 18:33:35 +00002758 case ISD::SMUL_LOHI: {
Evan Chengb24e51e2009-07-07 01:17:28 +00002759 if (Subtarget->isThumb1Only())
2760 break;
2761 if (Subtarget->isThumb()) {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002762 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson9f944592009-08-11 20:47:22 +00002763 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
Michael Liaob53d8962013-04-19 22:22:57 +00002764 return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002765 } else {
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002766 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
Owen Anderson9f944592009-08-11 20:47:22 +00002767 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
2768 CurDAG->getRegister(0, MVT::i32) };
Anton Korobeynikov62acecd2011-01-01 20:38:38 +00002769 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2770 ARM::SMULL : ARM::SMULLv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002771 dl, MVT::i32, MVT::i32, Ops);
Evan Chengb24e51e2009-07-07 01:17:28 +00002772 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002773 }
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002774 case ARMISD::UMLAL:{
2775 if (Subtarget->isThumb()) {
2776 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2777 N->getOperand(3), getAL(CurDAG),
2778 CurDAG->getRegister(0, MVT::i32)};
Michael Liaob53d8962013-04-19 22:22:57 +00002779 return CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002780 }else{
2781 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2782 N->getOperand(3), getAL(CurDAG),
2783 CurDAG->getRegister(0, MVT::i32),
2784 CurDAG->getRegister(0, MVT::i32) };
2785 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2786 ARM::UMLAL : ARM::UMLALv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002787 dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002788 }
2789 }
2790 case ARMISD::SMLAL:{
2791 if (Subtarget->isThumb()) {
2792 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2793 N->getOperand(3), getAL(CurDAG),
2794 CurDAG->getRegister(0, MVT::i32)};
Michael Liaob53d8962013-04-19 22:22:57 +00002795 return CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002796 }else{
2797 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
2798 N->getOperand(3), getAL(CurDAG),
2799 CurDAG->getRegister(0, MVT::i32),
2800 CurDAG->getRegister(0, MVT::i32) };
2801 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
2802 ARM::SMLAL : ARM::SMLALv5,
Michael Liaob53d8962013-04-19 22:22:57 +00002803 dl, MVT::i32, MVT::i32, Ops);
Arnold Schwaighoferf00fb1c2012-09-04 14:37:49 +00002804 }
2805 }
Evan Cheng10043e22007-01-19 07:51:42 +00002806 case ISD::LOAD: {
Evan Cheng84c6cda2009-07-02 07:28:31 +00002807 SDNode *ResNode = 0;
Evan Chengb24e51e2009-07-07 01:17:28 +00002808 if (Subtarget->isThumb() && Subtarget->hasThumb2())
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002809 ResNode = SelectT2IndexedLoad(N);
Evan Cheng84c6cda2009-07-02 07:28:31 +00002810 else
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002811 ResNode = SelectARMIndexedLoad(N);
Evan Chengd9c55362009-07-02 01:23:32 +00002812 if (ResNode)
2813 return ResNode;
Evan Cheng10043e22007-01-19 07:51:42 +00002814 // Other cases are autogenerated.
Rafael Espindola5f7ab1b2006-11-09 13:58:55 +00002815 break;
Rafael Espindola4e760152006-06-12 12:28:08 +00002816 }
Evan Cheng7e90b112007-07-05 07:15:27 +00002817 case ARMISD::BRCOND: {
2818 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2819 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2820 // Pattern complexity = 6 cost = 1 size = 0
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00002821
Evan Cheng7e90b112007-07-05 07:15:27 +00002822 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2823 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc)
2824 // Pattern complexity = 6 cost = 1 size = 0
2825
David Goodwin27303cd2009-06-30 18:04:13 +00002826 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc)
2827 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc)
2828 // Pattern complexity = 6 cost = 1 size = 0
2829
Jim Grosbachf24f9d92009-08-11 15:33:49 +00002830 unsigned Opc = Subtarget->isThumb() ?
David Goodwin27303cd2009-06-30 18:04:13 +00002831 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc;
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002832 SDValue Chain = N->getOperand(0);
2833 SDValue N1 = N->getOperand(1);
2834 SDValue N2 = N->getOperand(2);
2835 SDValue N3 = N->getOperand(3);
2836 SDValue InFlag = N->getOperand(4);
Evan Cheng7e90b112007-07-05 07:15:27 +00002837 assert(N1.getOpcode() == ISD::BasicBlock);
2838 assert(N2.getOpcode() == ISD::Constant);
2839 assert(N3.getOpcode() == ISD::Register);
2840
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002841 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
Dan Gohmaneffb8942008-09-12 16:56:44 +00002842 cast<ConstantSDNode>(N2)->getZExtValue()),
Owen Anderson9f944592009-08-11 20:47:22 +00002843 MVT::i32);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002844 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag };
Dan Gohman32f71d72009-09-25 18:54:59 +00002845 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
Michael Liaob53d8962013-04-19 22:22:57 +00002846 MVT::Glue, Ops);
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002847 Chain = SDValue(ResNode, 0);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002848 if (N->getNumValues() == 2) {
Dan Gohman2ce6f2a2008-07-27 21:46:04 +00002849 InFlag = SDValue(ResNode, 1);
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002850 ReplaceUses(SDValue(N, 1), InFlag);
Chris Lattnere99faac2008-02-03 03:20:59 +00002851 }
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002852 ReplaceUses(SDValue(N, 0),
Evan Cheng82adca82009-11-19 08:16:50 +00002853 SDValue(Chain.getNode(), Chain.getResNo()));
Evan Cheng7e90b112007-07-05 07:15:27 +00002854 return NULL;
2855 }
Evan Chengb6c77042009-11-19 21:45:22 +00002856 case ARMISD::CMOV:
Dan Gohmanea6f91f2010-01-05 01:24:18 +00002857 return SelectCMOVOp(N);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002858 case ARMISD::VZIP: {
2859 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002860 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002861 switch (VT.getSimpleVT().SimpleTy) {
2862 default: return NULL;
2863 case MVT::v8i8: Opc = ARM::VZIPd8; break;
2864 case MVT::v4i16: Opc = ARM::VZIPd16; break;
2865 case MVT::v2f32:
Jim Grosbach4640c812012-04-11 16:53:25 +00002866 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2867 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002868 case MVT::v16i8: Opc = ARM::VZIPq8; break;
2869 case MVT::v8i16: Opc = ARM::VZIPq16; break;
2870 case MVT::v4f32:
2871 case MVT::v4i32: Opc = ARM::VZIPq32; break;
2872 }
Evan Cheng3da64f762010-04-16 05:46:06 +00002873 SDValue Pred = getAL(CurDAG);
Evan Chenga33fc862009-11-21 06:21:52 +00002874 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2875 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002876 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002877 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002878 case ARMISD::VUZP: {
2879 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002880 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002881 switch (VT.getSimpleVT().SimpleTy) {
2882 default: return NULL;
2883 case MVT::v8i8: Opc = ARM::VUZPd8; break;
2884 case MVT::v4i16: Opc = ARM::VUZPd16; break;
2885 case MVT::v2f32:
Jim Grosbach6e536de2012-04-11 17:40:18 +00002886 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm.
2887 case MVT::v2i32: Opc = ARM::VTRNd32; break;
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002888 case MVT::v16i8: Opc = ARM::VUZPq8; break;
2889 case MVT::v8i16: Opc = ARM::VUZPq16; break;
2890 case MVT::v4f32:
2891 case MVT::v4i32: Opc = ARM::VUZPq32; break;
2892 }
Evan Cheng3da64f762010-04-16 05:46:06 +00002893 SDValue Pred = getAL(CurDAG);
Evan Chenga33fc862009-11-21 06:21:52 +00002894 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2895 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002896 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002897 }
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002898 case ARMISD::VTRN: {
2899 unsigned Opc = 0;
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002900 EVT VT = N->getValueType(0);
Anton Korobeynikov232b19c2009-08-21 12:41:42 +00002901 switch (VT.getSimpleVT().SimpleTy) {
2902 default: return NULL;
2903 case MVT::v8i8: Opc = ARM::VTRNd8; break;
2904 case MVT::v4i16: Opc = ARM::VTRNd16; break;
2905 case MVT::v2f32:
2906 case MVT::v2i32: Opc = ARM::VTRNd32; break;
2907 case MVT::v16i8: Opc = ARM::VTRNq8; break;
2908 case MVT::v8i16: Opc = ARM::VTRNq16; break;
2909 case MVT::v4f32:
2910 case MVT::v4i32: Opc = ARM::VTRNq32; break;
2911 }
Evan Cheng3da64f762010-04-16 05:46:06 +00002912 SDValue Pred = getAL(CurDAG);
Evan Chenga33fc862009-11-21 06:21:52 +00002913 SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
2914 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg };
Michael Liaob53d8962013-04-19 22:22:57 +00002915 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops);
Anton Korobeynikovce3ff1b2009-08-21 12:40:50 +00002916 }
Bob Wilsond8a9a042010-06-04 00:04:02 +00002917 case ARMISD::BUILD_VECTOR: {
2918 EVT VecVT = N->getValueType(0);
2919 EVT EltVT = VecVT.getVectorElementType();
2920 unsigned NumElts = VecVT.getVectorNumElements();
Duncan Sands14627772010-11-03 12:17:33 +00002921 if (EltVT == MVT::f64) {
Bob Wilsond8a9a042010-06-04 00:04:02 +00002922 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR");
Weiming Zhao95782222012-11-17 00:23:35 +00002923 return createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilsond8a9a042010-06-04 00:04:02 +00002924 }
Duncan Sands14627772010-11-03 12:17:33 +00002925 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR");
Bob Wilsond8a9a042010-06-04 00:04:02 +00002926 if (NumElts == 2)
Weiming Zhao95782222012-11-17 00:23:35 +00002927 return createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1));
Bob Wilsond8a9a042010-06-04 00:04:02 +00002928 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR");
Weiming Zhao95782222012-11-17 00:23:35 +00002929 return createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1),
Bob Wilsond8a9a042010-06-04 00:04:02 +00002930 N->getOperand(2), N->getOperand(3));
2931 }
Bob Wilsone0636a72009-08-26 17:39:53 +00002932
Bob Wilson2d790df2010-11-28 06:51:26 +00002933 case ARMISD::VLD2DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002934 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16,
2935 ARM::VLD2DUPd32 };
Bob Wilson06fce872011-02-07 17:43:21 +00002936 return SelectVLDDup(N, false, 2, Opcodes);
Bob Wilson2d790df2010-11-28 06:51:26 +00002937 }
2938
Bob Wilson77ab1652010-11-29 19:35:29 +00002939 case ARMISD::VLD3DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002940 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo,
2941 ARM::VLD3DUPd16Pseudo,
2942 ARM::VLD3DUPd32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00002943 return SelectVLDDup(N, false, 3, Opcodes);
Bob Wilson77ab1652010-11-29 19:35:29 +00002944 }
2945
Bob Wilson431ac4ef2010-11-30 00:00:35 +00002946 case ARMISD::VLD4DUP: {
Craig Topper01736f82012-05-24 05:17:00 +00002947 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo,
2948 ARM::VLD4DUPd16Pseudo,
2949 ARM::VLD4DUPd32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00002950 return SelectVLDDup(N, false, 4, Opcodes);
2951 }
2952
2953 case ARMISD::VLD2DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002954 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed,
2955 ARM::VLD2DUPd16wb_fixed,
2956 ARM::VLD2DUPd32wb_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00002957 return SelectVLDDup(N, true, 2, Opcodes);
2958 }
2959
2960 case ARMISD::VLD3DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002961 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD,
2962 ARM::VLD3DUPd16Pseudo_UPD,
2963 ARM::VLD3DUPd32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002964 return SelectVLDDup(N, true, 3, Opcodes);
2965 }
2966
2967 case ARMISD::VLD4DUP_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002968 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD,
2969 ARM::VLD4DUPd16Pseudo_UPD,
2970 ARM::VLD4DUPd32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00002971 return SelectVLDDup(N, true, 4, Opcodes);
2972 }
2973
2974 case ARMISD::VLD1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002975 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed,
2976 ARM::VLD1d16wb_fixed,
2977 ARM::VLD1d32wb_fixed,
2978 ARM::VLD1d64wb_fixed };
2979 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed,
2980 ARM::VLD1q16wb_fixed,
2981 ARM::VLD1q32wb_fixed,
2982 ARM::VLD1q64wb_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00002983 return SelectVLD(N, true, 1, DOpcodes, QOpcodes, 0);
2984 }
2985
2986 case ARMISD::VLD2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002987 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed,
2988 ARM::VLD2d16wb_fixed,
2989 ARM::VLD2d32wb_fixed,
2990 ARM::VLD1q64wb_fixed};
2991 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed,
2992 ARM::VLD2q16PseudoWB_fixed,
2993 ARM::VLD2q32PseudoWB_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00002994 return SelectVLD(N, true, 2, DOpcodes, QOpcodes, 0);
2995 }
2996
2997 case ARMISD::VLD3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00002998 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD,
2999 ARM::VLD3d16Pseudo_UPD,
3000 ARM::VLD3d32Pseudo_UPD,
3001 ARM::VLD1q64wb_fixed};
3002 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3003 ARM::VLD3q16Pseudo_UPD,
3004 ARM::VLD3q32Pseudo_UPD };
3005 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD,
3006 ARM::VLD3q16oddPseudo_UPD,
3007 ARM::VLD3q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003008 return SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3009 }
3010
3011 case ARMISD::VLD4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003012 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD,
3013 ARM::VLD4d16Pseudo_UPD,
3014 ARM::VLD4d32Pseudo_UPD,
3015 ARM::VLD1q64wb_fixed};
3016 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3017 ARM::VLD4q16Pseudo_UPD,
3018 ARM::VLD4q32Pseudo_UPD };
3019 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD,
3020 ARM::VLD4q16oddPseudo_UPD,
3021 ARM::VLD4q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003022 return SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3023 }
3024
3025 case ARMISD::VLD2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003026 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD,
3027 ARM::VLD2LNd16Pseudo_UPD,
3028 ARM::VLD2LNd32Pseudo_UPD };
3029 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD,
3030 ARM::VLD2LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003031 return SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes);
3032 }
3033
3034 case ARMISD::VLD3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003035 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD,
3036 ARM::VLD3LNd16Pseudo_UPD,
3037 ARM::VLD3LNd32Pseudo_UPD };
3038 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD,
3039 ARM::VLD3LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003040 return SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes);
3041 }
3042
3043 case ARMISD::VLD4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003044 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD,
3045 ARM::VLD4LNd16Pseudo_UPD,
3046 ARM::VLD4LNd32Pseudo_UPD };
3047 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD,
3048 ARM::VLD4LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003049 return SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes);
3050 }
3051
3052 case ARMISD::VST1_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003053 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed,
3054 ARM::VST1d16wb_fixed,
3055 ARM::VST1d32wb_fixed,
3056 ARM::VST1d64wb_fixed };
3057 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed,
3058 ARM::VST1q16wb_fixed,
3059 ARM::VST1q32wb_fixed,
3060 ARM::VST1q64wb_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00003061 return SelectVST(N, true, 1, DOpcodes, QOpcodes, 0);
3062 }
3063
3064 case ARMISD::VST2_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003065 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed,
3066 ARM::VST2d16wb_fixed,
3067 ARM::VST2d32wb_fixed,
3068 ARM::VST1q64wb_fixed};
3069 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed,
3070 ARM::VST2q16PseudoWB_fixed,
3071 ARM::VST2q32PseudoWB_fixed };
Bob Wilson06fce872011-02-07 17:43:21 +00003072 return SelectVST(N, true, 2, DOpcodes, QOpcodes, 0);
3073 }
3074
3075 case ARMISD::VST3_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003076 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD,
3077 ARM::VST3d16Pseudo_UPD,
3078 ARM::VST3d32Pseudo_UPD,
3079 ARM::VST1d64TPseudoWB_fixed};
3080 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3081 ARM::VST3q16Pseudo_UPD,
3082 ARM::VST3q32Pseudo_UPD };
3083 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD,
3084 ARM::VST3q16oddPseudo_UPD,
3085 ARM::VST3q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003086 return SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
3087 }
3088
3089 case ARMISD::VST4_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003090 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD,
3091 ARM::VST4d16Pseudo_UPD,
3092 ARM::VST4d32Pseudo_UPD,
3093 ARM::VST1d64QPseudoWB_fixed};
3094 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3095 ARM::VST4q16Pseudo_UPD,
3096 ARM::VST4q32Pseudo_UPD };
3097 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD,
3098 ARM::VST4q16oddPseudo_UPD,
3099 ARM::VST4q32oddPseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003100 return SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
3101 }
3102
3103 case ARMISD::VST2LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003104 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD,
3105 ARM::VST2LNd16Pseudo_UPD,
3106 ARM::VST2LNd32Pseudo_UPD };
3107 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD,
3108 ARM::VST2LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003109 return SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes);
3110 }
3111
3112 case ARMISD::VST3LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003113 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD,
3114 ARM::VST3LNd16Pseudo_UPD,
3115 ARM::VST3LNd32Pseudo_UPD };
3116 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD,
3117 ARM::VST3LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003118 return SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes);
3119 }
3120
3121 case ARMISD::VST4LN_UPD: {
Craig Topper01736f82012-05-24 05:17:00 +00003122 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD,
3123 ARM::VST4LNd16Pseudo_UPD,
3124 ARM::VST4LNd32Pseudo_UPD };
3125 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD,
3126 ARM::VST4LNq32Pseudo_UPD };
Bob Wilson06fce872011-02-07 17:43:21 +00003127 return SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes);
Bob Wilson431ac4ef2010-11-30 00:00:35 +00003128 }
3129
Bob Wilsone0636a72009-08-26 17:39:53 +00003130 case ISD::INTRINSIC_VOID:
3131 case ISD::INTRINSIC_W_CHAIN: {
3132 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Bob Wilsone0636a72009-08-26 17:39:53 +00003133 switch (IntNo) {
3134 default:
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003135 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003136
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003137 case Intrinsic::arm_ldrexd: {
3138 SDValue MemAddr = N->getOperand(2);
Andrew Trickef9de2a2013-05-25 02:42:55 +00003139 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003140 SDValue Chain = N->getOperand(0);
3141
Weiming Zhao8f56f882012-11-16 21:55:34 +00003142 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3143 unsigned NewOpc = isThumb ? ARM::t2LDREXD :ARM::LDREXD;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003144
3145 // arm_ldrexd returns a i64 value in {i32, i32}
3146 std::vector<EVT> ResTys;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003147 if (isThumb) {
3148 ResTys.push_back(MVT::i32);
3149 ResTys.push_back(MVT::i32);
3150 } else
3151 ResTys.push_back(MVT::Untyped);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003152 ResTys.push_back(MVT::Other);
3153
Weiming Zhao8f56f882012-11-16 21:55:34 +00003154 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003155 SmallVector<SDValue, 7> Ops;
3156 Ops.push_back(MemAddr);
3157 Ops.push_back(getAL(CurDAG));
3158 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3159 Ops.push_back(Chain);
Michael Liaob53d8962013-04-19 22:22:57 +00003160 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003161 // Transfer memoperands.
3162 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3163 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3164 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1);
3165
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003166 // Remap uses.
Lang Hamesbe3d9712013-03-09 22:56:09 +00003167 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003168 if (!SDValue(N, 0).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003169 SDValue Result;
3170 if (isThumb)
3171 Result = SDValue(Ld, 0);
3172 else {
3173 SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32);
3174 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003175 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003176 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003177 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003178 ReplaceUses(SDValue(N, 0), Result);
3179 }
3180 if (!SDValue(N, 1).use_empty()) {
Weiming Zhao8f56f882012-11-16 21:55:34 +00003181 SDValue Result;
3182 if (isThumb)
3183 Result = SDValue(Ld, 1);
3184 else {
3185 SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32);
3186 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
Lang Hamesbe3d9712013-03-09 22:56:09 +00003187 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003188 Result = SDValue(ResNode,0);
Weiming Zhao8f56f882012-11-16 21:55:34 +00003189 }
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003190 ReplaceUses(SDValue(N, 1), Result);
3191 }
Lang Hamesbe3d9712013-03-09 22:56:09 +00003192 ReplaceUses(SDValue(N, 2), OutChain);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003193 return NULL;
3194 }
3195
3196 case Intrinsic::arm_strexd: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003197 SDLoc dl(N);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003198 SDValue Chain = N->getOperand(0);
3199 SDValue Val0 = N->getOperand(2);
3200 SDValue Val1 = N->getOperand(3);
3201 SDValue MemAddr = N->getOperand(4);
3202
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003203 // Store exclusive double return a i32 value which is the return status
3204 // of the issued store.
Benjamin Kramerfdf362b2013-03-07 20:33:29 +00003205 EVT ResTys[] = { MVT::i32, MVT::Other };
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003206
Weiming Zhao8f56f882012-11-16 21:55:34 +00003207 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
3208 // Place arguments in the right order.
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003209 SmallVector<SDValue, 7> Ops;
Weiming Zhao8f56f882012-11-16 21:55:34 +00003210 if (isThumb) {
3211 Ops.push_back(Val0);
3212 Ops.push_back(Val1);
3213 } else
3214 // arm_strexd uses GPRPair.
3215 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0));
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003216 Ops.push_back(MemAddr);
3217 Ops.push_back(getAL(CurDAG));
3218 Ops.push_back(CurDAG->getRegister(0, MVT::i32));
3219 Ops.push_back(Chain);
3220
Weiming Zhao8f56f882012-11-16 21:55:34 +00003221 unsigned NewOpc = isThumb ? ARM::t2STREXD : ARM::STREXD;
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003222
Michael Liaob53d8962013-04-19 22:22:57 +00003223 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops);
Bruno Cardoso Lopes325110f2011-05-28 04:07:29 +00003224 // Transfer memoperands.
3225 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
3226 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
3227 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1);
3228
3229 return St;
3230 }
3231
Bob Wilson340861d2010-03-23 05:25:43 +00003232 case Intrinsic::arm_neon_vld1: {
Craig Topper01736f82012-05-24 05:17:00 +00003233 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16,
3234 ARM::VLD1d32, ARM::VLD1d64 };
3235 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16,
3236 ARM::VLD1q32, ARM::VLD1q64};
Bob Wilson06fce872011-02-07 17:43:21 +00003237 return SelectVLD(N, false, 1, DOpcodes, QOpcodes, 0);
Bob Wilson340861d2010-03-23 05:25:43 +00003238 }
3239
Bob Wilsone0636a72009-08-26 17:39:53 +00003240 case Intrinsic::arm_neon_vld2: {
Craig Topper01736f82012-05-24 05:17:00 +00003241 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16,
3242 ARM::VLD2d32, ARM::VLD1q64 };
3243 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo,
3244 ARM::VLD2q32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003245 return SelectVLD(N, false, 2, DOpcodes, QOpcodes, 0);
Bob Wilsone0636a72009-08-26 17:39:53 +00003246 }
3247
3248 case Intrinsic::arm_neon_vld3: {
Craig Topper01736f82012-05-24 05:17:00 +00003249 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo,
3250 ARM::VLD3d16Pseudo,
3251 ARM::VLD3d32Pseudo,
3252 ARM::VLD1d64TPseudo };
3253 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD,
3254 ARM::VLD3q16Pseudo_UPD,
3255 ARM::VLD3q32Pseudo_UPD };
3256 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo,
3257 ARM::VLD3q16oddPseudo,
3258 ARM::VLD3q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003259 return SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003260 }
3261
3262 case Intrinsic::arm_neon_vld4: {
Craig Topper01736f82012-05-24 05:17:00 +00003263 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo,
3264 ARM::VLD4d16Pseudo,
3265 ARM::VLD4d32Pseudo,
3266 ARM::VLD1d64QPseudo };
3267 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD,
3268 ARM::VLD4q16Pseudo_UPD,
3269 ARM::VLD4q32Pseudo_UPD };
3270 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo,
3271 ARM::VLD4q16oddPseudo,
3272 ARM::VLD4q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003273 return SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003274 }
3275
Bob Wilsonda9817c2009-09-01 04:26:28 +00003276 case Intrinsic::arm_neon_vld2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003277 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo,
3278 ARM::VLD2LNd16Pseudo,
3279 ARM::VLD2LNd32Pseudo };
3280 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo,
3281 ARM::VLD2LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003282 return SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003283 }
3284
3285 case Intrinsic::arm_neon_vld3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003286 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo,
3287 ARM::VLD3LNd16Pseudo,
3288 ARM::VLD3LNd32Pseudo };
3289 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo,
3290 ARM::VLD3LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003291 return SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003292 }
3293
3294 case Intrinsic::arm_neon_vld4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003295 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo,
3296 ARM::VLD4LNd16Pseudo,
3297 ARM::VLD4LNd32Pseudo };
3298 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo,
3299 ARM::VLD4LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003300 return SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes);
Bob Wilsonda9817c2009-09-01 04:26:28 +00003301 }
3302
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003303 case Intrinsic::arm_neon_vst1: {
Craig Topper01736f82012-05-24 05:17:00 +00003304 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16,
3305 ARM::VST1d32, ARM::VST1d64 };
3306 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16,
3307 ARM::VST1q32, ARM::VST1q64 };
Bob Wilson06fce872011-02-07 17:43:21 +00003308 return SelectVST(N, false, 1, DOpcodes, QOpcodes, 0);
Bob Wilsoncc0a2a72010-03-23 06:20:33 +00003309 }
3310
Bob Wilsone0636a72009-08-26 17:39:53 +00003311 case Intrinsic::arm_neon_vst2: {
Craig Topper01736f82012-05-24 05:17:00 +00003312 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16,
3313 ARM::VST2d32, ARM::VST1q64 };
3314 static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo,
3315 ARM::VST2q32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003316 return SelectVST(N, false, 2, DOpcodes, QOpcodes, 0);
Bob Wilsone0636a72009-08-26 17:39:53 +00003317 }
3318
3319 case Intrinsic::arm_neon_vst3: {
Craig Topper01736f82012-05-24 05:17:00 +00003320 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo,
3321 ARM::VST3d16Pseudo,
3322 ARM::VST3d32Pseudo,
3323 ARM::VST1d64TPseudo };
3324 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD,
3325 ARM::VST3q16Pseudo_UPD,
3326 ARM::VST3q32Pseudo_UPD };
3327 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo,
3328 ARM::VST3q16oddPseudo,
3329 ARM::VST3q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003330 return SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003331 }
3332
3333 case Intrinsic::arm_neon_vst4: {
Craig Topper01736f82012-05-24 05:17:00 +00003334 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo,
3335 ARM::VST4d16Pseudo,
3336 ARM::VST4d32Pseudo,
3337 ARM::VST1d64QPseudo };
3338 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD,
3339 ARM::VST4q16Pseudo_UPD,
3340 ARM::VST4q32Pseudo_UPD };
3341 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo,
3342 ARM::VST4q16oddPseudo,
3343 ARM::VST4q32oddPseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003344 return SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
Bob Wilsone0636a72009-08-26 17:39:53 +00003345 }
Bob Wilsond7797752009-09-01 18:51:56 +00003346
3347 case Intrinsic::arm_neon_vst2lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003348 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo,
3349 ARM::VST2LNd16Pseudo,
3350 ARM::VST2LNd32Pseudo };
3351 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo,
3352 ARM::VST2LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003353 return SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003354 }
3355
3356 case Intrinsic::arm_neon_vst3lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003357 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo,
3358 ARM::VST3LNd16Pseudo,
3359 ARM::VST3LNd32Pseudo };
3360 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo,
3361 ARM::VST3LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003362 return SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003363 }
3364
3365 case Intrinsic::arm_neon_vst4lane: {
Craig Topper01736f82012-05-24 05:17:00 +00003366 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo,
3367 ARM::VST4LNd16Pseudo,
3368 ARM::VST4LNd32Pseudo };
3369 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo,
3370 ARM::VST4LNq32Pseudo };
Bob Wilson06fce872011-02-07 17:43:21 +00003371 return SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes);
Bob Wilsond7797752009-09-01 18:51:56 +00003372 }
Bob Wilsone0636a72009-08-26 17:39:53 +00003373 }
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003374 break;
Bob Wilsone0636a72009-08-26 17:39:53 +00003375 }
Evan Chengd85631e2010-05-05 18:28:36 +00003376
Bob Wilson3ed511b2010-07-06 23:36:25 +00003377 case ISD::INTRINSIC_WO_CHAIN: {
3378 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
3379 switch (IntNo) {
3380 default:
3381 break;
3382
3383 case Intrinsic::arm_neon_vtbl2:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003384 return SelectVTBL(N, false, 2, ARM::VTBL2);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003385 case Intrinsic::arm_neon_vtbl3:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003386 return SelectVTBL(N, false, 3, ARM::VTBL3Pseudo);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003387 case Intrinsic::arm_neon_vtbl4:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003388 return SelectVTBL(N, false, 4, ARM::VTBL4Pseudo);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003389
3390 case Intrinsic::arm_neon_vtbx2:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003391 return SelectVTBL(N, true, 2, ARM::VTBX2);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003392 case Intrinsic::arm_neon_vtbx3:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003393 return SelectVTBL(N, true, 3, ARM::VTBX3Pseudo);
Bob Wilson5bc8a792010-07-07 00:08:54 +00003394 case Intrinsic::arm_neon_vtbx4:
Bob Wilsonc597fd3b2010-09-13 23:55:10 +00003395 return SelectVTBL(N, true, 4, ARM::VTBX4Pseudo);
Bob Wilson3ed511b2010-07-06 23:36:25 +00003396 }
3397 break;
3398 }
3399
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003400 case ARMISD::VTBL1: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003401 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003402 EVT VT = N->getValueType(0);
3403 SmallVector<SDValue, 6> Ops;
3404
3405 Ops.push_back(N->getOperand(0));
3406 Ops.push_back(N->getOperand(1));
3407 Ops.push_back(getAL(CurDAG)); // Predicate
3408 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Michael Liaob53d8962013-04-19 22:22:57 +00003409 return CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003410 }
3411 case ARMISD::VTBL2: {
Andrew Trickef9de2a2013-05-25 02:42:55 +00003412 SDLoc dl(N);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003413 EVT VT = N->getValueType(0);
3414
3415 // Form a REG_SEQUENCE to force register allocation.
3416 SDValue V0 = N->getOperand(0);
3417 SDValue V1 = N->getOperand(1);
Weiming Zhao95782222012-11-17 00:23:35 +00003418 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003419
3420 SmallVector<SDValue, 6> Ops;
3421 Ops.push_back(RegSeq);
3422 Ops.push_back(N->getOperand(2));
3423 Ops.push_back(getAL(CurDAG)); // Predicate
3424 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register
Michael Liaob53d8962013-04-19 22:22:57 +00003425 return CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops);
Bill Wendlinge1fd78f2011-03-14 23:02:38 +00003426 }
3427
Bob Wilsonf765e1f2010-05-06 16:05:26 +00003428 case ISD::CONCAT_VECTORS:
Evan Chengd85631e2010-05-05 18:28:36 +00003429 return SelectConcatVector(N);
Eli Friedmanc3f9c4a2011-08-31 00:31:29 +00003430
3431 case ARMISD::ATOMOR64_DAG:
3432 return SelectAtomic64(N, ARM::ATOMOR6432);
3433 case ARMISD::ATOMXOR64_DAG:
3434 return SelectAtomic64(N, ARM::ATOMXOR6432);
3435 case ARMISD::ATOMADD64_DAG:
3436 return SelectAtomic64(N, ARM::ATOMADD6432);
3437 case ARMISD::ATOMSUB64_DAG:
3438 return SelectAtomic64(N, ARM::ATOMSUB6432);
3439 case ARMISD::ATOMNAND64_DAG:
3440 return SelectAtomic64(N, ARM::ATOMNAND6432);
3441 case ARMISD::ATOMAND64_DAG:
3442 return SelectAtomic64(N, ARM::ATOMAND6432);
3443 case ARMISD::ATOMSWAP64_DAG:
3444 return SelectAtomic64(N, ARM::ATOMSWAP6432);
Eli Friedman1ccecbb2011-08-31 17:52:22 +00003445 case ARMISD::ATOMCMPXCHG64_DAG:
3446 return SelectAtomic64(N, ARM::ATOMCMPXCHG6432);
Silviu Baranga93aefa52012-11-29 14:41:25 +00003447
3448 case ARMISD::ATOMMIN64_DAG:
3449 return SelectAtomic64(N, ARM::ATOMMIN6432);
3450 case ARMISD::ATOMUMIN64_DAG:
3451 return SelectAtomic64(N, ARM::ATOMUMIN6432);
3452 case ARMISD::ATOMMAX64_DAG:
3453 return SelectAtomic64(N, ARM::ATOMMAX6432);
3454 case ARMISD::ATOMUMAX64_DAG:
3455 return SelectAtomic64(N, ARM::ATOMUMAX6432);
Evan Chengd85631e2010-05-05 18:28:36 +00003456 }
Evan Chengd5021732008-12-10 21:54:21 +00003457
Dan Gohmanea6f91f2010-01-05 01:24:18 +00003458 return SelectCode(N);
Evan Cheng10043e22007-01-19 07:51:42 +00003459}
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003460
Weiming Zhaoc5987002013-02-14 18:10:21 +00003461SDNode *ARMDAGToDAGISel::SelectInlineAsm(SDNode *N){
3462 std::vector<SDValue> AsmNodeOperands;
3463 unsigned Flag, Kind;
3464 bool Changed = false;
3465 unsigned NumOps = N->getNumOperands();
3466
Weiming Zhaoc5987002013-02-14 18:10:21 +00003467 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint.
3468 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require
3469 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs
3470 // respectively. Since there is no constraint to explicitly specify a
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003471 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb,
3472 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack
3473 // them into a GPRPair.
Weiming Zhaoc5987002013-02-14 18:10:21 +00003474
Andrew Trickef9de2a2013-05-25 02:42:55 +00003475 SDLoc dl(N);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003476 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1) : SDValue(0,0);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003477
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003478 SmallVector<bool, 8> OpChanged;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003479 // Glue node will be appended late.
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003480 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) {
Weiming Zhaoc5987002013-02-14 18:10:21 +00003481 SDValue op = N->getOperand(i);
3482 AsmNodeOperands.push_back(op);
3483
3484 if (i < InlineAsm::Op_FirstOperand)
3485 continue;
3486
3487 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) {
3488 Flag = C->getZExtValue();
3489 Kind = InlineAsm::getKind(Flag);
3490 }
3491 else
3492 continue;
3493
Joey Gouly606f3fb2013-07-05 10:19:40 +00003494 if (Kind == InlineAsm::Kind_Imm) {
3495 SDValue op = N->getOperand(++i);
3496 AsmNodeOperands.push_back(op);
3497 continue;
3498 }
3499
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003500 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag);
3501 if (NumRegs)
3502 OpChanged.push_back(false);
3503
3504 unsigned DefIdx = 0;
3505 bool IsTiedToChangedOp = false;
3506 // If it's a use that is tied with a previous def, it has no
3507 // reg class constraint.
3508 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx))
3509 IsTiedToChangedOp = OpChanged[DefIdx];
3510
Weiming Zhaoc5987002013-02-14 18:10:21 +00003511 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef
3512 && Kind != InlineAsm::Kind_RegDefEarlyClobber)
3513 continue;
3514
Weiming Zhaoc5987002013-02-14 18:10:21 +00003515 unsigned RC;
3516 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC);
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003517 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID))
3518 || NumRegs != 2)
Weiming Zhaoc5987002013-02-14 18:10:21 +00003519 continue;
3520
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003521 assert((i+2 < NumOps) && "Invalid number of operands in inline asm");
Weiming Zhaoc5987002013-02-14 18:10:21 +00003522 SDValue V0 = N->getOperand(i+1);
3523 SDValue V1 = N->getOperand(i+2);
3524 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg();
3525 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg();
3526 SDValue PairedReg;
3527 MachineRegisterInfo &MRI = MF->getRegInfo();
3528
3529 if (Kind == InlineAsm::Kind_RegDef ||
3530 Kind == InlineAsm::Kind_RegDefEarlyClobber) {
3531 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to
3532 // the original GPRs.
3533
3534 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3535 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3536 SDValue Chain = SDValue(N,0);
3537
3538 SDNode *GU = N->getGluedUser();
3539 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped,
3540 Chain.getValue(1));
3541
3542 // Extract values from a GPRPair reg and copy to the original GPR reg.
3543 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
3544 RegCopy);
3545 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
3546 RegCopy);
3547 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0,
3548 RegCopy.getValue(1));
3549 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1));
3550
3551 // Update the original glue user.
3552 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1);
3553 Ops.push_back(T1.getValue(1));
3554 CurDAG->UpdateNodeOperands(GU, &Ops[0], Ops.size());
3555 GU = T1.getNode();
3556 }
3557 else {
3558 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a
3559 // GPRPair and then pass the GPRPair to the inline asm.
3560 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain];
3561
3562 // As REG_SEQ doesn't take RegisterSDNode, we copy them first.
3563 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32,
3564 Chain.getValue(1));
3565 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32,
3566 T0.getValue(1));
3567 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0);
3568
3569 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two
3570 // i32 VRs of inline asm with it.
3571 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass);
3572 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped);
3573 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1));
3574
3575 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
3576 Glue = Chain.getValue(1);
3577 }
3578
3579 Changed = true;
3580
3581 if(PairedReg.getNode()) {
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003582 OpChanged[OpChanged.size() -1 ] = true;
Weiming Zhaoc5987002013-02-14 18:10:21 +00003583 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/);
3584 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID);
3585 // Replace the current flag.
3586 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant(
3587 Flag, MVT::i32);
3588 // Add the new register node and skip the original two GPRs.
3589 AsmNodeOperands.push_back(PairedReg);
3590 // Skip the next two GPRs.
3591 i += 2;
3592 }
3593 }
3594
Weiming Zhaoa3d87a12013-06-28 17:26:02 +00003595 if (Glue.getNode())
3596 AsmNodeOperands.push_back(Glue);
Weiming Zhaoc5987002013-02-14 18:10:21 +00003597 if (!Changed)
3598 return NULL;
3599
Andrew Trickef9de2a2013-05-25 02:42:55 +00003600 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N),
Weiming Zhaoc5987002013-02-14 18:10:21 +00003601 CurDAG->getVTList(MVT::Other, MVT::Glue), &AsmNodeOperands[0],
3602 AsmNodeOperands.size());
3603 New->setNodeId(-1);
3604 return New.getNode();
3605}
3606
3607
Bob Wilsona2c462b2009-05-19 05:53:42 +00003608bool ARMDAGToDAGISel::
3609SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
3610 std::vector<SDValue> &OutOps) {
3611 assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
Bob Wilson3b515602009-10-13 20:50:28 +00003612 // Require the address to be in a register. That is safe for all ARM
3613 // variants and it is hard to do anything much smarter without knowing
3614 // how the operand is used.
3615 OutOps.push_back(Op);
Bob Wilsona2c462b2009-05-19 05:53:42 +00003616 return false;
3617}
3618
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003619/// createARMISelDag - This pass converts a legalized DAG into a
3620/// ARM-specific DAG, ready for instruction scheduling.
3621///
Bob Wilson2dd957f2009-09-28 14:30:20 +00003622FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
3623 CodeGenOpt::Level OptLevel) {
3624 return new ARMDAGToDAGISel(TM, OptLevel);
Rafael Espindolaffdc24b2006-05-14 22:18:28 +00003625}