blob: 1cd00978eefcd22d4ada5fd85239732e80f772d4 [file] [log] [blame]
Scott Michel8efdca42007-12-04 22:23:35 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner081ce942007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Scott Michel8efdca42007-12-04 22:23:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SPUTargetLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPURegisterNames.h"
15#include "SPUISelLowering.h"
16#include "SPUTargetMachine.h"
Scott Michelbc5fbc12008-04-30 00:30:08 +000017#include "SPUFrameInfo.h"
Scott Michel8efdca42007-12-04 22:23:35 +000018#include "llvm/ADT/VectorExtras.h"
Scott Michel8efdca42007-12-04 22:23:35 +000019#include "llvm/CodeGen/CallingConvLower.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner1b989192007-12-31 04:13:23 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel8efdca42007-12-04 22:23:35 +000024#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel8efdca42007-12-04 22:23:35 +000025#include "llvm/Constants.h"
26#include "llvm/Function.h"
27#include "llvm/Intrinsics.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/MathExtras.h"
30#include "llvm/Target/TargetOptions.h"
31
32#include <map>
33
34using namespace llvm;
35
36// Used in getTargetNodeName() below
37namespace {
38 std::map<unsigned, const char *> node_names;
39
Duncan Sands92c43912008-06-06 12:08:01 +000040 //! MVT mapping to useful data for Cell SPU
Scott Michel8efdca42007-12-04 22:23:35 +000041 struct valtype_map_s {
Duncan Sands92c43912008-06-06 12:08:01 +000042 const MVT valtype;
Scott Michel5a6f17b2008-01-30 02:55:46 +000043 const int prefslot_byte;
Scott Michel8efdca42007-12-04 22:23:35 +000044 };
Scott Michel4ec722e2008-07-16 17:17:29 +000045
Scott Michel8efdca42007-12-04 22:23:35 +000046 const valtype_map_s valtype_map[] = {
47 { MVT::i1, 3 },
48 { MVT::i8, 3 },
49 { MVT::i16, 2 },
50 { MVT::i32, 0 },
51 { MVT::f32, 0 },
52 { MVT::i64, 0 },
53 { MVT::f64, 0 },
54 { MVT::i128, 0 }
55 };
56
57 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
58
Duncan Sands92c43912008-06-06 12:08:01 +000059 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel8efdca42007-12-04 22:23:35 +000060 const valtype_map_s *retval = 0;
61
62 for (size_t i = 0; i < n_valtype_map; ++i) {
63 if (valtype_map[i].valtype == VT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +000064 retval = valtype_map + i;
65 break;
Scott Michel8efdca42007-12-04 22:23:35 +000066 }
67 }
68
69#ifndef NDEBUG
70 if (retval == 0) {
71 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands92c43912008-06-06 12:08:01 +000072 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +000073 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +000074 abort();
75 }
76#endif
77
78 return retval;
79 }
80
81 //! Predicate that returns true if operand is a memory target
82 /*!
83 \arg Op Operand to test
84 \return true if the operand is a memory target (i.e., global
Scott Micheldbac4cf2008-01-11 02:53:15 +000085 address, external symbol, constant pool) or an A-form
Scott Michel8efdca42007-12-04 22:23:35 +000086 address.
87 */
Dan Gohman8181bd12008-07-27 21:46:04 +000088 bool isMemoryOperand(const SDValue &Op)
Scott Michel8efdca42007-12-04 22:23:35 +000089 {
90 const unsigned Opc = Op.getOpcode();
91 return (Opc == ISD::GlobalAddress
92 || Opc == ISD::GlobalTLSAddress
Scott Michel8efdca42007-12-04 22:23:35 +000093 || Opc == ISD::JumpTable
94 || Opc == ISD::ConstantPool
Bill Wendlingfef06052008-09-16 21:48:12 +000095 || Opc == ISD::ExternalSymbol
Scott Michel8efdca42007-12-04 22:23:35 +000096 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel8efdca42007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
Bill Wendlingfef06052008-09-16 21:48:12 +0000100 || Opc == ISD::TargetExternalSymbol
Scott Micheldbac4cf2008-01-11 02:53:15 +0000101 || Opc == SPUISD::AFormAddr);
Scott Michel8efdca42007-12-04 22:23:35 +0000102 }
Scott Michel394e26d2008-01-17 20:38:41 +0000103
104 //! Predicate that returns true if the operand is an indirect target
Dan Gohman8181bd12008-07-27 21:46:04 +0000105 bool isIndirectOperand(const SDValue &Op)
Scott Michel394e26d2008-01-17 20:38:41 +0000106 {
107 const unsigned Opc = Op.getOpcode();
108 return (Opc == ISD::Register
Scott Michel5a6f17b2008-01-30 02:55:46 +0000109 || Opc == SPUISD::LDRESULT);
Scott Michel394e26d2008-01-17 20:38:41 +0000110 }
Scott Michel8efdca42007-12-04 22:23:35 +0000111}
112
113SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
114 : TargetLowering(TM),
115 SPUTM(TM)
116{
117 // Fold away setcc operations if possible.
118 setPow2DivIsCheap();
119
120 // Use _setjmp/_longjmp instead of setjmp/longjmp.
121 setUseUnderscoreSetJmp(true);
122 setUseUnderscoreLongJmp(true);
Scott Michel4ec722e2008-07-16 17:17:29 +0000123
Scott Michel8efdca42007-12-04 22:23:35 +0000124 // Set up the SPU's register classes:
Scott Michel438be252007-12-17 22:32:34 +0000125 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
126 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
127 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
128 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
129 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
130 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
Scott Michel8efdca42007-12-04 22:23:35 +0000131 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel4ec722e2008-07-16 17:17:29 +0000132
Scott Michelabb8ca12008-11-20 16:36:33 +0000133 // Initialize libcalls:
134 setLibcallName(RTLIB::MUL_I64, "__muldi3");
135
Scott Michel8efdca42007-12-04 22:23:35 +0000136 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng08c171a2008-10-14 21:26:46 +0000137 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
138 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
139 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +0000140
Evan Cheng08c171a2008-10-14 21:26:46 +0000141 setLoadExtAction(ISD::EXTLOAD, MVT::i8, Custom);
142 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Custom);
143 setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Scott Michel55252632008-11-20 04:26:21 +0000144 setTruncStoreAction(MVT::i8, MVT::i8, Custom);
145 setTruncStoreAction(MVT::i16, MVT::i8, Custom);
146 setTruncStoreAction(MVT::i32, MVT::i8, Custom);
147 setTruncStoreAction(MVT::i64, MVT::i8, Custom);
148 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000149
Evan Cheng08c171a2008-10-14 21:26:46 +0000150 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Custom);
151 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Custom);
152 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000153
154 // SPU constant load actions are custom lowered:
155 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begeman78125042008-02-14 18:43:04 +0000156 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000157 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
158
159 // SPU's loads and stores have to be custom lowered:
Scott Michele1006032008-11-19 17:45:08 +0000160 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel8efdca42007-12-04 22:23:35 +0000161 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000162 MVT VT = (MVT::SimpleValueType)sctype;
163
164 setOperationAction(ISD::LOAD, VT, Custom);
165 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000166 }
167
Scott Michel394e26d2008-01-17 20:38:41 +0000168 // Custom lower BRCOND for i1, i8 to "promote" the result to
169 // i32 and i16, respectively.
170 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000171
172 // Expand the jumptable branches
173 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
174 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000175 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000176
177 // SPU has no intrinsics for these particular operations:
Andrew Lenharth0531ec52008-02-16 14:46:26 +0000178 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
179
Scott Michel8efdca42007-12-04 22:23:35 +0000180 // PowerPC has no SREM/UREM instructions
181 setOperationAction(ISD::SREM, MVT::i32, Expand);
182 setOperationAction(ISD::UREM, MVT::i32, Expand);
183 setOperationAction(ISD::SREM, MVT::i64, Expand);
184 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000185
Scott Michel8efdca42007-12-04 22:23:35 +0000186 // We don't support sin/cos/sqrt/fmod
187 setOperationAction(ISD::FSIN , MVT::f64, Expand);
188 setOperationAction(ISD::FCOS , MVT::f64, Expand);
189 setOperationAction(ISD::FREM , MVT::f64, Expand);
190 setOperationAction(ISD::FSIN , MVT::f32, Expand);
191 setOperationAction(ISD::FCOS , MVT::f32, Expand);
192 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000193
Scott Michel8efdca42007-12-04 22:23:35 +0000194 // If we're enabling GP optimizations, use hardware square root
195 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
196 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000197
Scott Michel8efdca42007-12-04 22:23:35 +0000198 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
199 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
200
201 // SPU can do rotate right and left, so legalize it... but customize for i8
202 // because instructions don't exist.
Bill Wendling965299c2008-08-31 02:59:23 +0000203
204 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
205 // .td files.
206 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
207 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
208 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
209
Scott Michel8efdca42007-12-04 22:23:35 +0000210 setOperationAction(ISD::ROTL, MVT::i32, Legal);
211 setOperationAction(ISD::ROTL, MVT::i16, Legal);
212 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Michelabb8ca12008-11-20 16:36:33 +0000213
Scott Michel8efdca42007-12-04 22:23:35 +0000214 // SPU has no native version of shift left/right for i8
215 setOperationAction(ISD::SHL, MVT::i8, Custom);
216 setOperationAction(ISD::SRL, MVT::i8, Custom);
217 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel97872d32008-02-23 18:41:37 +0000218 // And SPU needs custom lowering for shift left/right for i64
219 setOperationAction(ISD::SHL, MVT::i64, Custom);
220 setOperationAction(ISD::SRL, MVT::i64, Custom);
221 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000222
Scott Michel4ec722e2008-07-16 17:17:29 +0000223 // Custom lower i8, i32 and i64 multiplications
224 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000225 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michelabb8ca12008-11-20 16:36:33 +0000226 setOperationAction(ISD::MUL, MVT::i64, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000227
Scott Michel67224b22008-06-02 22:18:03 +0000228 // Need to custom handle (some) common i8, i64 math ops
229 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000230 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel67224b22008-06-02 22:18:03 +0000231 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000232
Scott Michel8efdca42007-12-04 22:23:35 +0000233 // SPU does not have BSWAP. It does have i32 support CTLZ.
234 // CTPOP has to be custom lowered.
235 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
236 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
237
238 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
239 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
240 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
241 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
242
243 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
244 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
245
246 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000247
Scott Michel67224b22008-06-02 22:18:03 +0000248 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel978b96f2008-03-10 23:49:09 +0000249 // select ought to work:
Scott Michel53ab7792008-03-10 16:58:52 +0000250 setOperationAction(ISD::SELECT, MVT::i1, Promote);
251 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000252 setOperationAction(ISD::SELECT, MVT::i16, Legal);
253 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000254 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000255
Scott Michel53ab7792008-03-10 16:58:52 +0000256 setOperationAction(ISD::SETCC, MVT::i1, Promote);
257 setOperationAction(ISD::SETCC, MVT::i8, Legal);
258 setOperationAction(ISD::SETCC, MVT::i16, Legal);
259 setOperationAction(ISD::SETCC, MVT::i32, Legal);
260 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michel6baba072008-03-05 23:02:02 +0000261
Scott Michel97872d32008-02-23 18:41:37 +0000262 // Zero extension and sign extension for i64 have to be
263 // custom legalized
264 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
265 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
266 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000267
Scott Michel8efdca42007-12-04 22:23:35 +0000268 // SPU has a legal FP -> signed INT instruction
269 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
270 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
271 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
272 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
273
274 // FDIV on SPU requires custom lowering
275 setOperationAction(ISD::FDIV, MVT::f32, Custom);
276 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
277
278 // SPU has [U|S]INT_TO_FP
279 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
280 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
281 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
282 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
283 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
284 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
285 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
286 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
287
Scott Michel754d8662007-12-20 00:44:13 +0000288 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
289 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
290 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
291 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000292
293 // We cannot sextinreg(i1). Expand to shifts.
294 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000295
Scott Michel8efdca42007-12-04 22:23:35 +0000296 // Support label based line numbers.
Dan Gohman472d12c2008-06-30 20:59:49 +0000297 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000298 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000299
300 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel8efdca42007-12-04 22:23:35 +0000301 // appropriate instructions to materialize the address.
Scott Michelf9f42e62008-01-29 02:16:57 +0000302 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
303 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000304 MVT VT = (MVT::SimpleValueType)sctype;
305
306 setOperationAction(ISD::GlobalAddress, VT, Custom);
307 setOperationAction(ISD::ConstantPool, VT, Custom);
308 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michelf9f42e62008-01-29 02:16:57 +0000309 }
Scott Michel8efdca42007-12-04 22:23:35 +0000310
311 // RET must be custom lowered, to meet ABI requirements
312 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000313
Scott Michel8efdca42007-12-04 22:23:35 +0000314 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
315 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000316
Scott Michel8efdca42007-12-04 22:23:35 +0000317 // Use the default implementation.
318 setOperationAction(ISD::VAARG , MVT::Other, Expand);
319 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
320 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000321 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000322 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
323 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
324 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
325
326 // Cell SPU has instructions for converting between i64 and fp.
327 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
328 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000329
Scott Michel8efdca42007-12-04 22:23:35 +0000330 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
331 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
332
333 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
334 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
335
336 // First set operation action for all vector types to expand. Then we
337 // will selectively turn on ones that can be effectively codegen'd.
338 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
339 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
340 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
341 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
342 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
343 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
344
Duncan Sands92c43912008-06-06 12:08:01 +0000345 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
346 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
347 MVT VT = (MVT::SimpleValueType)i;
Scott Michel8efdca42007-12-04 22:23:35 +0000348
Duncan Sands92c43912008-06-06 12:08:01 +0000349 // add/sub are legal for all supported vector VT's.
350 setOperationAction(ISD::ADD , VT, Legal);
351 setOperationAction(ISD::SUB , VT, Legal);
352 // mul has to be custom lowered.
353 setOperationAction(ISD::MUL , VT, Custom);
354
355 setOperationAction(ISD::AND , VT, Legal);
356 setOperationAction(ISD::OR , VT, Legal);
357 setOperationAction(ISD::XOR , VT, Legal);
358 setOperationAction(ISD::LOAD , VT, Legal);
359 setOperationAction(ISD::SELECT, VT, Legal);
360 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000361
Scott Michel8efdca42007-12-04 22:23:35 +0000362 // These operations need to be expanded:
Duncan Sands92c43912008-06-06 12:08:01 +0000363 setOperationAction(ISD::SDIV, VT, Expand);
364 setOperationAction(ISD::SREM, VT, Expand);
365 setOperationAction(ISD::UDIV, VT, Expand);
366 setOperationAction(ISD::UREM, VT, Expand);
367 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000368
369 // Custom lower build_vector, constant pool spills, insert and
370 // extract vector elements:
Duncan Sands92c43912008-06-06 12:08:01 +0000371 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
372 setOperationAction(ISD::ConstantPool, VT, Custom);
373 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
374 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
375 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
376 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000377 }
378
379 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
380 setOperationAction(ISD::AND, MVT::v16i8, Custom);
381 setOperationAction(ISD::OR, MVT::v16i8, Custom);
382 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
383 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000384
Scott Michel8efdca42007-12-04 22:23:35 +0000385 setShiftAmountType(MVT::i32);
386 setSetCCResultContents(ZeroOrOneSetCCResult);
Scott Michel4ec722e2008-07-16 17:17:29 +0000387
Scott Michel8efdca42007-12-04 22:23:35 +0000388 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel4ec722e2008-07-16 17:17:29 +0000389
Scott Michel8efdca42007-12-04 22:23:35 +0000390 // We have target-specific dag combine patterns for the following nodes:
Scott Michelf9f42e62008-01-29 02:16:57 +0000391 setTargetDAGCombine(ISD::ADD);
Scott Michel97872d32008-02-23 18:41:37 +0000392 setTargetDAGCombine(ISD::ZERO_EXTEND);
393 setTargetDAGCombine(ISD::SIGN_EXTEND);
394 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel4ec722e2008-07-16 17:17:29 +0000395
Scott Michel8efdca42007-12-04 22:23:35 +0000396 computeRegisterProperties();
397}
398
399const char *
400SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
401{
402 if (node_names.empty()) {
403 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
404 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
405 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
406 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Micheldbac4cf2008-01-11 02:53:15 +0000407 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michelf9f42e62008-01-29 02:16:57 +0000408 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel8efdca42007-12-04 22:23:35 +0000409 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
410 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
411 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
412 node_names[(unsigned) SPUISD::INSERT_MASK] = "SPUISD::INSERT_MASK";
413 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
414 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
415 node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
Gabor Greife9f7f582008-08-31 15:37:04 +0000416 node_names[(unsigned) SPUISD::EXTRACT_ELT0_CHAINED]
417 = "SPUISD::EXTRACT_ELT0_CHAINED";
Scott Michel8efdca42007-12-04 22:23:35 +0000418 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
419 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
420 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
421 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
422 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
423 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
424 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
425 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michel97872d32008-02-23 18:41:37 +0000426 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
427 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel8efdca42007-12-04 22:23:35 +0000428 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
429 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
430 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
431 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
432 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michel97872d32008-02-23 18:41:37 +0000433 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
434 "SPUISD::ROTQUAD_RZ_BYTES";
435 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
436 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel8efdca42007-12-04 22:23:35 +0000437 node_names[(unsigned) SPUISD::ROTBYTES_RIGHT_S] =
438 "SPUISD::ROTBYTES_RIGHT_S";
439 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
440 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
441 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel67224b22008-06-02 22:18:03 +0000442 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
443 "SPUISD::ROTBYTES_LEFT_BITS";
444 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000445 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel67224b22008-06-02 22:18:03 +0000446 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
447 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
448 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
449 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel8efdca42007-12-04 22:23:35 +0000450 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
451 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
452 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
453 }
454
455 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
456
457 return ((i != node_names.end()) ? i->second : 0);
458}
459
Dan Gohman8181bd12008-07-27 21:46:04 +0000460MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands92c43912008-06-06 12:08:01 +0000461 MVT VT = Op.getValueType();
Scott Michela313fb02008-10-30 01:51:48 +0000462 return (VT.isInteger() ? VT : MVT(MVT::i32));
Scott Michel53ab7792008-03-10 16:58:52 +0000463}
464
Scott Michel8efdca42007-12-04 22:23:35 +0000465//===----------------------------------------------------------------------===//
466// Calling convention code:
467//===----------------------------------------------------------------------===//
468
469#include "SPUGenCallingConv.inc"
470
471//===----------------------------------------------------------------------===//
472// LowerOperation implementation
473//===----------------------------------------------------------------------===//
474
Scott Micheldbac4cf2008-01-11 02:53:15 +0000475/// Aligned load common code for CellSPU
476/*!
477 \param[in] Op The SelectionDAG load or store operand
478 \param[in] DAG The selection DAG
479 \param[in] ST CellSPU subtarget information structure
480 \param[in,out] alignment Caller initializes this to the load or store node's
481 value from getAlignment(), may be updated while generating the aligned load
482 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
483 offset (divisible by 16, modulo 16 == 0)
484 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
485 offset of the preferred slot (modulo 16 != 0)
486 \param[in,out] VT Caller initializes this value type to the the load or store
487 node's loaded or stored value type; may be updated if an i1-extended load or
488 store.
489 \param[out] was16aligned true if the base pointer had 16-byte alignment,
490 otherwise false. Can help to determine if the chunk needs to be rotated.
491
492 Both load and store lowering load a block of data aligned on a 16-byte
493 boundary. This is the common aligned load code shared between both.
494 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000495static SDValue
496AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Micheldbac4cf2008-01-11 02:53:15 +0000497 LSBaseSDNode *LSN,
498 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands92c43912008-06-06 12:08:01 +0000499 MVT &VT, bool &was16aligned)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000500{
Duncan Sands92c43912008-06-06 12:08:01 +0000501 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000502 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman8181bd12008-07-27 21:46:04 +0000503 SDValue basePtr = LSN->getBasePtr();
504 SDValue chain = LSN->getChain();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000505
506 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greif1c80d112008-08-28 21:40:38 +0000507 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000508
Gabor Greife9f7f582008-08-31 15:37:04 +0000509 if (Op1.getOpcode() == ISD::Constant
510 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel394e26d2008-01-17 20:38:41 +0000511 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000512
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000513 alignOffs = (int) CN->getZExtValue();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000514 prefSlotOffs = (int) (alignOffs & 0xf);
515
516 // Adjust the rotation amount to ensure that the final result ends up in
517 // the preferred slot:
518 prefSlotOffs -= vtm->prefslot_byte;
519 basePtr = basePtr.getOperand(0);
520
Scott Michel394e26d2008-01-17 20:38:41 +0000521 // Loading from memory, can we adjust alignment?
522 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000523 SDValue APtr = basePtr.getOperand(0);
Scott Michel394e26d2008-01-17 20:38:41 +0000524 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
525 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
526 alignment = GSDN->getGlobal()->getAlignment();
527 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000528 }
529 } else {
530 alignOffs = 0;
531 prefSlotOffs = -vtm->prefslot_byte;
532 }
Scott Michelbc5fbc12008-04-30 00:30:08 +0000533 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
534 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
535 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
536 prefSlotOffs = (int) (alignOffs & 0xf);
537 prefSlotOffs -= vtm->prefslot_byte;
538 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000539 } else {
540 alignOffs = 0;
541 prefSlotOffs = -vtm->prefslot_byte;
542 }
543
544 if (alignment == 16) {
545 // Realign the base pointer as a D-Form address:
546 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel394e26d2008-01-17 20:38:41 +0000547 basePtr = DAG.getNode(ISD::ADD, PtrVT,
548 basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000549 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000550 }
551
552 // Emit the vector load:
553 was16aligned = true;
554 return DAG.getLoad(MVT::v16i8, chain, basePtr,
555 LSN->getSrcValue(), LSN->getSrcValueOffset(),
556 LSN->isVolatile(), 16);
557 }
558
559 // Unaligned load or we're using the "large memory" model, which means that
560 // we have to be very pessimistic:
Scott Michel394e26d2008-01-17 20:38:41 +0000561 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greife9f7f582008-08-31 15:37:04 +0000562 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
563 DAG.getConstant(0, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000564 }
565
566 // Add the offset
Scott Michelf9f42e62008-01-29 02:16:57 +0000567 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000568 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000569 was16aligned = false;
570 return DAG.getLoad(MVT::v16i8, chain, basePtr,
571 LSN->getSrcValue(), LSN->getSrcValueOffset(),
572 LSN->isVolatile(), 16);
573}
574
Scott Michel8efdca42007-12-04 22:23:35 +0000575/// Custom lower loads for CellSPU
576/*!
577 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
578 within a 16-byte block, we have to rotate to extract the requested element.
579 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000580static SDValue
581LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000582 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000583 SDValue the_chain = LN->getChain();
Duncan Sands92c43912008-06-06 12:08:01 +0000584 MVT VT = LN->getMemoryVT();
Gabor Greif1c80d112008-08-28 21:40:38 +0000585 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000586 ISD::LoadExtType ExtType = LN->getExtensionType();
587 unsigned alignment = LN->getAlignment();
Dan Gohman8181bd12008-07-27 21:46:04 +0000588 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +0000589
Scott Michel8efdca42007-12-04 22:23:35 +0000590 switch (LN->getAddressingMode()) {
591 case ISD::UNINDEXED: {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000592 int offset, rotamt;
593 bool was16aligned;
Dan Gohman8181bd12008-07-27 21:46:04 +0000594 SDValue result =
Scott Micheldbac4cf2008-01-11 02:53:15 +0000595 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel8efdca42007-12-04 22:23:35 +0000596
Gabor Greif1c80d112008-08-28 21:40:38 +0000597 if (result.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +0000598 return result;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000599
600 the_chain = result.getValue(1);
601 // Rotate the chunk if necessary
602 if (rotamt < 0)
603 rotamt += 16;
Scott Michelabc58242008-01-11 21:01:19 +0000604 if (rotamt != 0 || !was16aligned) {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000605 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
606
Scott Michel394e26d2008-01-17 20:38:41 +0000607 Ops[0] = the_chain;
608 Ops[1] = result;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000609 if (was16aligned) {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000610 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
611 } else {
Duncan Sands92c43912008-06-06 12:08:01 +0000612 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000613 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michelabc58242008-01-11 21:01:19 +0000614 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel5a6f17b2008-01-30 02:55:46 +0000615 DAG.getConstant(rotamt, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000616 }
617
618 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
619 the_chain = result.getValue(1);
Scott Michel8efdca42007-12-04 22:23:35 +0000620 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000621
622 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
623 SDVTList scalarvts;
Duncan Sands92c43912008-06-06 12:08:01 +0000624 MVT vecVT = MVT::v16i8;
Scott Michel4ec722e2008-07-16 17:17:29 +0000625
Scott Micheldbac4cf2008-01-11 02:53:15 +0000626 // Convert the loaded v16i8 vector to the appropriate vector type
627 // specified by the operand:
628 if (OpVT == VT) {
629 if (VT != MVT::i1)
Duncan Sands92c43912008-06-06 12:08:01 +0000630 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000631 } else
Duncan Sands92c43912008-06-06 12:08:01 +0000632 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000633
634 Ops[0] = the_chain;
635 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
636 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
637 result = DAG.getNode(SPUISD::EXTRACT_ELT0_CHAINED, scalarvts, Ops, 2);
638 the_chain = result.getValue(1);
639 } else {
640 // Handle the sign and zero-extending loads for i1 and i8:
641 unsigned NewOpC;
642
643 if (ExtType == ISD::SEXTLOAD) {
644 NewOpC = (OpVT == MVT::i1
645 ? SPUISD::EXTRACT_I1_SEXT
646 : SPUISD::EXTRACT_I8_SEXT);
647 } else {
648 assert(ExtType == ISD::ZEXTLOAD);
649 NewOpC = (OpVT == MVT::i1
650 ? SPUISD::EXTRACT_I1_ZEXT
651 : SPUISD::EXTRACT_I8_ZEXT);
652 }
653
654 result = DAG.getNode(NewOpC, OpVT, result);
655 }
656
657 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman8181bd12008-07-27 21:46:04 +0000658 SDValue retops[2] = {
Scott Michel394e26d2008-01-17 20:38:41 +0000659 result,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000660 the_chain
Scott Michel394e26d2008-01-17 20:38:41 +0000661 };
Scott Micheldbac4cf2008-01-11 02:53:15 +0000662
Scott Michel394e26d2008-01-17 20:38:41 +0000663 result = DAG.getNode(SPUISD::LDRESULT, retvts,
664 retops, sizeof(retops) / sizeof(retops[0]));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000665 return result;
Scott Michel8efdca42007-12-04 22:23:35 +0000666 }
667 case ISD::PRE_INC:
668 case ISD::PRE_DEC:
669 case ISD::POST_INC:
670 case ISD::POST_DEC:
671 case ISD::LAST_INDEXED_MODE:
672 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
673 "UNINDEXED\n";
674 cerr << (unsigned) LN->getAddressingMode() << "\n";
675 abort();
676 /*NOTREACHED*/
677 }
678
Dan Gohman8181bd12008-07-27 21:46:04 +0000679 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000680}
681
682/// Custom lower stores for CellSPU
683/*!
684 All CellSPU stores are aligned to 16-byte boundaries, so for elements
685 within a 16-byte block, we have to generate a shuffle to insert the
686 requested element into its place, then store the resulting block.
687 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000688static SDValue
689LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000690 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000691 SDValue Value = SN->getValue();
Duncan Sands92c43912008-06-06 12:08:01 +0000692 MVT VT = Value.getValueType();
693 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
694 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000695 unsigned alignment = SN->getAlignment();
Scott Michel8efdca42007-12-04 22:23:35 +0000696
697 switch (SN->getAddressingMode()) {
698 case ISD::UNINDEXED: {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000699 int chunk_offset, slot_offset;
700 bool was16aligned;
Scott Michel8efdca42007-12-04 22:23:35 +0000701
702 // The vector type we really want to load from the 16-byte chunk, except
703 // in the case of MVT::i1, which has to be v16i8.
Scott Michele1006032008-11-19 17:45:08 +0000704 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
705 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +0000706
Dan Gohman8181bd12008-07-27 21:46:04 +0000707 SDValue alignLoadVec =
Scott Micheldbac4cf2008-01-11 02:53:15 +0000708 AlignedLoad(Op, DAG, ST, SN, alignment,
709 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel8efdca42007-12-04 22:23:35 +0000710
Gabor Greif1c80d112008-08-28 21:40:38 +0000711 if (alignLoadVec.getNode() == 0)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000712 return alignLoadVec;
Scott Michel8efdca42007-12-04 22:23:35 +0000713
Scott Micheldbac4cf2008-01-11 02:53:15 +0000714 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman8181bd12008-07-27 21:46:04 +0000715 SDValue basePtr = LN->getBasePtr();
716 SDValue the_chain = alignLoadVec.getValue(1);
717 SDValue theValue = SN->getValue();
718 SDValue result;
Scott Michel8efdca42007-12-04 22:23:35 +0000719
720 if (StVT != VT
Scott Michel5a6f17b2008-01-30 02:55:46 +0000721 && (theValue.getOpcode() == ISD::AssertZext
722 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel8efdca42007-12-04 22:23:35 +0000723 // Drill down and get the value for zero- and sign-extended
724 // quantities
Scott Michel4ec722e2008-07-16 17:17:29 +0000725 theValue = theValue.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000726 }
727
Scott Micheldbac4cf2008-01-11 02:53:15 +0000728 chunk_offset &= 0xf;
Scott Michel8efdca42007-12-04 22:23:35 +0000729
Dan Gohman8181bd12008-07-27 21:46:04 +0000730 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
731 SDValue insertEltPtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000732
733 // If the base pointer is already a D-form address, then just create
734 // a new D-form address with a slot offset and the orignal base pointer.
735 // Otherwise generate a D-form address with the slot offset relative
736 // to the stack pointer, which is always aligned.
Scott Michelabc58242008-01-11 21:01:19 +0000737 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greif1c80d112008-08-28 21:40:38 +0000738 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michelabc58242008-01-11 21:01:19 +0000739 DEBUG(cerr << "\n");
740
Scott Michelf9f42e62008-01-29 02:16:57 +0000741 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
742 (basePtr.getOpcode() == ISD::ADD
743 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michelabc58242008-01-11 21:01:19 +0000744 insertEltPtr = basePtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000745 } else {
Scott Michelf9f42e62008-01-29 02:16:57 +0000746 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000747 }
748
Scott Michelf65c8f02008-11-19 15:24:16 +0000749 SDValue insertEltOp =
750 DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
Scott Michele1006032008-11-19 17:45:08 +0000751 SDValue vectorizeOp =
752 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michelf65c8f02008-11-19 15:24:16 +0000753
754 result = DAG.getNode(SPUISD::SHUFB, vecVT, vectorizeOp, alignLoadVec,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000755 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel8efdca42007-12-04 22:23:35 +0000756
Scott Micheldbac4cf2008-01-11 02:53:15 +0000757 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel8efdca42007-12-04 22:23:35 +0000758 LN->getSrcValue(), LN->getSrcValueOffset(),
759 LN->isVolatile(), LN->getAlignment());
760
Scott Michele1006032008-11-19 17:45:08 +0000761#if 0 && defined(NDEBUG)
Scott Michelf65c8f02008-11-19 15:24:16 +0000762 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
763 const SDValue &currentRoot = DAG.getRoot();
764
765 DAG.setRoot(result);
766 cerr << "------- CellSPU:LowerStore result:\n";
767 DAG.dump();
768 cerr << "-------\n";
769 DAG.setRoot(currentRoot);
770 }
771#endif
772
Scott Michel8efdca42007-12-04 22:23:35 +0000773 return result;
774 /*UNREACHED*/
775 }
776 case ISD::PRE_INC:
777 case ISD::PRE_DEC:
778 case ISD::POST_INC:
779 case ISD::POST_DEC:
780 case ISD::LAST_INDEXED_MODE:
781 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
782 "UNINDEXED\n";
783 cerr << (unsigned) SN->getAddressingMode() << "\n";
784 abort();
785 /*NOTREACHED*/
786 }
787
Dan Gohman8181bd12008-07-27 21:46:04 +0000788 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000789}
790
791/// Generate the address of a constant pool entry.
Dan Gohman8181bd12008-07-27 21:46:04 +0000792static SDValue
793LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000794 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000795 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
796 Constant *C = CP->getConstVal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000797 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
798 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000799 const TargetMachine &TM = DAG.getTarget();
Scott Michel8efdca42007-12-04 22:23:35 +0000800
801 if (TM.getRelocationModel() == Reloc::Static) {
802 if (!ST->usingLargeMem()) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000803 // Just return the SDValue with the constant pool address in it.
Scott Michel394e26d2008-01-17 20:38:41 +0000804 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +0000805 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000806 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
807 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000808 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel8efdca42007-12-04 22:23:35 +0000809 }
810 }
811
812 assert(0 &&
Gabor Greife9f7f582008-08-31 15:37:04 +0000813 "LowerConstantPool: Relocation model other than static"
814 " not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000815 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000816}
817
Dan Gohman8181bd12008-07-27 21:46:04 +0000818static SDValue
819LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000820 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000821 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000822 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
823 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000824 const TargetMachine &TM = DAG.getTarget();
825
826 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel97872d32008-02-23 18:41:37 +0000827 if (!ST->usingLargeMem()) {
828 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
829 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000830 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
831 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000832 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
833 }
Scott Michel8efdca42007-12-04 22:23:35 +0000834 }
835
836 assert(0 &&
837 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000838 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000839}
840
Dan Gohman8181bd12008-07-27 21:46:04 +0000841static SDValue
842LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000843 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000844 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
845 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000846 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel8efdca42007-12-04 22:23:35 +0000847 const TargetMachine &TM = DAG.getTarget();
Dan Gohman8181bd12008-07-27 21:46:04 +0000848 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel4ec722e2008-07-16 17:17:29 +0000849
Scott Michel8efdca42007-12-04 22:23:35 +0000850 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michelf9f42e62008-01-29 02:16:57 +0000851 if (!ST->usingLargeMem()) {
852 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
853 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000854 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
855 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michelf9f42e62008-01-29 02:16:57 +0000856 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
857 }
Scott Michel8efdca42007-12-04 22:23:35 +0000858 } else {
859 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel5a6f17b2008-01-30 02:55:46 +0000860 << "supported.\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000861 abort();
862 /*NOTREACHED*/
863 }
864
Dan Gohman8181bd12008-07-27 21:46:04 +0000865 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000866}
867
868//! Custom lower i64 integer constants
869/*!
870 This code inserts all of the necessary juggling that needs to occur to load
871 a 64-bit constant into a register.
872 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000873static SDValue
874LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000875 MVT VT = Op.getValueType();
Gabor Greif1c80d112008-08-28 21:40:38 +0000876 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel8efdca42007-12-04 22:23:35 +0000877
878 if (VT == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000879 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +0000880 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000881 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +0000882 } else {
883 cerr << "LowerConstant: unhandled constant type "
Duncan Sands92c43912008-06-06 12:08:01 +0000884 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +0000885 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000886 abort();
887 /*NOTREACHED*/
888 }
889
Dan Gohman8181bd12008-07-27 21:46:04 +0000890 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000891}
892
Nate Begeman78125042008-02-14 18:43:04 +0000893//! Custom lower double precision floating point constants
Dan Gohman8181bd12008-07-27 21:46:04 +0000894static SDValue
895LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000896 MVT VT = Op.getValueType();
Gabor Greif1c80d112008-08-28 21:40:38 +0000897 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel8efdca42007-12-04 22:23:35 +0000898
899 assert((FP != 0) &&
Scott Michel5a6f17b2008-01-30 02:55:46 +0000900 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel8efdca42007-12-04 22:23:35 +0000901
Nate Begeman78125042008-02-14 18:43:04 +0000902 if (VT == MVT::f64) {
Scott Michel11e88bb2007-12-19 20:15:47 +0000903 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel8efdca42007-12-04 22:23:35 +0000904 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000905 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel8efdca42007-12-04 22:23:35 +0000906 }
907
Dan Gohman8181bd12008-07-27 21:46:04 +0000908 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000909}
910
Scott Michel394e26d2008-01-17 20:38:41 +0000911//! Lower MVT::i1, MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman8181bd12008-07-27 21:46:04 +0000912static SDValue
913LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel394e26d2008-01-17 20:38:41 +0000914{
Dan Gohman8181bd12008-07-27 21:46:04 +0000915 SDValue Cond = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +0000916 MVT CondVT = Cond.getValueType();
917 MVT CondNVT;
Scott Michel394e26d2008-01-17 20:38:41 +0000918
919 if (CondVT == MVT::i1 || CondVT == MVT::i8) {
920 CondNVT = (CondVT == MVT::i1 ? MVT::i32 : MVT::i16);
921 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
922 Op.getOperand(0),
923 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
924 Op.getOperand(2));
925 } else
Dan Gohman8181bd12008-07-27 21:46:04 +0000926 return SDValue(); // Unchanged
Scott Michel394e26d2008-01-17 20:38:41 +0000927}
928
Dan Gohman8181bd12008-07-27 21:46:04 +0000929static SDValue
930LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel8efdca42007-12-04 22:23:35 +0000931{
932 MachineFunction &MF = DAG.getMachineFunction();
933 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner1b989192007-12-31 04:13:23 +0000934 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michela313fb02008-10-30 01:51:48 +0000935 SmallVector<SDValue, 48> ArgValues;
Dan Gohman8181bd12008-07-27 21:46:04 +0000936 SDValue Root = Op.getOperand(0);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000937 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel8efdca42007-12-04 22:23:35 +0000938
939 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
940 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel4ec722e2008-07-16 17:17:29 +0000941
Scott Michel8efdca42007-12-04 22:23:35 +0000942 unsigned ArgOffset = SPUFrameInfo::minStackSize();
943 unsigned ArgRegIdx = 0;
944 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel4ec722e2008-07-16 17:17:29 +0000945
Duncan Sands92c43912008-06-06 12:08:01 +0000946 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +0000947
Scott Michel8efdca42007-12-04 22:23:35 +0000948 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greife9f7f582008-08-31 15:37:04 +0000949 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
950 ArgNo != e; ++ArgNo) {
Duncan Sands92c43912008-06-06 12:08:01 +0000951 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
952 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michela313fb02008-10-30 01:51:48 +0000953 SDValue ArgVal;
Scott Michel8efdca42007-12-04 22:23:35 +0000954
Scott Michela313fb02008-10-30 01:51:48 +0000955 if (ArgRegIdx < NumArgRegs) {
956 const TargetRegisterClass *ArgRegClass;
Scott Michel4ec722e2008-07-16 17:17:29 +0000957
Scott Michela313fb02008-10-30 01:51:48 +0000958 switch (ObjectVT.getSimpleVT()) {
959 default: {
960 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
961 << ObjectVT.getMVTString()
962 << "\n";
963 abort();
964 }
965 case MVT::i8:
966 ArgRegClass = &SPU::R8CRegClass;
967 break;
968 case MVT::i16:
969 ArgRegClass = &SPU::R16CRegClass;
970 break;
971 case MVT::i32:
972 ArgRegClass = &SPU::R32CRegClass;
973 break;
974 case MVT::i64:
975 ArgRegClass = &SPU::R64CRegClass;
976 break;
977 case MVT::f32:
978 ArgRegClass = &SPU::R32FPRegClass;
979 break;
980 case MVT::f64:
981 ArgRegClass = &SPU::R64FPRegClass;
982 break;
983 case MVT::v2f64:
984 case MVT::v4f32:
985 case MVT::v2i64:
986 case MVT::v4i32:
987 case MVT::v8i16:
988 case MVT::v16i8:
989 ArgRegClass = &SPU::VECREGRegClass;
Scott Michela313fb02008-10-30 01:51:48 +0000990 break;
991 }
992
993 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
994 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
995 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
996 ++ArgRegIdx;
997 } else {
998 // We need to load the argument to a virtual register if we determined
999 // above that we ran out of physical registers of the appropriate type
1000 // or we're forced to do vararg
Chris Lattner60069452008-02-13 07:35:30 +00001001 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman8181bd12008-07-27 21:46:04 +00001002 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner60069452008-02-13 07:35:30 +00001003 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel8efdca42007-12-04 22:23:35 +00001004 ArgOffset += StackSlotSize;
1005 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001006
Scott Michel8efdca42007-12-04 22:23:35 +00001007 ArgValues.push_back(ArgVal);
Scott Michela313fb02008-10-30 01:51:48 +00001008 // Update the chain
1009 Root = ArgVal.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001010 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001011
Scott Michela313fb02008-10-30 01:51:48 +00001012 // vararg handling:
Scott Michel8efdca42007-12-04 22:23:35 +00001013 if (isVarArg) {
Scott Michela313fb02008-10-30 01:51:48 +00001014 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1015 // We will spill (79-3)+1 registers to the stack
1016 SmallVector<SDValue, 79-3+1> MemOps;
1017
1018 // Create the frame slot
1019
Scott Michel8efdca42007-12-04 22:23:35 +00001020 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Michela313fb02008-10-30 01:51:48 +00001021 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1022 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1023 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1024 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1025 Root = Store.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001026 MemOps.push_back(Store);
Scott Michela313fb02008-10-30 01:51:48 +00001027
1028 // Increment address by stack slot size for the next stored argument
1029 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001030 }
1031 if (!MemOps.empty())
Scott Michela313fb02008-10-30 01:51:48 +00001032 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001033 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001034
Scott Michel8efdca42007-12-04 22:23:35 +00001035 ArgValues.push_back(Root);
Scott Michel4ec722e2008-07-16 17:17:29 +00001036
Scott Michel8efdca42007-12-04 22:23:35 +00001037 // Return the new list of results.
Gabor Greif1c80d112008-08-28 21:40:38 +00001038 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf19591c2008-06-30 10:19:09 +00001039 ArgValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001040}
1041
1042/// isLSAAddress - Return the immediate to use if the specified
1043/// value is representable as a LSA address.
Dan Gohman8181bd12008-07-27 21:46:04 +00001044static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel5974f432008-11-11 03:06:06 +00001045 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel8efdca42007-12-04 22:23:35 +00001046 if (!C) return 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001047
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001048 int Addr = C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001049 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1050 (Addr << 14 >> 14) != Addr)
1051 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel4ec722e2008-07-16 17:17:29 +00001052
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001053 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel8efdca42007-12-04 22:23:35 +00001054}
1055
1056static
Dan Gohman8181bd12008-07-27 21:46:04 +00001057SDValue
1058LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001059 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1060 SDValue Chain = TheCall->getChain();
Dan Gohman705e3f72008-09-13 01:54:27 +00001061 SDValue Callee = TheCall->getCallee();
1062 unsigned NumOps = TheCall->getNumArgs();
Scott Michel8efdca42007-12-04 22:23:35 +00001063 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1064 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1065 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1066
1067 // Handy pointer type
Duncan Sands92c43912008-06-06 12:08:01 +00001068 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +00001069
Scott Michel8efdca42007-12-04 22:23:35 +00001070 // Accumulate how many bytes are to be pushed on the stack, including the
1071 // linkage area, and parameter passing area. According to the SPU ABI,
1072 // we minimally need space for [LR] and [SP]
1073 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel4ec722e2008-07-16 17:17:29 +00001074
Scott Michel8efdca42007-12-04 22:23:35 +00001075 // Set up a copy of the stack pointer for use loading and storing any
1076 // arguments that may not fit in the registers available for argument
1077 // passing.
Dan Gohman8181bd12008-07-27 21:46:04 +00001078 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel4ec722e2008-07-16 17:17:29 +00001079
Scott Michel8efdca42007-12-04 22:23:35 +00001080 // Figure out which arguments are going to go in registers, and which in
1081 // memory.
1082 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1083 unsigned ArgRegIdx = 0;
1084
1085 // Keep track of registers passing arguments
Dan Gohman8181bd12008-07-27 21:46:04 +00001086 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel8efdca42007-12-04 22:23:35 +00001087 // And the arguments passed on the stack
Dan Gohman8181bd12008-07-27 21:46:04 +00001088 SmallVector<SDValue, 8> MemOpChains;
Scott Michel8efdca42007-12-04 22:23:35 +00001089
1090 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001091 SDValue Arg = TheCall->getArg(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001092
Scott Michel8efdca42007-12-04 22:23:35 +00001093 // PtrOff will be used to store the current argument to the stack if a
1094 // register cannot be found for it.
Dan Gohman8181bd12008-07-27 21:46:04 +00001095 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel8efdca42007-12-04 22:23:35 +00001096 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1097
Duncan Sands92c43912008-06-06 12:08:01 +00001098 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001099 default: assert(0 && "Unexpected ValueType for argument!");
1100 case MVT::i32:
1101 case MVT::i64:
1102 case MVT::i128:
1103 if (ArgRegIdx != NumArgRegs) {
1104 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1105 } else {
1106 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001107 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001108 }
1109 break;
1110 case MVT::f32:
1111 case MVT::f64:
1112 if (ArgRegIdx != NumArgRegs) {
1113 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1114 } else {
1115 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001116 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001117 }
1118 break;
1119 case MVT::v4f32:
1120 case MVT::v4i32:
1121 case MVT::v8i16:
1122 case MVT::v16i8:
1123 if (ArgRegIdx != NumArgRegs) {
1124 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1125 } else {
1126 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001127 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001128 }
1129 break;
1130 }
1131 }
1132
1133 // Update number of stack bytes actually used, insert a call sequence start
1134 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001135 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1136 true));
Scott Michel8efdca42007-12-04 22:23:35 +00001137
1138 if (!MemOpChains.empty()) {
1139 // Adjust the stack pointer for the stack arguments.
1140 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1141 &MemOpChains[0], MemOpChains.size());
1142 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001143
Scott Michel8efdca42007-12-04 22:23:35 +00001144 // Build a sequence of copy-to-reg nodes chained together with token chain
1145 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman8181bd12008-07-27 21:46:04 +00001146 SDValue InFlag;
Scott Michel8efdca42007-12-04 22:23:35 +00001147 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1148 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1149 InFlag);
1150 InFlag = Chain.getValue(1);
1151 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001152
Dan Gohman8181bd12008-07-27 21:46:04 +00001153 SmallVector<SDValue, 8> Ops;
Scott Michel8efdca42007-12-04 22:23:35 +00001154 unsigned CallOpc = SPUISD::CALL;
Scott Michel4ec722e2008-07-16 17:17:29 +00001155
Bill Wendlingfef06052008-09-16 21:48:12 +00001156 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1157 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1158 // node so that legalize doesn't hack it.
Scott Michel5974f432008-11-11 03:06:06 +00001159 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001160 GlobalValue *GV = G->getGlobal();
Duncan Sands92c43912008-06-06 12:08:01 +00001161 MVT CalleeVT = Callee.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001162 SDValue Zero = DAG.getConstant(0, PtrVT);
1163 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001164
Scott Micheldbac4cf2008-01-11 02:53:15 +00001165 if (!ST->usingLargeMem()) {
1166 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1167 // style calls, otherwise, external symbols are BRASL calls. This assumes
1168 // that declared/defined symbols are in the same compilation unit and can
1169 // be reached through PC-relative jumps.
1170 //
1171 // NOTE:
1172 // This may be an unsafe assumption for JIT and really large compilation
1173 // units.
1174 if (GV->isDeclaration()) {
1175 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1176 } else {
1177 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1178 }
Scott Michel8efdca42007-12-04 22:23:35 +00001179 } else {
Scott Micheldbac4cf2008-01-11 02:53:15 +00001180 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1181 // address pairs:
Scott Michelf9f42e62008-01-29 02:16:57 +00001182 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +00001183 }
Scott Michel5974f432008-11-11 03:06:06 +00001184 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendlingfef06052008-09-16 21:48:12 +00001185 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Micheldbac4cf2008-01-11 02:53:15 +00001186 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001187 // If this is an absolute destination address that appears to be a legal
1188 // local store address, use the munged value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001189 Callee = SDValue(Dest, 0);
Scott Micheldbac4cf2008-01-11 02:53:15 +00001190 }
Scott Michel8efdca42007-12-04 22:23:35 +00001191
1192 Ops.push_back(Chain);
1193 Ops.push_back(Callee);
Scott Michel4ec722e2008-07-16 17:17:29 +00001194
Scott Michel8efdca42007-12-04 22:23:35 +00001195 // Add argument registers to the end of the list so that they are known live
1196 // into the call.
1197 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel4ec722e2008-07-16 17:17:29 +00001198 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel8efdca42007-12-04 22:23:35 +00001199 RegsToPass[i].second.getValueType()));
Scott Michel4ec722e2008-07-16 17:17:29 +00001200
Gabor Greif1c80d112008-08-28 21:40:38 +00001201 if (InFlag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001202 Ops.push_back(InFlag);
Duncan Sands698842f2008-07-02 17:40:58 +00001203 // Returns a chain and a flag for retval copy to use.
1204 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1205 &Ops[0], Ops.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001206 InFlag = Chain.getValue(1);
1207
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001208 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1209 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman705e3f72008-09-13 01:54:27 +00001210 if (TheCall->getValueType(0) != MVT::Other)
Evan Cheng07322bb2008-02-05 22:44:06 +00001211 InFlag = Chain.getValue(1);
1212
Dan Gohman8181bd12008-07-27 21:46:04 +00001213 SDValue ResultVals[3];
Scott Michel8efdca42007-12-04 22:23:35 +00001214 unsigned NumResults = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001215
Scott Michel8efdca42007-12-04 22:23:35 +00001216 // If the call has results, copy the values out of the ret val registers.
Dan Gohman705e3f72008-09-13 01:54:27 +00001217 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001218 default: assert(0 && "Unexpected ret value!");
1219 case MVT::Other: break;
1220 case MVT::i32:
Dan Gohman705e3f72008-09-13 01:54:27 +00001221 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001222 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1223 ResultVals[0] = Chain.getValue(0);
1224 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1225 Chain.getValue(2)).getValue(1);
1226 ResultVals[1] = Chain.getValue(0);
1227 NumResults = 2;
Scott Michel8efdca42007-12-04 22:23:35 +00001228 } else {
1229 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1230 ResultVals[0] = Chain.getValue(0);
1231 NumResults = 1;
1232 }
Scott Michel8efdca42007-12-04 22:23:35 +00001233 break;
1234 case MVT::i64:
1235 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1236 ResultVals[0] = Chain.getValue(0);
1237 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001238 break;
1239 case MVT::f32:
1240 case MVT::f64:
Dan Gohman705e3f72008-09-13 01:54:27 +00001241 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001242 InFlag).getValue(1);
1243 ResultVals[0] = Chain.getValue(0);
1244 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001245 break;
1246 case MVT::v2f64:
1247 case MVT::v4f32:
1248 case MVT::v4i32:
1249 case MVT::v8i16:
1250 case MVT::v16i8:
Dan Gohman705e3f72008-09-13 01:54:27 +00001251 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001252 InFlag).getValue(1);
1253 ResultVals[0] = Chain.getValue(0);
1254 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001255 break;
1256 }
Duncan Sands698842f2008-07-02 17:40:58 +00001257
Scott Michel8efdca42007-12-04 22:23:35 +00001258 // If the function returns void, just return the chain.
1259 if (NumResults == 0)
1260 return Chain;
Scott Michel4ec722e2008-07-16 17:17:29 +00001261
Scott Michel8efdca42007-12-04 22:23:35 +00001262 // Otherwise, merge everything together with a MERGE_VALUES node.
1263 ResultVals[NumResults++] = Chain;
Dan Gohman8181bd12008-07-27 21:46:04 +00001264 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif46bf5472008-08-26 22:36:50 +00001265 return Res.getValue(Op.getResNo());
Scott Michel8efdca42007-12-04 22:23:35 +00001266}
1267
Dan Gohman8181bd12008-07-27 21:46:04 +00001268static SDValue
1269LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel8efdca42007-12-04 22:23:35 +00001270 SmallVector<CCValAssign, 16> RVLocs;
1271 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1272 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1273 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greif1c80d112008-08-28 21:40:38 +00001274 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel4ec722e2008-07-16 17:17:29 +00001275
Scott Michel8efdca42007-12-04 22:23:35 +00001276 // If this is the first return lowered for this function, add the regs to the
1277 // liveout set for the function.
Chris Lattner1b989192007-12-31 04:13:23 +00001278 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001279 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner1b989192007-12-31 04:13:23 +00001280 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel8efdca42007-12-04 22:23:35 +00001281 }
1282
Dan Gohman8181bd12008-07-27 21:46:04 +00001283 SDValue Chain = Op.getOperand(0);
1284 SDValue Flag;
Scott Michel4ec722e2008-07-16 17:17:29 +00001285
Scott Michel8efdca42007-12-04 22:23:35 +00001286 // Copy the result values into the output registers.
1287 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1288 CCValAssign &VA = RVLocs[i];
1289 assert(VA.isRegLoc() && "Can only return in registers!");
1290 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1291 Flag = Chain.getValue(1);
1292 }
1293
Gabor Greif1c80d112008-08-28 21:40:38 +00001294 if (Flag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001295 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1296 else
1297 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1298}
1299
1300
1301//===----------------------------------------------------------------------===//
1302// Vector related lowering:
1303//===----------------------------------------------------------------------===//
1304
1305static ConstantSDNode *
1306getVecImm(SDNode *N) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001307 SDValue OpVal(0, 0);
Scott Michel4ec722e2008-07-16 17:17:29 +00001308
Scott Michel8efdca42007-12-04 22:23:35 +00001309 // Check to see if this buildvec has a single non-undef value in its elements.
1310 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1311 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greif1c80d112008-08-28 21:40:38 +00001312 if (OpVal.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +00001313 OpVal = N->getOperand(i);
1314 else if (OpVal != N->getOperand(i))
1315 return 0;
1316 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001317
Gabor Greif1c80d112008-08-28 21:40:38 +00001318 if (OpVal.getNode() != 0) {
Scott Michel5974f432008-11-11 03:06:06 +00001319 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001320 return CN;
1321 }
1322 }
1323
1324 return 0; // All UNDEF: use implicit def.; not Constant node
1325}
1326
1327/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1328/// and the value fits into an unsigned 18-bit constant, and if so, return the
1329/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001330SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001331 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001332 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001333 uint64_t Value = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001334 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001335 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001336 uint32_t upper = uint32_t(UValue >> 32);
1337 uint32_t lower = uint32_t(UValue);
1338 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001339 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001340 Value = Value >> 32;
1341 }
Scott Michel8efdca42007-12-04 22:23:35 +00001342 if (Value <= 0x3ffff)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001343 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001344 }
1345
Dan Gohman8181bd12008-07-27 21:46:04 +00001346 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001347}
1348
1349/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1350/// and the value fits into a signed 16-bit constant, and if so, return the
1351/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001352SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001353 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001354 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001355 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001356 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001357 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001358 uint32_t upper = uint32_t(UValue >> 32);
1359 uint32_t lower = uint32_t(UValue);
1360 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001361 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001362 Value = Value >> 32;
1363 }
Scott Michel6baba072008-03-05 23:02:02 +00001364 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001365 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001366 }
1367 }
1368
Dan Gohman8181bd12008-07-27 21:46:04 +00001369 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001370}
1371
1372/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1373/// and the value fits into a signed 10-bit constant, and if so, return the
1374/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001375SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001376 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001377 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001378 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001379 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001380 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001381 uint32_t upper = uint32_t(UValue >> 32);
1382 uint32_t lower = uint32_t(UValue);
1383 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001384 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001385 Value = Value >> 32;
1386 }
Scott Michel6baba072008-03-05 23:02:02 +00001387 if (isS10Constant(Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001388 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001389 }
1390
Dan Gohman8181bd12008-07-27 21:46:04 +00001391 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001392}
1393
1394/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1395/// and the value fits into a signed 8-bit constant, and if so, return the
1396/// constant.
1397///
1398/// @note: The incoming vector is v16i8 because that's the only way we can load
1399/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1400/// same value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001401SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001402 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001403 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001404 int Value = (int) CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001405 if (ValueType == MVT::i16
Scott Michel5a6f17b2008-01-30 02:55:46 +00001406 && Value <= 0xffff /* truncated from uint64_t */
1407 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001408 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001409 else if (ValueType == MVT::i8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001410 && (Value & 0xff) == Value)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001411 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001412 }
1413
Dan Gohman8181bd12008-07-27 21:46:04 +00001414 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001415}
1416
1417/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1418/// and the value fits into a signed 16-bit constant, and if so, return the
1419/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001420SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001421 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001422 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001423 uint64_t Value = CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001424 if ((ValueType == MVT::i32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001425 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1426 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001427 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001428 }
1429
Dan Gohman8181bd12008-07-27 21:46:04 +00001430 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001431}
1432
1433/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001434SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001435 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001436 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001437 }
1438
Dan Gohman8181bd12008-07-27 21:46:04 +00001439 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001440}
1441
1442/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001443SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001444 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001445 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001446 }
1447
Dan Gohman8181bd12008-07-27 21:46:04 +00001448 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001449}
1450
1451// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001452// UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001453// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1454// zero. Return true if this is not an array of constants, false if it is.
1455//
1456static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1457 uint64_t UndefBits[2]) {
1458 // Start with zero'd results.
1459 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001460
Duncan Sands92c43912008-06-06 12:08:01 +00001461 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel8efdca42007-12-04 22:23:35 +00001462 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001463 SDValue OpVal = BV->getOperand(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001464
Scott Michel8efdca42007-12-04 22:23:35 +00001465 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1466 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1467
1468 uint64_t EltBits = 0;
1469 if (OpVal.getOpcode() == ISD::UNDEF) {
1470 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1471 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1472 continue;
Scott Michel5974f432008-11-11 03:06:06 +00001473 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001474 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel5974f432008-11-11 03:06:06 +00001475 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001476 const APFloat &apf = CN->getValueAPF();
1477 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001478 ? FloatToBits(apf.convertToFloat())
1479 : DoubleToBits(apf.convertToDouble()));
Scott Michel8efdca42007-12-04 22:23:35 +00001480 } else {
1481 // Nonconstant element.
1482 return true;
1483 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001484
Scott Michel8efdca42007-12-04 22:23:35 +00001485 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1486 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001487
1488 //printf("%llx %llx %llx %llx\n",
Scott Michel8efdca42007-12-04 22:23:35 +00001489 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1490 return false;
1491}
1492
1493/// If this is a splat (repetition) of a value across the whole vector, return
1494/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel4ec722e2008-07-16 17:17:29 +00001495/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel8efdca42007-12-04 22:23:35 +00001496/// SplatSize = 1 byte.
Scott Michel4ec722e2008-07-16 17:17:29 +00001497static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel8efdca42007-12-04 22:23:35 +00001498 const uint64_t Undef128[2],
Scott Michel5a6f17b2008-01-30 02:55:46 +00001499 int MinSplatBits,
Scott Michel8efdca42007-12-04 22:23:35 +00001500 uint64_t &SplatBits, uint64_t &SplatUndef,
1501 int &SplatSize) {
1502 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1503 // the same as the lower 64-bits, ignoring undefs.
1504 uint64_t Bits64 = Bits128[0] | Bits128[1];
1505 uint64_t Undef64 = Undef128[0] & Undef128[1];
1506 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1507 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1508 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1509 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1510
1511 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1512 if (MinSplatBits < 64) {
Scott Michel4ec722e2008-07-16 17:17:29 +00001513
Scott Michel8efdca42007-12-04 22:23:35 +00001514 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1515 // undefs.
1516 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001517 if (MinSplatBits < 32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001518
Scott Michel5a6f17b2008-01-30 02:55:46 +00001519 // If the top 16-bits are different than the lower 16-bits, ignoring
1520 // undefs, we have an i32 splat.
1521 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1522 if (MinSplatBits < 16) {
1523 // If the top 8-bits are different than the lower 8-bits, ignoring
1524 // undefs, we have an i16 splat.
Gabor Greife9f7f582008-08-31 15:37:04 +00001525 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1526 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001527 // Otherwise, we have an 8-bit splat.
1528 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1529 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1530 SplatSize = 1;
1531 return true;
1532 }
1533 } else {
1534 SplatBits = Bits16;
1535 SplatUndef = Undef16;
1536 SplatSize = 2;
1537 return true;
1538 }
1539 }
1540 } else {
1541 SplatBits = Bits32;
1542 SplatUndef = Undef32;
1543 SplatSize = 4;
1544 return true;
1545 }
Scott Michel8efdca42007-12-04 22:23:35 +00001546 }
1547 } else {
1548 SplatBits = Bits128[0];
1549 SplatUndef = Undef128[0];
1550 SplatSize = 8;
1551 return true;
1552 }
1553 }
1554
1555 return false; // Can't be a splat if two pieces don't match.
1556}
1557
1558// If this is a case we can't handle, return null and let the default
1559// expansion code take care of it. If we CAN select this case, and if it
1560// selects to a single instruction, return Op. Otherwise, if we can codegen
1561// this case more efficiently than a constant pool load, lower it to the
1562// sequence of ops that should be used.
Dan Gohman8181bd12008-07-27 21:46:04 +00001563static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001564 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00001565 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001566 // UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001567 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel4ec722e2008-07-16 17:17:29 +00001568 // zero.
Scott Michel8efdca42007-12-04 22:23:35 +00001569 uint64_t VectorBits[2];
1570 uint64_t UndefBits[2];
1571 uint64_t SplatBits, SplatUndef;
1572 int SplatSize;
Gabor Greif1c80d112008-08-28 21:40:38 +00001573 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel8efdca42007-12-04 22:23:35 +00001574 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00001575 VT.getVectorElementType().getSizeInBits(),
Scott Michel8efdca42007-12-04 22:23:35 +00001576 SplatBits, SplatUndef, SplatSize))
Dan Gohman8181bd12008-07-27 21:46:04 +00001577 return SDValue(); // Not a constant vector, not a splat.
Scott Michel4ec722e2008-07-16 17:17:29 +00001578
Duncan Sands92c43912008-06-06 12:08:01 +00001579 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001580 default:
1581 case MVT::v4f32: {
1582 uint32_t Value32 = SplatBits;
1583 assert(SplatSize == 4
Scott Michel5a6f17b2008-01-30 02:55:46 +00001584 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel8efdca42007-12-04 22:23:35 +00001585 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001586 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001587 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001588 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001589 break;
1590 }
1591 case MVT::v2f64: {
1592 uint64_t f64val = SplatBits;
1593 assert(SplatSize == 8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001594 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel8efdca42007-12-04 22:23:35 +00001595 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001596 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001597 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001598 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001599 break;
1600 }
1601 case MVT::v16i8: {
1602 // 8-bit constants have to be expanded to 16-bits
1603 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman8181bd12008-07-27 21:46:04 +00001604 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001605 for (int i = 0; i < 8; ++i)
1606 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1607 return DAG.getNode(ISD::BIT_CONVERT, VT,
1608 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1609 }
1610 case MVT::v8i16: {
1611 unsigned short Value16;
Scott Michel4ec722e2008-07-16 17:17:29 +00001612 if (SplatSize == 2)
Scott Michel8efdca42007-12-04 22:23:35 +00001613 Value16 = (unsigned short) (SplatBits & 0xffff);
1614 else
1615 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman8181bd12008-07-27 21:46:04 +00001616 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1617 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001618 for (int i = 0; i < 8; ++i) Ops[i] = T;
1619 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1620 }
1621 case MVT::v4i32: {
1622 unsigned int Value = SplatBits;
Dan Gohman8181bd12008-07-27 21:46:04 +00001623 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel8efdca42007-12-04 22:23:35 +00001624 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1625 }
1626 case MVT::v2i64: {
1627 uint64_t val = SplatBits;
1628 uint32_t upper = uint32_t(val >> 32);
1629 uint32_t lower = uint32_t(val);
1630
Scott Michelbcc7b672008-03-06 04:02:54 +00001631 if (upper == lower) {
1632 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman8181bd12008-07-27 21:46:04 +00001633 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michelbcc7b672008-03-06 04:02:54 +00001634 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michel6baba072008-03-05 23:02:02 +00001635 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +00001636 SDValue LO32;
1637 SDValue HI32;
1638 SmallVector<SDValue, 16> ShufBytes;
1639 SDValue Result;
Scott Michel8efdca42007-12-04 22:23:35 +00001640 bool upper_special, lower_special;
1641
1642 // NOTE: This code creates common-case shuffle masks that can be easily
1643 // detected as common expressions. It is not attempting to create highly
1644 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1645
1646 // Detect if the upper or lower half is a special shuffle mask pattern:
1647 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1648 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1649
1650 // Create lower vector if not a special pattern
1651 if (!lower_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001652 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001653 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1654 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1655 LO32C, LO32C, LO32C, LO32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001656 }
1657
1658 // Create upper vector if not a special pattern
1659 if (!upper_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001660 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001661 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1662 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1663 HI32C, HI32C, HI32C, HI32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001664 }
1665
1666 // If either upper or lower are special, then the two input operands are
1667 // the same (basically, one of them is a "don't care")
1668 if (lower_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001669 LO32 = HI32;
Scott Michel8efdca42007-12-04 22:23:35 +00001670 if (upper_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001671 HI32 = LO32;
Scott Michel8efdca42007-12-04 22:23:35 +00001672 if (lower_special && upper_special) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001673 // Unhappy situation... both upper and lower are special, so punt with
1674 // a target constant:
Dan Gohman8181bd12008-07-27 21:46:04 +00001675 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001676 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel8efdca42007-12-04 22:23:35 +00001677 Zero, Zero);
1678 }
1679
1680 for (int i = 0; i < 4; ++i) {
Scott Michel67224b22008-06-02 22:18:03 +00001681 uint64_t val = 0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001682 for (int j = 0; j < 4; ++j) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001683 SDValue V;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001684 bool process_upper, process_lower;
Scott Michel67224b22008-06-02 22:18:03 +00001685 val <<= 8;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001686 process_upper = (upper_special && (i & 1) == 0);
1687 process_lower = (lower_special && (i & 1) == 1);
Scott Michel8efdca42007-12-04 22:23:35 +00001688
Scott Michel5a6f17b2008-01-30 02:55:46 +00001689 if (process_upper || process_lower) {
1690 if ((process_upper && upper == 0)
1691 || (process_lower && lower == 0))
Scott Michel67224b22008-06-02 22:18:03 +00001692 val |= 0x80;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001693 else if ((process_upper && upper == 0xffffffff)
1694 || (process_lower && lower == 0xffffffff))
Scott Michel67224b22008-06-02 22:18:03 +00001695 val |= 0xc0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001696 else if ((process_upper && upper == 0x80000000)
1697 || (process_lower && lower == 0x80000000))
Scott Michel67224b22008-06-02 22:18:03 +00001698 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001699 } else
Scott Michel67224b22008-06-02 22:18:03 +00001700 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001701 }
Scott Michel67224b22008-06-02 22:18:03 +00001702
1703 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001704 }
1705
1706 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel67224b22008-06-02 22:18:03 +00001707 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001708 &ShufBytes[0], ShufBytes.size()));
Scott Michel8efdca42007-12-04 22:23:35 +00001709 }
1710 }
1711 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001712
Dan Gohman8181bd12008-07-27 21:46:04 +00001713 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001714}
1715
1716/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1717/// which the Cell can operate. The code inspects V3 to ascertain whether the
1718/// permutation vector, V3, is monotonically increasing with one "exception"
1719/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1720/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1721/// In either case, the net result is going to eventually invoke SHUFB to
1722/// permute/shuffle the bytes from V1 and V2.
1723/// \note
1724/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1725/// control word for byte/halfword/word insertion. This takes care of a single
1726/// element move from V2 into V1.
1727/// \note
1728/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman8181bd12008-07-27 21:46:04 +00001729static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1730 SDValue V1 = Op.getOperand(0);
1731 SDValue V2 = Op.getOperand(1);
1732 SDValue PermMask = Op.getOperand(2);
Scott Michel4ec722e2008-07-16 17:17:29 +00001733
Scott Michel8efdca42007-12-04 22:23:35 +00001734 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel4ec722e2008-07-16 17:17:29 +00001735
Scott Michel8efdca42007-12-04 22:23:35 +00001736 // If we have a single element being moved from V1 to V2, this can be handled
1737 // using the C*[DX] compute mask instructions, but the vector elements have
1738 // to be monotonically increasing with one exception element.
Duncan Sands92c43912008-06-06 12:08:01 +00001739 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel8efdca42007-12-04 22:23:35 +00001740 unsigned EltsFromV2 = 0;
1741 unsigned V2Elt = 0;
1742 unsigned V2EltIdx0 = 0;
1743 unsigned CurrElt = 0;
1744 bool monotonic = true;
1745 if (EltVT == MVT::i8)
1746 V2EltIdx0 = 16;
1747 else if (EltVT == MVT::i16)
1748 V2EltIdx0 = 8;
1749 else if (EltVT == MVT::i32)
1750 V2EltIdx0 = 4;
1751 else
1752 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1753
1754 for (unsigned i = 0, e = PermMask.getNumOperands();
1755 EltsFromV2 <= 1 && monotonic && i != e;
1756 ++i) {
1757 unsigned SrcElt;
1758 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1759 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001760 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001761 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001762
1763 if (SrcElt >= V2EltIdx0) {
1764 ++EltsFromV2;
1765 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1766 } else if (CurrElt != SrcElt) {
1767 monotonic = false;
1768 }
1769
1770 ++CurrElt;
1771 }
1772
1773 if (EltsFromV2 == 1 && monotonic) {
1774 // Compute mask and shuffle
1775 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001776 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1777 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands92c43912008-06-06 12:08:01 +00001778 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00001779 // Initialize temporary register to 0
Dan Gohman8181bd12008-07-27 21:46:04 +00001780 SDValue InitTempReg =
Scott Michel8efdca42007-12-04 22:23:35 +00001781 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1782 // Copy register's contents as index in INSERT_MASK:
Dan Gohman8181bd12008-07-27 21:46:04 +00001783 SDValue ShufMaskOp =
Scott Michel8efdca42007-12-04 22:23:35 +00001784 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001785 DAG.getTargetConstant(V2Elt, MVT::i32),
1786 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +00001787 // Use shuffle mask in SHUFB synthetic instruction:
1788 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1789 } else {
Gabor Greife9f7f582008-08-31 15:37:04 +00001790 // Convert the SHUFFLE_VECTOR mask's input element units to the
1791 // actual bytes.
Duncan Sands92c43912008-06-06 12:08:01 +00001792 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel4ec722e2008-07-16 17:17:29 +00001793
Dan Gohman8181bd12008-07-27 21:46:04 +00001794 SmallVector<SDValue, 16> ResultMask;
Scott Michel8efdca42007-12-04 22:23:35 +00001795 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1796 unsigned SrcElt;
1797 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001798 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001799 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001800 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel4ec722e2008-07-16 17:17:29 +00001801
Scott Michel97872d32008-02-23 18:41:37 +00001802 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001803 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1804 MVT::i8));
Scott Michel8efdca42007-12-04 22:23:35 +00001805 }
1806 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001807
Dan Gohman8181bd12008-07-27 21:46:04 +00001808 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001809 &ResultMask[0], ResultMask.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001810 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1811 }
1812}
1813
Dan Gohman8181bd12008-07-27 21:46:04 +00001814static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1815 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel8efdca42007-12-04 22:23:35 +00001816
Gabor Greif1c80d112008-08-28 21:40:38 +00001817 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel8efdca42007-12-04 22:23:35 +00001818 // For a constant, build the appropriate constant vector, which will
1819 // eventually simplify to a vector register load.
1820
Gabor Greif1c80d112008-08-28 21:40:38 +00001821 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman8181bd12008-07-27 21:46:04 +00001822 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands92c43912008-06-06 12:08:01 +00001823 MVT VT;
Scott Michel8efdca42007-12-04 22:23:35 +00001824 size_t n_copies;
1825
1826 // Create a constant vector:
Duncan Sands92c43912008-06-06 12:08:01 +00001827 switch (Op.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001828 default: assert(0 && "Unexpected constant value type in "
Scott Michel5a6f17b2008-01-30 02:55:46 +00001829 "LowerSCALAR_TO_VECTOR");
Scott Michel8efdca42007-12-04 22:23:35 +00001830 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1831 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1832 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1833 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1834 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1835 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1836 }
1837
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001838 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel8efdca42007-12-04 22:23:35 +00001839 for (size_t j = 0; j < n_copies; ++j)
1840 ConstVecValues.push_back(CValue);
1841
1842 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001843 &ConstVecValues[0], ConstVecValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001844 } else {
1845 // Otherwise, copy the value from one register to another:
Duncan Sands92c43912008-06-06 12:08:01 +00001846 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001847 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1848 case MVT::i8:
1849 case MVT::i16:
1850 case MVT::i32:
1851 case MVT::i64:
1852 case MVT::f32:
1853 case MVT::f64:
1854 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1855 }
1856 }
1857
Dan Gohman8181bd12008-07-27 21:46:04 +00001858 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001859}
1860
Dan Gohman8181bd12008-07-27 21:46:04 +00001861static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001862 switch (Op.getValueType().getSimpleVT()) {
1863 default:
1864 cerr << "CellSPU: Unknown vector multiplication, got "
1865 << Op.getValueType().getMVTString()
1866 << "\n";
1867 abort();
1868 /*NOTREACHED*/
1869
Scott Michel8efdca42007-12-04 22:23:35 +00001870 case MVT::v4i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001871 SDValue rA = Op.getOperand(0);
1872 SDValue rB = Op.getOperand(1);
1873 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1874 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1875 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1876 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel8efdca42007-12-04 22:23:35 +00001877
1878 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1879 break;
1880 }
1881
1882 // Multiply two v8i16 vectors (pipeline friendly version):
1883 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1884 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1885 // c) Use SELB to select upper and lower halves from the intermediate results
1886 //
Scott Michel67224b22008-06-02 22:18:03 +00001887 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel8efdca42007-12-04 22:23:35 +00001888 // dual-issue. This code does manage to do this, even if it's a little on
1889 // the wacky side
1890 case MVT::v8i16: {
1891 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001892 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman8181bd12008-07-27 21:46:04 +00001893 SDValue Chain = Op.getOperand(0);
1894 SDValue rA = Op.getOperand(0);
1895 SDValue rB = Op.getOperand(1);
Chris Lattner1b989192007-12-31 04:13:23 +00001896 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1897 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00001898
Dan Gohman8181bd12008-07-27 21:46:04 +00001899 SDValue FSMBOp =
Scott Michel8efdca42007-12-04 22:23:35 +00001900 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel67224b22008-06-02 22:18:03 +00001901 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001902 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel8efdca42007-12-04 22:23:35 +00001903
Dan Gohman8181bd12008-07-27 21:46:04 +00001904 SDValue HHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001905 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001906 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001907
Dan Gohman8181bd12008-07-27 21:46:04 +00001908 SDValue HHProd_v4i32 =
Scott Michel8efdca42007-12-04 22:23:35 +00001909 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001910 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001911
1912 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001913 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1914 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1915 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1916 HHProd_v4i32,
1917 DAG.getConstant(16, MVT::i16))),
1918 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001919 }
1920
1921 // This M00sE is N@stI! (apologies to Monty Python)
1922 //
1923 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1924 // is to break it all apart, sign extend, and reassemble the various
1925 // intermediate products.
1926 case MVT::v16i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001927 SDValue rA = Op.getOperand(0);
1928 SDValue rB = Op.getOperand(1);
1929 SDValue c8 = DAG.getConstant(8, MVT::i32);
1930 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001931
Dan Gohman8181bd12008-07-27 21:46:04 +00001932 SDValue LLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001933 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001934 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1935 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001936
Dan Gohman8181bd12008-07-27 21:46:04 +00001937 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001938
Dan Gohman8181bd12008-07-27 21:46:04 +00001939 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001940
Dan Gohman8181bd12008-07-27 21:46:04 +00001941 SDValue LHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001942 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001943 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001944
Dan Gohman8181bd12008-07-27 21:46:04 +00001945 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001946 DAG.getConstant(0x2222, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001947
Dan Gohman8181bd12008-07-27 21:46:04 +00001948 SDValue LoProdParts =
Scott Michel97872d32008-02-23 18:41:37 +00001949 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1950 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1951 LLProd, LHProd, FSMBmask));
Scott Michel8efdca42007-12-04 22:23:35 +00001952
Dan Gohman8181bd12008-07-27 21:46:04 +00001953 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001954
Dan Gohman8181bd12008-07-27 21:46:04 +00001955 SDValue LoProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001956 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michel97872d32008-02-23 18:41:37 +00001957 LoProdParts,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001958 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1959 LoProdMask, LoProdMask,
1960 LoProdMask, LoProdMask));
Scott Michel8efdca42007-12-04 22:23:35 +00001961
Dan Gohman8181bd12008-07-27 21:46:04 +00001962 SDValue rAH =
Scott Michel8efdca42007-12-04 22:23:35 +00001963 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001964 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00001965
Dan Gohman8181bd12008-07-27 21:46:04 +00001966 SDValue rBH =
Scott Michel8efdca42007-12-04 22:23:35 +00001967 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001968 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00001969
Dan Gohman8181bd12008-07-27 21:46:04 +00001970 SDValue HLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001971 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001972 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
1973 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel8efdca42007-12-04 22:23:35 +00001974
Dan Gohman8181bd12008-07-27 21:46:04 +00001975 SDValue HHProd_1 =
Scott Michel8efdca42007-12-04 22:23:35 +00001976 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001977 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00001978 DAG.getNode(SPUISD::VEC_SRA,
1979 MVT::v4i32, rAH, c8)),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001980 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00001981 DAG.getNode(SPUISD::VEC_SRA,
1982 MVT::v4i32, rBH, c8)));
Scott Michel8efdca42007-12-04 22:23:35 +00001983
Dan Gohman8181bd12008-07-27 21:46:04 +00001984 SDValue HHProd =
Scott Michel97872d32008-02-23 18:41:37 +00001985 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1986 HLProd,
1987 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
1988 FSMBmask);
Scott Michel8efdca42007-12-04 22:23:35 +00001989
Dan Gohman8181bd12008-07-27 21:46:04 +00001990 SDValue HiProd =
Scott Michel97872d32008-02-23 18:41:37 +00001991 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel8efdca42007-12-04 22:23:35 +00001992
1993 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001994 DAG.getNode(ISD::OR, MVT::v4i32,
1995 LoProd, HiProd));
Scott Michel8efdca42007-12-04 22:23:35 +00001996 }
Scott Michel8efdca42007-12-04 22:23:35 +00001997 }
1998
Dan Gohman8181bd12008-07-27 21:46:04 +00001999 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002000}
2001
Dan Gohman8181bd12008-07-27 21:46:04 +00002002static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00002003 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002004 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002005
Dan Gohman8181bd12008-07-27 21:46:04 +00002006 SDValue A = Op.getOperand(0);
2007 SDValue B = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002008 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002009
2010 unsigned VRegBR, VRegC;
2011
2012 if (VT == MVT::f32) {
Chris Lattner1b989192007-12-31 04:13:23 +00002013 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2014 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002015 } else {
Chris Lattner1b989192007-12-31 04:13:23 +00002016 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2017 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002018 }
2019 // TODO: make sure we're feeding FPInterp the right arguments
2020 // Right now: fi B, frest(B)
2021
2022 // Computes BRcpl =
2023 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman8181bd12008-07-27 21:46:04 +00002024 SDValue BRcpl =
Scott Michel4ec722e2008-07-16 17:17:29 +00002025 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2026 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002027 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002028
Scott Michel8efdca42007-12-04 22:23:35 +00002029 // Computes A * BRcpl and stores in a temporary register
Dan Gohman8181bd12008-07-27 21:46:04 +00002030 SDValue AxBRcpl =
Scott Michel8efdca42007-12-04 22:23:35 +00002031 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel4ec722e2008-07-16 17:17:29 +00002032 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002033 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel8efdca42007-12-04 22:23:35 +00002034 // What's the Chain variable do? It's magic!
2035 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel4ec722e2008-07-16 17:17:29 +00002036
2037 return DAG.getNode(ISD::FADD, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002038 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel4ec722e2008-07-16 17:17:29 +00002039 DAG.getNode(ISD::FMUL, VT,
2040 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002041 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel4ec722e2008-07-16 17:17:29 +00002042 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002043 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel8efdca42007-12-04 22:23:35 +00002044}
2045
Dan Gohman8181bd12008-07-27 21:46:04 +00002046static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002047 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002048 SDValue N = Op.getOperand(0);
2049 SDValue Elt = Op.getOperand(1);
2050 SDValue ShufMask[16];
Scott Michel5974f432008-11-11 03:06:06 +00002051 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
Scott Michel8efdca42007-12-04 22:23:35 +00002052
2053 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2054
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002055 int EltNo = (int) C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002056
2057 // sanity checks:
2058 if (VT == MVT::i8 && EltNo >= 16)
2059 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2060 else if (VT == MVT::i16 && EltNo >= 8)
2061 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2062 else if (VT == MVT::i32 && EltNo >= 4)
2063 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2064 else if (VT == MVT::i64 && EltNo >= 2)
2065 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2066
2067 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2068 // i32 and i64: Element 0 is the preferred slot
2069 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2070 }
2071
2072 // Need to generate shuffle mask and extract:
Scott Michel4c07cbd2007-12-19 21:17:42 +00002073 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands92c43912008-06-06 12:08:01 +00002074 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel8efdca42007-12-04 22:23:35 +00002075
Duncan Sands92c43912008-06-06 12:08:01 +00002076 switch (VT.getSimpleVT()) {
2077 default:
2078 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002079 case MVT::i8: {
2080 prefslot_begin = prefslot_end = 3;
2081 break;
2082 }
2083 case MVT::i16: {
2084 prefslot_begin = 2; prefslot_end = 3;
2085 break;
2086 }
Scott Michel6e2d68b2008-11-10 23:43:06 +00002087 case MVT::i32:
2088 case MVT::f32: {
Scott Michel8efdca42007-12-04 22:23:35 +00002089 prefslot_begin = 0; prefslot_end = 3;
2090 break;
2091 }
Scott Michel6e2d68b2008-11-10 23:43:06 +00002092 case MVT::i64:
2093 case MVT::f64: {
Scott Michel8efdca42007-12-04 22:23:35 +00002094 prefslot_begin = 0; prefslot_end = 7;
2095 break;
2096 }
2097 }
2098
Scott Michel4c07cbd2007-12-19 21:17:42 +00002099 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel5a6f17b2008-01-30 02:55:46 +00002100 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel4c07cbd2007-12-19 21:17:42 +00002101
Scott Michel8efdca42007-12-04 22:23:35 +00002102 for (int i = 0; i < 16; ++i) {
2103 // zero fill uppper part of preferred slot, don't care about the
2104 // other slots:
2105 unsigned int mask_val;
2106
2107 if (i <= prefslot_end) {
2108 mask_val =
Scott Michel5a6f17b2008-01-30 02:55:46 +00002109 ((i < prefslot_begin)
2110 ? 0x80
2111 : elt_byte + (i - prefslot_begin));
Scott Michel8efdca42007-12-04 22:23:35 +00002112
Scott Michel4c07cbd2007-12-19 21:17:42 +00002113 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel4ec722e2008-07-16 17:17:29 +00002114 } else
Scott Michel8efdca42007-12-04 22:23:35 +00002115 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2116 }
2117
Dan Gohman8181bd12008-07-27 21:46:04 +00002118 SDValue ShufMaskVec =
Scott Michel8efdca42007-12-04 22:23:35 +00002119 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002120 &ShufMask[0],
2121 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel8efdca42007-12-04 22:23:35 +00002122
2123 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002124 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2125 N, N, ShufMaskVec));
Scott Michel4ec722e2008-07-16 17:17:29 +00002126
Scott Michel8efdca42007-12-04 22:23:35 +00002127}
2128
Dan Gohman8181bd12008-07-27 21:46:04 +00002129static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2130 SDValue VecOp = Op.getOperand(0);
2131 SDValue ValOp = Op.getOperand(1);
2132 SDValue IdxOp = Op.getOperand(2);
Duncan Sands92c43912008-06-06 12:08:01 +00002133 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002134
2135 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2136 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2137
Duncan Sands92c43912008-06-06 12:08:01 +00002138 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00002139 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman8181bd12008-07-27 21:46:04 +00002140 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +00002141
Dan Gohman8181bd12008-07-27 21:46:04 +00002142 SDValue result =
Scott Michel8efdca42007-12-04 22:23:35 +00002143 DAG.getNode(SPUISD::SHUFB, VT,
2144 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2145 VecOp,
2146 DAG.getNode(SPUISD::INSERT_MASK, VT,
2147 DAG.getNode(ISD::ADD, PtrVT,
2148 PtrBase,
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002149 DAG.getConstant(CN->getZExtValue(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002150 PtrVT))));
Scott Michel8efdca42007-12-04 22:23:35 +00002151
2152 return result;
2153}
2154
Dan Gohman8181bd12008-07-27 21:46:04 +00002155static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002156{
Dan Gohman8181bd12008-07-27 21:46:04 +00002157 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel8efdca42007-12-04 22:23:35 +00002158
2159 assert(Op.getValueType() == MVT::i8);
2160 switch (Opc) {
2161 default:
2162 assert(0 && "Unhandled i8 math operator");
2163 /*NOTREACHED*/
2164 break;
2165 case ISD::SUB: {
2166 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2167 // the result:
Dan Gohman8181bd12008-07-27 21:46:04 +00002168 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002169 N0 = (N0.getOpcode() != ISD::Constant
2170 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002171 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2172 MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00002173 N1 = (N1.getOpcode() != ISD::Constant
2174 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002175 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2176 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002177 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002178 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel4ec722e2008-07-16 17:17:29 +00002179 }
Scott Michel8efdca42007-12-04 22:23:35 +00002180 case ISD::ROTR:
2181 case ISD::ROTL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002182 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002183 unsigned N1Opc;
2184 N0 = (N0.getOpcode() != ISD::Constant
2185 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002186 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2187 MVT::i16));
Duncan Sands7aef60d2008-10-30 19:24:28 +00002188 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greife9f7f582008-08-31 15:37:04 +00002189 ? ISD::ZERO_EXTEND
2190 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002191 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sands7aef60d2008-10-30 19:24:28 +00002192 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002193 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sands7aef60d2008-10-30 19:24:28 +00002194 MVT::i32));
Dan Gohman8181bd12008-07-27 21:46:04 +00002195 SDValue ExpandArg =
Scott Michel8efdca42007-12-04 22:23:35 +00002196 DAG.getNode(ISD::OR, MVT::i16, N0,
2197 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sands7aef60d2008-10-30 19:24:28 +00002198 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002199 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002200 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2201 }
2202 case ISD::SRL:
2203 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002204 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002205 unsigned N1Opc;
2206 N0 = (N0.getOpcode() != ISD::Constant
2207 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002208 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2209 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002210 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2211 ? ISD::ZERO_EXTEND
2212 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002213 N1 = (N1.getOpcode() != ISD::Constant
2214 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002215 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2216 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002217 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002218 DAG.getNode(Opc, MVT::i16, N0, N1));
2219 }
2220 case ISD::SRA: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002221 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002222 unsigned N1Opc;
2223 N0 = (N0.getOpcode() != ISD::Constant
2224 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002225 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2226 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002227 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2228 ? ISD::SIGN_EXTEND
2229 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002230 N1 = (N1.getOpcode() != ISD::Constant
2231 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002232 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2233 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002234 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002235 DAG.getNode(Opc, MVT::i16, N0, N1));
2236 }
2237 case ISD::MUL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002238 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002239 unsigned N1Opc;
2240 N0 = (N0.getOpcode() != ISD::Constant
2241 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002242 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2243 MVT::i16));
Duncan Sandsec142ee2008-06-08 20:54:56 +00002244 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002245 N1 = (N1.getOpcode() != ISD::Constant
2246 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002247 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2248 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002249 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002250 DAG.getNode(Opc, MVT::i16, N0, N1));
2251 break;
2252 }
2253 }
2254
Dan Gohman8181bd12008-07-27 21:46:04 +00002255 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002256}
2257
Dan Gohman8181bd12008-07-27 21:46:04 +00002258static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002259{
Duncan Sands92c43912008-06-06 12:08:01 +00002260 MVT VT = Op.getValueType();
2261 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002262
Dan Gohman8181bd12008-07-27 21:46:04 +00002263 SDValue Op0 = Op.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002264
2265 switch (Opc) {
2266 case ISD::ZERO_EXTEND:
2267 case ISD::SIGN_EXTEND:
2268 case ISD::ANY_EXTEND: {
Duncan Sands92c43912008-06-06 12:08:01 +00002269 MVT Op0VT = Op0.getValueType();
2270 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002271
2272 assert(Op0VT == MVT::i32
2273 && "CellSPU: Zero/sign extending something other than i32");
Scott Michelbc5fbc12008-04-30 00:30:08 +00002274 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michel97872d32008-02-23 18:41:37 +00002275
2276 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2277 ? SPUISD::ROTBYTES_RIGHT_S
2278 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman8181bd12008-07-27 21:46:04 +00002279 SDValue PromoteScalar =
Scott Michel97872d32008-02-23 18:41:37 +00002280 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2281
2282 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2283 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2284 DAG.getNode(NewOpc, Op0VecVT,
2285 PromoteScalar,
2286 DAG.getConstant(4, MVT::i32))));
2287 }
2288
Scott Michel67224b22008-06-02 22:18:03 +00002289 case ISD::ADD: {
2290 // Turn operands into vectors to satisfy type checking (shufb works on
2291 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002292 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002293 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002294 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002295 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002296 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002297
2298 // Create the shuffle mask for "rotating" the borrow up one register slot
2299 // once the borrow is generated.
2300 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2301 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2302 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2303 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2304
Dan Gohman8181bd12008-07-27 21:46:04 +00002305 SDValue CarryGen =
Scott Michel67224b22008-06-02 22:18:03 +00002306 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002307 SDValue ShiftedCarry =
Scott Michel67224b22008-06-02 22:18:03 +00002308 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2309 CarryGen, CarryGen,
2310 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2311 &ShufBytes[0], ShufBytes.size()));
2312
2313 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2314 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2315 Op0, Op1, ShiftedCarry));
2316 }
2317
2318 case ISD::SUB: {
2319 // Turn operands into vectors to satisfy type checking (shufb works on
2320 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002321 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002322 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002323 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002324 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002325 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002326
2327 // Create the shuffle mask for "rotating" the borrow up one register slot
2328 // once the borrow is generated.
2329 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2330 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2331 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2332 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2333
Dan Gohman8181bd12008-07-27 21:46:04 +00002334 SDValue BorrowGen =
Scott Michel67224b22008-06-02 22:18:03 +00002335 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002336 SDValue ShiftedBorrow =
Scott Michel67224b22008-06-02 22:18:03 +00002337 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2338 BorrowGen, BorrowGen,
2339 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2340 &ShufBytes[0], ShufBytes.size()));
2341
2342 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2343 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2344 Op0, Op1, ShiftedBorrow));
2345 }
2346
Scott Michel97872d32008-02-23 18:41:37 +00002347 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002348 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002349 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002350 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2351 SDValue MaskLower =
Scott Michel97872d32008-02-23 18:41:37 +00002352 DAG.getNode(SPUISD::SELB, VecVT,
2353 Op0Vec,
2354 DAG.getConstant(0, VecVT),
Scott Michel67224b22008-06-02 22:18:03 +00002355 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michel97872d32008-02-23 18:41:37 +00002356 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman8181bd12008-07-27 21:46:04 +00002357 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002358 DAG.getNode(ISD::SRL, ShiftAmtVT,
2359 ShiftAmt,
2360 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002361 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002362 DAG.getNode(ISD::AND, ShiftAmtVT,
2363 ShiftAmt,
2364 DAG.getConstant(7, ShiftAmtVT));
2365
2366 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2367 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2368 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2369 MaskLower, ShiftAmtBytes),
2370 ShiftAmtBits));
2371 }
2372
2373 case ISD::SRL: {
Duncan Sands92c43912008-06-06 12:08:01 +00002374 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002375 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002376 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002377 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002378 DAG.getNode(ISD::SRL, ShiftAmtVT,
2379 ShiftAmt,
2380 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002381 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002382 DAG.getNode(ISD::AND, ShiftAmtVT,
2383 ShiftAmt,
2384 DAG.getConstant(7, ShiftAmtVT));
2385
2386 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2387 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2388 Op0, ShiftAmtBytes),
2389 ShiftAmtBits);
2390 }
Scott Michel67224b22008-06-02 22:18:03 +00002391
2392 case ISD::SRA: {
2393 // Promote Op0 to vector
Dan Gohman8181bd12008-07-27 21:46:04 +00002394 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002395 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002396 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002397 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel67224b22008-06-02 22:18:03 +00002398
2399 // Negate variable shift amounts
2400 if (!isa<ConstantSDNode>(ShiftAmt)) {
2401 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2402 DAG.getConstant(0, ShiftVT), ShiftAmt);
2403 }
2404
Dan Gohman8181bd12008-07-27 21:46:04 +00002405 SDValue UpperHalfSign =
Scott Michel67224b22008-06-02 22:18:03 +00002406 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2407 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2408 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2409 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman8181bd12008-07-27 21:46:04 +00002410 SDValue UpperHalfSignMask =
Scott Michel67224b22008-06-02 22:18:03 +00002411 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman8181bd12008-07-27 21:46:04 +00002412 SDValue UpperLowerMask =
Scott Michel67224b22008-06-02 22:18:03 +00002413 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2414 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman8181bd12008-07-27 21:46:04 +00002415 SDValue UpperLowerSelect =
Scott Michel67224b22008-06-02 22:18:03 +00002416 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2417 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman8181bd12008-07-27 21:46:04 +00002418 SDValue RotateLeftBytes =
Scott Michel67224b22008-06-02 22:18:03 +00002419 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2420 UpperLowerSelect, ShiftAmt);
Dan Gohman8181bd12008-07-27 21:46:04 +00002421 SDValue RotateLeftBits =
Scott Michel67224b22008-06-02 22:18:03 +00002422 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2423 RotateLeftBytes, ShiftAmt);
2424
2425 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2426 RotateLeftBits);
2427 }
Scott Michel97872d32008-02-23 18:41:37 +00002428 }
2429
Dan Gohman8181bd12008-07-27 21:46:04 +00002430 return SDValue();
Scott Michel97872d32008-02-23 18:41:37 +00002431}
2432
Scott Michel8efdca42007-12-04 22:23:35 +00002433//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman8181bd12008-07-27 21:46:04 +00002434static SDValue
2435LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2436 SDValue ConstVec;
2437 SDValue Arg;
Duncan Sands92c43912008-06-06 12:08:01 +00002438 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002439
2440 ConstVec = Op.getOperand(0);
2441 Arg = Op.getOperand(1);
Gabor Greif1c80d112008-08-28 21:40:38 +00002442 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2443 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel8efdca42007-12-04 22:23:35 +00002444 ConstVec = ConstVec.getOperand(0);
2445 } else {
2446 ConstVec = Op.getOperand(1);
2447 Arg = Op.getOperand(0);
Gabor Greif1c80d112008-08-28 21:40:38 +00002448 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00002449 ConstVec = ConstVec.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00002450 }
2451 }
2452 }
2453
Gabor Greif1c80d112008-08-28 21:40:38 +00002454 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel8efdca42007-12-04 22:23:35 +00002455 uint64_t VectorBits[2];
2456 uint64_t UndefBits[2];
2457 uint64_t SplatBits, SplatUndef;
2458 int SplatSize;
2459
Gabor Greif1c80d112008-08-28 21:40:38 +00002460 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002461 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00002462 VT.getVectorElementType().getSizeInBits(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002463 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002464 SDValue tcVec[16];
2465 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel8efdca42007-12-04 22:23:35 +00002466 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2467
2468 // Turn the BUILD_VECTOR into a set of target constants:
2469 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002470 tcVec[i] = tc;
Scott Michel8efdca42007-12-04 22:23:35 +00002471
Gabor Greif1c80d112008-08-28 21:40:38 +00002472 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002473 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel8efdca42007-12-04 22:23:35 +00002474 }
2475 }
Nate Begeman7569e762008-07-29 19:07:27 +00002476 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2477 // lowered. Return the operation, rather than a null SDValue.
2478 return Op;
Scott Michel8efdca42007-12-04 22:23:35 +00002479}
2480
2481//! Lower i32 multiplication
Dan Gohman8181bd12008-07-27 21:46:04 +00002482static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel8efdca42007-12-04 22:23:35 +00002483 unsigned Opc) {
Duncan Sands92c43912008-06-06 12:08:01 +00002484 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00002485 default:
2486 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands92c43912008-06-06 12:08:01 +00002487 << Op.getValueType().getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +00002488 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +00002489 abort();
2490 /*NOTREACHED*/
2491
2492 case MVT::i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002493 SDValue rA = Op.getOperand(0);
2494 SDValue rB = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002495
2496 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002497 DAG.getNode(ISD::ADD, MVT::i32,
2498 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2499 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2500 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00002501 }
2502 }
2503
Dan Gohman8181bd12008-07-27 21:46:04 +00002504 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002505}
2506
2507//! Custom lowering for CTPOP (count population)
2508/*!
2509 Custom lowering code that counts the number ones in the input
2510 operand. SPU has such an instruction, but it counts the number of
2511 ones per byte, which then have to be accumulated.
2512*/
Dan Gohman8181bd12008-07-27 21:46:04 +00002513static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002514 MVT VT = Op.getValueType();
2515 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +00002516
Duncan Sands92c43912008-06-06 12:08:01 +00002517 switch (VT.getSimpleVT()) {
2518 default:
2519 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002520 case MVT::i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002521 SDValue N = Op.getOperand(0);
2522 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002523
Dan Gohman8181bd12008-07-27 21:46:04 +00002524 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2525 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002526
2527 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2528 }
2529
2530 case MVT::i16: {
2531 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002532 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002533
Chris Lattner1b989192007-12-31 04:13:23 +00002534 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002535
Dan Gohman8181bd12008-07-27 21:46:04 +00002536 SDValue N = Op.getOperand(0);
2537 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2538 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sands7aef60d2008-10-30 19:24:28 +00002539 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002540
Dan Gohman8181bd12008-07-27 21:46:04 +00002541 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2542 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002543
2544 // CNTB_result becomes the chain to which all of the virtual registers
2545 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002546 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002547 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002548
Dan Gohman8181bd12008-07-27 21:46:04 +00002549 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002550 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2551
Dan Gohman8181bd12008-07-27 21:46:04 +00002552 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002553
2554 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002555 DAG.getNode(ISD::ADD, MVT::i16,
2556 DAG.getNode(ISD::SRL, MVT::i16,
2557 Tmp1, Shift1),
2558 Tmp1),
2559 Mask0);
Scott Michel8efdca42007-12-04 22:23:35 +00002560 }
2561
2562 case MVT::i32: {
2563 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002564 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002565
Chris Lattner1b989192007-12-31 04:13:23 +00002566 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2567 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002568
Dan Gohman8181bd12008-07-27 21:46:04 +00002569 SDValue N = Op.getOperand(0);
2570 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2571 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2572 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2573 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002574
Dan Gohman8181bd12008-07-27 21:46:04 +00002575 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2576 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002577
2578 // CNTB_result becomes the chain to which all of the virtual registers
2579 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002580 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002581 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002582
Dan Gohman8181bd12008-07-27 21:46:04 +00002583 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002584 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2585
Dan Gohman8181bd12008-07-27 21:46:04 +00002586 SDValue Comp1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002587 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002588 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel8efdca42007-12-04 22:23:35 +00002589
Dan Gohman8181bd12008-07-27 21:46:04 +00002590 SDValue Sum1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002591 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002592 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002593
Dan Gohman8181bd12008-07-27 21:46:04 +00002594 SDValue Sum1_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002595 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2596
Dan Gohman8181bd12008-07-27 21:46:04 +00002597 SDValue Comp2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002598 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002599 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2600 Shift2);
Dan Gohman8181bd12008-07-27 21:46:04 +00002601 SDValue Sum2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002602 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002603 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002604
2605 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2606 }
2607
2608 case MVT::i64:
2609 break;
2610 }
2611
Dan Gohman8181bd12008-07-27 21:46:04 +00002612 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002613}
2614
2615/// LowerOperation - Provide custom lowering hooks for some operations.
2616///
Dan Gohman8181bd12008-07-27 21:46:04 +00002617SDValue
2618SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel8efdca42007-12-04 22:23:35 +00002619{
Scott Michel97872d32008-02-23 18:41:37 +00002620 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands92c43912008-06-06 12:08:01 +00002621 MVT VT = Op.getValueType();
Scott Michel97872d32008-02-23 18:41:37 +00002622
2623 switch (Opc) {
Scott Michel8efdca42007-12-04 22:23:35 +00002624 default: {
2625 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michel97872d32008-02-23 18:41:37 +00002626 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greif1c80d112008-08-28 21:40:38 +00002627 cerr << "*Op.getNode():\n";
2628 Op.getNode()->dump();
Scott Michel8efdca42007-12-04 22:23:35 +00002629 abort();
2630 }
2631 case ISD::LOAD:
2632 case ISD::SEXTLOAD:
2633 case ISD::ZEXTLOAD:
2634 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2635 case ISD::STORE:
2636 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2637 case ISD::ConstantPool:
2638 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2639 case ISD::GlobalAddress:
2640 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2641 case ISD::JumpTable:
2642 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2643 case ISD::Constant:
2644 return LowerConstant(Op, DAG);
2645 case ISD::ConstantFP:
2646 return LowerConstantFP(Op, DAG);
Scott Michel394e26d2008-01-17 20:38:41 +00002647 case ISD::BRCOND:
2648 return LowerBRCOND(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002649 case ISD::FORMAL_ARGUMENTS:
Scott Michel394e26d2008-01-17 20:38:41 +00002650 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel8efdca42007-12-04 22:23:35 +00002651 case ISD::CALL:
Scott Micheldbac4cf2008-01-11 02:53:15 +00002652 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel8efdca42007-12-04 22:23:35 +00002653 case ISD::RET:
2654 return LowerRET(Op, DAG, getTargetMachine());
2655
Scott Michel97872d32008-02-23 18:41:37 +00002656
2657 // i8, i64 math ops:
2658 case ISD::ZERO_EXTEND:
2659 case ISD::SIGN_EXTEND:
2660 case ISD::ANY_EXTEND:
Scott Michel67224b22008-06-02 22:18:03 +00002661 case ISD::ADD:
Scott Michel8efdca42007-12-04 22:23:35 +00002662 case ISD::SUB:
2663 case ISD::ROTR:
2664 case ISD::ROTL:
2665 case ISD::SRL:
2666 case ISD::SHL:
Scott Michel67224b22008-06-02 22:18:03 +00002667 case ISD::SRA: {
Scott Michel97872d32008-02-23 18:41:37 +00002668 if (VT == MVT::i8)
2669 return LowerI8Math(Op, DAG, Opc);
2670 else if (VT == MVT::i64)
2671 return LowerI64Math(Op, DAG, Opc);
2672 break;
Scott Michel67224b22008-06-02 22:18:03 +00002673 }
Scott Michel8efdca42007-12-04 22:23:35 +00002674
2675 // Vector-related lowering.
2676 case ISD::BUILD_VECTOR:
2677 return LowerBUILD_VECTOR(Op, DAG);
2678 case ISD::SCALAR_TO_VECTOR:
2679 return LowerSCALAR_TO_VECTOR(Op, DAG);
2680 case ISD::VECTOR_SHUFFLE:
2681 return LowerVECTOR_SHUFFLE(Op, DAG);
2682 case ISD::EXTRACT_VECTOR_ELT:
2683 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2684 case ISD::INSERT_VECTOR_ELT:
2685 return LowerINSERT_VECTOR_ELT(Op, DAG);
2686
2687 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2688 case ISD::AND:
2689 case ISD::OR:
2690 case ISD::XOR:
2691 return LowerByteImmed(Op, DAG);
2692
2693 // Vector and i8 multiply:
2694 case ISD::MUL:
Duncan Sands92c43912008-06-06 12:08:01 +00002695 if (VT.isVector())
Scott Michel8efdca42007-12-04 22:23:35 +00002696 return LowerVectorMUL(Op, DAG);
Scott Michel97872d32008-02-23 18:41:37 +00002697 else if (VT == MVT::i8)
2698 return LowerI8Math(Op, DAG, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002699 else
Scott Michel97872d32008-02-23 18:41:37 +00002700 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002701
2702 case ISD::FDIV:
Scott Michel97872d32008-02-23 18:41:37 +00002703 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel8efdca42007-12-04 22:23:35 +00002704 return LowerFDIVf32(Op, DAG);
2705// else if (Op.getValueType() == MVT::f64)
2706// return LowerFDIVf64(Op, DAG);
2707 else
2708 assert(0 && "Calling FDIV on unsupported MVT");
2709
2710 case ISD::CTPOP:
2711 return LowerCTPOP(Op, DAG);
2712 }
2713
Dan Gohman8181bd12008-07-27 21:46:04 +00002714 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002715}
2716
Scott Michel6e2d68b2008-11-10 23:43:06 +00002717SDNode *SPUTargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG)
2718{
2719#if 0
2720 unsigned Opc = (unsigned) N->getOpcode();
2721 MVT OpVT = N->getValueType(0);
2722
2723 switch (Opc) {
2724 default: {
2725 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2726 cerr << "Op.getOpcode() = " << Opc << "\n";
2727 cerr << "*Op.getNode():\n";
2728 N->dump();
2729 abort();
2730 /*NOTREACHED*/
2731 }
2732 }
2733#endif
2734
2735 /* Otherwise, return unchanged */
2736 return 0;
2737}
2738
Scott Michel8efdca42007-12-04 22:23:35 +00002739//===----------------------------------------------------------------------===//
Scott Michel8efdca42007-12-04 22:23:35 +00002740// Target Optimization Hooks
2741//===----------------------------------------------------------------------===//
2742
Dan Gohman8181bd12008-07-27 21:46:04 +00002743SDValue
Scott Michel8efdca42007-12-04 22:23:35 +00002744SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2745{
2746#if 0
2747 TargetMachine &TM = getTargetMachine();
Scott Michelf9f42e62008-01-29 02:16:57 +00002748#endif
2749 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel8efdca42007-12-04 22:23:35 +00002750 SelectionDAG &DAG = DCI.DAG;
Dan Gohman8181bd12008-07-27 21:46:04 +00002751 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2752 SDValue Result; // Initially, NULL result
Scott Michel8efdca42007-12-04 22:23:35 +00002753
2754 switch (N->getOpcode()) {
2755 default: break;
Scott Michelf9f42e62008-01-29 02:16:57 +00002756 case ISD::ADD: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002757 SDValue Op1 = N->getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002758
Scott Michel67224b22008-06-02 22:18:03 +00002759 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002760 SDValue Op01 = Op0.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002761 if (Op01.getOpcode() == ISD::Constant
2762 || Op01.getOpcode() == ISD::TargetConstant) {
2763 // (add <const>, (SPUindirect <arg>, <const>)) ->
2764 // (SPUindirect <arg>, <const + const>)
2765 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2766 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman8181bd12008-07-27 21:46:04 +00002767 SDValue combinedConst =
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002768 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michelf9f42e62008-01-29 02:16:57 +00002769 Op0.getValueType());
2770
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002771 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2772 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002773 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002774 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002775 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2776 Op0.getOperand(0), combinedConst);
2777 }
Scott Michel67224b22008-06-02 22:18:03 +00002778 } else if (isa<ConstantSDNode>(Op0)
Scott Michelf9f42e62008-01-29 02:16:57 +00002779 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002780 SDValue Op11 = Op1.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002781 if (Op11.getOpcode() == ISD::Constant
2782 || Op11.getOpcode() == ISD::TargetConstant) {
2783 // (add (SPUindirect <arg>, <const>), <const>) ->
2784 // (SPUindirect <arg>, <const + const>)
2785 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2786 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman8181bd12008-07-27 21:46:04 +00002787 SDValue combinedConst =
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002788 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michelf9f42e62008-01-29 02:16:57 +00002789 Op0.getValueType());
2790
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002791 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2792 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002793 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002794 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002795
2796 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2797 Op1.getOperand(0), combinedConst);
2798 }
2799 }
Scott Michel97872d32008-02-23 18:41:37 +00002800 break;
2801 }
2802 case ISD::SIGN_EXTEND:
2803 case ISD::ZERO_EXTEND:
2804 case ISD::ANY_EXTEND: {
2805 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2806 N->getValueType(0) == Op0.getValueType()) {
2807 // (any_extend (SPUextract_elt0 <arg>)) ->
2808 // (SPUextract_elt0 <arg>)
2809 // Types must match, however...
2810 DEBUG(cerr << "Replace: ");
2811 DEBUG(N->dump(&DAG));
2812 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002813 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002814 DEBUG(cerr << "\n");
2815
2816 return Op0;
2817 }
2818 break;
2819 }
2820 case SPUISD::IndirectAddr: {
2821 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2822 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002823 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00002824 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2825 // (SPUaform <addr>, 0)
2826
2827 DEBUG(cerr << "Replace: ");
2828 DEBUG(N->dump(&DAG));
2829 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002830 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002831 DEBUG(cerr << "\n");
2832
2833 return Op0;
2834 }
2835 }
2836 break;
2837 }
2838 case SPUISD::SHLQUAD_L_BITS:
2839 case SPUISD::SHLQUAD_L_BYTES:
2840 case SPUISD::VEC_SHL:
2841 case SPUISD::VEC_SRL:
2842 case SPUISD::VEC_SRA:
2843 case SPUISD::ROTQUAD_RZ_BYTES:
2844 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002845 SDValue Op1 = N->getOperand(1);
Scott Michel97872d32008-02-23 18:41:37 +00002846
2847 if (isa<ConstantSDNode>(Op1)) {
2848 // Kill degenerate vector shifts:
2849 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2850
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002851 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00002852 Result = Op0;
2853 }
2854 }
2855 break;
2856 }
2857 case SPUISD::PROMOTE_SCALAR: {
2858 switch (Op0.getOpcode()) {
2859 default:
2860 break;
2861 case ISD::ANY_EXTEND:
2862 case ISD::ZERO_EXTEND:
2863 case ISD::SIGN_EXTEND: {
2864 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2865 // <arg>
2866 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman8181bd12008-07-27 21:46:04 +00002867 SDValue Op00 = Op0.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002868 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002869 SDValue Op000 = Op00.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002870 if (Op000.getValueType() == N->getValueType(0)) {
2871 Result = Op000;
2872 }
2873 }
2874 break;
2875 }
2876 case SPUISD::EXTRACT_ELT0: {
2877 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2878 // <arg>
2879 Result = Op0.getOperand(0);
2880 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00002881 }
Scott Michel97872d32008-02-23 18:41:37 +00002882 }
2883 break;
Scott Michelf9f42e62008-01-29 02:16:57 +00002884 }
2885 }
Scott Michel394e26d2008-01-17 20:38:41 +00002886 // Otherwise, return unchanged.
Scott Michelbc5fbc12008-04-30 00:30:08 +00002887#if 1
Gabor Greif1c80d112008-08-28 21:40:38 +00002888 if (Result.getNode()) {
Scott Michel97872d32008-02-23 18:41:37 +00002889 DEBUG(cerr << "\nReplace.SPU: ");
2890 DEBUG(N->dump(&DAG));
2891 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002892 DEBUG(Result.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002893 DEBUG(cerr << "\n");
2894 }
2895#endif
2896
2897 return Result;
Scott Michel8efdca42007-12-04 22:23:35 +00002898}
2899
2900//===----------------------------------------------------------------------===//
2901// Inline Assembly Support
2902//===----------------------------------------------------------------------===//
2903
2904/// getConstraintType - Given a constraint letter, return the type of
2905/// constraint it is for this target.
Scott Michel4ec722e2008-07-16 17:17:29 +00002906SPUTargetLowering::ConstraintType
Scott Michel8efdca42007-12-04 22:23:35 +00002907SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2908 if (ConstraintLetter.size() == 1) {
2909 switch (ConstraintLetter[0]) {
2910 default: break;
2911 case 'b':
2912 case 'r':
2913 case 'f':
2914 case 'v':
2915 case 'y':
2916 return C_RegisterClass;
Scott Michel4ec722e2008-07-16 17:17:29 +00002917 }
Scott Michel8efdca42007-12-04 22:23:35 +00002918 }
2919 return TargetLowering::getConstraintType(ConstraintLetter);
2920}
2921
Scott Michel4ec722e2008-07-16 17:17:29 +00002922std::pair<unsigned, const TargetRegisterClass*>
Scott Michel8efdca42007-12-04 22:23:35 +00002923SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands92c43912008-06-06 12:08:01 +00002924 MVT VT) const
Scott Michel8efdca42007-12-04 22:23:35 +00002925{
2926 if (Constraint.size() == 1) {
2927 // GCC RS6000 Constraint Letters
2928 switch (Constraint[0]) {
2929 case 'b': // R1-R31
2930 case 'r': // R0-R31
2931 if (VT == MVT::i64)
2932 return std::make_pair(0U, SPU::R64CRegisterClass);
2933 return std::make_pair(0U, SPU::R32CRegisterClass);
2934 case 'f':
2935 if (VT == MVT::f32)
2936 return std::make_pair(0U, SPU::R32FPRegisterClass);
2937 else if (VT == MVT::f64)
2938 return std::make_pair(0U, SPU::R64FPRegisterClass);
2939 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00002940 case 'v':
Scott Michel8efdca42007-12-04 22:23:35 +00002941 return std::make_pair(0U, SPU::GPRCRegisterClass);
2942 }
2943 }
Scott Michel4ec722e2008-07-16 17:17:29 +00002944
Scott Michel8efdca42007-12-04 22:23:35 +00002945 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2946}
2947
Scott Michel97872d32008-02-23 18:41:37 +00002948//! Compute used/known bits for a SPU operand
Scott Michel8efdca42007-12-04 22:23:35 +00002949void
Dan Gohman8181bd12008-07-27 21:46:04 +00002950SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohmand0dfc772008-02-13 22:28:48 +00002951 const APInt &Mask,
Scott Michel4ec722e2008-07-16 17:17:29 +00002952 APInt &KnownZero,
Dan Gohman229fa052008-02-13 00:35:47 +00002953 APInt &KnownOne,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002954 const SelectionDAG &DAG,
2955 unsigned Depth ) const {
Scott Michelbc5fbc12008-04-30 00:30:08 +00002956#if 0
Scott Michel97872d32008-02-23 18:41:37 +00002957 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michelbc5fbc12008-04-30 00:30:08 +00002958#endif
Scott Michel97872d32008-02-23 18:41:37 +00002959
2960 switch (Op.getOpcode()) {
2961 default:
2962 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2963 break;
2964
2965#if 0
2966 case CALL:
2967 case SHUFB:
2968 case INSERT_MASK:
2969 case CNTB:
2970#endif
2971
2972 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002973 SDValue Op0 = Op.getOperand(0);
Duncan Sands92c43912008-06-06 12:08:01 +00002974 MVT Op0VT = Op0.getValueType();
2975 unsigned Op0VTBits = Op0VT.getSizeInBits();
2976 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00002977 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2978 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00002979 break;
2980 }
Scott Michel4ec722e2008-07-16 17:17:29 +00002981
Scott Michel97872d32008-02-23 18:41:37 +00002982 case SPUISD::LDRESULT:
2983 case SPUISD::EXTRACT_ELT0:
2984 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands92c43912008-06-06 12:08:01 +00002985 MVT OpVT = Op.getValueType();
2986 unsigned OpVTBits = OpVT.getSizeInBits();
2987 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00002988 KnownZero |= APInt(OpVTBits, ~InMask, false);
2989 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00002990 break;
2991 }
2992
2993#if 0
2994 case EXTRACT_I1_ZEXT:
2995 case EXTRACT_I1_SEXT:
2996 case EXTRACT_I8_ZEXT:
2997 case EXTRACT_I8_SEXT:
2998 case MPY:
2999 case MPYU:
3000 case MPYH:
3001 case MPYHH:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003002 case SPUISD::SHLQUAD_L_BITS:
3003 case SPUISD::SHLQUAD_L_BYTES:
3004 case SPUISD::VEC_SHL:
3005 case SPUISD::VEC_SRL:
3006 case SPUISD::VEC_SRA:
3007 case SPUISD::VEC_ROTL:
3008 case SPUISD::VEC_ROTR:
3009 case SPUISD::ROTQUAD_RZ_BYTES:
3010 case SPUISD::ROTQUAD_RZ_BITS:
3011 case SPUISD::ROTBYTES_RIGHT_S:
3012 case SPUISD::ROTBYTES_LEFT:
3013 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel67224b22008-06-02 22:18:03 +00003014 case SPUISD::SELECT_MASK:
3015 case SPUISD::SELB:
3016 case SPUISD::FPInterp:
3017 case SPUISD::FPRecipEst:
3018 case SPUISD::SEXT32TO64:
Scott Michel97872d32008-02-23 18:41:37 +00003019#endif
3020 }
Scott Michel8efdca42007-12-04 22:23:35 +00003021}
3022
Scott Michelbc5fbc12008-04-30 00:30:08 +00003023// LowerAsmOperandForConstraint
3024void
Dan Gohman8181bd12008-07-27 21:46:04 +00003025SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003026 char ConstraintLetter,
Evan Cheng7f250d62008-09-24 00:05:32 +00003027 bool hasMemory,
Dan Gohman8181bd12008-07-27 21:46:04 +00003028 std::vector<SDValue> &Ops,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003029 SelectionDAG &DAG) const {
3030 // Default, for the time being, to the base class handler
Evan Cheng7f250d62008-09-24 00:05:32 +00003031 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3032 Ops, DAG);
Scott Michelbc5fbc12008-04-30 00:30:08 +00003033}
3034
Scott Michel8efdca42007-12-04 22:23:35 +00003035/// isLegalAddressImmediate - Return true if the integer value can be used
3036/// as the offset of the target addressing mode.
Gabor Greife9f7f582008-08-31 15:37:04 +00003037bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3038 const Type *Ty) const {
Scott Michel8efdca42007-12-04 22:23:35 +00003039 // SPU's addresses are 256K:
3040 return (V > -(1 << 18) && V < (1 << 18) - 1);
3041}
3042
3043bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel4ec722e2008-07-16 17:17:29 +00003044 return false;
Scott Michel8efdca42007-12-04 22:23:35 +00003045}
Dan Gohman36322c72008-10-18 02:06:02 +00003046
3047bool
3048SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3049 // The SPU target isn't yet aware of offsets.
3050 return false;
3051}