blob: c13d696f3cff311ef8640b7197b68f8ef0511e98 [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 Michel06eabde2008-12-27 04:51:36 +000018#include "llvm/ADT/APInt.h"
Scott Michel8efdca42007-12-04 22:23:35 +000019#include "llvm/ADT/VectorExtras.h"
Scott Michel8efdca42007-12-04 22:23:35 +000020#include "llvm/CodeGen/CallingConvLower.h"
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/CodeGen/MachineFunction.h"
23#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner1b989192007-12-31 04:13:23 +000024#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel8efdca42007-12-04 22:23:35 +000025#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel8efdca42007-12-04 22:23:35 +000026#include "llvm/Constants.h"
27#include "llvm/Function.h"
28#include "llvm/Intrinsics.h"
29#include "llvm/Support/Debug.h"
30#include "llvm/Support/MathExtras.h"
31#include "llvm/Target/TargetOptions.h"
32
33#include <map>
34
35using namespace llvm;
36
37// Used in getTargetNodeName() below
38namespace {
39 std::map<unsigned, const char *> node_names;
40
Duncan Sands92c43912008-06-06 12:08:01 +000041 //! MVT mapping to useful data for Cell SPU
Scott Michel8efdca42007-12-04 22:23:35 +000042 struct valtype_map_s {
Scott Michel56a125e2008-11-22 23:50:42 +000043 const MVT valtype;
44 const int prefslot_byte;
Scott Michel8efdca42007-12-04 22:23:35 +000045 };
Scott Michel4ec722e2008-07-16 17:17:29 +000046
Scott Michel8efdca42007-12-04 22:23:35 +000047 const valtype_map_s valtype_map[] = {
48 { MVT::i1, 3 },
49 { MVT::i8, 3 },
50 { MVT::i16, 2 },
51 { MVT::i32, 0 },
52 { MVT::f32, 0 },
53 { MVT::i64, 0 },
54 { MVT::f64, 0 },
55 { MVT::i128, 0 }
56 };
57
58 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
59
Duncan Sands92c43912008-06-06 12:08:01 +000060 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel8efdca42007-12-04 22:23:35 +000061 const valtype_map_s *retval = 0;
62
63 for (size_t i = 0; i < n_valtype_map; ++i) {
64 if (valtype_map[i].valtype == VT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +000065 retval = valtype_map + i;
66 break;
Scott Michel8efdca42007-12-04 22:23:35 +000067 }
68 }
69
70#ifndef NDEBUG
71 if (retval == 0) {
72 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands92c43912008-06-06 12:08:01 +000073 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +000074 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +000075 abort();
76 }
77#endif
78
79 return retval;
80 }
Scott Michel8efdca42007-12-04 22:23:35 +000081}
82
83SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
84 : TargetLowering(TM),
85 SPUTM(TM)
86{
87 // Fold away setcc operations if possible.
88 setPow2DivIsCheap();
89
90 // Use _setjmp/_longjmp instead of setjmp/longjmp.
91 setUseUnderscoreSetJmp(true);
92 setUseUnderscoreLongJmp(true);
Scott Michel4ec722e2008-07-16 17:17:29 +000093
Scott Michel8efdca42007-12-04 22:23:35 +000094 // Set up the SPU's register classes:
Scott Michel438be252007-12-17 22:32:34 +000095 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
96 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
97 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
98 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
99 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
100 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
Scott Michel8efdca42007-12-04 22:23:35 +0000101 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel4ec722e2008-07-16 17:17:29 +0000102
Scott Michel8efdca42007-12-04 22:23:35 +0000103 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng08c171a2008-10-14 21:26:46 +0000104 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
105 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
106 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +0000107
Scott Michel06eabde2008-12-27 04:51:36 +0000108 setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
109 setLoadExtAction(ISD::EXTLOAD, MVT::f64, Expand);
Scott Michelec8c82e2008-12-02 19:53:53 +0000110
Scott Michel8efdca42007-12-04 22:23:35 +0000111 // SPU constant load actions are custom lowered:
112 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begeman78125042008-02-14 18:43:04 +0000113 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000114 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
115
116 // SPU's loads and stores have to be custom lowered:
Scott Michele1006032008-11-19 17:45:08 +0000117 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel8efdca42007-12-04 22:23:35 +0000118 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000119 MVT VT = (MVT::SimpleValueType)sctype;
120
Scott Michel06eabde2008-12-27 04:51:36 +0000121 setOperationAction(ISD::LOAD, VT, Custom);
122 setOperationAction(ISD::STORE, VT, Custom);
123 setLoadExtAction(ISD::EXTLOAD, VT, Custom);
124 setLoadExtAction(ISD::ZEXTLOAD, VT, Custom);
125 setLoadExtAction(ISD::SEXTLOAD, VT, Custom);
126
Scott Michelae5cbf52008-12-29 03:23:36 +0000127 // SMUL_LOHI, UMUL_LOHI are not legal for Cell:
128 setOperationAction(ISD::SMUL_LOHI, VT, Expand);
129 setOperationAction(ISD::UMUL_LOHI, VT, Expand);
130
Scott Michel06eabde2008-12-27 04:51:36 +0000131 for (unsigned stype = sctype - 1; stype >= (unsigned) MVT::i8; --stype) {
132 MVT StoreVT = (MVT::SimpleValueType) stype;
133 setTruncStoreAction(VT, StoreVT, Expand);
134 }
Scott Michel8efdca42007-12-04 22:23:35 +0000135 }
136
Scott Michel06eabde2008-12-27 04:51:36 +0000137 for (unsigned sctype = (unsigned) MVT::f32; sctype < (unsigned) MVT::f64;
138 ++sctype) {
139 MVT VT = (MVT::SimpleValueType) sctype;
140
141 setOperationAction(ISD::LOAD, VT, Custom);
142 setOperationAction(ISD::STORE, VT, Custom);
143
144 for (unsigned stype = sctype - 1; stype >= (unsigned) MVT::f32; --stype) {
145 MVT StoreVT = (MVT::SimpleValueType) stype;
146 setTruncStoreAction(VT, StoreVT, Expand);
147 }
148 }
149
Scott Michel8efdca42007-12-04 22:23:35 +0000150 // Expand the jumptable branches
151 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
152 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel56a125e2008-11-22 23:50:42 +0000153
154 // Custom lower SELECT_CC for most cases, but expand by default
Scott Michel4ec722e2008-07-16 17:17:29 +0000155 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel56a125e2008-11-22 23:50:42 +0000156 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
157 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
158 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
159 setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000160
161 // SPU has no intrinsics for these particular operations:
Andrew Lenharth0531ec52008-02-16 14:46:26 +0000162 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
163
Scott Michel06eabde2008-12-27 04:51:36 +0000164 // SPU has no SREM/UREM instructions
Scott Michel8efdca42007-12-04 22:23:35 +0000165 setOperationAction(ISD::SREM, MVT::i32, Expand);
166 setOperationAction(ISD::UREM, MVT::i32, Expand);
167 setOperationAction(ISD::SREM, MVT::i64, Expand);
168 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000169
Scott Michel8efdca42007-12-04 22:23:35 +0000170 // We don't support sin/cos/sqrt/fmod
171 setOperationAction(ISD::FSIN , MVT::f64, Expand);
172 setOperationAction(ISD::FCOS , MVT::f64, Expand);
173 setOperationAction(ISD::FREM , MVT::f64, Expand);
174 setOperationAction(ISD::FSIN , MVT::f32, Expand);
175 setOperationAction(ISD::FCOS , MVT::f32, Expand);
176 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000177
Scott Michel8efdca42007-12-04 22:23:35 +0000178 // If we're enabling GP optimizations, use hardware square root
179 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
180 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000181
Scott Michel8efdca42007-12-04 22:23:35 +0000182 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
183 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
184
185 // SPU can do rotate right and left, so legalize it... but customize for i8
186 // because instructions don't exist.
Bill Wendling965299c2008-08-31 02:59:23 +0000187
188 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
189 // .td files.
190 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
191 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
192 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
193
Scott Michel8efdca42007-12-04 22:23:35 +0000194 setOperationAction(ISD::ROTL, MVT::i32, Legal);
195 setOperationAction(ISD::ROTL, MVT::i16, Legal);
196 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Michelabb8ca12008-11-20 16:36:33 +0000197
Scott Michel8efdca42007-12-04 22:23:35 +0000198 // SPU has no native version of shift left/right for i8
199 setOperationAction(ISD::SHL, MVT::i8, Custom);
200 setOperationAction(ISD::SRL, MVT::i8, Custom);
201 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel33d73eb2008-11-21 02:56:16 +0000202
Scott Michel4d07fb72008-12-30 23:28:25 +0000203 // Make these operations legal and handle them during instruction selection:
204 setOperationAction(ISD::SHL, MVT::i64, Legal);
205 setOperationAction(ISD::SRL, MVT::i64, Legal);
206 setOperationAction(ISD::SRA, MVT::i64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000207
Scott Michel4ec722e2008-07-16 17:17:29 +0000208 // Custom lower i8, i32 and i64 multiplications
209 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michelae5cbf52008-12-29 03:23:36 +0000210 setOperationAction(ISD::MUL, MVT::i32, Legal);
Scott Michel33d73eb2008-11-21 02:56:16 +0000211 setOperationAction(ISD::MUL, MVT::i64, Expand); // libcall
212
Scott Michel67224b22008-06-02 22:18:03 +0000213 // Need to custom handle (some) common i8, i64 math ops
Scott Michel4d07fb72008-12-30 23:28:25 +0000214 setOperationAction(ISD::ADD, MVT::i8, Custom);
Scott Michel67224b22008-06-02 22:18:03 +0000215 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000216 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel67224b22008-06-02 22:18:03 +0000217 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000218
Scott Michel8efdca42007-12-04 22:23:35 +0000219 // SPU does not have BSWAP. It does have i32 support CTLZ.
220 // CTPOP has to be custom lowered.
221 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
222 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
223
224 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
225 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
226 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
227 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
228
229 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
230 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
231
232 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000233
Scott Michel67224b22008-06-02 22:18:03 +0000234 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel978b96f2008-03-10 23:49:09 +0000235 // select ought to work:
Scott Michel53ab7792008-03-10 16:58:52 +0000236 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000237 setOperationAction(ISD::SELECT, MVT::i16, Legal);
238 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel06eabde2008-12-27 04:51:36 +0000239 setOperationAction(ISD::SELECT, MVT::i64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000240
Scott Michel53ab7792008-03-10 16:58:52 +0000241 setOperationAction(ISD::SETCC, MVT::i8, Legal);
242 setOperationAction(ISD::SETCC, MVT::i16, Legal);
Scott Michelae5cbf52008-12-29 03:23:36 +0000243 setOperationAction(ISD::SETCC, MVT::i32, Legal);
244 setOperationAction(ISD::SETCC, MVT::i64, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000245
Scott Michel97872d32008-02-23 18:41:37 +0000246 // Zero extension and sign extension for i64 have to be
247 // custom legalized
248 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
Scott Michel97872d32008-02-23 18:41:37 +0000249 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000250
Scott Michel06eabde2008-12-27 04:51:36 +0000251 // Custom lower i128 -> i64 truncates
Scott Michelec8c82e2008-12-02 19:53:53 +0000252 setOperationAction(ISD::TRUNCATE, MVT::i64, Custom);
253
Scott Michel8efdca42007-12-04 22:23:35 +0000254 // SPU has a legal FP -> signed INT instruction
255 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
256 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
257 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
258 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
259
260 // FDIV on SPU requires custom lowering
Scott Michel06eabde2008-12-27 04:51:36 +0000261 setOperationAction(ISD::FDIV, MVT::f64, Expand); // libcall
Scott Michel8efdca42007-12-04 22:23:35 +0000262
263 // SPU has [U|S]INT_TO_FP
264 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
265 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
266 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
267 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
268 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
269 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
270 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
271 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
272
Scott Michel754d8662007-12-20 00:44:13 +0000273 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
274 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
275 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
276 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000277
278 // We cannot sextinreg(i1). Expand to shifts.
279 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000280
Scott Michel8efdca42007-12-04 22:23:35 +0000281 // Support label based line numbers.
Dan Gohman472d12c2008-06-30 20:59:49 +0000282 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000283 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000284
285 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel8efdca42007-12-04 22:23:35 +0000286 // appropriate instructions to materialize the address.
Scott Michel33d73eb2008-11-21 02:56:16 +0000287 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michelf9f42e62008-01-29 02:16:57 +0000288 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000289 MVT VT = (MVT::SimpleValueType)sctype;
290
Scott Michelae5cbf52008-12-29 03:23:36 +0000291 setOperationAction(ISD::GlobalAddress, VT, Custom);
292 setOperationAction(ISD::ConstantPool, VT, Custom);
293 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michelf9f42e62008-01-29 02:16:57 +0000294 }
Scott Michel8efdca42007-12-04 22:23:35 +0000295
296 // RET must be custom lowered, to meet ABI requirements
297 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000298
Scott Michel8efdca42007-12-04 22:23:35 +0000299 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
300 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000301
Scott Michel8efdca42007-12-04 22:23:35 +0000302 // Use the default implementation.
303 setOperationAction(ISD::VAARG , MVT::Other, Expand);
304 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
305 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000306 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000307 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
308 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
309 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
310
311 // Cell SPU has instructions for converting between i64 and fp.
312 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
313 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000314
Scott Michel8efdca42007-12-04 22:23:35 +0000315 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
316 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
317
318 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
319 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
320
321 // First set operation action for all vector types to expand. Then we
322 // will selectively turn on ones that can be effectively codegen'd.
323 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
324 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
325 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
326 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
327 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
328 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
329
Duncan Sands92c43912008-06-06 12:08:01 +0000330 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
331 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
332 MVT VT = (MVT::SimpleValueType)i;
Scott Michel8efdca42007-12-04 22:23:35 +0000333
Duncan Sands92c43912008-06-06 12:08:01 +0000334 // add/sub are legal for all supported vector VT's.
335 setOperationAction(ISD::ADD , VT, Legal);
336 setOperationAction(ISD::SUB , VT, Legal);
337 // mul has to be custom lowered.
Scott Michel4d07fb72008-12-30 23:28:25 +0000338 // TODO: v2i64 vector multiply
339 setOperationAction(ISD::MUL , VT, Legal);
Duncan Sands92c43912008-06-06 12:08:01 +0000340
341 setOperationAction(ISD::AND , VT, Legal);
342 setOperationAction(ISD::OR , VT, Legal);
343 setOperationAction(ISD::XOR , VT, Legal);
344 setOperationAction(ISD::LOAD , VT, Legal);
345 setOperationAction(ISD::SELECT, VT, Legal);
346 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000347
Scott Michel8efdca42007-12-04 22:23:35 +0000348 // These operations need to be expanded:
Duncan Sands92c43912008-06-06 12:08:01 +0000349 setOperationAction(ISD::SDIV, VT, Expand);
350 setOperationAction(ISD::SREM, VT, Expand);
351 setOperationAction(ISD::UDIV, VT, Expand);
352 setOperationAction(ISD::UREM, VT, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000353
354 // Custom lower build_vector, constant pool spills, insert and
355 // extract vector elements:
Duncan Sands92c43912008-06-06 12:08:01 +0000356 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
357 setOperationAction(ISD::ConstantPool, VT, Custom);
358 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
359 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
360 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
361 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000362 }
363
Scott Michel8efdca42007-12-04 22:23:35 +0000364 setOperationAction(ISD::AND, MVT::v16i8, Custom);
365 setOperationAction(ISD::OR, MVT::v16i8, Custom);
366 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
367 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000368
Scott Michel4d07fb72008-12-30 23:28:25 +0000369 setOperationAction(ISD::FDIV, MVT::v4f32, Legal);
Scott Michelae5cbf52008-12-29 03:23:36 +0000370
Scott Michel8efdca42007-12-04 22:23:35 +0000371 setShiftAmountType(MVT::i32);
Scott Michel06eabde2008-12-27 04:51:36 +0000372 setBooleanContents(ZeroOrNegativeOneBooleanContent);
Scott Michel4ec722e2008-07-16 17:17:29 +0000373
Scott Michel8efdca42007-12-04 22:23:35 +0000374 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel4ec722e2008-07-16 17:17:29 +0000375
Scott Michel8efdca42007-12-04 22:23:35 +0000376 // We have target-specific dag combine patterns for the following nodes:
Scott Michelf9f42e62008-01-29 02:16:57 +0000377 setTargetDAGCombine(ISD::ADD);
Scott Michel97872d32008-02-23 18:41:37 +0000378 setTargetDAGCombine(ISD::ZERO_EXTEND);
379 setTargetDAGCombine(ISD::SIGN_EXTEND);
380 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel4ec722e2008-07-16 17:17:29 +0000381
Scott Michel8efdca42007-12-04 22:23:35 +0000382 computeRegisterProperties();
Scott Michel56a125e2008-11-22 23:50:42 +0000383
Scott Michel2c261072008-12-09 03:37:19 +0000384 // Set pre-RA register scheduler default to BURR, which produces slightly
385 // better code than the default (could also be TDRR, but TargetLowering.h
386 // needs a mod to support that model):
387 setSchedulingPreference(SchedulingForRegPressure);
Scott Michel8efdca42007-12-04 22:23:35 +0000388}
389
390const char *
391SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
392{
393 if (node_names.empty()) {
394 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
395 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
396 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
397 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Micheldbac4cf2008-01-11 02:53:15 +0000398 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michelf9f42e62008-01-29 02:16:57 +0000399 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel8efdca42007-12-04 22:23:35 +0000400 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
401 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
402 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
Scott Michel56a125e2008-11-22 23:50:42 +0000403 node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000404 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
Scott Michelae5cbf52008-12-29 03:23:36 +0000405 node_names[(unsigned) SPUISD::PREFSLOT2VEC] = "SPUISD::PREFSLOT2VEC";
Scott Michelc630c412008-11-24 17:11:17 +0000406 node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
Scott Michel97872d32008-02-23 18:41:37 +0000407 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
408 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel8efdca42007-12-04 22:23:35 +0000409 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
410 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
411 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
412 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
413 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michel67224b22008-06-02 22:18:03 +0000414 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000415 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel67224b22008-06-02 22:18:03 +0000416 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
417 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
418 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
419 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel8efdca42007-12-04 22:23:35 +0000420 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
421 }
422
423 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
424
425 return ((i != node_names.end()) ? i->second : 0);
426}
427
Scott Michel06eabde2008-12-27 04:51:36 +0000428//===----------------------------------------------------------------------===//
429// Return the Cell SPU's SETCC result type
430//===----------------------------------------------------------------------===//
431
Duncan Sands4a361272009-01-01 15:52:00 +0000432MVT SPUTargetLowering::getSetCCResultType(MVT VT) const {
Scott Michel06eabde2008-12-27 04:51:36 +0000433 // i16 and i32 are valid SETCC result types
434 return ((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) ? VT : MVT::i32);
Scott Michel53ab7792008-03-10 16:58:52 +0000435}
436
Scott Michel8efdca42007-12-04 22:23:35 +0000437//===----------------------------------------------------------------------===//
438// Calling convention code:
439//===----------------------------------------------------------------------===//
440
441#include "SPUGenCallingConv.inc"
442
443//===----------------------------------------------------------------------===//
444// LowerOperation implementation
445//===----------------------------------------------------------------------===//
446
447/// Custom lower loads for CellSPU
448/*!
449 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
450 within a 16-byte block, we have to rotate to extract the requested element.
Scott Michel6ccefab2008-12-04 03:02:42 +0000451
452 For extending loads, we also want to ensure that the following sequence is
453 emitted, e.g. for MVT::f32 extending load to MVT::f64:
454
455\verbatim
Scott Michelae5cbf52008-12-29 03:23:36 +0000456%1 v16i8,ch = load
Scott Michel6ccefab2008-12-04 03:02:42 +0000457%2 v16i8,ch = rotate %1
Scott Michelae5cbf52008-12-29 03:23:36 +0000458%3 v4f8, ch = bitconvert %2
Scott Michel6ccefab2008-12-04 03:02:42 +0000459%4 f32 = vec2perfslot %3
460%5 f64 = fp_extend %4
461\endverbatim
462*/
Dan Gohman8181bd12008-07-27 21:46:04 +0000463static SDValue
464LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000465 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000466 SDValue the_chain = LN->getChain();
Scott Michel06eabde2008-12-27 04:51:36 +0000467 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel6ccefab2008-12-04 03:02:42 +0000468 MVT InVT = LN->getMemoryVT();
469 MVT OutVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000470 ISD::LoadExtType ExtType = LN->getExtensionType();
471 unsigned alignment = LN->getAlignment();
Scott Michel06eabde2008-12-27 04:51:36 +0000472 const valtype_map_s *vtm = getValueTypeMapEntry(InVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000473
Scott Michel8efdca42007-12-04 22:23:35 +0000474 switch (LN->getAddressingMode()) {
475 case ISD::UNINDEXED: {
Scott Michel06eabde2008-12-27 04:51:36 +0000476 SDValue result;
477 SDValue basePtr = LN->getBasePtr();
478 SDValue rotate;
Scott Michel8efdca42007-12-04 22:23:35 +0000479
Scott Michel06eabde2008-12-27 04:51:36 +0000480 if (alignment == 16) {
481 ConstantSDNode *CN;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000482
Scott Michel06eabde2008-12-27 04:51:36 +0000483 // Special cases for a known aligned load to simplify the base pointer
484 // and the rotation amount:
485 if (basePtr.getOpcode() == ISD::ADD
486 && (CN = dyn_cast<ConstantSDNode > (basePtr.getOperand(1))) != 0) {
487 // Known offset into basePtr
488 int64_t offset = CN->getSExtValue();
489 int64_t rotamt = int64_t((offset & 0xf) - vtm->prefslot_byte);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000490
Scott Michel06eabde2008-12-27 04:51:36 +0000491 if (rotamt < 0)
492 rotamt += 16;
493
494 rotate = DAG.getConstant(rotamt, MVT::i16);
495
496 // Simplify the base pointer for this case:
497 basePtr = basePtr.getOperand(0);
498 if ((offset & ~0xf) > 0) {
499 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
500 basePtr,
501 DAG.getConstant((offset & ~0xf), PtrVT));
502 }
503 } else if ((basePtr.getOpcode() == SPUISD::AFormAddr)
504 || (basePtr.getOpcode() == SPUISD::IndirectAddr
505 && basePtr.getOperand(0).getOpcode() == SPUISD::Hi
506 && basePtr.getOperand(1).getOpcode() == SPUISD::Lo)) {
507 // Plain aligned a-form address: rotate into preferred slot
508 // Same for (SPUindirect (SPUhi ...), (SPUlo ...))
509 int64_t rotamt = -vtm->prefslot_byte;
510 if (rotamt < 0)
511 rotamt += 16;
512 rotate = DAG.getConstant(rotamt, MVT::i16);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000513 } else {
Scott Michel06eabde2008-12-27 04:51:36 +0000514 // Offset the rotate amount by the basePtr and the preferred slot
515 // byte offset
516 int64_t rotamt = -vtm->prefslot_byte;
517 if (rotamt < 0)
518 rotamt += 16;
519 rotate = DAG.getNode(ISD::ADD, PtrVT,
520 basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000521 DAG.getConstant(rotamt, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000522 }
Scott Michel06eabde2008-12-27 04:51:36 +0000523 } else {
524 // Unaligned load: must be more pessimistic about addressing modes:
525 if (basePtr.getOpcode() == ISD::ADD) {
526 MachineFunction &MF = DAG.getMachineFunction();
527 MachineRegisterInfo &RegInfo = MF.getRegInfo();
528 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
529 SDValue Flag;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000530
Scott Michel06eabde2008-12-27 04:51:36 +0000531 SDValue Op0 = basePtr.getOperand(0);
532 SDValue Op1 = basePtr.getOperand(1);
533
534 if (isa<ConstantSDNode>(Op1)) {
535 // Convert the (add <ptr>, <const>) to an indirect address contained
536 // in a register. Note that this is done because we need to avoid
537 // creating a 0(reg) d-form address due to the SPU's block loads.
538 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
539 the_chain = DAG.getCopyToReg(the_chain, VReg, basePtr, Flag);
540 basePtr = DAG.getCopyFromReg(the_chain, VReg, PtrVT);
541 } else {
542 // Convert the (add <arg1>, <arg2>) to an indirect address, which
543 // will likely be lowered as a reg(reg) x-form address.
544 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
545 }
546 } else {
547 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
548 basePtr,
549 DAG.getConstant(0, PtrVT));
550 }
551
552 // Offset the rotate amount by the basePtr and the preferred slot
553 // byte offset
554 rotate = DAG.getNode(ISD::ADD, PtrVT,
555 basePtr,
556 DAG.getConstant(-vtm->prefslot_byte, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +0000557 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000558
Scott Michel06eabde2008-12-27 04:51:36 +0000559 // Re-emit as a v16i8 vector load
560 result = DAG.getLoad(MVT::v16i8, the_chain, basePtr,
561 LN->getSrcValue(), LN->getSrcValueOffset(),
562 LN->isVolatile(), 16);
563
564 // Update the chain
565 the_chain = result.getValue(1);
566
567 // Rotate into the preferred slot:
568 result = DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v16i8,
569 result.getValue(0), rotate);
570
Scott Michel6ccefab2008-12-04 03:02:42 +0000571 // Convert the loaded v16i8 vector to the appropriate vector type
572 // specified by the operand:
573 MVT vecVT = MVT::getVectorVT(InVT, (128 / InVT.getSizeInBits()));
574 result = DAG.getNode(SPUISD::VEC2PREFSLOT, InVT,
575 DAG.getNode(ISD::BIT_CONVERT, vecVT, result));
Scott Michel4ec722e2008-07-16 17:17:29 +0000576
Scott Michel6ccefab2008-12-04 03:02:42 +0000577 // Handle extending loads by extending the scalar result:
578 if (ExtType == ISD::SEXTLOAD) {
579 result = DAG.getNode(ISD::SIGN_EXTEND, OutVT, result);
580 } else if (ExtType == ISD::ZEXTLOAD) {
581 result = DAG.getNode(ISD::ZERO_EXTEND, OutVT, result);
582 } else if (ExtType == ISD::EXTLOAD) {
583 unsigned NewOpc = ISD::ANY_EXTEND;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000584
Scott Michel6ccefab2008-12-04 03:02:42 +0000585 if (OutVT.isFloatingPoint())
586 NewOpc = ISD::FP_EXTEND;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000587
Scott Michel6ccefab2008-12-04 03:02:42 +0000588 result = DAG.getNode(NewOpc, OutVT, result);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000589 }
590
Scott Michel6ccefab2008-12-04 03:02:42 +0000591 SDVTList retvts = DAG.getVTList(OutVT, MVT::Other);
Dan Gohman8181bd12008-07-27 21:46:04 +0000592 SDValue retops[2] = {
Scott Michel394e26d2008-01-17 20:38:41 +0000593 result,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000594 the_chain
Scott Michel394e26d2008-01-17 20:38:41 +0000595 };
Scott Micheldbac4cf2008-01-11 02:53:15 +0000596
Scott Michel394e26d2008-01-17 20:38:41 +0000597 result = DAG.getNode(SPUISD::LDRESULT, retvts,
598 retops, sizeof(retops) / sizeof(retops[0]));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000599 return result;
Scott Michel8efdca42007-12-04 22:23:35 +0000600 }
601 case ISD::PRE_INC:
602 case ISD::PRE_DEC:
603 case ISD::POST_INC:
604 case ISD::POST_DEC:
605 case ISD::LAST_INDEXED_MODE:
606 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
607 "UNINDEXED\n";
608 cerr << (unsigned) LN->getAddressingMode() << "\n";
609 abort();
610 /*NOTREACHED*/
611 }
612
Dan Gohman8181bd12008-07-27 21:46:04 +0000613 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000614}
615
616/// Custom lower stores for CellSPU
617/*!
618 All CellSPU stores are aligned to 16-byte boundaries, so for elements
619 within a 16-byte block, we have to generate a shuffle to insert the
620 requested element into its place, then store the resulting block.
621 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000622static SDValue
623LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000624 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000625 SDValue Value = SN->getValue();
Duncan Sands92c43912008-06-06 12:08:01 +0000626 MVT VT = Value.getValueType();
627 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
628 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000629 unsigned alignment = SN->getAlignment();
Scott Michel8efdca42007-12-04 22:23:35 +0000630
631 switch (SN->getAddressingMode()) {
632 case ISD::UNINDEXED: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000633 // The vector type we really want to load from the 16-byte chunk.
Scott Michele1006032008-11-19 17:45:08 +0000634 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
635 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +0000636
Scott Michel06eabde2008-12-27 04:51:36 +0000637 SDValue alignLoadVec;
638 SDValue basePtr = SN->getBasePtr();
639 SDValue the_chain = SN->getChain();
640 SDValue insertEltOffs;
Scott Michel8efdca42007-12-04 22:23:35 +0000641
Scott Michel06eabde2008-12-27 04:51:36 +0000642 if (alignment == 16) {
643 ConstantSDNode *CN;
644
645 // Special cases for a known aligned load to simplify the base pointer
646 // and insertion byte:
647 if (basePtr.getOpcode() == ISD::ADD
648 && (CN = dyn_cast<ConstantSDNode>(basePtr.getOperand(1))) != 0) {
649 // Known offset into basePtr
650 int64_t offset = CN->getSExtValue();
651
652 // Simplify the base pointer for this case:
653 basePtr = basePtr.getOperand(0);
654 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
655 basePtr,
656 DAG.getConstant((offset & 0xf), PtrVT));
657
658 if ((offset & ~0xf) > 0) {
659 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
660 basePtr,
661 DAG.getConstant((offset & ~0xf), PtrVT));
662 }
663 } else {
664 // Otherwise, assume it's at byte 0 of basePtr
665 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
666 basePtr,
667 DAG.getConstant(0, PtrVT));
668 }
669 } else {
670 // Unaligned load: must be more pessimistic about addressing modes:
671 if (basePtr.getOpcode() == ISD::ADD) {
672 MachineFunction &MF = DAG.getMachineFunction();
673 MachineRegisterInfo &RegInfo = MF.getRegInfo();
674 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
675 SDValue Flag;
676
677 SDValue Op0 = basePtr.getOperand(0);
678 SDValue Op1 = basePtr.getOperand(1);
679
680 if (isa<ConstantSDNode>(Op1)) {
681 // Convert the (add <ptr>, <const>) to an indirect address contained
682 // in a register. Note that this is done because we need to avoid
683 // creating a 0(reg) d-form address due to the SPU's block loads.
684 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
685 the_chain = DAG.getCopyToReg(the_chain, VReg, basePtr, Flag);
686 basePtr = DAG.getCopyFromReg(the_chain, VReg, PtrVT);
687 } else {
688 // Convert the (add <arg1>, <arg2>) to an indirect address, which
689 // will likely be lowered as a reg(reg) x-form address.
690 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
691 }
692 } else {
693 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
694 basePtr,
695 DAG.getConstant(0, PtrVT));
696 }
697
698 // Insertion point is solely determined by basePtr's contents
699 insertEltOffs = DAG.getNode(ISD::ADD, PtrVT,
700 basePtr,
701 DAG.getConstant(0, PtrVT));
702 }
703
704 // Re-emit as a v16i8 vector load
705 alignLoadVec = DAG.getLoad(MVT::v16i8, the_chain, basePtr,
706 SN->getSrcValue(), SN->getSrcValueOffset(),
707 SN->isVolatile(), 16);
708
709 // Update the chain
710 the_chain = alignLoadVec.getValue(1);
Scott Michel8efdca42007-12-04 22:23:35 +0000711
Scott Micheldbac4cf2008-01-11 02:53:15 +0000712 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman8181bd12008-07-27 21:46:04 +0000713 SDValue theValue = SN->getValue();
714 SDValue result;
Scott Michel8efdca42007-12-04 22:23:35 +0000715
716 if (StVT != VT
Scott Michel5a6f17b2008-01-30 02:55:46 +0000717 && (theValue.getOpcode() == ISD::AssertZext
718 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel8efdca42007-12-04 22:23:35 +0000719 // Drill down and get the value for zero- and sign-extended
720 // quantities
Scott Michel4ec722e2008-07-16 17:17:29 +0000721 theValue = theValue.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000722 }
723
Scott Micheldbac4cf2008-01-11 02:53:15 +0000724 // If the base pointer is already a D-form address, then just create
725 // a new D-form address with a slot offset and the orignal base pointer.
726 // Otherwise generate a D-form address with the slot offset relative
727 // to the stack pointer, which is always aligned.
Scott Michel06eabde2008-12-27 04:51:36 +0000728#if !defined(NDEBUG)
729 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
730 cerr << "CellSPU LowerSTORE: basePtr = ";
731 basePtr.getNode()->dump(&DAG);
732 cerr << "\n";
733 }
734#endif
Scott Micheldbac4cf2008-01-11 02:53:15 +0000735
Scott Michelf65c8f02008-11-19 15:24:16 +0000736 SDValue insertEltOp =
Scott Michel06eabde2008-12-27 04:51:36 +0000737 DAG.getNode(SPUISD::SHUFFLE_MASK, vecVT, insertEltOffs);
Scott Michele1006032008-11-19 17:45:08 +0000738 SDValue vectorizeOp =
739 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michelf65c8f02008-11-19 15:24:16 +0000740
Scott Michel0718cd82008-12-01 17:56:02 +0000741 result = DAG.getNode(SPUISD::SHUFB, vecVT,
742 vectorizeOp, alignLoadVec,
743 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, insertEltOp));
Scott Michel8efdca42007-12-04 22:23:35 +0000744
Scott Micheldbac4cf2008-01-11 02:53:15 +0000745 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel8efdca42007-12-04 22:23:35 +0000746 LN->getSrcValue(), LN->getSrcValueOffset(),
747 LN->isVolatile(), LN->getAlignment());
748
Scott Michel8c2746e2008-12-04 17:16:59 +0000749#if 0 && !defined(NDEBUG)
Scott Michelf65c8f02008-11-19 15:24:16 +0000750 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
751 const SDValue &currentRoot = DAG.getRoot();
752
753 DAG.setRoot(result);
754 cerr << "------- CellSPU:LowerStore result:\n";
755 DAG.dump();
756 cerr << "-------\n";
757 DAG.setRoot(currentRoot);
758 }
759#endif
Scott Michelec8c82e2008-12-02 19:53:53 +0000760
Scott Michel8efdca42007-12-04 22:23:35 +0000761 return result;
762 /*UNREACHED*/
763 }
764 case ISD::PRE_INC:
765 case ISD::PRE_DEC:
766 case ISD::POST_INC:
767 case ISD::POST_DEC:
768 case ISD::LAST_INDEXED_MODE:
769 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
770 "UNINDEXED\n";
771 cerr << (unsigned) SN->getAddressingMode() << "\n";
772 abort();
773 /*NOTREACHED*/
774 }
775
Dan Gohman8181bd12008-07-27 21:46:04 +0000776 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000777}
778
779/// Generate the address of a constant pool entry.
Dan Gohman8181bd12008-07-27 21:46:04 +0000780static SDValue
781LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000782 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000783 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
784 Constant *C = CP->getConstVal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000785 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
786 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000787 const TargetMachine &TM = DAG.getTarget();
Scott Michel8efdca42007-12-04 22:23:35 +0000788
789 if (TM.getRelocationModel() == Reloc::Static) {
790 if (!ST->usingLargeMem()) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000791 // Just return the SDValue with the constant pool address in it.
Scott Michel394e26d2008-01-17 20:38:41 +0000792 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +0000793 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000794 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
795 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000796 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel8efdca42007-12-04 22:23:35 +0000797 }
798 }
799
800 assert(0 &&
Gabor Greife9f7f582008-08-31 15:37:04 +0000801 "LowerConstantPool: Relocation model other than static"
802 " not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000803 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000804}
805
Dan Gohman8181bd12008-07-27 21:46:04 +0000806static SDValue
807LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000808 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000809 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000810 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
811 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000812 const TargetMachine &TM = DAG.getTarget();
813
814 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel97872d32008-02-23 18:41:37 +0000815 if (!ST->usingLargeMem()) {
816 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
817 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000818 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
819 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000820 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
821 }
Scott Michel8efdca42007-12-04 22:23:35 +0000822 }
823
824 assert(0 &&
825 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000826 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000827}
828
Dan Gohman8181bd12008-07-27 21:46:04 +0000829static SDValue
830LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000831 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000832 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
833 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000834 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel8efdca42007-12-04 22:23:35 +0000835 const TargetMachine &TM = DAG.getTarget();
Dan Gohman8181bd12008-07-27 21:46:04 +0000836 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel4ec722e2008-07-16 17:17:29 +0000837
Scott Michel8efdca42007-12-04 22:23:35 +0000838 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michelf9f42e62008-01-29 02:16:57 +0000839 if (!ST->usingLargeMem()) {
840 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
841 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000842 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
843 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michelf9f42e62008-01-29 02:16:57 +0000844 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
845 }
Scott Michel8efdca42007-12-04 22:23:35 +0000846 } else {
847 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel5a6f17b2008-01-30 02:55:46 +0000848 << "supported.\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000849 abort();
850 /*NOTREACHED*/
851 }
852
Dan Gohman8181bd12008-07-27 21:46:04 +0000853 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000854}
855
856//! Custom lower i64 integer constants
857/*!
858 This code inserts all of the necessary juggling that needs to occur to load
859 a 64-bit constant into a register.
860 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000861static SDValue
862LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000863 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000864
865 if (VT == MVT::i64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000866 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
867 SDValue T = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michelc630c412008-11-24 17:11:17 +0000868 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000869 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +0000870 } else {
871 cerr << "LowerConstant: unhandled constant type "
Duncan Sands92c43912008-06-06 12:08:01 +0000872 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +0000873 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000874 abort();
875 /*NOTREACHED*/
876 }
877
Dan Gohman8181bd12008-07-27 21:46:04 +0000878 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000879}
880
Nate Begeman78125042008-02-14 18:43:04 +0000881//! Custom lower double precision floating point constants
Dan Gohman8181bd12008-07-27 21:46:04 +0000882static SDValue
883LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000884 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000885
Nate Begeman78125042008-02-14 18:43:04 +0000886 if (VT == MVT::f64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000887 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
888
889 assert((FP != 0) &&
890 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michelae5cbf52008-12-29 03:23:36 +0000891
Scott Michel11e88bb2007-12-19 20:15:47 +0000892 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel0718cd82008-12-01 17:56:02 +0000893 SDValue T = DAG.getConstant(dbits, MVT::i64);
894 SDValue Tvec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T);
895 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
896 DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64, Tvec));
Scott Michel8efdca42007-12-04 22:23:35 +0000897 }
898
Dan Gohman8181bd12008-07-27 21:46:04 +0000899 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000900}
901
Dan Gohman8181bd12008-07-27 21:46:04 +0000902static SDValue
Dan Gohman8181bd12008-07-27 21:46:04 +0000903LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel8efdca42007-12-04 22:23:35 +0000904{
905 MachineFunction &MF = DAG.getMachineFunction();
906 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner1b989192007-12-31 04:13:23 +0000907 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michela313fb02008-10-30 01:51:48 +0000908 SmallVector<SDValue, 48> ArgValues;
Dan Gohman8181bd12008-07-27 21:46:04 +0000909 SDValue Root = Op.getOperand(0);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000910 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel8efdca42007-12-04 22:23:35 +0000911
912 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
913 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel4ec722e2008-07-16 17:17:29 +0000914
Scott Michel8efdca42007-12-04 22:23:35 +0000915 unsigned ArgOffset = SPUFrameInfo::minStackSize();
916 unsigned ArgRegIdx = 0;
917 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel4ec722e2008-07-16 17:17:29 +0000918
Duncan Sands92c43912008-06-06 12:08:01 +0000919 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +0000920
Scott Michel8efdca42007-12-04 22:23:35 +0000921 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greife9f7f582008-08-31 15:37:04 +0000922 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
923 ArgNo != e; ++ArgNo) {
Duncan Sands92c43912008-06-06 12:08:01 +0000924 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
925 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michela313fb02008-10-30 01:51:48 +0000926 SDValue ArgVal;
Scott Michel8efdca42007-12-04 22:23:35 +0000927
Scott Michela313fb02008-10-30 01:51:48 +0000928 if (ArgRegIdx < NumArgRegs) {
929 const TargetRegisterClass *ArgRegClass;
Scott Michel4ec722e2008-07-16 17:17:29 +0000930
Scott Michela313fb02008-10-30 01:51:48 +0000931 switch (ObjectVT.getSimpleVT()) {
932 default: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000933 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
934 << ObjectVT.getMVTString()
935 << "\n";
936 abort();
Scott Michela313fb02008-10-30 01:51:48 +0000937 }
938 case MVT::i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000939 ArgRegClass = &SPU::R8CRegClass;
940 break;
Scott Michela313fb02008-10-30 01:51:48 +0000941 case MVT::i16:
Scott Michel33d73eb2008-11-21 02:56:16 +0000942 ArgRegClass = &SPU::R16CRegClass;
943 break;
Scott Michela313fb02008-10-30 01:51:48 +0000944 case MVT::i32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000945 ArgRegClass = &SPU::R32CRegClass;
946 break;
Scott Michela313fb02008-10-30 01:51:48 +0000947 case MVT::i64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000948 ArgRegClass = &SPU::R64CRegClass;
949 break;
Scott Michela313fb02008-10-30 01:51:48 +0000950 case MVT::f32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000951 ArgRegClass = &SPU::R32FPRegClass;
952 break;
Scott Michela313fb02008-10-30 01:51:48 +0000953 case MVT::f64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000954 ArgRegClass = &SPU::R64FPRegClass;
955 break;
Scott Michela313fb02008-10-30 01:51:48 +0000956 case MVT::v2f64:
957 case MVT::v4f32:
958 case MVT::v2i64:
959 case MVT::v4i32:
960 case MVT::v8i16:
961 case MVT::v16i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000962 ArgRegClass = &SPU::VECREGRegClass;
963 break;
Scott Michela313fb02008-10-30 01:51:48 +0000964 }
965
966 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
967 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
968 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
969 ++ArgRegIdx;
970 } else {
971 // We need to load the argument to a virtual register if we determined
972 // above that we ran out of physical registers of the appropriate type
973 // or we're forced to do vararg
Chris Lattner60069452008-02-13 07:35:30 +0000974 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman8181bd12008-07-27 21:46:04 +0000975 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner60069452008-02-13 07:35:30 +0000976 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel8efdca42007-12-04 22:23:35 +0000977 ArgOffset += StackSlotSize;
978 }
Scott Michel4ec722e2008-07-16 17:17:29 +0000979
Scott Michel8efdca42007-12-04 22:23:35 +0000980 ArgValues.push_back(ArgVal);
Scott Michela313fb02008-10-30 01:51:48 +0000981 // Update the chain
982 Root = ArgVal.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000983 }
Scott Michel4ec722e2008-07-16 17:17:29 +0000984
Scott Michela313fb02008-10-30 01:51:48 +0000985 // vararg handling:
Scott Michel8efdca42007-12-04 22:23:35 +0000986 if (isVarArg) {
Scott Michela313fb02008-10-30 01:51:48 +0000987 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
988 // We will spill (79-3)+1 registers to the stack
989 SmallVector<SDValue, 79-3+1> MemOps;
990
991 // Create the frame slot
992
Scott Michel8efdca42007-12-04 22:23:35 +0000993 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Michela313fb02008-10-30 01:51:48 +0000994 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
995 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
996 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
997 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
998 Root = Store.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000999 MemOps.push_back(Store);
Scott Michela313fb02008-10-30 01:51:48 +00001000
1001 // Increment address by stack slot size for the next stored argument
1002 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001003 }
1004 if (!MemOps.empty())
Scott Michela313fb02008-10-30 01:51:48 +00001005 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001006 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001007
Scott Michel8efdca42007-12-04 22:23:35 +00001008 ArgValues.push_back(Root);
Scott Michel4ec722e2008-07-16 17:17:29 +00001009
Scott Michel8efdca42007-12-04 22:23:35 +00001010 // Return the new list of results.
Duncan Sands42d7bb82008-12-01 11:41:29 +00001011 return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(),
1012 &ArgValues[0], ArgValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001013}
1014
1015/// isLSAAddress - Return the immediate to use if the specified
1016/// value is representable as a LSA address.
Dan Gohman8181bd12008-07-27 21:46:04 +00001017static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel5974f432008-11-11 03:06:06 +00001018 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel8efdca42007-12-04 22:23:35 +00001019 if (!C) return 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001020
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001021 int Addr = C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001022 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1023 (Addr << 14 >> 14) != Addr)
1024 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel4ec722e2008-07-16 17:17:29 +00001025
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001026 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel8efdca42007-12-04 22:23:35 +00001027}
1028
1029static
Dan Gohman8181bd12008-07-27 21:46:04 +00001030SDValue
1031LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001032 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1033 SDValue Chain = TheCall->getChain();
Dan Gohman705e3f72008-09-13 01:54:27 +00001034 SDValue Callee = TheCall->getCallee();
1035 unsigned NumOps = TheCall->getNumArgs();
Scott Michel8efdca42007-12-04 22:23:35 +00001036 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1037 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1038 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1039
1040 // Handy pointer type
Duncan Sands92c43912008-06-06 12:08:01 +00001041 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +00001042
Scott Michel8efdca42007-12-04 22:23:35 +00001043 // Accumulate how many bytes are to be pushed on the stack, including the
1044 // linkage area, and parameter passing area. According to the SPU ABI,
1045 // we minimally need space for [LR] and [SP]
1046 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel4ec722e2008-07-16 17:17:29 +00001047
Scott Michel8efdca42007-12-04 22:23:35 +00001048 // Set up a copy of the stack pointer for use loading and storing any
1049 // arguments that may not fit in the registers available for argument
1050 // passing.
Dan Gohman8181bd12008-07-27 21:46:04 +00001051 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel4ec722e2008-07-16 17:17:29 +00001052
Scott Michel8efdca42007-12-04 22:23:35 +00001053 // Figure out which arguments are going to go in registers, and which in
1054 // memory.
1055 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1056 unsigned ArgRegIdx = 0;
1057
1058 // Keep track of registers passing arguments
Dan Gohman8181bd12008-07-27 21:46:04 +00001059 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel8efdca42007-12-04 22:23:35 +00001060 // And the arguments passed on the stack
Dan Gohman8181bd12008-07-27 21:46:04 +00001061 SmallVector<SDValue, 8> MemOpChains;
Scott Michel8efdca42007-12-04 22:23:35 +00001062
1063 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001064 SDValue Arg = TheCall->getArg(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001065
Scott Michel8efdca42007-12-04 22:23:35 +00001066 // PtrOff will be used to store the current argument to the stack if a
1067 // register cannot be found for it.
Dan Gohman8181bd12008-07-27 21:46:04 +00001068 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel8efdca42007-12-04 22:23:35 +00001069 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1070
Duncan Sands92c43912008-06-06 12:08:01 +00001071 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001072 default: assert(0 && "Unexpected ValueType for argument!");
1073 case MVT::i32:
1074 case MVT::i64:
1075 case MVT::i128:
1076 if (ArgRegIdx != NumArgRegs) {
1077 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1078 } else {
1079 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001080 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001081 }
1082 break;
1083 case MVT::f32:
1084 case MVT::f64:
1085 if (ArgRegIdx != NumArgRegs) {
1086 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1087 } else {
1088 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001089 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001090 }
1091 break;
Scott Michele2641a12008-12-04 21:01:44 +00001092 case MVT::v2i64:
1093 case MVT::v2f64:
Scott Michel8efdca42007-12-04 22:23:35 +00001094 case MVT::v4f32:
1095 case MVT::v4i32:
1096 case MVT::v8i16:
1097 case MVT::v16i8:
1098 if (ArgRegIdx != NumArgRegs) {
1099 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1100 } else {
1101 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001102 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001103 }
1104 break;
1105 }
1106 }
1107
1108 // Update number of stack bytes actually used, insert a call sequence start
1109 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001110 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1111 true));
Scott Michel8efdca42007-12-04 22:23:35 +00001112
1113 if (!MemOpChains.empty()) {
1114 // Adjust the stack pointer for the stack arguments.
1115 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1116 &MemOpChains[0], MemOpChains.size());
1117 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001118
Scott Michel8efdca42007-12-04 22:23:35 +00001119 // Build a sequence of copy-to-reg nodes chained together with token chain
1120 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman8181bd12008-07-27 21:46:04 +00001121 SDValue InFlag;
Scott Michel8efdca42007-12-04 22:23:35 +00001122 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1123 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1124 InFlag);
1125 InFlag = Chain.getValue(1);
1126 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001127
Dan Gohman8181bd12008-07-27 21:46:04 +00001128 SmallVector<SDValue, 8> Ops;
Scott Michel8efdca42007-12-04 22:23:35 +00001129 unsigned CallOpc = SPUISD::CALL;
Scott Michel4ec722e2008-07-16 17:17:29 +00001130
Bill Wendlingfef06052008-09-16 21:48:12 +00001131 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1132 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1133 // node so that legalize doesn't hack it.
Scott Michel5974f432008-11-11 03:06:06 +00001134 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001135 GlobalValue *GV = G->getGlobal();
Duncan Sands92c43912008-06-06 12:08:01 +00001136 MVT CalleeVT = Callee.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001137 SDValue Zero = DAG.getConstant(0, PtrVT);
1138 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001139
Scott Micheldbac4cf2008-01-11 02:53:15 +00001140 if (!ST->usingLargeMem()) {
1141 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1142 // style calls, otherwise, external symbols are BRASL calls. This assumes
1143 // that declared/defined symbols are in the same compilation unit and can
1144 // be reached through PC-relative jumps.
1145 //
1146 // NOTE:
1147 // This may be an unsafe assumption for JIT and really large compilation
1148 // units.
1149 if (GV->isDeclaration()) {
1150 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1151 } else {
1152 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1153 }
Scott Michel8efdca42007-12-04 22:23:35 +00001154 } else {
Scott Micheldbac4cf2008-01-11 02:53:15 +00001155 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1156 // address pairs:
Scott Michelf9f42e62008-01-29 02:16:57 +00001157 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +00001158 }
Scott Michelae5cbf52008-12-29 03:23:36 +00001159 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
1160 MVT CalleeVT = Callee.getValueType();
1161 SDValue Zero = DAG.getConstant(0, PtrVT);
1162 SDValue ExtSym = DAG.getTargetExternalSymbol(S->getSymbol(),
1163 Callee.getValueType());
1164
1165 if (!ST->usingLargeMem()) {
1166 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, ExtSym, Zero);
1167 } else {
1168 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, ExtSym, Zero);
1169 }
1170 } else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001171 // If this is an absolute destination address that appears to be a legal
1172 // local store address, use the munged value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001173 Callee = SDValue(Dest, 0);
Scott Micheldbac4cf2008-01-11 02:53:15 +00001174 }
Scott Michel8efdca42007-12-04 22:23:35 +00001175
1176 Ops.push_back(Chain);
1177 Ops.push_back(Callee);
Scott Michel4ec722e2008-07-16 17:17:29 +00001178
Scott Michel8efdca42007-12-04 22:23:35 +00001179 // Add argument registers to the end of the list so that they are known live
1180 // into the call.
1181 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel4ec722e2008-07-16 17:17:29 +00001182 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel8efdca42007-12-04 22:23:35 +00001183 RegsToPass[i].second.getValueType()));
Scott Michel4ec722e2008-07-16 17:17:29 +00001184
Gabor Greif1c80d112008-08-28 21:40:38 +00001185 if (InFlag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001186 Ops.push_back(InFlag);
Duncan Sands698842f2008-07-02 17:40:58 +00001187 // Returns a chain and a flag for retval copy to use.
1188 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1189 &Ops[0], Ops.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001190 InFlag = Chain.getValue(1);
1191
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001192 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1193 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman705e3f72008-09-13 01:54:27 +00001194 if (TheCall->getValueType(0) != MVT::Other)
Evan Cheng07322bb2008-02-05 22:44:06 +00001195 InFlag = Chain.getValue(1);
1196
Dan Gohman8181bd12008-07-27 21:46:04 +00001197 SDValue ResultVals[3];
Scott Michel8efdca42007-12-04 22:23:35 +00001198 unsigned NumResults = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001199
Scott Michel8efdca42007-12-04 22:23:35 +00001200 // If the call has results, copy the values out of the ret val registers.
Dan Gohman705e3f72008-09-13 01:54:27 +00001201 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001202 default: assert(0 && "Unexpected ret value!");
1203 case MVT::Other: break;
1204 case MVT::i32:
Dan Gohman705e3f72008-09-13 01:54:27 +00001205 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001206 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1207 ResultVals[0] = Chain.getValue(0);
1208 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1209 Chain.getValue(2)).getValue(1);
1210 ResultVals[1] = Chain.getValue(0);
1211 NumResults = 2;
Scott Michel8efdca42007-12-04 22:23:35 +00001212 } else {
1213 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1214 ResultVals[0] = Chain.getValue(0);
1215 NumResults = 1;
1216 }
Scott Michel8efdca42007-12-04 22:23:35 +00001217 break;
1218 case MVT::i64:
1219 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1220 ResultVals[0] = Chain.getValue(0);
1221 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001222 break;
1223 case MVT::f32:
1224 case MVT::f64:
Dan Gohman705e3f72008-09-13 01:54:27 +00001225 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001226 InFlag).getValue(1);
1227 ResultVals[0] = Chain.getValue(0);
1228 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001229 break;
1230 case MVT::v2f64:
Scott Michele2641a12008-12-04 21:01:44 +00001231 case MVT::v2i64:
Scott Michel8efdca42007-12-04 22:23:35 +00001232 case MVT::v4f32:
1233 case MVT::v4i32:
1234 case MVT::v8i16:
1235 case MVT::v16i8:
Dan Gohman705e3f72008-09-13 01:54:27 +00001236 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001237 InFlag).getValue(1);
1238 ResultVals[0] = Chain.getValue(0);
1239 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001240 break;
1241 }
Duncan Sands698842f2008-07-02 17:40:58 +00001242
Scott Michel8efdca42007-12-04 22:23:35 +00001243 // If the function returns void, just return the chain.
1244 if (NumResults == 0)
1245 return Chain;
Scott Michel4ec722e2008-07-16 17:17:29 +00001246
Scott Michel8efdca42007-12-04 22:23:35 +00001247 // Otherwise, merge everything together with a MERGE_VALUES node.
1248 ResultVals[NumResults++] = Chain;
Dan Gohman8181bd12008-07-27 21:46:04 +00001249 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif46bf5472008-08-26 22:36:50 +00001250 return Res.getValue(Op.getResNo());
Scott Michel8efdca42007-12-04 22:23:35 +00001251}
1252
Dan Gohman8181bd12008-07-27 21:46:04 +00001253static SDValue
1254LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel8efdca42007-12-04 22:23:35 +00001255 SmallVector<CCValAssign, 16> RVLocs;
1256 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1257 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1258 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greif1c80d112008-08-28 21:40:38 +00001259 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel4ec722e2008-07-16 17:17:29 +00001260
Scott Michel8efdca42007-12-04 22:23:35 +00001261 // If this is the first return lowered for this function, add the regs to the
1262 // liveout set for the function.
Chris Lattner1b989192007-12-31 04:13:23 +00001263 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001264 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner1b989192007-12-31 04:13:23 +00001265 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel8efdca42007-12-04 22:23:35 +00001266 }
1267
Dan Gohman8181bd12008-07-27 21:46:04 +00001268 SDValue Chain = Op.getOperand(0);
1269 SDValue Flag;
Scott Michel4ec722e2008-07-16 17:17:29 +00001270
Scott Michel8efdca42007-12-04 22:23:35 +00001271 // Copy the result values into the output registers.
1272 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1273 CCValAssign &VA = RVLocs[i];
1274 assert(VA.isRegLoc() && "Can only return in registers!");
1275 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1276 Flag = Chain.getValue(1);
1277 }
1278
Gabor Greif1c80d112008-08-28 21:40:38 +00001279 if (Flag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001280 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1281 else
1282 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1283}
1284
1285
1286//===----------------------------------------------------------------------===//
1287// Vector related lowering:
1288//===----------------------------------------------------------------------===//
1289
1290static ConstantSDNode *
1291getVecImm(SDNode *N) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001292 SDValue OpVal(0, 0);
Scott Michel4ec722e2008-07-16 17:17:29 +00001293
Scott Michel8efdca42007-12-04 22:23:35 +00001294 // Check to see if this buildvec has a single non-undef value in its elements.
1295 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1296 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greif1c80d112008-08-28 21:40:38 +00001297 if (OpVal.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +00001298 OpVal = N->getOperand(i);
1299 else if (OpVal != N->getOperand(i))
1300 return 0;
1301 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001302
Gabor Greif1c80d112008-08-28 21:40:38 +00001303 if (OpVal.getNode() != 0) {
Scott Michel5974f432008-11-11 03:06:06 +00001304 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001305 return CN;
1306 }
1307 }
1308
1309 return 0; // All UNDEF: use implicit def.; not Constant node
1310}
1311
1312/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1313/// and the value fits into an unsigned 18-bit constant, and if so, return the
1314/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001315SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001316 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001317 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001318 uint64_t Value = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001319 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001320 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001321 uint32_t upper = uint32_t(UValue >> 32);
1322 uint32_t lower = uint32_t(UValue);
1323 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001324 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001325 Value = Value >> 32;
1326 }
Scott Michel8efdca42007-12-04 22:23:35 +00001327 if (Value <= 0x3ffff)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001328 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001329 }
1330
Dan Gohman8181bd12008-07-27 21:46:04 +00001331 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001332}
1333
1334/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1335/// and the value fits into a signed 16-bit constant, and if so, return the
1336/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001337SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001338 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001339 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001340 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001341 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001342 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001343 uint32_t upper = uint32_t(UValue >> 32);
1344 uint32_t lower = uint32_t(UValue);
1345 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001346 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001347 Value = Value >> 32;
1348 }
Scott Michel6baba072008-03-05 23:02:02 +00001349 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001350 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001351 }
1352 }
1353
Dan Gohman8181bd12008-07-27 21:46:04 +00001354 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001355}
1356
1357/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1358/// and the value fits into a signed 10-bit constant, and if so, return the
1359/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001360SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001361 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001362 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001363 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001364 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001365 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001366 uint32_t upper = uint32_t(UValue >> 32);
1367 uint32_t lower = uint32_t(UValue);
1368 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001369 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001370 Value = Value >> 32;
1371 }
Scott Michel6baba072008-03-05 23:02:02 +00001372 if (isS10Constant(Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001373 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001374 }
1375
Dan Gohman8181bd12008-07-27 21:46:04 +00001376 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001377}
1378
1379/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1380/// and the value fits into a signed 8-bit constant, and if so, return the
1381/// constant.
1382///
1383/// @note: The incoming vector is v16i8 because that's the only way we can load
1384/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1385/// same value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001386SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001387 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001388 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001389 int Value = (int) CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001390 if (ValueType == MVT::i16
Scott Michel5a6f17b2008-01-30 02:55:46 +00001391 && Value <= 0xffff /* truncated from uint64_t */
1392 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001393 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001394 else if (ValueType == MVT::i8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001395 && (Value & 0xff) == Value)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001396 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001397 }
1398
Dan Gohman8181bd12008-07-27 21:46:04 +00001399 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001400}
1401
1402/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1403/// and the value fits into a signed 16-bit constant, and if so, return the
1404/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001405SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001406 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001407 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001408 uint64_t Value = CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001409 if ((ValueType == MVT::i32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001410 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1411 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001412 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001413 }
1414
Dan Gohman8181bd12008-07-27 21:46:04 +00001415 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001416}
1417
1418/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001419SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001420 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001421 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001422 }
1423
Dan Gohman8181bd12008-07-27 21:46:04 +00001424 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001425}
1426
1427/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001428SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001429 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001430 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001431 }
1432
Dan Gohman8181bd12008-07-27 21:46:04 +00001433 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001434}
1435
1436// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001437// UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001438// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1439// zero. Return true if this is not an array of constants, false if it is.
1440//
1441static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1442 uint64_t UndefBits[2]) {
1443 // Start with zero'd results.
1444 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001445
Duncan Sands92c43912008-06-06 12:08:01 +00001446 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel8efdca42007-12-04 22:23:35 +00001447 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001448 SDValue OpVal = BV->getOperand(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001449
Scott Michel8efdca42007-12-04 22:23:35 +00001450 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1451 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1452
1453 uint64_t EltBits = 0;
1454 if (OpVal.getOpcode() == ISD::UNDEF) {
1455 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1456 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1457 continue;
Scott Michel5974f432008-11-11 03:06:06 +00001458 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001459 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel5974f432008-11-11 03:06:06 +00001460 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001461 const APFloat &apf = CN->getValueAPF();
1462 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001463 ? FloatToBits(apf.convertToFloat())
1464 : DoubleToBits(apf.convertToDouble()));
Scott Michel8efdca42007-12-04 22:23:35 +00001465 } else {
1466 // Nonconstant element.
1467 return true;
1468 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001469
Scott Michel8efdca42007-12-04 22:23:35 +00001470 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1471 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001472
1473 //printf("%llx %llx %llx %llx\n",
Scott Michel8efdca42007-12-04 22:23:35 +00001474 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1475 return false;
1476}
1477
1478/// If this is a splat (repetition) of a value across the whole vector, return
1479/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel4ec722e2008-07-16 17:17:29 +00001480/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel8efdca42007-12-04 22:23:35 +00001481/// SplatSize = 1 byte.
Scott Michel4ec722e2008-07-16 17:17:29 +00001482static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel8efdca42007-12-04 22:23:35 +00001483 const uint64_t Undef128[2],
Scott Michel5a6f17b2008-01-30 02:55:46 +00001484 int MinSplatBits,
Scott Michel8efdca42007-12-04 22:23:35 +00001485 uint64_t &SplatBits, uint64_t &SplatUndef,
1486 int &SplatSize) {
1487 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1488 // the same as the lower 64-bits, ignoring undefs.
1489 uint64_t Bits64 = Bits128[0] | Bits128[1];
1490 uint64_t Undef64 = Undef128[0] & Undef128[1];
1491 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1492 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1493 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1494 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1495
1496 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1497 if (MinSplatBits < 64) {
Scott Michel4ec722e2008-07-16 17:17:29 +00001498
Scott Michel8efdca42007-12-04 22:23:35 +00001499 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1500 // undefs.
1501 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001502 if (MinSplatBits < 32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001503
Scott Michel5a6f17b2008-01-30 02:55:46 +00001504 // If the top 16-bits are different than the lower 16-bits, ignoring
1505 // undefs, we have an i32 splat.
1506 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1507 if (MinSplatBits < 16) {
1508 // If the top 8-bits are different than the lower 8-bits, ignoring
1509 // undefs, we have an i16 splat.
Gabor Greife9f7f582008-08-31 15:37:04 +00001510 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1511 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001512 // Otherwise, we have an 8-bit splat.
1513 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1514 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1515 SplatSize = 1;
1516 return true;
1517 }
1518 } else {
1519 SplatBits = Bits16;
1520 SplatUndef = Undef16;
1521 SplatSize = 2;
1522 return true;
1523 }
1524 }
1525 } else {
1526 SplatBits = Bits32;
1527 SplatUndef = Undef32;
1528 SplatSize = 4;
1529 return true;
1530 }
Scott Michel8efdca42007-12-04 22:23:35 +00001531 }
1532 } else {
1533 SplatBits = Bits128[0];
1534 SplatUndef = Undef128[0];
1535 SplatSize = 8;
1536 return true;
1537 }
1538 }
1539
1540 return false; // Can't be a splat if two pieces don't match.
1541}
1542
1543// If this is a case we can't handle, return null and let the default
1544// expansion code take care of it. If we CAN select this case, and if it
1545// selects to a single instruction, return Op. Otherwise, if we can codegen
1546// this case more efficiently than a constant pool load, lower it to the
1547// sequence of ops that should be used.
Dan Gohman8181bd12008-07-27 21:46:04 +00001548static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001549 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00001550 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001551 // UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001552 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel4ec722e2008-07-16 17:17:29 +00001553 // zero.
Scott Michel8efdca42007-12-04 22:23:35 +00001554 uint64_t VectorBits[2];
1555 uint64_t UndefBits[2];
1556 uint64_t SplatBits, SplatUndef;
1557 int SplatSize;
Gabor Greif1c80d112008-08-28 21:40:38 +00001558 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel8efdca42007-12-04 22:23:35 +00001559 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00001560 VT.getVectorElementType().getSizeInBits(),
Scott Michel8efdca42007-12-04 22:23:35 +00001561 SplatBits, SplatUndef, SplatSize))
Dan Gohman8181bd12008-07-27 21:46:04 +00001562 return SDValue(); // Not a constant vector, not a splat.
Scott Michel4ec722e2008-07-16 17:17:29 +00001563
Duncan Sands92c43912008-06-06 12:08:01 +00001564 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001565 default:
1566 case MVT::v4f32: {
1567 uint32_t Value32 = SplatBits;
1568 assert(SplatSize == 4
Scott Michel5a6f17b2008-01-30 02:55:46 +00001569 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel8efdca42007-12-04 22:23:35 +00001570 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001571 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001572 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001573 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001574 break;
1575 }
1576 case MVT::v2f64: {
1577 uint64_t f64val = SplatBits;
1578 assert(SplatSize == 8
Scott Michelc630c412008-11-24 17:11:17 +00001579 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel8efdca42007-12-04 22:23:35 +00001580 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001581 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001582 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001583 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001584 break;
1585 }
1586 case MVT::v16i8: {
1587 // 8-bit constants have to be expanded to 16-bits
1588 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman8181bd12008-07-27 21:46:04 +00001589 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001590 for (int i = 0; i < 8; ++i)
1591 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1592 return DAG.getNode(ISD::BIT_CONVERT, VT,
1593 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1594 }
1595 case MVT::v8i16: {
1596 unsigned short Value16;
Scott Michel4ec722e2008-07-16 17:17:29 +00001597 if (SplatSize == 2)
Scott Michel8efdca42007-12-04 22:23:35 +00001598 Value16 = (unsigned short) (SplatBits & 0xffff);
1599 else
1600 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman8181bd12008-07-27 21:46:04 +00001601 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1602 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001603 for (int i = 0; i < 8; ++i) Ops[i] = T;
1604 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1605 }
1606 case MVT::v4i32: {
1607 unsigned int Value = SplatBits;
Dan Gohman8181bd12008-07-27 21:46:04 +00001608 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel8efdca42007-12-04 22:23:35 +00001609 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1610 }
1611 case MVT::v2i64: {
1612 uint64_t val = SplatBits;
1613 uint32_t upper = uint32_t(val >> 32);
1614 uint32_t lower = uint32_t(val);
1615
Scott Michelbcc7b672008-03-06 04:02:54 +00001616 if (upper == lower) {
1617 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman8181bd12008-07-27 21:46:04 +00001618 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michelbcc7b672008-03-06 04:02:54 +00001619 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michel6baba072008-03-05 23:02:02 +00001620 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +00001621 SDValue LO32;
1622 SDValue HI32;
1623 SmallVector<SDValue, 16> ShufBytes;
1624 SDValue Result;
Scott Michel8efdca42007-12-04 22:23:35 +00001625 bool upper_special, lower_special;
1626
1627 // NOTE: This code creates common-case shuffle masks that can be easily
1628 // detected as common expressions. It is not attempting to create highly
1629 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1630
1631 // Detect if the upper or lower half is a special shuffle mask pattern:
Scott Michelc630c412008-11-24 17:11:17 +00001632 upper_special = (upper == 0||upper == 0xffffffff||upper == 0x80000000);
1633 lower_special = (lower == 0||lower == 0xffffffff||lower == 0x80000000);
Scott Michel8efdca42007-12-04 22:23:35 +00001634
1635 // Create lower vector if not a special pattern
1636 if (!lower_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001637 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001638 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1639 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1640 LO32C, LO32C, LO32C, LO32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001641 }
1642
1643 // Create upper vector if not a special pattern
1644 if (!upper_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001645 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001646 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1647 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1648 HI32C, HI32C, HI32C, HI32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001649 }
1650
1651 // If either upper or lower are special, then the two input operands are
1652 // the same (basically, one of them is a "don't care")
1653 if (lower_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001654 LO32 = HI32;
Scott Michel8efdca42007-12-04 22:23:35 +00001655 if (upper_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001656 HI32 = LO32;
Scott Michel8efdca42007-12-04 22:23:35 +00001657 if (lower_special && upper_special) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001658 // Unhappy situation... both upper and lower are special, so punt with
1659 // a target constant:
Dan Gohman8181bd12008-07-27 21:46:04 +00001660 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001661 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel8efdca42007-12-04 22:23:35 +00001662 Zero, Zero);
1663 }
1664
1665 for (int i = 0; i < 4; ++i) {
Scott Michel67224b22008-06-02 22:18:03 +00001666 uint64_t val = 0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001667 for (int j = 0; j < 4; ++j) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001668 SDValue V;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001669 bool process_upper, process_lower;
Scott Michel67224b22008-06-02 22:18:03 +00001670 val <<= 8;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001671 process_upper = (upper_special && (i & 1) == 0);
1672 process_lower = (lower_special && (i & 1) == 1);
Scott Michel8efdca42007-12-04 22:23:35 +00001673
Scott Michel5a6f17b2008-01-30 02:55:46 +00001674 if (process_upper || process_lower) {
1675 if ((process_upper && upper == 0)
1676 || (process_lower && lower == 0))
Scott Michel67224b22008-06-02 22:18:03 +00001677 val |= 0x80;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001678 else if ((process_upper && upper == 0xffffffff)
1679 || (process_lower && lower == 0xffffffff))
Scott Michel67224b22008-06-02 22:18:03 +00001680 val |= 0xc0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001681 else if ((process_upper && upper == 0x80000000)
1682 || (process_lower && lower == 0x80000000))
Scott Michel67224b22008-06-02 22:18:03 +00001683 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001684 } else
Scott Michel67224b22008-06-02 22:18:03 +00001685 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001686 }
Scott Michel67224b22008-06-02 22:18:03 +00001687
1688 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001689 }
1690
1691 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel67224b22008-06-02 22:18:03 +00001692 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001693 &ShufBytes[0], ShufBytes.size()));
Scott Michel8efdca42007-12-04 22:23:35 +00001694 }
1695 }
1696 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001697
Dan Gohman8181bd12008-07-27 21:46:04 +00001698 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001699}
1700
1701/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1702/// which the Cell can operate. The code inspects V3 to ascertain whether the
1703/// permutation vector, V3, is monotonically increasing with one "exception"
1704/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel56a125e2008-11-22 23:50:42 +00001705/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel8efdca42007-12-04 22:23:35 +00001706/// In either case, the net result is going to eventually invoke SHUFB to
1707/// permute/shuffle the bytes from V1 and V2.
1708/// \note
Scott Michel56a125e2008-11-22 23:50:42 +00001709/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel8efdca42007-12-04 22:23:35 +00001710/// control word for byte/halfword/word insertion. This takes care of a single
1711/// element move from V2 into V1.
1712/// \note
1713/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman8181bd12008-07-27 21:46:04 +00001714static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1715 SDValue V1 = Op.getOperand(0);
1716 SDValue V2 = Op.getOperand(1);
1717 SDValue PermMask = Op.getOperand(2);
Scott Michel4ec722e2008-07-16 17:17:29 +00001718
Scott Michel8efdca42007-12-04 22:23:35 +00001719 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel4ec722e2008-07-16 17:17:29 +00001720
Scott Michel8efdca42007-12-04 22:23:35 +00001721 // If we have a single element being moved from V1 to V2, this can be handled
1722 // using the C*[DX] compute mask instructions, but the vector elements have
1723 // to be monotonically increasing with one exception element.
Scott Michele2641a12008-12-04 21:01:44 +00001724 MVT VecVT = V1.getValueType();
1725 MVT EltVT = VecVT.getVectorElementType();
Scott Michel8efdca42007-12-04 22:23:35 +00001726 unsigned EltsFromV2 = 0;
1727 unsigned V2Elt = 0;
1728 unsigned V2EltIdx0 = 0;
1729 unsigned CurrElt = 0;
Scott Michele2641a12008-12-04 21:01:44 +00001730 unsigned MaxElts = VecVT.getVectorNumElements();
1731 unsigned PrevElt = 0;
1732 unsigned V0Elt = 0;
Scott Michel8efdca42007-12-04 22:23:35 +00001733 bool monotonic = true;
Scott Michele2641a12008-12-04 21:01:44 +00001734 bool rotate = true;
1735
1736 if (EltVT == MVT::i8) {
Scott Michel8efdca42007-12-04 22:23:35 +00001737 V2EltIdx0 = 16;
Scott Michele2641a12008-12-04 21:01:44 +00001738 } else if (EltVT == MVT::i16) {
Scott Michel8efdca42007-12-04 22:23:35 +00001739 V2EltIdx0 = 8;
Scott Michele2641a12008-12-04 21:01:44 +00001740 } else if (EltVT == MVT::i32 || EltVT == MVT::f32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001741 V2EltIdx0 = 4;
Scott Michele2641a12008-12-04 21:01:44 +00001742 } else if (EltVT == MVT::i64 || EltVT == MVT::f64) {
1743 V2EltIdx0 = 2;
1744 } else
Scott Michel8efdca42007-12-04 22:23:35 +00001745 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1746
Scott Michele2641a12008-12-04 21:01:44 +00001747 for (unsigned i = 0; i != PermMask.getNumOperands(); ++i) {
1748 if (PermMask.getOperand(i).getOpcode() != ISD::UNDEF) {
1749 unsigned SrcElt = cast<ConstantSDNode > (PermMask.getOperand(i))->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001750
Scott Michele2641a12008-12-04 21:01:44 +00001751 if (monotonic) {
1752 if (SrcElt >= V2EltIdx0) {
1753 if (1 >= (++EltsFromV2)) {
1754 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1755 }
1756 } else if (CurrElt != SrcElt) {
1757 monotonic = false;
1758 }
1759
1760 ++CurrElt;
1761 }
1762
1763 if (rotate) {
1764 if (PrevElt > 0 && SrcElt < MaxElts) {
1765 if ((PrevElt == SrcElt - 1)
1766 || (PrevElt == MaxElts - 1 && SrcElt == 0)) {
1767 PrevElt = SrcElt;
1768 if (SrcElt == 0)
1769 V0Elt = i;
1770 } else {
1771 rotate = false;
1772 }
1773 } else if (PrevElt == 0) {
1774 // First time through, need to keep track of previous element
1775 PrevElt = SrcElt;
1776 } else {
1777 // This isn't a rotation, takes elements from vector 2
1778 rotate = false;
1779 }
1780 }
Scott Michel8efdca42007-12-04 22:23:35 +00001781 }
Scott Michel8efdca42007-12-04 22:23:35 +00001782 }
1783
1784 if (EltsFromV2 == 1 && monotonic) {
1785 // Compute mask and shuffle
1786 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001787 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1788 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands92c43912008-06-06 12:08:01 +00001789 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00001790 // Initialize temporary register to 0
Dan Gohman8181bd12008-07-27 21:46:04 +00001791 SDValue InitTempReg =
Scott Michel8efdca42007-12-04 22:23:35 +00001792 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel56a125e2008-11-22 23:50:42 +00001793 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman8181bd12008-07-27 21:46:04 +00001794 SDValue ShufMaskOp =
Scott Michel0718cd82008-12-01 17:56:02 +00001795 DAG.getNode(SPUISD::SHUFFLE_MASK, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001796 DAG.getTargetConstant(V2Elt, MVT::i32),
1797 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +00001798 // Use shuffle mask in SHUFB synthetic instruction:
1799 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
Scott Michele2641a12008-12-04 21:01:44 +00001800 } else if (rotate) {
1801 int rotamt = (MaxElts - V0Elt) * EltVT.getSizeInBits()/8;
Scott Michelae5cbf52008-12-29 03:23:36 +00001802
Scott Michele2641a12008-12-04 21:01:44 +00001803 return DAG.getNode(SPUISD::ROTBYTES_LEFT, V1.getValueType(),
1804 V1, DAG.getConstant(rotamt, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001805 } else {
Gabor Greife9f7f582008-08-31 15:37:04 +00001806 // Convert the SHUFFLE_VECTOR mask's input element units to the
1807 // actual bytes.
Duncan Sands92c43912008-06-06 12:08:01 +00001808 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel4ec722e2008-07-16 17:17:29 +00001809
Dan Gohman8181bd12008-07-27 21:46:04 +00001810 SmallVector<SDValue, 16> ResultMask;
Scott Michel8efdca42007-12-04 22:23:35 +00001811 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1812 unsigned SrcElt;
1813 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001814 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001815 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001816 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel4ec722e2008-07-16 17:17:29 +00001817
Scott Michel97872d32008-02-23 18:41:37 +00001818 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001819 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1820 MVT::i8));
Scott Michel8efdca42007-12-04 22:23:35 +00001821 }
1822 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001823
Dan Gohman8181bd12008-07-27 21:46:04 +00001824 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel0718cd82008-12-01 17:56:02 +00001825 &ResultMask[0], ResultMask.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001826 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1827 }
1828}
1829
Dan Gohman8181bd12008-07-27 21:46:04 +00001830static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1831 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel8efdca42007-12-04 22:23:35 +00001832
Gabor Greif1c80d112008-08-28 21:40:38 +00001833 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel8efdca42007-12-04 22:23:35 +00001834 // For a constant, build the appropriate constant vector, which will
1835 // eventually simplify to a vector register load.
1836
Gabor Greif1c80d112008-08-28 21:40:38 +00001837 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman8181bd12008-07-27 21:46:04 +00001838 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands92c43912008-06-06 12:08:01 +00001839 MVT VT;
Scott Michel8efdca42007-12-04 22:23:35 +00001840 size_t n_copies;
1841
1842 // Create a constant vector:
Duncan Sands92c43912008-06-06 12:08:01 +00001843 switch (Op.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001844 default: assert(0 && "Unexpected constant value type in "
Scott Michel5a6f17b2008-01-30 02:55:46 +00001845 "LowerSCALAR_TO_VECTOR");
Scott Michel8efdca42007-12-04 22:23:35 +00001846 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1847 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1848 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1849 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1850 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1851 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1852 }
1853
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001854 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel8efdca42007-12-04 22:23:35 +00001855 for (size_t j = 0; j < n_copies; ++j)
1856 ConstVecValues.push_back(CValue);
1857
1858 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001859 &ConstVecValues[0], ConstVecValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001860 } else {
1861 // Otherwise, copy the value from one register to another:
Duncan Sands92c43912008-06-06 12:08:01 +00001862 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001863 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1864 case MVT::i8:
1865 case MVT::i16:
1866 case MVT::i32:
1867 case MVT::i64:
1868 case MVT::f32:
1869 case MVT::f64:
Scott Michel06eabde2008-12-27 04:51:36 +00001870 return DAG.getNode(SPUISD::PREFSLOT2VEC, Op.getValueType(), Op0, Op0);
Scott Michel8efdca42007-12-04 22:23:35 +00001871 }
1872 }
1873
Dan Gohman8181bd12008-07-27 21:46:04 +00001874 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001875}
1876
Dan Gohman8181bd12008-07-27 21:46:04 +00001877static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001878 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001879 SDValue N = Op.getOperand(0);
1880 SDValue Elt = Op.getOperand(1);
Scott Michel56a125e2008-11-22 23:50:42 +00001881 SDValue retval;
Scott Michel8efdca42007-12-04 22:23:35 +00001882
Scott Michel56a125e2008-11-22 23:50:42 +00001883 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
1884 // Constant argument:
1885 int EltNo = (int) C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001886
Scott Michel56a125e2008-11-22 23:50:42 +00001887 // sanity checks:
1888 if (VT == MVT::i8 && EltNo >= 16)
1889 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
1890 else if (VT == MVT::i16 && EltNo >= 8)
1891 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
1892 else if (VT == MVT::i32 && EltNo >= 4)
1893 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
1894 else if (VT == MVT::i64 && EltNo >= 2)
1895 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel8efdca42007-12-04 22:23:35 +00001896
Scott Michel56a125e2008-11-22 23:50:42 +00001897 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
1898 // i32 and i64: Element 0 is the preferred slot
Scott Michelc630c412008-11-24 17:11:17 +00001899 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel56a125e2008-11-22 23:50:42 +00001900 }
Scott Michel8efdca42007-12-04 22:23:35 +00001901
Scott Michel56a125e2008-11-22 23:50:42 +00001902 // Need to generate shuffle mask and extract:
1903 int prefslot_begin = -1, prefslot_end = -1;
1904 int elt_byte = EltNo * VT.getSizeInBits() / 8;
1905
1906 switch (VT.getSimpleVT()) {
1907 default:
1908 assert(false && "Invalid value type!");
1909 case MVT::i8: {
1910 prefslot_begin = prefslot_end = 3;
1911 break;
1912 }
1913 case MVT::i16: {
1914 prefslot_begin = 2; prefslot_end = 3;
1915 break;
1916 }
1917 case MVT::i32:
1918 case MVT::f32: {
1919 prefslot_begin = 0; prefslot_end = 3;
1920 break;
1921 }
1922 case MVT::i64:
1923 case MVT::f64: {
1924 prefslot_begin = 0; prefslot_end = 7;
1925 break;
1926 }
1927 }
1928
1929 assert(prefslot_begin != -1 && prefslot_end != -1 &&
1930 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
1931
1932 unsigned int ShufBytes[16];
1933 for (int i = 0; i < 16; ++i) {
1934 // zero fill uppper part of preferred slot, don't care about the
1935 // other slots:
1936 unsigned int mask_val;
1937 if (i <= prefslot_end) {
1938 mask_val =
1939 ((i < prefslot_begin)
1940 ? 0x80
1941 : elt_byte + (i - prefslot_begin));
1942
1943 ShufBytes[i] = mask_val;
1944 } else
1945 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
1946 }
1947
1948 SDValue ShufMask[4];
1949 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
Scott Michele2641a12008-12-04 21:01:44 +00001950 unsigned bidx = i * 4;
Scott Michel56a125e2008-11-22 23:50:42 +00001951 unsigned int bits = ((ShufBytes[bidx] << 24) |
1952 (ShufBytes[bidx+1] << 16) |
1953 (ShufBytes[bidx+2] << 8) |
1954 ShufBytes[bidx+3]);
1955 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
1956 }
1957
1958 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1959 &ShufMask[0],
1960 sizeof(ShufMask) / sizeof(ShufMask[0]));
1961
Scott Michelc630c412008-11-24 17:11:17 +00001962 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel56a125e2008-11-22 23:50:42 +00001963 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
1964 N, N, ShufMaskVec));
1965 } else {
1966 // Variable index: Rotate the requested element into slot 0, then replicate
1967 // slot 0 across the vector
1968 MVT VecVT = N.getValueType();
1969 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
1970 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
1971 abort();
1972 }
1973
1974 // Make life easier by making sure the index is zero-extended to i32
1975 if (Elt.getValueType() != MVT::i32)
1976 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
1977
1978 // Scale the index to a bit/byte shift quantity
1979 APInt scaleFactor =
Scott Michelc630c412008-11-24 17:11:17 +00001980 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
1981 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel56a125e2008-11-22 23:50:42 +00001982 SDValue vecShift;
Scott Michel56a125e2008-11-22 23:50:42 +00001983
Scott Michelc630c412008-11-24 17:11:17 +00001984 if (scaleShift > 0) {
1985 // Scale the shift factor:
Scott Michel56a125e2008-11-22 23:50:42 +00001986 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel0718cd82008-12-01 17:56:02 +00001987 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel56a125e2008-11-22 23:50:42 +00001988 }
1989
Scott Michelc630c412008-11-24 17:11:17 +00001990 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
1991
1992 // Replicate the bytes starting at byte 0 across the entire vector (for
1993 // consistency with the notion of a unified register set)
Scott Michel56a125e2008-11-22 23:50:42 +00001994 SDValue replicate;
1995
1996 switch (VT.getSimpleVT()) {
1997 default:
1998 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
1999 abort();
2000 /*NOTREACHED*/
2001 case MVT::i8: {
Scott Michelc630c412008-11-24 17:11:17 +00002002 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002003 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2004 factor, factor);
2005 break;
2006 }
2007 case MVT::i16: {
Scott Michelc630c412008-11-24 17:11:17 +00002008 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002009 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2010 factor, factor);
2011 break;
2012 }
2013 case MVT::i32:
2014 case MVT::f32: {
2015 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2016 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2017 factor, factor);
2018 break;
2019 }
2020 case MVT::i64:
2021 case MVT::f64: {
2022 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2023 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2024 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2025 loFactor, hiFactor);
2026 break;
2027 }
2028 }
2029
Scott Michelc630c412008-11-24 17:11:17 +00002030 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel0718cd82008-12-01 17:56:02 +00002031 DAG.getNode(SPUISD::SHUFB, VecVT,
2032 vecShift, vecShift, replicate));
Scott Michel8efdca42007-12-04 22:23:35 +00002033 }
2034
Scott Michel56a125e2008-11-22 23:50:42 +00002035 return retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002036}
2037
Dan Gohman8181bd12008-07-27 21:46:04 +00002038static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2039 SDValue VecOp = Op.getOperand(0);
2040 SDValue ValOp = Op.getOperand(1);
2041 SDValue IdxOp = Op.getOperand(2);
Duncan Sands92c43912008-06-06 12:08:01 +00002042 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002043
2044 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2045 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2046
Duncan Sands92c43912008-06-06 12:08:01 +00002047 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel0718cd82008-12-01 17:56:02 +00002048 // Use $sp ($1) because it's always 16-byte aligned and it's available:
2049 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
2050 DAG.getRegister(SPU::R1, PtrVT),
2051 DAG.getConstant(CN->getSExtValue(), PtrVT));
2052 SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, VT, Pointer);
Scott Michel8efdca42007-12-04 22:23:35 +00002053
Dan Gohman8181bd12008-07-27 21:46:04 +00002054 SDValue result =
Scott Michel8efdca42007-12-04 22:23:35 +00002055 DAG.getNode(SPUISD::SHUFB, VT,
2056 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
Scott Michelae5cbf52008-12-29 03:23:36 +00002057 VecOp,
Scott Michel0718cd82008-12-01 17:56:02 +00002058 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, ShufMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002059
2060 return result;
2061}
2062
Scott Michel06eabde2008-12-27 04:51:36 +00002063static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc,
2064 const TargetLowering &TLI)
Scott Michel97872d32008-02-23 18:41:37 +00002065{
Dan Gohman8181bd12008-07-27 21:46:04 +00002066 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel06eabde2008-12-27 04:51:36 +00002067 MVT ShiftVT = TLI.getShiftAmountTy();
Scott Michel8efdca42007-12-04 22:23:35 +00002068
2069 assert(Op.getValueType() == MVT::i8);
2070 switch (Opc) {
2071 default:
2072 assert(0 && "Unhandled i8 math operator");
2073 /*NOTREACHED*/
2074 break;
Scott Michel4d07fb72008-12-30 23:28:25 +00002075 case ISD::ADD: {
2076 // 8-bit addition: Promote the arguments up to 16-bits and truncate
2077 // the result:
2078 SDValue N1 = Op.getOperand(1);
2079 N0 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0);
2080 N1 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1);
2081 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
2082 DAG.getNode(Opc, MVT::i16, N0, N1));
2083
2084 }
2085
Scott Michel8efdca42007-12-04 22:23:35 +00002086 case ISD::SUB: {
2087 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2088 // the result:
Dan Gohman8181bd12008-07-27 21:46:04 +00002089 SDValue N1 = Op.getOperand(1);
Scott Michel4d07fb72008-12-30 23:28:25 +00002090 N0 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0);
2091 N1 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1);
Scott Michel4ec722e2008-07-16 17:17:29 +00002092 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002093 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel4ec722e2008-07-16 17:17:29 +00002094 }
Scott Michel8efdca42007-12-04 22:23:35 +00002095 case ISD::ROTR:
2096 case ISD::ROTL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002097 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002098 unsigned N1Opc;
2099 N0 = (N0.getOpcode() != ISD::Constant
2100 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002101 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2102 MVT::i16));
Scott Michel06eabde2008-12-27 04:51:36 +00002103 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greife9f7f582008-08-31 15:37:04 +00002104 ? ISD::ZERO_EXTEND
2105 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002106 N1 = (N1.getOpcode() != ISD::Constant
Scott Michel06eabde2008-12-27 04:51:36 +00002107 ? DAG.getNode(N1Opc, ShiftVT, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002108 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Scott Michel06eabde2008-12-27 04:51:36 +00002109 TLI.getShiftAmountTy()));
Dan Gohman8181bd12008-07-27 21:46:04 +00002110 SDValue ExpandArg =
Scott Michel8efdca42007-12-04 22:23:35 +00002111 DAG.getNode(ISD::OR, MVT::i16, N0,
2112 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sands7aef60d2008-10-30 19:24:28 +00002113 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002114 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002115 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2116 }
2117 case ISD::SRL:
2118 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002119 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002120 unsigned N1Opc;
2121 N0 = (N0.getOpcode() != ISD::Constant
2122 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002123 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
Scott Michel06eabde2008-12-27 04:51:36 +00002124 MVT::i32));
2125 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greife9f7f582008-08-31 15:37:04 +00002126 ? ISD::ZERO_EXTEND
2127 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002128 N1 = (N1.getOpcode() != ISD::Constant
Scott Michel06eabde2008-12-27 04:51:36 +00002129 ? DAG.getNode(N1Opc, ShiftVT, N1)
2130 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(), ShiftVT));
Scott Michel4ec722e2008-07-16 17:17:29 +00002131 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002132 DAG.getNode(Opc, MVT::i16, N0, N1));
2133 }
2134 case ISD::SRA: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002135 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002136 unsigned N1Opc;
2137 N0 = (N0.getOpcode() != ISD::Constant
2138 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Scott Michel06eabde2008-12-27 04:51:36 +00002139 : DAG.getConstant(cast<ConstantSDNode>(N0)->getSExtValue(),
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002140 MVT::i16));
Scott Michel06eabde2008-12-27 04:51:36 +00002141 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greife9f7f582008-08-31 15:37:04 +00002142 ? ISD::SIGN_EXTEND
2143 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002144 N1 = (N1.getOpcode() != ISD::Constant
Scott Michel06eabde2008-12-27 04:51:36 +00002145 ? DAG.getNode(N1Opc, ShiftVT, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002146 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Scott Michel06eabde2008-12-27 04:51:36 +00002147 ShiftVT));
Scott Michel4ec722e2008-07-16 17:17:29 +00002148 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002149 DAG.getNode(Opc, MVT::i16, N0, N1));
2150 }
2151 case ISD::MUL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002152 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002153 unsigned N1Opc;
2154 N0 = (N0.getOpcode() != ISD::Constant
2155 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002156 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2157 MVT::i16));
Duncan Sandsec142ee2008-06-08 20:54:56 +00002158 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002159 N1 = (N1.getOpcode() != ISD::Constant
2160 ? DAG.getNode(N1Opc, MVT::i16, N1)
Scott Michel06eabde2008-12-27 04:51:36 +00002161 : DAG.getConstant(cast<ConstantSDNode>(N1)->getSExtValue(),
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002162 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002163 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002164 DAG.getNode(Opc, MVT::i16, N0, N1));
2165 break;
2166 }
2167 }
2168
Dan Gohman8181bd12008-07-27 21:46:04 +00002169 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002170}
2171
Dan Gohman8181bd12008-07-27 21:46:04 +00002172static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002173{
Duncan Sands92c43912008-06-06 12:08:01 +00002174 MVT VT = Op.getValueType();
2175 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002176
Dan Gohman8181bd12008-07-27 21:46:04 +00002177 SDValue Op0 = Op.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002178
2179 switch (Opc) {
2180 case ISD::ZERO_EXTEND:
Scott Michel97872d32008-02-23 18:41:37 +00002181 case ISD::ANY_EXTEND: {
Duncan Sands92c43912008-06-06 12:08:01 +00002182 MVT Op0VT = Op0.getValueType();
2183 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002184
2185 assert(Op0VT == MVT::i32
2186 && "CellSPU: Zero/sign extending something other than i32");
2187
Scott Michelc630c412008-11-24 17:11:17 +00002188 DEBUG(cerr << "CellSPU.LowerI64Math: lowering zero/sign/any extend\n");
2189
Dan Gohman8181bd12008-07-27 21:46:04 +00002190 SDValue PromoteScalar =
Scott Michel06eabde2008-12-27 04:51:36 +00002191 DAG.getNode(SPUISD::PREFSLOT2VEC, Op0VecVT, Op0);
Scott Michel97872d32008-02-23 18:41:37 +00002192
Scott Michel4d07fb72008-12-30 23:28:25 +00002193 // Use a shuffle to zero extend the i32 to i64 directly:
2194 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, Op0VecVT,
2195 DAG.getConstant(0x80808080, MVT::i32), DAG.getConstant(0x00010203,
2196 MVT::i32), DAG.getConstant(0x80808080, MVT::i32), DAG.getConstant(
2197 0x08090a0b, MVT::i32));
2198 SDValue zextShuffle = DAG.getNode(SPUISD::SHUFB, Op0VecVT, PromoteScalar,
2199 PromoteScalar, shufMask);
Scott Michelf2df6cb2008-11-24 18:20:46 +00002200
Scott Michel4d07fb72008-12-30 23:28:25 +00002201 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, DAG.getNode(ISD::BIT_CONVERT,
2202 VecVT, zextShuffle));
Scott Michel97872d32008-02-23 18:41:37 +00002203 }
2204
Scott Michel67224b22008-06-02 22:18:03 +00002205 case ISD::ADD: {
2206 // Turn operands into vectors to satisfy type checking (shufb works on
2207 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002208 SDValue Op0 =
Scott Michel06eabde2008-12-27 04:51:36 +00002209 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002210 SDValue Op1 =
Scott Michel06eabde2008-12-27 04:51:36 +00002211 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002212 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002213
2214 // Create the shuffle mask for "rotating" the borrow up one register slot
2215 // once the borrow is generated.
2216 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2217 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2218 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2219 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2220
Dan Gohman8181bd12008-07-27 21:46:04 +00002221 SDValue CarryGen =
Scott Michel67224b22008-06-02 22:18:03 +00002222 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002223 SDValue ShiftedCarry =
Scott Michel67224b22008-06-02 22:18:03 +00002224 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2225 CarryGen, CarryGen,
2226 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2227 &ShufBytes[0], ShufBytes.size()));
2228
Scott Michelc630c412008-11-24 17:11:17 +00002229 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002230 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2231 Op0, Op1, ShiftedCarry));
2232 }
2233
2234 case ISD::SUB: {
2235 // Turn operands into vectors to satisfy type checking (shufb works on
2236 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002237 SDValue Op0 =
Scott Michel06eabde2008-12-27 04:51:36 +00002238 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002239 SDValue Op1 =
Scott Michel06eabde2008-12-27 04:51:36 +00002240 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002241 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002242
2243 // Create the shuffle mask for "rotating" the borrow up one register slot
2244 // once the borrow is generated.
2245 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2246 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2247 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2248 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2249
Dan Gohman8181bd12008-07-27 21:46:04 +00002250 SDValue BorrowGen =
Scott Michel67224b22008-06-02 22:18:03 +00002251 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002252 SDValue ShiftedBorrow =
Scott Michel67224b22008-06-02 22:18:03 +00002253 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2254 BorrowGen, BorrowGen,
2255 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2256 &ShufBytes[0], ShufBytes.size()));
2257
Scott Michelc630c412008-11-24 17:11:17 +00002258 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002259 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2260 Op0, Op1, ShiftedBorrow));
2261 }
Scott Michel97872d32008-02-23 18:41:37 +00002262 }
2263
Dan Gohman8181bd12008-07-27 21:46:04 +00002264 return SDValue();
Scott Michel97872d32008-02-23 18:41:37 +00002265}
2266
Scott Michel8efdca42007-12-04 22:23:35 +00002267//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman8181bd12008-07-27 21:46:04 +00002268static SDValue
2269LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2270 SDValue ConstVec;
2271 SDValue Arg;
Duncan Sands92c43912008-06-06 12:08:01 +00002272 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002273
2274 ConstVec = Op.getOperand(0);
2275 Arg = Op.getOperand(1);
Gabor Greif1c80d112008-08-28 21:40:38 +00002276 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2277 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel8efdca42007-12-04 22:23:35 +00002278 ConstVec = ConstVec.getOperand(0);
2279 } else {
2280 ConstVec = Op.getOperand(1);
2281 Arg = Op.getOperand(0);
Gabor Greif1c80d112008-08-28 21:40:38 +00002282 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00002283 ConstVec = ConstVec.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00002284 }
2285 }
2286 }
2287
Gabor Greif1c80d112008-08-28 21:40:38 +00002288 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel8efdca42007-12-04 22:23:35 +00002289 uint64_t VectorBits[2];
2290 uint64_t UndefBits[2];
2291 uint64_t SplatBits, SplatUndef;
2292 int SplatSize;
2293
Gabor Greif1c80d112008-08-28 21:40:38 +00002294 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002295 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00002296 VT.getVectorElementType().getSizeInBits(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002297 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002298 SDValue tcVec[16];
2299 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel8efdca42007-12-04 22:23:35 +00002300 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2301
2302 // Turn the BUILD_VECTOR into a set of target constants:
2303 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002304 tcVec[i] = tc;
Scott Michel8efdca42007-12-04 22:23:35 +00002305
Gabor Greif1c80d112008-08-28 21:40:38 +00002306 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002307 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel8efdca42007-12-04 22:23:35 +00002308 }
2309 }
Nate Begeman7569e762008-07-29 19:07:27 +00002310 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2311 // lowered. Return the operation, rather than a null SDValue.
2312 return Op;
Scott Michel8efdca42007-12-04 22:23:35 +00002313}
2314
Scott Michel8efdca42007-12-04 22:23:35 +00002315//! Custom lowering for CTPOP (count population)
2316/*!
2317 Custom lowering code that counts the number ones in the input
2318 operand. SPU has such an instruction, but it counts the number of
2319 ones per byte, which then have to be accumulated.
2320*/
Dan Gohman8181bd12008-07-27 21:46:04 +00002321static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002322 MVT VT = Op.getValueType();
2323 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +00002324
Duncan Sands92c43912008-06-06 12:08:01 +00002325 switch (VT.getSimpleVT()) {
2326 default:
2327 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002328 case MVT::i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002329 SDValue N = Op.getOperand(0);
2330 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002331
Scott Michel06eabde2008-12-27 04:51:36 +00002332 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman8181bd12008-07-27 21:46:04 +00002333 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002334
2335 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2336 }
2337
2338 case MVT::i16: {
2339 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002340 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002341
Chris Lattner1b989192007-12-31 04:13:23 +00002342 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002343
Dan Gohman8181bd12008-07-27 21:46:04 +00002344 SDValue N = Op.getOperand(0);
2345 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2346 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sands7aef60d2008-10-30 19:24:28 +00002347 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002348
Scott Michel06eabde2008-12-27 04:51:36 +00002349 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman8181bd12008-07-27 21:46:04 +00002350 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002351
2352 // CNTB_result becomes the chain to which all of the virtual registers
2353 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002354 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002355 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002356
Dan Gohman8181bd12008-07-27 21:46:04 +00002357 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002358 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2359
Dan Gohman8181bd12008-07-27 21:46:04 +00002360 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002361
2362 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002363 DAG.getNode(ISD::ADD, MVT::i16,
2364 DAG.getNode(ISD::SRL, MVT::i16,
2365 Tmp1, Shift1),
2366 Tmp1),
2367 Mask0);
Scott Michel8efdca42007-12-04 22:23:35 +00002368 }
2369
2370 case MVT::i32: {
2371 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002372 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002373
Chris Lattner1b989192007-12-31 04:13:23 +00002374 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2375 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002376
Dan Gohman8181bd12008-07-27 21:46:04 +00002377 SDValue N = Op.getOperand(0);
2378 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2379 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2380 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2381 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002382
Scott Michel06eabde2008-12-27 04:51:36 +00002383 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman8181bd12008-07-27 21:46:04 +00002384 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002385
2386 // CNTB_result becomes the chain to which all of the virtual registers
2387 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002388 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002389 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002390
Dan Gohman8181bd12008-07-27 21:46:04 +00002391 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002392 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2393
Dan Gohman8181bd12008-07-27 21:46:04 +00002394 SDValue Comp1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002395 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002396 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel8efdca42007-12-04 22:23:35 +00002397
Dan Gohman8181bd12008-07-27 21:46:04 +00002398 SDValue Sum1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002399 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002400 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002401
Dan Gohman8181bd12008-07-27 21:46:04 +00002402 SDValue Sum1_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002403 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2404
Dan Gohman8181bd12008-07-27 21:46:04 +00002405 SDValue Comp2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002406 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002407 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2408 Shift2);
Dan Gohman8181bd12008-07-27 21:46:04 +00002409 SDValue Sum2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002410 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002411 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002412
2413 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2414 }
2415
2416 case MVT::i64:
2417 break;
2418 }
2419
Dan Gohman8181bd12008-07-27 21:46:04 +00002420 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002421}
2422
Scott Michel06eabde2008-12-27 04:51:36 +00002423//! Lower ISD::SETCC
2424/*!
2425 Lower i64 condition code handling.
2426 */
2427
2428static SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) {
2429 MVT VT = Op.getValueType();
2430 SDValue lhs = Op.getOperand(0);
2431 SDValue rhs = Op.getOperand(1);
2432 SDValue condition = Op.getOperand(2);
2433
2434 if (VT == MVT::i32 && lhs.getValueType() == MVT::i64) {
2435 // Expand the i64 comparisons to what Cell can actually support,
2436 // which is eq, ugt and sgt:
2437#if 0
2438 CondCodeSDNode *ccvalue = dyn_cast<CondCodeSDValue>(condition);
2439
2440 switch (ccvalue->get()) {
2441 case
2442 }
2443#endif
2444 }
2445
2446 return SDValue();
2447}
2448
Scott Michel56a125e2008-11-22 23:50:42 +00002449//! Lower ISD::SELECT_CC
2450/*!
2451 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2452 SELB instruction.
2453
2454 \note Need to revisit this in the future: if the code path through the true
2455 and false value computations is longer than the latency of a branch (6
2456 cycles), then it would be more advantageous to branch and insert a new basic
2457 block and branch on the condition. However, this code does not make that
2458 assumption, given the simplisitc uses so far.
2459 */
2460
Scott Michel06eabde2008-12-27 04:51:36 +00002461static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
2462 const TargetLowering &TLI) {
Scott Michel56a125e2008-11-22 23:50:42 +00002463 MVT VT = Op.getValueType();
2464 SDValue lhs = Op.getOperand(0);
2465 SDValue rhs = Op.getOperand(1);
2466 SDValue trueval = Op.getOperand(2);
2467 SDValue falseval = Op.getOperand(3);
2468 SDValue condition = Op.getOperand(4);
2469
Scott Michel06eabde2008-12-27 04:51:36 +00002470 // NOTE: SELB's arguments: $rA, $rB, $mask
2471 //
2472 // SELB selects bits from $rA where bits in $mask are 0, bits from $rB
2473 // where bits in $mask are 1. CCond will be inverted, having 1s where the
2474 // condition was true and 0s where the condition was false. Hence, the
2475 // arguments to SELB get reversed.
2476
Scott Michel56a125e2008-11-22 23:50:42 +00002477 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2478 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2479 // with another "cannot select select_cc" assert:
2480
Duncan Sands4a361272009-01-01 15:52:00 +00002481 SDValue compare = DAG.getNode(ISD::SETCC,
2482 TLI.getSetCCResultType(Op.getValueType()),
Scott Michel06eabde2008-12-27 04:51:36 +00002483 lhs, rhs, condition);
2484 return DAG.getNode(SPUISD::SELB, VT, falseval, trueval, compare);
Scott Michel56a125e2008-11-22 23:50:42 +00002485}
2486
Scott Michelec8c82e2008-12-02 19:53:53 +00002487//! Custom lower ISD::TRUNCATE
2488static SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG)
2489{
2490 MVT VT = Op.getValueType();
2491 MVT::SimpleValueType simpleVT = VT.getSimpleVT();
2492 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
2493
2494 SDValue Op0 = Op.getOperand(0);
2495 MVT Op0VT = Op0.getValueType();
2496 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
2497
Scott Michel06eabde2008-12-27 04:51:36 +00002498 if (Op0VT.getSimpleVT() == MVT::i128 && simpleVT == MVT::i64) {
Scott Michelc5a29fe2009-01-03 00:27:53 +00002499 // Create shuffle mask, least significant doubleword of quadword
Scott Michel06eabde2008-12-27 04:51:36 +00002500 unsigned maskHigh = 0x08090a0b;
2501 unsigned maskLow = 0x0c0d0e0f;
2502 // Use a shuffle to perform the truncation
2503 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2504 DAG.getConstant(maskHigh, MVT::i32),
2505 DAG.getConstant(maskLow, MVT::i32),
2506 DAG.getConstant(maskHigh, MVT::i32),
2507 DAG.getConstant(maskLow, MVT::i32));
2508
2509
2510 SDValue PromoteScalar = DAG.getNode(SPUISD::PREFSLOT2VEC, Op0VecVT, Op0);
2511
2512 SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2513 PromoteScalar, PromoteScalar, shufMask);
2514
2515 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2516 DAG.getNode(ISD::BIT_CONVERT, VecVT, truncShuffle));
Scott Michelec8c82e2008-12-02 19:53:53 +00002517 }
2518
Scott Michel06eabde2008-12-27 04:51:36 +00002519 return SDValue(); // Leave the truncate unmolested
Scott Michelec8c82e2008-12-02 19:53:53 +00002520}
2521
Scott Michel56a125e2008-11-22 23:50:42 +00002522//! Custom (target-specific) lowering entry point
2523/*!
2524 This is where LLVM's DAG selection process calls to do target-specific
2525 lowering of nodes.
2526 */
Dan Gohman8181bd12008-07-27 21:46:04 +00002527SDValue
2528SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel8efdca42007-12-04 22:23:35 +00002529{
Scott Michel97872d32008-02-23 18:41:37 +00002530 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands92c43912008-06-06 12:08:01 +00002531 MVT VT = Op.getValueType();
Scott Michel97872d32008-02-23 18:41:37 +00002532
2533 switch (Opc) {
Scott Michel8efdca42007-12-04 22:23:35 +00002534 default: {
2535 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michel97872d32008-02-23 18:41:37 +00002536 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greif1c80d112008-08-28 21:40:38 +00002537 cerr << "*Op.getNode():\n";
2538 Op.getNode()->dump();
Scott Michel8efdca42007-12-04 22:23:35 +00002539 abort();
2540 }
2541 case ISD::LOAD:
Scott Michelec8c82e2008-12-02 19:53:53 +00002542 case ISD::EXTLOAD:
Scott Michel8efdca42007-12-04 22:23:35 +00002543 case ISD::SEXTLOAD:
2544 case ISD::ZEXTLOAD:
2545 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2546 case ISD::STORE:
2547 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2548 case ISD::ConstantPool:
2549 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2550 case ISD::GlobalAddress:
2551 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2552 case ISD::JumpTable:
2553 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2554 case ISD::Constant:
2555 return LowerConstant(Op, DAG);
2556 case ISD::ConstantFP:
2557 return LowerConstantFP(Op, DAG);
2558 case ISD::FORMAL_ARGUMENTS:
Scott Michel394e26d2008-01-17 20:38:41 +00002559 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel8efdca42007-12-04 22:23:35 +00002560 case ISD::CALL:
Scott Micheldbac4cf2008-01-11 02:53:15 +00002561 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel8efdca42007-12-04 22:23:35 +00002562 case ISD::RET:
2563 return LowerRET(Op, DAG, getTargetMachine());
2564
Scott Michel97872d32008-02-23 18:41:37 +00002565
Scott Michel97872d32008-02-23 18:41:37 +00002566 case ISD::ZERO_EXTEND:
Scott Michel97872d32008-02-23 18:41:37 +00002567 case ISD::ANY_EXTEND:
Scott Michel4d07fb72008-12-30 23:28:25 +00002568 return LowerI64Math(Op, DAG, Opc);
2569
2570 // i8, i64 math ops:
Scott Michel67224b22008-06-02 22:18:03 +00002571 case ISD::ADD:
Scott Michel8efdca42007-12-04 22:23:35 +00002572 case ISD::SUB:
2573 case ISD::ROTR:
2574 case ISD::ROTL:
2575 case ISD::SRL:
2576 case ISD::SHL:
Scott Michel67224b22008-06-02 22:18:03 +00002577 case ISD::SRA: {
Scott Michel97872d32008-02-23 18:41:37 +00002578 if (VT == MVT::i8)
Scott Michel06eabde2008-12-27 04:51:36 +00002579 return LowerI8Math(Op, DAG, Opc, *this);
Scott Michel97872d32008-02-23 18:41:37 +00002580 else if (VT == MVT::i64)
2581 return LowerI64Math(Op, DAG, Opc);
2582 break;
Scott Michel67224b22008-06-02 22:18:03 +00002583 }
Scott Michel8efdca42007-12-04 22:23:35 +00002584
2585 // Vector-related lowering.
2586 case ISD::BUILD_VECTOR:
2587 return LowerBUILD_VECTOR(Op, DAG);
2588 case ISD::SCALAR_TO_VECTOR:
2589 return LowerSCALAR_TO_VECTOR(Op, DAG);
2590 case ISD::VECTOR_SHUFFLE:
2591 return LowerVECTOR_SHUFFLE(Op, DAG);
2592 case ISD::EXTRACT_VECTOR_ELT:
2593 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2594 case ISD::INSERT_VECTOR_ELT:
2595 return LowerINSERT_VECTOR_ELT(Op, DAG);
2596
2597 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2598 case ISD::AND:
2599 case ISD::OR:
2600 case ISD::XOR:
2601 return LowerByteImmed(Op, DAG);
2602
2603 // Vector and i8 multiply:
2604 case ISD::MUL:
Scott Michel4d07fb72008-12-30 23:28:25 +00002605 if (VT == MVT::i8)
Scott Michel06eabde2008-12-27 04:51:36 +00002606 return LowerI8Math(Op, DAG, Opc, *this);
Scott Michel8efdca42007-12-04 22:23:35 +00002607
Scott Michel8efdca42007-12-04 22:23:35 +00002608 case ISD::CTPOP:
2609 return LowerCTPOP(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002610
2611 case ISD::SELECT_CC:
Scott Michel06eabde2008-12-27 04:51:36 +00002612 return LowerSELECT_CC(Op, DAG, *this);
Scott Michelec8c82e2008-12-02 19:53:53 +00002613
2614 case ISD::TRUNCATE:
2615 return LowerTRUNCATE(Op, DAG);
Scott Michel06eabde2008-12-27 04:51:36 +00002616
2617 case ISD::SETCC:
2618 return LowerSETCC(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002619 }
2620
Dan Gohman8181bd12008-07-27 21:46:04 +00002621 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002622}
2623
Duncan Sands7d9834b2008-12-01 11:39:25 +00002624void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
2625 SmallVectorImpl<SDValue>&Results,
2626 SelectionDAG &DAG)
Scott Michel6e2d68b2008-11-10 23:43:06 +00002627{
2628#if 0
2629 unsigned Opc = (unsigned) N->getOpcode();
2630 MVT OpVT = N->getValueType(0);
2631
2632 switch (Opc) {
2633 default: {
2634 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2635 cerr << "Op.getOpcode() = " << Opc << "\n";
2636 cerr << "*Op.getNode():\n";
2637 N->dump();
2638 abort();
2639 /*NOTREACHED*/
2640 }
2641 }
2642#endif
2643
2644 /* Otherwise, return unchanged */
Scott Michel6e2d68b2008-11-10 23:43:06 +00002645}
2646
Scott Michel8efdca42007-12-04 22:23:35 +00002647//===----------------------------------------------------------------------===//
Scott Michel8efdca42007-12-04 22:23:35 +00002648// Target Optimization Hooks
2649//===----------------------------------------------------------------------===//
2650
Dan Gohman8181bd12008-07-27 21:46:04 +00002651SDValue
Scott Michel8efdca42007-12-04 22:23:35 +00002652SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2653{
2654#if 0
2655 TargetMachine &TM = getTargetMachine();
Scott Michelf9f42e62008-01-29 02:16:57 +00002656#endif
2657 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel8efdca42007-12-04 22:23:35 +00002658 SelectionDAG &DAG = DCI.DAG;
Scott Michel0718cd82008-12-01 17:56:02 +00002659 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2660 MVT NodeVT = N->getValueType(0); // The node's value type
Scott Michel06eabde2008-12-27 04:51:36 +00002661 MVT Op0VT = Op0.getValueType(); // The first operand's result
Scott Michel0718cd82008-12-01 17:56:02 +00002662 SDValue Result; // Initially, empty result
Scott Michel8efdca42007-12-04 22:23:35 +00002663
2664 switch (N->getOpcode()) {
2665 default: break;
Scott Michelf9f42e62008-01-29 02:16:57 +00002666 case ISD::ADD: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002667 SDValue Op1 = N->getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002668
Scott Michel06eabde2008-12-27 04:51:36 +00002669 if (Op0.getOpcode() == SPUISD::IndirectAddr
2670 || Op1.getOpcode() == SPUISD::IndirectAddr) {
2671 // Normalize the operands to reduce repeated code
2672 SDValue IndirectArg = Op0, AddArg = Op1;
Scott Michelae5cbf52008-12-29 03:23:36 +00002673
Scott Michel06eabde2008-12-27 04:51:36 +00002674 if (Op1.getOpcode() == SPUISD::IndirectAddr) {
2675 IndirectArg = Op1;
2676 AddArg = Op0;
2677 }
2678
2679 if (isa<ConstantSDNode>(AddArg)) {
2680 ConstantSDNode *CN0 = cast<ConstantSDNode > (AddArg);
2681 SDValue IndOp1 = IndirectArg.getOperand(1);
2682
2683 if (CN0->isNullValue()) {
2684 // (add (SPUindirect <arg>, <arg>), 0) ->
2685 // (SPUindirect <arg>, <arg>)
Scott Michelf9f42e62008-01-29 02:16:57 +00002686
Scott Michel8c2746e2008-12-04 17:16:59 +00002687#if !defined(NDEBUG)
Scott Michel06eabde2008-12-27 04:51:36 +00002688 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel6ccefab2008-12-04 03:02:42 +00002689 cerr << "\n"
Scott Michel06eabde2008-12-27 04:51:36 +00002690 << "Replace: (add (SPUindirect <arg>, <arg>), 0)\n"
2691 << "With: (SPUindirect <arg>, <arg>)\n";
2692 }
Scott Michel6ccefab2008-12-04 03:02:42 +00002693#endif
2694
Scott Michel06eabde2008-12-27 04:51:36 +00002695 return IndirectArg;
2696 } else if (isa<ConstantSDNode>(IndOp1)) {
2697 // (add (SPUindirect <arg>, <const>), <const>) ->
2698 // (SPUindirect <arg>, <const + const>)
2699 ConstantSDNode *CN1 = cast<ConstantSDNode > (IndOp1);
2700 int64_t combinedConst = CN0->getSExtValue() + CN1->getSExtValue();
2701 SDValue combinedValue = DAG.getConstant(combinedConst, Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00002702
Scott Michel06eabde2008-12-27 04:51:36 +00002703#if !defined(NDEBUG)
2704 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
2705 cerr << "\n"
2706 << "Replace: (add (SPUindirect <arg>, " << CN1->getSExtValue()
2707 << "), " << CN0->getSExtValue() << ")\n"
2708 << "With: (SPUindirect <arg>, "
2709 << combinedConst << ")\n";
2710 }
2711#endif
Scott Michelf9f42e62008-01-29 02:16:57 +00002712
Scott Michel06eabde2008-12-27 04:51:36 +00002713 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
2714 IndirectArg, combinedValue);
2715 }
Scott Michelf9f42e62008-01-29 02:16:57 +00002716 }
2717 }
Scott Michel97872d32008-02-23 18:41:37 +00002718 break;
2719 }
2720 case ISD::SIGN_EXTEND:
2721 case ISD::ZERO_EXTEND:
2722 case ISD::ANY_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00002723 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT && NodeVT == Op0VT) {
Scott Michel97872d32008-02-23 18:41:37 +00002724 // (any_extend (SPUextract_elt0 <arg>)) ->
2725 // (SPUextract_elt0 <arg>)
2726 // Types must match, however...
Scott Michel8c2746e2008-12-04 17:16:59 +00002727#if !defined(NDEBUG)
2728 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel6ccefab2008-12-04 03:02:42 +00002729 cerr << "\nReplace: ";
2730 N->dump(&DAG);
2731 cerr << "\nWith: ";
2732 Op0.getNode()->dump(&DAG);
2733 cerr << "\n";
Scott Michel8c2746e2008-12-04 17:16:59 +00002734 }
Scott Michel6ccefab2008-12-04 03:02:42 +00002735#endif
Scott Michel97872d32008-02-23 18:41:37 +00002736
2737 return Op0;
2738 }
2739 break;
2740 }
2741 case SPUISD::IndirectAddr: {
2742 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2743 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002744 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00002745 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2746 // (SPUaform <addr>, 0)
2747
2748 DEBUG(cerr << "Replace: ");
2749 DEBUG(N->dump(&DAG));
2750 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002751 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002752 DEBUG(cerr << "\n");
2753
2754 return Op0;
2755 }
Scott Michel06eabde2008-12-27 04:51:36 +00002756 } else if (Op0.getOpcode() == ISD::ADD) {
2757 SDValue Op1 = N->getOperand(1);
2758 if (ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(Op1)) {
2759 // (SPUindirect (add <arg>, <arg>), 0) ->
2760 // (SPUindirect <arg>, <arg>)
2761 if (CN1->isNullValue()) {
2762
2763#if !defined(NDEBUG)
2764 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
2765 cerr << "\n"
2766 << "Replace: (SPUindirect (add <arg>, <arg>), 0)\n"
2767 << "With: (SPUindirect <arg>, <arg>)\n";
2768 }
2769#endif
2770
2771 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
2772 Op0.getOperand(0), Op0.getOperand(1));
2773 }
2774 }
Scott Michel97872d32008-02-23 18:41:37 +00002775 }
2776 break;
2777 }
2778 case SPUISD::SHLQUAD_L_BITS:
2779 case SPUISD::SHLQUAD_L_BYTES:
2780 case SPUISD::VEC_SHL:
2781 case SPUISD::VEC_SRL:
2782 case SPUISD::VEC_SRA:
Scott Michel06eabde2008-12-27 04:51:36 +00002783 case SPUISD::ROTBYTES_LEFT: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002784 SDValue Op1 = N->getOperand(1);
Scott Michel97872d32008-02-23 18:41:37 +00002785
Scott Michel06eabde2008-12-27 04:51:36 +00002786 // Kill degenerate vector shifts:
2787 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1)) {
2788 if (CN->isNullValue()) {
Scott Michel97872d32008-02-23 18:41:37 +00002789 Result = Op0;
2790 }
2791 }
2792 break;
2793 }
Scott Michel06eabde2008-12-27 04:51:36 +00002794 case SPUISD::PREFSLOT2VEC: {
Scott Michel97872d32008-02-23 18:41:37 +00002795 switch (Op0.getOpcode()) {
2796 default:
2797 break;
2798 case ISD::ANY_EXTEND:
2799 case ISD::ZERO_EXTEND:
2800 case ISD::SIGN_EXTEND: {
Scott Michelae5cbf52008-12-29 03:23:36 +00002801 // (SPUprefslot2vec (any|zero|sign_extend (SPUvec2prefslot <arg>))) ->
Scott Michel97872d32008-02-23 18:41:37 +00002802 // <arg>
Scott Michelae5cbf52008-12-29 03:23:36 +00002803 // but only if the SPUprefslot2vec and <arg> types match.
Dan Gohman8181bd12008-07-27 21:46:04 +00002804 SDValue Op00 = Op0.getOperand(0);
Scott Michelc630c412008-11-24 17:11:17 +00002805 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002806 SDValue Op000 = Op00.getOperand(0);
Scott Michel0718cd82008-12-01 17:56:02 +00002807 if (Op000.getValueType() == NodeVT) {
Scott Michel97872d32008-02-23 18:41:37 +00002808 Result = Op000;
2809 }
2810 }
2811 break;
2812 }
Scott Michelc630c412008-11-24 17:11:17 +00002813 case SPUISD::VEC2PREFSLOT: {
Scott Michelae5cbf52008-12-29 03:23:36 +00002814 // (SPUprefslot2vec (SPUvec2prefslot <arg>)) ->
Scott Michel97872d32008-02-23 18:41:37 +00002815 // <arg>
2816 Result = Op0.getOperand(0);
2817 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00002818 }
Scott Michel97872d32008-02-23 18:41:37 +00002819 }
2820 break;
Scott Michelf9f42e62008-01-29 02:16:57 +00002821 }
2822 }
Scott Michel394e26d2008-01-17 20:38:41 +00002823 // Otherwise, return unchanged.
Scott Michel0718cd82008-12-01 17:56:02 +00002824#ifndef NDEBUG
Gabor Greif1c80d112008-08-28 21:40:38 +00002825 if (Result.getNode()) {
Scott Michel97872d32008-02-23 18:41:37 +00002826 DEBUG(cerr << "\nReplace.SPU: ");
2827 DEBUG(N->dump(&DAG));
2828 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002829 DEBUG(Result.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002830 DEBUG(cerr << "\n");
2831 }
2832#endif
2833
2834 return Result;
Scott Michel8efdca42007-12-04 22:23:35 +00002835}
2836
2837//===----------------------------------------------------------------------===//
2838// Inline Assembly Support
2839//===----------------------------------------------------------------------===//
2840
2841/// getConstraintType - Given a constraint letter, return the type of
2842/// constraint it is for this target.
Scott Michel4ec722e2008-07-16 17:17:29 +00002843SPUTargetLowering::ConstraintType
Scott Michel8efdca42007-12-04 22:23:35 +00002844SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2845 if (ConstraintLetter.size() == 1) {
2846 switch (ConstraintLetter[0]) {
2847 default: break;
2848 case 'b':
2849 case 'r':
2850 case 'f':
2851 case 'v':
2852 case 'y':
2853 return C_RegisterClass;
Scott Michel4ec722e2008-07-16 17:17:29 +00002854 }
Scott Michel8efdca42007-12-04 22:23:35 +00002855 }
2856 return TargetLowering::getConstraintType(ConstraintLetter);
2857}
2858
Scott Michel4ec722e2008-07-16 17:17:29 +00002859std::pair<unsigned, const TargetRegisterClass*>
Scott Michel8efdca42007-12-04 22:23:35 +00002860SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands92c43912008-06-06 12:08:01 +00002861 MVT VT) const
Scott Michel8efdca42007-12-04 22:23:35 +00002862{
2863 if (Constraint.size() == 1) {
2864 // GCC RS6000 Constraint Letters
2865 switch (Constraint[0]) {
2866 case 'b': // R1-R31
2867 case 'r': // R0-R31
2868 if (VT == MVT::i64)
2869 return std::make_pair(0U, SPU::R64CRegisterClass);
2870 return std::make_pair(0U, SPU::R32CRegisterClass);
2871 case 'f':
2872 if (VT == MVT::f32)
2873 return std::make_pair(0U, SPU::R32FPRegisterClass);
2874 else if (VT == MVT::f64)
2875 return std::make_pair(0U, SPU::R64FPRegisterClass);
2876 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00002877 case 'v':
Scott Michel8efdca42007-12-04 22:23:35 +00002878 return std::make_pair(0U, SPU::GPRCRegisterClass);
2879 }
2880 }
Scott Michel4ec722e2008-07-16 17:17:29 +00002881
Scott Michel8efdca42007-12-04 22:23:35 +00002882 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2883}
2884
Scott Michel97872d32008-02-23 18:41:37 +00002885//! Compute used/known bits for a SPU operand
Scott Michel8efdca42007-12-04 22:23:35 +00002886void
Dan Gohman8181bd12008-07-27 21:46:04 +00002887SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohmand0dfc772008-02-13 22:28:48 +00002888 const APInt &Mask,
Scott Michel4ec722e2008-07-16 17:17:29 +00002889 APInt &KnownZero,
Dan Gohman229fa052008-02-13 00:35:47 +00002890 APInt &KnownOne,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002891 const SelectionDAG &DAG,
2892 unsigned Depth ) const {
Scott Michelbc5fbc12008-04-30 00:30:08 +00002893#if 0
Scott Michel97872d32008-02-23 18:41:37 +00002894 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michelbc5fbc12008-04-30 00:30:08 +00002895#endif
Scott Michel97872d32008-02-23 18:41:37 +00002896
2897 switch (Op.getOpcode()) {
2898 default:
2899 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2900 break;
2901
2902#if 0
2903 case CALL:
2904 case SHUFB:
Scott Michel56a125e2008-11-22 23:50:42 +00002905 case SHUFFLE_MASK:
Scott Michel97872d32008-02-23 18:41:37 +00002906 case CNTB:
2907#endif
2908
Scott Michel06eabde2008-12-27 04:51:36 +00002909 case SPUISD::PREFSLOT2VEC: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002910 SDValue Op0 = Op.getOperand(0);
Duncan Sands92c43912008-06-06 12:08:01 +00002911 MVT Op0VT = Op0.getValueType();
2912 unsigned Op0VTBits = Op0VT.getSizeInBits();
2913 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00002914 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2915 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00002916 break;
2917 }
Scott Michel4ec722e2008-07-16 17:17:29 +00002918
Scott Michel97872d32008-02-23 18:41:37 +00002919 case SPUISD::LDRESULT:
Scott Michel6ccefab2008-12-04 03:02:42 +00002920 case SPUISD::VEC2PREFSLOT: {
Duncan Sands92c43912008-06-06 12:08:01 +00002921 MVT OpVT = Op.getValueType();
2922 unsigned OpVTBits = OpVT.getSizeInBits();
2923 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00002924 KnownZero |= APInt(OpVTBits, ~InMask, false);
2925 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00002926 break;
2927 }
2928
2929#if 0
Scott Michelbc5fbc12008-04-30 00:30:08 +00002930 case SPUISD::SHLQUAD_L_BITS:
2931 case SPUISD::SHLQUAD_L_BYTES:
2932 case SPUISD::VEC_SHL:
2933 case SPUISD::VEC_SRL:
2934 case SPUISD::VEC_SRA:
2935 case SPUISD::VEC_ROTL:
2936 case SPUISD::VEC_ROTR:
Scott Michelbc5fbc12008-04-30 00:30:08 +00002937 case SPUISD::ROTBYTES_LEFT:
Scott Michel67224b22008-06-02 22:18:03 +00002938 case SPUISD::SELECT_MASK:
2939 case SPUISD::SELB:
Scott Michel67224b22008-06-02 22:18:03 +00002940 case SPUISD::SEXT32TO64:
Scott Michel97872d32008-02-23 18:41:37 +00002941#endif
2942 }
Scott Michel8efdca42007-12-04 22:23:35 +00002943}
Scott Michel4d07fb72008-12-30 23:28:25 +00002944
Scott Michel06eabde2008-12-27 04:51:36 +00002945unsigned
2946SPUTargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op,
2947 unsigned Depth) const {
2948 switch (Op.getOpcode()) {
2949 default:
2950 return 1;
Scott Michel8efdca42007-12-04 22:23:35 +00002951
Scott Michel06eabde2008-12-27 04:51:36 +00002952 case ISD::SETCC: {
2953 MVT VT = Op.getValueType();
2954
2955 if (VT != MVT::i8 && VT != MVT::i16 && VT != MVT::i32) {
2956 VT = MVT::i32;
2957 }
2958 return VT.getSizeInBits();
2959 }
2960 }
2961}
Scott Michelae5cbf52008-12-29 03:23:36 +00002962
Scott Michelbc5fbc12008-04-30 00:30:08 +00002963// LowerAsmOperandForConstraint
2964void
Dan Gohman8181bd12008-07-27 21:46:04 +00002965SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michelbc5fbc12008-04-30 00:30:08 +00002966 char ConstraintLetter,
Evan Cheng7f250d62008-09-24 00:05:32 +00002967 bool hasMemory,
Dan Gohman8181bd12008-07-27 21:46:04 +00002968 std::vector<SDValue> &Ops,
Scott Michelbc5fbc12008-04-30 00:30:08 +00002969 SelectionDAG &DAG) const {
2970 // Default, for the time being, to the base class handler
Evan Cheng7f250d62008-09-24 00:05:32 +00002971 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
2972 Ops, DAG);
Scott Michelbc5fbc12008-04-30 00:30:08 +00002973}
2974
Scott Michel8efdca42007-12-04 22:23:35 +00002975/// isLegalAddressImmediate - Return true if the integer value can be used
2976/// as the offset of the target addressing mode.
Gabor Greife9f7f582008-08-31 15:37:04 +00002977bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
2978 const Type *Ty) const {
Scott Michel8efdca42007-12-04 22:23:35 +00002979 // SPU's addresses are 256K:
2980 return (V > -(1 << 18) && V < (1 << 18) - 1);
2981}
2982
2983bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel4ec722e2008-07-16 17:17:29 +00002984 return false;
Scott Michel8efdca42007-12-04 22:23:35 +00002985}
Dan Gohman36322c72008-10-18 02:06:02 +00002986
2987bool
2988SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
2989 // The SPU target isn't yet aware of offsets.
2990 return false;
2991}