blob: a0c667847e2ec2d5b51b2e1ff643fcd48d54bc6b [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
150 // Custom lower BRCOND for i8 to "promote" the result to whatever the result
151 // operand happens to be:
Scott Michel394e26d2008-01-17 20:38:41 +0000152 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000153
154 // Expand the jumptable branches
155 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
156 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel56a125e2008-11-22 23:50:42 +0000157
158 // Custom lower SELECT_CC for most cases, but expand by default
Scott Michel4ec722e2008-07-16 17:17:29 +0000159 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel56a125e2008-11-22 23:50:42 +0000160 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
161 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
162 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
163 setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000164
165 // SPU has no intrinsics for these particular operations:
Andrew Lenharth0531ec52008-02-16 14:46:26 +0000166 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
167
Scott Michel06eabde2008-12-27 04:51:36 +0000168 // SPU has no SREM/UREM instructions
Scott Michel8efdca42007-12-04 22:23:35 +0000169 setOperationAction(ISD::SREM, MVT::i32, Expand);
170 setOperationAction(ISD::UREM, MVT::i32, Expand);
171 setOperationAction(ISD::SREM, MVT::i64, Expand);
172 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000173
Scott Michel8efdca42007-12-04 22:23:35 +0000174 // We don't support sin/cos/sqrt/fmod
175 setOperationAction(ISD::FSIN , MVT::f64, Expand);
176 setOperationAction(ISD::FCOS , MVT::f64, Expand);
177 setOperationAction(ISD::FREM , MVT::f64, Expand);
178 setOperationAction(ISD::FSIN , MVT::f32, Expand);
179 setOperationAction(ISD::FCOS , MVT::f32, Expand);
180 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000181
Scott Michel8efdca42007-12-04 22:23:35 +0000182 // If we're enabling GP optimizations, use hardware square root
183 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
184 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000185
Scott Michel8efdca42007-12-04 22:23:35 +0000186 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
187 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
188
189 // SPU can do rotate right and left, so legalize it... but customize for i8
190 // because instructions don't exist.
Bill Wendling965299c2008-08-31 02:59:23 +0000191
192 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
193 // .td files.
194 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
195 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
196 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
197
Scott Michel8efdca42007-12-04 22:23:35 +0000198 setOperationAction(ISD::ROTL, MVT::i32, Legal);
199 setOperationAction(ISD::ROTL, MVT::i16, Legal);
200 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Michelabb8ca12008-11-20 16:36:33 +0000201
Scott Michel8efdca42007-12-04 22:23:35 +0000202 // SPU has no native version of shift left/right for i8
203 setOperationAction(ISD::SHL, MVT::i8, Custom);
204 setOperationAction(ISD::SRL, MVT::i8, Custom);
205 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel33d73eb2008-11-21 02:56:16 +0000206
Scott Michel4d07fb72008-12-30 23:28:25 +0000207 // Make these operations legal and handle them during instruction selection:
208 setOperationAction(ISD::SHL, MVT::i64, Legal);
209 setOperationAction(ISD::SRL, MVT::i64, Legal);
210 setOperationAction(ISD::SRA, MVT::i64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000211
Scott Michel4ec722e2008-07-16 17:17:29 +0000212 // Custom lower i8, i32 and i64 multiplications
213 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michelae5cbf52008-12-29 03:23:36 +0000214 setOperationAction(ISD::MUL, MVT::i32, Legal);
Scott Michel33d73eb2008-11-21 02:56:16 +0000215 setOperationAction(ISD::MUL, MVT::i64, Expand); // libcall
216
Scott Michel67224b22008-06-02 22:18:03 +0000217 // Need to custom handle (some) common i8, i64 math ops
Scott Michel4d07fb72008-12-30 23:28:25 +0000218 setOperationAction(ISD::ADD, MVT::i8, Custom);
Scott Michel67224b22008-06-02 22:18:03 +0000219 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000220 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel67224b22008-06-02 22:18:03 +0000221 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000222
Scott Michel8efdca42007-12-04 22:23:35 +0000223 // SPU does not have BSWAP. It does have i32 support CTLZ.
224 // CTPOP has to be custom lowered.
225 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
226 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
227
228 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
229 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
230 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
231 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
232
233 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
234 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
235
236 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000237
Scott Michel67224b22008-06-02 22:18:03 +0000238 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel978b96f2008-03-10 23:49:09 +0000239 // select ought to work:
Scott Michel53ab7792008-03-10 16:58:52 +0000240 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000241 setOperationAction(ISD::SELECT, MVT::i16, Legal);
242 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel06eabde2008-12-27 04:51:36 +0000243 setOperationAction(ISD::SELECT, MVT::i64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000244
Scott Michel53ab7792008-03-10 16:58:52 +0000245 setOperationAction(ISD::SETCC, MVT::i8, Legal);
246 setOperationAction(ISD::SETCC, MVT::i16, Legal);
Scott Michelae5cbf52008-12-29 03:23:36 +0000247 setOperationAction(ISD::SETCC, MVT::i32, Legal);
248 setOperationAction(ISD::SETCC, MVT::i64, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000249
Scott Michel97872d32008-02-23 18:41:37 +0000250 // Zero extension and sign extension for i64 have to be
251 // custom legalized
252 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
Scott Michel97872d32008-02-23 18:41:37 +0000253 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000254
Scott Michel06eabde2008-12-27 04:51:36 +0000255 // Custom lower i128 -> i64 truncates
Scott Michelec8c82e2008-12-02 19:53:53 +0000256 setOperationAction(ISD::TRUNCATE, MVT::i64, Custom);
257
Scott Michel8efdca42007-12-04 22:23:35 +0000258 // SPU has a legal FP -> signed INT instruction
259 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
260 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
261 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
262 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
263
264 // FDIV on SPU requires custom lowering
Scott Michel06eabde2008-12-27 04:51:36 +0000265 setOperationAction(ISD::FDIV, MVT::f64, Expand); // libcall
Scott Michel8efdca42007-12-04 22:23:35 +0000266
267 // SPU has [U|S]INT_TO_FP
268 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
269 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
270 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
271 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
272 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
273 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
274 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
275 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
276
Scott Michel754d8662007-12-20 00:44:13 +0000277 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
278 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
279 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
280 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000281
282 // We cannot sextinreg(i1). Expand to shifts.
283 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000284
Scott Michel8efdca42007-12-04 22:23:35 +0000285 // Support label based line numbers.
Dan Gohman472d12c2008-06-30 20:59:49 +0000286 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000287 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000288
289 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel8efdca42007-12-04 22:23:35 +0000290 // appropriate instructions to materialize the address.
Scott Michel33d73eb2008-11-21 02:56:16 +0000291 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michelf9f42e62008-01-29 02:16:57 +0000292 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000293 MVT VT = (MVT::SimpleValueType)sctype;
294
Scott Michelae5cbf52008-12-29 03:23:36 +0000295 setOperationAction(ISD::GlobalAddress, VT, Custom);
296 setOperationAction(ISD::ConstantPool, VT, Custom);
297 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michelf9f42e62008-01-29 02:16:57 +0000298 }
Scott Michel8efdca42007-12-04 22:23:35 +0000299
300 // RET must be custom lowered, to meet ABI requirements
301 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000302
Scott Michel8efdca42007-12-04 22:23:35 +0000303 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
304 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000305
Scott Michel8efdca42007-12-04 22:23:35 +0000306 // Use the default implementation.
307 setOperationAction(ISD::VAARG , MVT::Other, Expand);
308 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
309 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000310 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000311 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
312 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
313 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
314
315 // Cell SPU has instructions for converting between i64 and fp.
316 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
317 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000318
Scott Michel8efdca42007-12-04 22:23:35 +0000319 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
320 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
321
322 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
323 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
324
325 // First set operation action for all vector types to expand. Then we
326 // will selectively turn on ones that can be effectively codegen'd.
327 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
328 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
329 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
330 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
331 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
332 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
333
Duncan Sands92c43912008-06-06 12:08:01 +0000334 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
335 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
336 MVT VT = (MVT::SimpleValueType)i;
Scott Michel8efdca42007-12-04 22:23:35 +0000337
Duncan Sands92c43912008-06-06 12:08:01 +0000338 // add/sub are legal for all supported vector VT's.
339 setOperationAction(ISD::ADD , VT, Legal);
340 setOperationAction(ISD::SUB , VT, Legal);
341 // mul has to be custom lowered.
Scott Michel4d07fb72008-12-30 23:28:25 +0000342 // TODO: v2i64 vector multiply
343 setOperationAction(ISD::MUL , VT, Legal);
Duncan Sands92c43912008-06-06 12:08:01 +0000344
345 setOperationAction(ISD::AND , VT, Legal);
346 setOperationAction(ISD::OR , VT, Legal);
347 setOperationAction(ISD::XOR , VT, Legal);
348 setOperationAction(ISD::LOAD , VT, Legal);
349 setOperationAction(ISD::SELECT, VT, Legal);
350 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000351
Scott Michel8efdca42007-12-04 22:23:35 +0000352 // These operations need to be expanded:
Duncan Sands92c43912008-06-06 12:08:01 +0000353 setOperationAction(ISD::SDIV, VT, Expand);
354 setOperationAction(ISD::SREM, VT, Expand);
355 setOperationAction(ISD::UDIV, VT, Expand);
356 setOperationAction(ISD::UREM, VT, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000357
358 // Custom lower build_vector, constant pool spills, insert and
359 // extract vector elements:
Duncan Sands92c43912008-06-06 12:08:01 +0000360 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
361 setOperationAction(ISD::ConstantPool, VT, Custom);
362 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
363 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
364 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
365 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000366 }
367
Scott Michel8efdca42007-12-04 22:23:35 +0000368 setOperationAction(ISD::AND, MVT::v16i8, Custom);
369 setOperationAction(ISD::OR, MVT::v16i8, Custom);
370 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
371 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000372
Scott Michel4d07fb72008-12-30 23:28:25 +0000373 setOperationAction(ISD::FDIV, MVT::v4f32, Legal);
Scott Michelae5cbf52008-12-29 03:23:36 +0000374
Scott Michel8efdca42007-12-04 22:23:35 +0000375 setShiftAmountType(MVT::i32);
Scott Michel06eabde2008-12-27 04:51:36 +0000376 setBooleanContents(ZeroOrNegativeOneBooleanContent);
Scott Michel4ec722e2008-07-16 17:17:29 +0000377
Scott Michel8efdca42007-12-04 22:23:35 +0000378 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel4ec722e2008-07-16 17:17:29 +0000379
Scott Michel8efdca42007-12-04 22:23:35 +0000380 // We have target-specific dag combine patterns for the following nodes:
Scott Michelf9f42e62008-01-29 02:16:57 +0000381 setTargetDAGCombine(ISD::ADD);
Scott Michel97872d32008-02-23 18:41:37 +0000382 setTargetDAGCombine(ISD::ZERO_EXTEND);
383 setTargetDAGCombine(ISD::SIGN_EXTEND);
384 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel4ec722e2008-07-16 17:17:29 +0000385
Scott Michel8efdca42007-12-04 22:23:35 +0000386 computeRegisterProperties();
Scott Michel56a125e2008-11-22 23:50:42 +0000387
Scott Michel2c261072008-12-09 03:37:19 +0000388 // Set pre-RA register scheduler default to BURR, which produces slightly
389 // better code than the default (could also be TDRR, but TargetLowering.h
390 // needs a mod to support that model):
391 setSchedulingPreference(SchedulingForRegPressure);
Scott Michel8efdca42007-12-04 22:23:35 +0000392}
393
394const char *
395SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
396{
397 if (node_names.empty()) {
398 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
399 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
400 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
401 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Micheldbac4cf2008-01-11 02:53:15 +0000402 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michelf9f42e62008-01-29 02:16:57 +0000403 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel8efdca42007-12-04 22:23:35 +0000404 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
405 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
406 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
Scott Michel56a125e2008-11-22 23:50:42 +0000407 node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000408 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
Scott Michelae5cbf52008-12-29 03:23:36 +0000409 node_names[(unsigned) SPUISD::PREFSLOT2VEC] = "SPUISD::PREFSLOT2VEC";
Scott Michelc630c412008-11-24 17:11:17 +0000410 node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
Scott Michel97872d32008-02-23 18:41:37 +0000411 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
412 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel8efdca42007-12-04 22:23:35 +0000413 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
414 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
415 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
416 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
417 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michel67224b22008-06-02 22:18:03 +0000418 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000419 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel67224b22008-06-02 22:18:03 +0000420 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
421 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
422 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
423 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel8efdca42007-12-04 22:23:35 +0000424 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
425 }
426
427 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
428
429 return ((i != node_names.end()) ? i->second : 0);
430}
431
Scott Michel06eabde2008-12-27 04:51:36 +0000432//===----------------------------------------------------------------------===//
433// Return the Cell SPU's SETCC result type
434//===----------------------------------------------------------------------===//
435
Duncan Sands4a361272009-01-01 15:52:00 +0000436MVT SPUTargetLowering::getSetCCResultType(MVT VT) const {
Scott Michel06eabde2008-12-27 04:51:36 +0000437 // i16 and i32 are valid SETCC result types
438 return ((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) ? VT : MVT::i32);
Scott Michel53ab7792008-03-10 16:58:52 +0000439}
440
Scott Michel8efdca42007-12-04 22:23:35 +0000441//===----------------------------------------------------------------------===//
442// Calling convention code:
443//===----------------------------------------------------------------------===//
444
445#include "SPUGenCallingConv.inc"
446
447//===----------------------------------------------------------------------===//
448// LowerOperation implementation
449//===----------------------------------------------------------------------===//
450
451/// Custom lower loads for CellSPU
452/*!
453 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
454 within a 16-byte block, we have to rotate to extract the requested element.
Scott Michel6ccefab2008-12-04 03:02:42 +0000455
456 For extending loads, we also want to ensure that the following sequence is
457 emitted, e.g. for MVT::f32 extending load to MVT::f64:
458
459\verbatim
Scott Michelae5cbf52008-12-29 03:23:36 +0000460%1 v16i8,ch = load
Scott Michel6ccefab2008-12-04 03:02:42 +0000461%2 v16i8,ch = rotate %1
Scott Michelae5cbf52008-12-29 03:23:36 +0000462%3 v4f8, ch = bitconvert %2
Scott Michel6ccefab2008-12-04 03:02:42 +0000463%4 f32 = vec2perfslot %3
464%5 f64 = fp_extend %4
465\endverbatim
466*/
Dan Gohman8181bd12008-07-27 21:46:04 +0000467static SDValue
468LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000469 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000470 SDValue the_chain = LN->getChain();
Scott Michel06eabde2008-12-27 04:51:36 +0000471 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel6ccefab2008-12-04 03:02:42 +0000472 MVT InVT = LN->getMemoryVT();
473 MVT OutVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000474 ISD::LoadExtType ExtType = LN->getExtensionType();
475 unsigned alignment = LN->getAlignment();
Scott Michel06eabde2008-12-27 04:51:36 +0000476 const valtype_map_s *vtm = getValueTypeMapEntry(InVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000477
Scott Michel8efdca42007-12-04 22:23:35 +0000478 switch (LN->getAddressingMode()) {
479 case ISD::UNINDEXED: {
Scott Michel06eabde2008-12-27 04:51:36 +0000480 SDValue result;
481 SDValue basePtr = LN->getBasePtr();
482 SDValue rotate;
Scott Michel8efdca42007-12-04 22:23:35 +0000483
Scott Michel06eabde2008-12-27 04:51:36 +0000484 if (alignment == 16) {
485 ConstantSDNode *CN;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000486
Scott Michel06eabde2008-12-27 04:51:36 +0000487 // Special cases for a known aligned load to simplify the base pointer
488 // and the rotation amount:
489 if (basePtr.getOpcode() == ISD::ADD
490 && (CN = dyn_cast<ConstantSDNode > (basePtr.getOperand(1))) != 0) {
491 // Known offset into basePtr
492 int64_t offset = CN->getSExtValue();
493 int64_t rotamt = int64_t((offset & 0xf) - vtm->prefslot_byte);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000494
Scott Michel06eabde2008-12-27 04:51:36 +0000495 if (rotamt < 0)
496 rotamt += 16;
497
498 rotate = DAG.getConstant(rotamt, MVT::i16);
499
500 // Simplify the base pointer for this case:
501 basePtr = basePtr.getOperand(0);
502 if ((offset & ~0xf) > 0) {
503 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
504 basePtr,
505 DAG.getConstant((offset & ~0xf), PtrVT));
506 }
507 } else if ((basePtr.getOpcode() == SPUISD::AFormAddr)
508 || (basePtr.getOpcode() == SPUISD::IndirectAddr
509 && basePtr.getOperand(0).getOpcode() == SPUISD::Hi
510 && basePtr.getOperand(1).getOpcode() == SPUISD::Lo)) {
511 // Plain aligned a-form address: rotate into preferred slot
512 // Same for (SPUindirect (SPUhi ...), (SPUlo ...))
513 int64_t rotamt = -vtm->prefslot_byte;
514 if (rotamt < 0)
515 rotamt += 16;
516 rotate = DAG.getConstant(rotamt, MVT::i16);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000517 } else {
Scott Michel06eabde2008-12-27 04:51:36 +0000518 // Offset the rotate amount by the basePtr and the preferred slot
519 // byte offset
520 int64_t rotamt = -vtm->prefslot_byte;
521 if (rotamt < 0)
522 rotamt += 16;
523 rotate = DAG.getNode(ISD::ADD, PtrVT,
524 basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000525 DAG.getConstant(rotamt, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000526 }
Scott Michel06eabde2008-12-27 04:51:36 +0000527 } else {
528 // Unaligned load: must be more pessimistic about addressing modes:
529 if (basePtr.getOpcode() == ISD::ADD) {
530 MachineFunction &MF = DAG.getMachineFunction();
531 MachineRegisterInfo &RegInfo = MF.getRegInfo();
532 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
533 SDValue Flag;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000534
Scott Michel06eabde2008-12-27 04:51:36 +0000535 SDValue Op0 = basePtr.getOperand(0);
536 SDValue Op1 = basePtr.getOperand(1);
537
538 if (isa<ConstantSDNode>(Op1)) {
539 // Convert the (add <ptr>, <const>) to an indirect address contained
540 // in a register. Note that this is done because we need to avoid
541 // creating a 0(reg) d-form address due to the SPU's block loads.
542 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
543 the_chain = DAG.getCopyToReg(the_chain, VReg, basePtr, Flag);
544 basePtr = DAG.getCopyFromReg(the_chain, VReg, PtrVT);
545 } else {
546 // Convert the (add <arg1>, <arg2>) to an indirect address, which
547 // will likely be lowered as a reg(reg) x-form address.
548 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
549 }
550 } else {
551 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
552 basePtr,
553 DAG.getConstant(0, PtrVT));
554 }
555
556 // Offset the rotate amount by the basePtr and the preferred slot
557 // byte offset
558 rotate = DAG.getNode(ISD::ADD, PtrVT,
559 basePtr,
560 DAG.getConstant(-vtm->prefslot_byte, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +0000561 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000562
Scott Michel06eabde2008-12-27 04:51:36 +0000563 // Re-emit as a v16i8 vector load
564 result = DAG.getLoad(MVT::v16i8, the_chain, basePtr,
565 LN->getSrcValue(), LN->getSrcValueOffset(),
566 LN->isVolatile(), 16);
567
568 // Update the chain
569 the_chain = result.getValue(1);
570
571 // Rotate into the preferred slot:
572 result = DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v16i8,
573 result.getValue(0), rotate);
574
Scott Michel6ccefab2008-12-04 03:02:42 +0000575 // Convert the loaded v16i8 vector to the appropriate vector type
576 // specified by the operand:
577 MVT vecVT = MVT::getVectorVT(InVT, (128 / InVT.getSizeInBits()));
578 result = DAG.getNode(SPUISD::VEC2PREFSLOT, InVT,
579 DAG.getNode(ISD::BIT_CONVERT, vecVT, result));
Scott Michel4ec722e2008-07-16 17:17:29 +0000580
Scott Michel6ccefab2008-12-04 03:02:42 +0000581 // Handle extending loads by extending the scalar result:
582 if (ExtType == ISD::SEXTLOAD) {
583 result = DAG.getNode(ISD::SIGN_EXTEND, OutVT, result);
584 } else if (ExtType == ISD::ZEXTLOAD) {
585 result = DAG.getNode(ISD::ZERO_EXTEND, OutVT, result);
586 } else if (ExtType == ISD::EXTLOAD) {
587 unsigned NewOpc = ISD::ANY_EXTEND;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000588
Scott Michel6ccefab2008-12-04 03:02:42 +0000589 if (OutVT.isFloatingPoint())
590 NewOpc = ISD::FP_EXTEND;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000591
Scott Michel6ccefab2008-12-04 03:02:42 +0000592 result = DAG.getNode(NewOpc, OutVT, result);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000593 }
594
Scott Michel6ccefab2008-12-04 03:02:42 +0000595 SDVTList retvts = DAG.getVTList(OutVT, MVT::Other);
Dan Gohman8181bd12008-07-27 21:46:04 +0000596 SDValue retops[2] = {
Scott Michel394e26d2008-01-17 20:38:41 +0000597 result,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000598 the_chain
Scott Michel394e26d2008-01-17 20:38:41 +0000599 };
Scott Micheldbac4cf2008-01-11 02:53:15 +0000600
Scott Michel394e26d2008-01-17 20:38:41 +0000601 result = DAG.getNode(SPUISD::LDRESULT, retvts,
602 retops, sizeof(retops) / sizeof(retops[0]));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000603 return result;
Scott Michel8efdca42007-12-04 22:23:35 +0000604 }
605 case ISD::PRE_INC:
606 case ISD::PRE_DEC:
607 case ISD::POST_INC:
608 case ISD::POST_DEC:
609 case ISD::LAST_INDEXED_MODE:
610 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
611 "UNINDEXED\n";
612 cerr << (unsigned) LN->getAddressingMode() << "\n";
613 abort();
614 /*NOTREACHED*/
615 }
616
Dan Gohman8181bd12008-07-27 21:46:04 +0000617 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000618}
619
620/// Custom lower stores for CellSPU
621/*!
622 All CellSPU stores are aligned to 16-byte boundaries, so for elements
623 within a 16-byte block, we have to generate a shuffle to insert the
624 requested element into its place, then store the resulting block.
625 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000626static SDValue
627LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000628 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000629 SDValue Value = SN->getValue();
Duncan Sands92c43912008-06-06 12:08:01 +0000630 MVT VT = Value.getValueType();
631 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
632 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000633 unsigned alignment = SN->getAlignment();
Scott Michel8efdca42007-12-04 22:23:35 +0000634
635 switch (SN->getAddressingMode()) {
636 case ISD::UNINDEXED: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000637 // The vector type we really want to load from the 16-byte chunk.
Scott Michele1006032008-11-19 17:45:08 +0000638 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
639 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +0000640
Scott Michel06eabde2008-12-27 04:51:36 +0000641 SDValue alignLoadVec;
642 SDValue basePtr = SN->getBasePtr();
643 SDValue the_chain = SN->getChain();
644 SDValue insertEltOffs;
Scott Michel8efdca42007-12-04 22:23:35 +0000645
Scott Michel06eabde2008-12-27 04:51:36 +0000646 if (alignment == 16) {
647 ConstantSDNode *CN;
648
649 // Special cases for a known aligned load to simplify the base pointer
650 // and insertion byte:
651 if (basePtr.getOpcode() == ISD::ADD
652 && (CN = dyn_cast<ConstantSDNode>(basePtr.getOperand(1))) != 0) {
653 // Known offset into basePtr
654 int64_t offset = CN->getSExtValue();
655
656 // Simplify the base pointer for this case:
657 basePtr = basePtr.getOperand(0);
658 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
659 basePtr,
660 DAG.getConstant((offset & 0xf), PtrVT));
661
662 if ((offset & ~0xf) > 0) {
663 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
664 basePtr,
665 DAG.getConstant((offset & ~0xf), PtrVT));
666 }
667 } else {
668 // Otherwise, assume it's at byte 0 of basePtr
669 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
670 basePtr,
671 DAG.getConstant(0, PtrVT));
672 }
673 } else {
674 // Unaligned load: must be more pessimistic about addressing modes:
675 if (basePtr.getOpcode() == ISD::ADD) {
676 MachineFunction &MF = DAG.getMachineFunction();
677 MachineRegisterInfo &RegInfo = MF.getRegInfo();
678 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
679 SDValue Flag;
680
681 SDValue Op0 = basePtr.getOperand(0);
682 SDValue Op1 = basePtr.getOperand(1);
683
684 if (isa<ConstantSDNode>(Op1)) {
685 // Convert the (add <ptr>, <const>) to an indirect address contained
686 // in a register. Note that this is done because we need to avoid
687 // creating a 0(reg) d-form address due to the SPU's block loads.
688 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
689 the_chain = DAG.getCopyToReg(the_chain, VReg, basePtr, Flag);
690 basePtr = DAG.getCopyFromReg(the_chain, VReg, PtrVT);
691 } else {
692 // Convert the (add <arg1>, <arg2>) to an indirect address, which
693 // will likely be lowered as a reg(reg) x-form address.
694 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
695 }
696 } else {
697 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
698 basePtr,
699 DAG.getConstant(0, PtrVT));
700 }
701
702 // Insertion point is solely determined by basePtr's contents
703 insertEltOffs = DAG.getNode(ISD::ADD, PtrVT,
704 basePtr,
705 DAG.getConstant(0, PtrVT));
706 }
707
708 // Re-emit as a v16i8 vector load
709 alignLoadVec = DAG.getLoad(MVT::v16i8, the_chain, basePtr,
710 SN->getSrcValue(), SN->getSrcValueOffset(),
711 SN->isVolatile(), 16);
712
713 // Update the chain
714 the_chain = alignLoadVec.getValue(1);
Scott Michel8efdca42007-12-04 22:23:35 +0000715
Scott Micheldbac4cf2008-01-11 02:53:15 +0000716 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman8181bd12008-07-27 21:46:04 +0000717 SDValue theValue = SN->getValue();
718 SDValue result;
Scott Michel8efdca42007-12-04 22:23:35 +0000719
720 if (StVT != VT
Scott Michel5a6f17b2008-01-30 02:55:46 +0000721 && (theValue.getOpcode() == ISD::AssertZext
722 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel8efdca42007-12-04 22:23:35 +0000723 // Drill down and get the value for zero- and sign-extended
724 // quantities
Scott Michel4ec722e2008-07-16 17:17:29 +0000725 theValue = theValue.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000726 }
727
Scott Micheldbac4cf2008-01-11 02:53:15 +0000728 // If the base pointer is already a D-form address, then just create
729 // a new D-form address with a slot offset and the orignal base pointer.
730 // Otherwise generate a D-form address with the slot offset relative
731 // to the stack pointer, which is always aligned.
Scott Michel06eabde2008-12-27 04:51:36 +0000732#if !defined(NDEBUG)
733 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
734 cerr << "CellSPU LowerSTORE: basePtr = ";
735 basePtr.getNode()->dump(&DAG);
736 cerr << "\n";
737 }
738#endif
Scott Micheldbac4cf2008-01-11 02:53:15 +0000739
Scott Michelf65c8f02008-11-19 15:24:16 +0000740 SDValue insertEltOp =
Scott Michel06eabde2008-12-27 04:51:36 +0000741 DAG.getNode(SPUISD::SHUFFLE_MASK, vecVT, insertEltOffs);
Scott Michele1006032008-11-19 17:45:08 +0000742 SDValue vectorizeOp =
743 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michelf65c8f02008-11-19 15:24:16 +0000744
Scott Michel0718cd82008-12-01 17:56:02 +0000745 result = DAG.getNode(SPUISD::SHUFB, vecVT,
746 vectorizeOp, alignLoadVec,
747 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, insertEltOp));
Scott Michel8efdca42007-12-04 22:23:35 +0000748
Scott Micheldbac4cf2008-01-11 02:53:15 +0000749 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel8efdca42007-12-04 22:23:35 +0000750 LN->getSrcValue(), LN->getSrcValueOffset(),
751 LN->isVolatile(), LN->getAlignment());
752
Scott Michel8c2746e2008-12-04 17:16:59 +0000753#if 0 && !defined(NDEBUG)
Scott Michelf65c8f02008-11-19 15:24:16 +0000754 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
755 const SDValue &currentRoot = DAG.getRoot();
756
757 DAG.setRoot(result);
758 cerr << "------- CellSPU:LowerStore result:\n";
759 DAG.dump();
760 cerr << "-------\n";
761 DAG.setRoot(currentRoot);
762 }
763#endif
Scott Michelec8c82e2008-12-02 19:53:53 +0000764
Scott Michel8efdca42007-12-04 22:23:35 +0000765 return result;
766 /*UNREACHED*/
767 }
768 case ISD::PRE_INC:
769 case ISD::PRE_DEC:
770 case ISD::POST_INC:
771 case ISD::POST_DEC:
772 case ISD::LAST_INDEXED_MODE:
773 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
774 "UNINDEXED\n";
775 cerr << (unsigned) SN->getAddressingMode() << "\n";
776 abort();
777 /*NOTREACHED*/
778 }
779
Dan Gohman8181bd12008-07-27 21:46:04 +0000780 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000781}
782
783/// Generate the address of a constant pool entry.
Dan Gohman8181bd12008-07-27 21:46:04 +0000784static SDValue
785LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000786 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000787 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
788 Constant *C = CP->getConstVal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000789 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
790 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000791 const TargetMachine &TM = DAG.getTarget();
Scott Michel8efdca42007-12-04 22:23:35 +0000792
793 if (TM.getRelocationModel() == Reloc::Static) {
794 if (!ST->usingLargeMem()) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000795 // Just return the SDValue with the constant pool address in it.
Scott Michel394e26d2008-01-17 20:38:41 +0000796 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +0000797 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000798 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
799 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000800 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel8efdca42007-12-04 22:23:35 +0000801 }
802 }
803
804 assert(0 &&
Gabor Greife9f7f582008-08-31 15:37:04 +0000805 "LowerConstantPool: Relocation model other than static"
806 " not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000807 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000808}
809
Dan Gohman8181bd12008-07-27 21:46:04 +0000810static SDValue
811LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000812 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000813 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000814 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
815 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000816 const TargetMachine &TM = DAG.getTarget();
817
818 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel97872d32008-02-23 18:41:37 +0000819 if (!ST->usingLargeMem()) {
820 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
821 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000822 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
823 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000824 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
825 }
Scott Michel8efdca42007-12-04 22:23:35 +0000826 }
827
828 assert(0 &&
829 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000830 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000831}
832
Dan Gohman8181bd12008-07-27 21:46:04 +0000833static SDValue
834LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000835 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000836 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
837 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000838 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel8efdca42007-12-04 22:23:35 +0000839 const TargetMachine &TM = DAG.getTarget();
Dan Gohman8181bd12008-07-27 21:46:04 +0000840 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel4ec722e2008-07-16 17:17:29 +0000841
Scott Michel8efdca42007-12-04 22:23:35 +0000842 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michelf9f42e62008-01-29 02:16:57 +0000843 if (!ST->usingLargeMem()) {
844 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
845 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000846 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
847 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michelf9f42e62008-01-29 02:16:57 +0000848 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
849 }
Scott Michel8efdca42007-12-04 22:23:35 +0000850 } else {
851 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel5a6f17b2008-01-30 02:55:46 +0000852 << "supported.\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000853 abort();
854 /*NOTREACHED*/
855 }
856
Dan Gohman8181bd12008-07-27 21:46:04 +0000857 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000858}
859
860//! Custom lower i64 integer constants
861/*!
862 This code inserts all of the necessary juggling that needs to occur to load
863 a 64-bit constant into a register.
864 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000865static SDValue
866LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000867 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000868
869 if (VT == MVT::i64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000870 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
871 SDValue T = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michelc630c412008-11-24 17:11:17 +0000872 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000873 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +0000874 } else {
875 cerr << "LowerConstant: unhandled constant type "
Duncan Sands92c43912008-06-06 12:08:01 +0000876 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +0000877 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000878 abort();
879 /*NOTREACHED*/
880 }
881
Dan Gohman8181bd12008-07-27 21:46:04 +0000882 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000883}
884
Nate Begeman78125042008-02-14 18:43:04 +0000885//! Custom lower double precision floating point constants
Dan Gohman8181bd12008-07-27 21:46:04 +0000886static SDValue
887LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000888 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000889
Nate Begeman78125042008-02-14 18:43:04 +0000890 if (VT == MVT::f64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000891 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
892
893 assert((FP != 0) &&
894 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michelae5cbf52008-12-29 03:23:36 +0000895
Scott Michel11e88bb2007-12-19 20:15:47 +0000896 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel0718cd82008-12-01 17:56:02 +0000897 SDValue T = DAG.getConstant(dbits, MVT::i64);
898 SDValue Tvec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T);
899 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
900 DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64, Tvec));
Scott Michel8efdca42007-12-04 22:23:35 +0000901 }
902
Dan Gohman8181bd12008-07-27 21:46:04 +0000903 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000904}
905
Dan Gohman8181bd12008-07-27 21:46:04 +0000906static SDValue
Scott Michel06eabde2008-12-27 04:51:36 +0000907LowerBRCOND(SDValue Op, SelectionDAG &DAG, const TargetLowering &TLI) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000908 SDValue Cond = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +0000909 MVT CondVT = Cond.getValueType();
Scott Michel06eabde2008-12-27 04:51:36 +0000910 unsigned CondOpc;
Scott Michel394e26d2008-01-17 20:38:41 +0000911
Scott Michel33d73eb2008-11-21 02:56:16 +0000912 if (CondVT == MVT::i8) {
Scott Michel06eabde2008-12-27 04:51:36 +0000913 SDValue CondOp0 = Cond.getOperand(0);
914 if (Cond.getOpcode() == ISD::TRUNCATE) {
915 // Use the truncate's value type and ANY_EXTEND the condition (DAGcombine
916 // will then remove the truncate)
917 CondVT = CondOp0.getValueType();
918 CondOpc = ISD::ANY_EXTEND;
919 } else {
920 CondVT = MVT::i32; // default to something reasonable
921 CondOpc = ISD::ZERO_EXTEND;
922 }
923
924 Cond = DAG.getNode(CondOpc, CondVT, Op.getOperand(1));
925
Scott Michel394e26d2008-01-17 20:38:41 +0000926 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
Scott Michel06eabde2008-12-27 04:51:36 +0000927 Op.getOperand(0), Cond, Op.getOperand(2));
928 }
Scott Michelae5cbf52008-12-29 03:23:36 +0000929
Scott Michel06eabde2008-12-27 04:51:36 +0000930 return SDValue(); // Unchanged
Scott Michel394e26d2008-01-17 20:38:41 +0000931}
932
Dan Gohman8181bd12008-07-27 21:46:04 +0000933static SDValue
934LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel8efdca42007-12-04 22:23:35 +0000935{
936 MachineFunction &MF = DAG.getMachineFunction();
937 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner1b989192007-12-31 04:13:23 +0000938 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michela313fb02008-10-30 01:51:48 +0000939 SmallVector<SDValue, 48> ArgValues;
Dan Gohman8181bd12008-07-27 21:46:04 +0000940 SDValue Root = Op.getOperand(0);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000941 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel8efdca42007-12-04 22:23:35 +0000942
943 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
944 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel4ec722e2008-07-16 17:17:29 +0000945
Scott Michel8efdca42007-12-04 22:23:35 +0000946 unsigned ArgOffset = SPUFrameInfo::minStackSize();
947 unsigned ArgRegIdx = 0;
948 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel4ec722e2008-07-16 17:17:29 +0000949
Duncan Sands92c43912008-06-06 12:08:01 +0000950 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +0000951
Scott Michel8efdca42007-12-04 22:23:35 +0000952 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greife9f7f582008-08-31 15:37:04 +0000953 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
954 ArgNo != e; ++ArgNo) {
Duncan Sands92c43912008-06-06 12:08:01 +0000955 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
956 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michela313fb02008-10-30 01:51:48 +0000957 SDValue ArgVal;
Scott Michel8efdca42007-12-04 22:23:35 +0000958
Scott Michela313fb02008-10-30 01:51:48 +0000959 if (ArgRegIdx < NumArgRegs) {
960 const TargetRegisterClass *ArgRegClass;
Scott Michel4ec722e2008-07-16 17:17:29 +0000961
Scott Michela313fb02008-10-30 01:51:48 +0000962 switch (ObjectVT.getSimpleVT()) {
963 default: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000964 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
965 << ObjectVT.getMVTString()
966 << "\n";
967 abort();
Scott Michela313fb02008-10-30 01:51:48 +0000968 }
969 case MVT::i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000970 ArgRegClass = &SPU::R8CRegClass;
971 break;
Scott Michela313fb02008-10-30 01:51:48 +0000972 case MVT::i16:
Scott Michel33d73eb2008-11-21 02:56:16 +0000973 ArgRegClass = &SPU::R16CRegClass;
974 break;
Scott Michela313fb02008-10-30 01:51:48 +0000975 case MVT::i32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000976 ArgRegClass = &SPU::R32CRegClass;
977 break;
Scott Michela313fb02008-10-30 01:51:48 +0000978 case MVT::i64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000979 ArgRegClass = &SPU::R64CRegClass;
980 break;
Scott Michela313fb02008-10-30 01:51:48 +0000981 case MVT::f32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000982 ArgRegClass = &SPU::R32FPRegClass;
983 break;
Scott Michela313fb02008-10-30 01:51:48 +0000984 case MVT::f64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000985 ArgRegClass = &SPU::R64FPRegClass;
986 break;
Scott Michela313fb02008-10-30 01:51:48 +0000987 case MVT::v2f64:
988 case MVT::v4f32:
989 case MVT::v2i64:
990 case MVT::v4i32:
991 case MVT::v8i16:
992 case MVT::v16i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000993 ArgRegClass = &SPU::VECREGRegClass;
994 break;
Scott Michela313fb02008-10-30 01:51:48 +0000995 }
996
997 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
998 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
999 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1000 ++ArgRegIdx;
1001 } else {
1002 // We need to load the argument to a virtual register if we determined
1003 // above that we ran out of physical registers of the appropriate type
1004 // or we're forced to do vararg
Chris Lattner60069452008-02-13 07:35:30 +00001005 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman8181bd12008-07-27 21:46:04 +00001006 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner60069452008-02-13 07:35:30 +00001007 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel8efdca42007-12-04 22:23:35 +00001008 ArgOffset += StackSlotSize;
1009 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001010
Scott Michel8efdca42007-12-04 22:23:35 +00001011 ArgValues.push_back(ArgVal);
Scott Michela313fb02008-10-30 01:51:48 +00001012 // Update the chain
1013 Root = ArgVal.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001014 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001015
Scott Michela313fb02008-10-30 01:51:48 +00001016 // vararg handling:
Scott Michel8efdca42007-12-04 22:23:35 +00001017 if (isVarArg) {
Scott Michela313fb02008-10-30 01:51:48 +00001018 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1019 // We will spill (79-3)+1 registers to the stack
1020 SmallVector<SDValue, 79-3+1> MemOps;
1021
1022 // Create the frame slot
1023
Scott Michel8efdca42007-12-04 22:23:35 +00001024 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Michela313fb02008-10-30 01:51:48 +00001025 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1026 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1027 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1028 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1029 Root = Store.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001030 MemOps.push_back(Store);
Scott Michela313fb02008-10-30 01:51:48 +00001031
1032 // Increment address by stack slot size for the next stored argument
1033 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001034 }
1035 if (!MemOps.empty())
Scott Michela313fb02008-10-30 01:51:48 +00001036 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001037 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001038
Scott Michel8efdca42007-12-04 22:23:35 +00001039 ArgValues.push_back(Root);
Scott Michel4ec722e2008-07-16 17:17:29 +00001040
Scott Michel8efdca42007-12-04 22:23:35 +00001041 // Return the new list of results.
Duncan Sands42d7bb82008-12-01 11:41:29 +00001042 return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(),
1043 &ArgValues[0], ArgValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001044}
1045
1046/// isLSAAddress - Return the immediate to use if the specified
1047/// value is representable as a LSA address.
Dan Gohman8181bd12008-07-27 21:46:04 +00001048static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel5974f432008-11-11 03:06:06 +00001049 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel8efdca42007-12-04 22:23:35 +00001050 if (!C) return 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001051
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001052 int Addr = C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001053 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1054 (Addr << 14 >> 14) != Addr)
1055 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel4ec722e2008-07-16 17:17:29 +00001056
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001057 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel8efdca42007-12-04 22:23:35 +00001058}
1059
1060static
Dan Gohman8181bd12008-07-27 21:46:04 +00001061SDValue
1062LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001063 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1064 SDValue Chain = TheCall->getChain();
Dan Gohman705e3f72008-09-13 01:54:27 +00001065 SDValue Callee = TheCall->getCallee();
1066 unsigned NumOps = TheCall->getNumArgs();
Scott Michel8efdca42007-12-04 22:23:35 +00001067 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1068 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1069 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1070
1071 // Handy pointer type
Duncan Sands92c43912008-06-06 12:08:01 +00001072 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +00001073
Scott Michel8efdca42007-12-04 22:23:35 +00001074 // Accumulate how many bytes are to be pushed on the stack, including the
1075 // linkage area, and parameter passing area. According to the SPU ABI,
1076 // we minimally need space for [LR] and [SP]
1077 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel4ec722e2008-07-16 17:17:29 +00001078
Scott Michel8efdca42007-12-04 22:23:35 +00001079 // Set up a copy of the stack pointer for use loading and storing any
1080 // arguments that may not fit in the registers available for argument
1081 // passing.
Dan Gohman8181bd12008-07-27 21:46:04 +00001082 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel4ec722e2008-07-16 17:17:29 +00001083
Scott Michel8efdca42007-12-04 22:23:35 +00001084 // Figure out which arguments are going to go in registers, and which in
1085 // memory.
1086 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1087 unsigned ArgRegIdx = 0;
1088
1089 // Keep track of registers passing arguments
Dan Gohman8181bd12008-07-27 21:46:04 +00001090 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel8efdca42007-12-04 22:23:35 +00001091 // And the arguments passed on the stack
Dan Gohman8181bd12008-07-27 21:46:04 +00001092 SmallVector<SDValue, 8> MemOpChains;
Scott Michel8efdca42007-12-04 22:23:35 +00001093
1094 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001095 SDValue Arg = TheCall->getArg(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001096
Scott Michel8efdca42007-12-04 22:23:35 +00001097 // PtrOff will be used to store the current argument to the stack if a
1098 // register cannot be found for it.
Dan Gohman8181bd12008-07-27 21:46:04 +00001099 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel8efdca42007-12-04 22:23:35 +00001100 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1101
Duncan Sands92c43912008-06-06 12:08:01 +00001102 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001103 default: assert(0 && "Unexpected ValueType for argument!");
1104 case MVT::i32:
1105 case MVT::i64:
1106 case MVT::i128:
1107 if (ArgRegIdx != NumArgRegs) {
1108 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1109 } else {
1110 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001111 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001112 }
1113 break;
1114 case MVT::f32:
1115 case MVT::f64:
1116 if (ArgRegIdx != NumArgRegs) {
1117 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1118 } else {
1119 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001120 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001121 }
1122 break;
Scott Michele2641a12008-12-04 21:01:44 +00001123 case MVT::v2i64:
1124 case MVT::v2f64:
Scott Michel8efdca42007-12-04 22:23:35 +00001125 case MVT::v4f32:
1126 case MVT::v4i32:
1127 case MVT::v8i16:
1128 case MVT::v16i8:
1129 if (ArgRegIdx != NumArgRegs) {
1130 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1131 } else {
1132 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001133 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001134 }
1135 break;
1136 }
1137 }
1138
1139 // Update number of stack bytes actually used, insert a call sequence start
1140 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001141 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1142 true));
Scott Michel8efdca42007-12-04 22:23:35 +00001143
1144 if (!MemOpChains.empty()) {
1145 // Adjust the stack pointer for the stack arguments.
1146 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1147 &MemOpChains[0], MemOpChains.size());
1148 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001149
Scott Michel8efdca42007-12-04 22:23:35 +00001150 // Build a sequence of copy-to-reg nodes chained together with token chain
1151 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman8181bd12008-07-27 21:46:04 +00001152 SDValue InFlag;
Scott Michel8efdca42007-12-04 22:23:35 +00001153 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1154 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1155 InFlag);
1156 InFlag = Chain.getValue(1);
1157 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001158
Dan Gohman8181bd12008-07-27 21:46:04 +00001159 SmallVector<SDValue, 8> Ops;
Scott Michel8efdca42007-12-04 22:23:35 +00001160 unsigned CallOpc = SPUISD::CALL;
Scott Michel4ec722e2008-07-16 17:17:29 +00001161
Bill Wendlingfef06052008-09-16 21:48:12 +00001162 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1163 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1164 // node so that legalize doesn't hack it.
Scott Michel5974f432008-11-11 03:06:06 +00001165 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001166 GlobalValue *GV = G->getGlobal();
Duncan Sands92c43912008-06-06 12:08:01 +00001167 MVT CalleeVT = Callee.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001168 SDValue Zero = DAG.getConstant(0, PtrVT);
1169 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001170
Scott Micheldbac4cf2008-01-11 02:53:15 +00001171 if (!ST->usingLargeMem()) {
1172 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1173 // style calls, otherwise, external symbols are BRASL calls. This assumes
1174 // that declared/defined symbols are in the same compilation unit and can
1175 // be reached through PC-relative jumps.
1176 //
1177 // NOTE:
1178 // This may be an unsafe assumption for JIT and really large compilation
1179 // units.
1180 if (GV->isDeclaration()) {
1181 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1182 } else {
1183 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1184 }
Scott Michel8efdca42007-12-04 22:23:35 +00001185 } else {
Scott Micheldbac4cf2008-01-11 02:53:15 +00001186 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1187 // address pairs:
Scott Michelf9f42e62008-01-29 02:16:57 +00001188 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +00001189 }
Scott Michelae5cbf52008-12-29 03:23:36 +00001190 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
1191 MVT CalleeVT = Callee.getValueType();
1192 SDValue Zero = DAG.getConstant(0, PtrVT);
1193 SDValue ExtSym = DAG.getTargetExternalSymbol(S->getSymbol(),
1194 Callee.getValueType());
1195
1196 if (!ST->usingLargeMem()) {
1197 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, ExtSym, Zero);
1198 } else {
1199 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, ExtSym, Zero);
1200 }
1201 } else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001202 // If this is an absolute destination address that appears to be a legal
1203 // local store address, use the munged value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001204 Callee = SDValue(Dest, 0);
Scott Micheldbac4cf2008-01-11 02:53:15 +00001205 }
Scott Michel8efdca42007-12-04 22:23:35 +00001206
1207 Ops.push_back(Chain);
1208 Ops.push_back(Callee);
Scott Michel4ec722e2008-07-16 17:17:29 +00001209
Scott Michel8efdca42007-12-04 22:23:35 +00001210 // Add argument registers to the end of the list so that they are known live
1211 // into the call.
1212 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel4ec722e2008-07-16 17:17:29 +00001213 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel8efdca42007-12-04 22:23:35 +00001214 RegsToPass[i].second.getValueType()));
Scott Michel4ec722e2008-07-16 17:17:29 +00001215
Gabor Greif1c80d112008-08-28 21:40:38 +00001216 if (InFlag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001217 Ops.push_back(InFlag);
Duncan Sands698842f2008-07-02 17:40:58 +00001218 // Returns a chain and a flag for retval copy to use.
1219 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1220 &Ops[0], Ops.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001221 InFlag = Chain.getValue(1);
1222
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001223 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1224 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman705e3f72008-09-13 01:54:27 +00001225 if (TheCall->getValueType(0) != MVT::Other)
Evan Cheng07322bb2008-02-05 22:44:06 +00001226 InFlag = Chain.getValue(1);
1227
Dan Gohman8181bd12008-07-27 21:46:04 +00001228 SDValue ResultVals[3];
Scott Michel8efdca42007-12-04 22:23:35 +00001229 unsigned NumResults = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001230
Scott Michel8efdca42007-12-04 22:23:35 +00001231 // If the call has results, copy the values out of the ret val registers.
Dan Gohman705e3f72008-09-13 01:54:27 +00001232 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001233 default: assert(0 && "Unexpected ret value!");
1234 case MVT::Other: break;
1235 case MVT::i32:
Dan Gohman705e3f72008-09-13 01:54:27 +00001236 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001237 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1238 ResultVals[0] = Chain.getValue(0);
1239 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1240 Chain.getValue(2)).getValue(1);
1241 ResultVals[1] = Chain.getValue(0);
1242 NumResults = 2;
Scott Michel8efdca42007-12-04 22:23:35 +00001243 } else {
1244 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1245 ResultVals[0] = Chain.getValue(0);
1246 NumResults = 1;
1247 }
Scott Michel8efdca42007-12-04 22:23:35 +00001248 break;
1249 case MVT::i64:
1250 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1251 ResultVals[0] = Chain.getValue(0);
1252 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001253 break;
1254 case MVT::f32:
1255 case MVT::f64:
Dan Gohman705e3f72008-09-13 01:54:27 +00001256 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001257 InFlag).getValue(1);
1258 ResultVals[0] = Chain.getValue(0);
1259 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001260 break;
1261 case MVT::v2f64:
Scott Michele2641a12008-12-04 21:01:44 +00001262 case MVT::v2i64:
Scott Michel8efdca42007-12-04 22:23:35 +00001263 case MVT::v4f32:
1264 case MVT::v4i32:
1265 case MVT::v8i16:
1266 case MVT::v16i8:
Dan Gohman705e3f72008-09-13 01:54:27 +00001267 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001268 InFlag).getValue(1);
1269 ResultVals[0] = Chain.getValue(0);
1270 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001271 break;
1272 }
Duncan Sands698842f2008-07-02 17:40:58 +00001273
Scott Michel8efdca42007-12-04 22:23:35 +00001274 // If the function returns void, just return the chain.
1275 if (NumResults == 0)
1276 return Chain;
Scott Michel4ec722e2008-07-16 17:17:29 +00001277
Scott Michel8efdca42007-12-04 22:23:35 +00001278 // Otherwise, merge everything together with a MERGE_VALUES node.
1279 ResultVals[NumResults++] = Chain;
Dan Gohman8181bd12008-07-27 21:46:04 +00001280 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif46bf5472008-08-26 22:36:50 +00001281 return Res.getValue(Op.getResNo());
Scott Michel8efdca42007-12-04 22:23:35 +00001282}
1283
Dan Gohman8181bd12008-07-27 21:46:04 +00001284static SDValue
1285LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel8efdca42007-12-04 22:23:35 +00001286 SmallVector<CCValAssign, 16> RVLocs;
1287 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1288 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1289 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greif1c80d112008-08-28 21:40:38 +00001290 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel4ec722e2008-07-16 17:17:29 +00001291
Scott Michel8efdca42007-12-04 22:23:35 +00001292 // If this is the first return lowered for this function, add the regs to the
1293 // liveout set for the function.
Chris Lattner1b989192007-12-31 04:13:23 +00001294 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001295 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner1b989192007-12-31 04:13:23 +00001296 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel8efdca42007-12-04 22:23:35 +00001297 }
1298
Dan Gohman8181bd12008-07-27 21:46:04 +00001299 SDValue Chain = Op.getOperand(0);
1300 SDValue Flag;
Scott Michel4ec722e2008-07-16 17:17:29 +00001301
Scott Michel8efdca42007-12-04 22:23:35 +00001302 // Copy the result values into the output registers.
1303 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1304 CCValAssign &VA = RVLocs[i];
1305 assert(VA.isRegLoc() && "Can only return in registers!");
1306 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1307 Flag = Chain.getValue(1);
1308 }
1309
Gabor Greif1c80d112008-08-28 21:40:38 +00001310 if (Flag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001311 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1312 else
1313 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1314}
1315
1316
1317//===----------------------------------------------------------------------===//
1318// Vector related lowering:
1319//===----------------------------------------------------------------------===//
1320
1321static ConstantSDNode *
1322getVecImm(SDNode *N) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001323 SDValue OpVal(0, 0);
Scott Michel4ec722e2008-07-16 17:17:29 +00001324
Scott Michel8efdca42007-12-04 22:23:35 +00001325 // Check to see if this buildvec has a single non-undef value in its elements.
1326 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1327 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greif1c80d112008-08-28 21:40:38 +00001328 if (OpVal.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +00001329 OpVal = N->getOperand(i);
1330 else if (OpVal != N->getOperand(i))
1331 return 0;
1332 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001333
Gabor Greif1c80d112008-08-28 21:40:38 +00001334 if (OpVal.getNode() != 0) {
Scott Michel5974f432008-11-11 03:06:06 +00001335 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001336 return CN;
1337 }
1338 }
1339
1340 return 0; // All UNDEF: use implicit def.; not Constant node
1341}
1342
1343/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1344/// and the value fits into an unsigned 18-bit constant, and if so, return the
1345/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001346SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001347 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001348 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001349 uint64_t Value = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001350 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001351 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001352 uint32_t upper = uint32_t(UValue >> 32);
1353 uint32_t lower = uint32_t(UValue);
1354 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001355 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001356 Value = Value >> 32;
1357 }
Scott Michel8efdca42007-12-04 22:23:35 +00001358 if (Value <= 0x3ffff)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001359 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001360 }
1361
Dan Gohman8181bd12008-07-27 21:46:04 +00001362 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001363}
1364
1365/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1366/// and the value fits into a signed 16-bit constant, and if so, return the
1367/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001368SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001369 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001370 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001371 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001372 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001373 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001374 uint32_t upper = uint32_t(UValue >> 32);
1375 uint32_t lower = uint32_t(UValue);
1376 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001377 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001378 Value = Value >> 32;
1379 }
Scott Michel6baba072008-03-05 23:02:02 +00001380 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001381 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001382 }
1383 }
1384
Dan Gohman8181bd12008-07-27 21:46:04 +00001385 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001386}
1387
1388/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1389/// and the value fits into a signed 10-bit constant, and if so, return the
1390/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001391SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001392 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001393 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001394 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001395 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001396 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001397 uint32_t upper = uint32_t(UValue >> 32);
1398 uint32_t lower = uint32_t(UValue);
1399 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001400 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001401 Value = Value >> 32;
1402 }
Scott Michel6baba072008-03-05 23:02:02 +00001403 if (isS10Constant(Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001404 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001405 }
1406
Dan Gohman8181bd12008-07-27 21:46:04 +00001407 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001408}
1409
1410/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1411/// and the value fits into a signed 8-bit constant, and if so, return the
1412/// constant.
1413///
1414/// @note: The incoming vector is v16i8 because that's the only way we can load
1415/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1416/// same value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001417SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001418 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001419 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001420 int Value = (int) CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001421 if (ValueType == MVT::i16
Scott Michel5a6f17b2008-01-30 02:55:46 +00001422 && Value <= 0xffff /* truncated from uint64_t */
1423 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001424 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001425 else if (ValueType == MVT::i8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001426 && (Value & 0xff) == Value)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001427 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001428 }
1429
Dan Gohman8181bd12008-07-27 21:46:04 +00001430 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001431}
1432
1433/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1434/// and the value fits into a signed 16-bit constant, and if so, return the
1435/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001436SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001437 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001438 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001439 uint64_t Value = CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001440 if ((ValueType == MVT::i32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001441 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1442 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001443 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001444 }
1445
Dan Gohman8181bd12008-07-27 21:46:04 +00001446 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001447}
1448
1449/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001450SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001451 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001452 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001453 }
1454
Dan Gohman8181bd12008-07-27 21:46:04 +00001455 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001456}
1457
1458/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001459SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001460 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001461 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001462 }
1463
Dan Gohman8181bd12008-07-27 21:46:04 +00001464 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001465}
1466
1467// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001468// UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001469// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1470// zero. Return true if this is not an array of constants, false if it is.
1471//
1472static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1473 uint64_t UndefBits[2]) {
1474 // Start with zero'd results.
1475 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001476
Duncan Sands92c43912008-06-06 12:08:01 +00001477 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel8efdca42007-12-04 22:23:35 +00001478 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001479 SDValue OpVal = BV->getOperand(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001480
Scott Michel8efdca42007-12-04 22:23:35 +00001481 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1482 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1483
1484 uint64_t EltBits = 0;
1485 if (OpVal.getOpcode() == ISD::UNDEF) {
1486 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1487 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1488 continue;
Scott Michel5974f432008-11-11 03:06:06 +00001489 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001490 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel5974f432008-11-11 03:06:06 +00001491 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001492 const APFloat &apf = CN->getValueAPF();
1493 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001494 ? FloatToBits(apf.convertToFloat())
1495 : DoubleToBits(apf.convertToDouble()));
Scott Michel8efdca42007-12-04 22:23:35 +00001496 } else {
1497 // Nonconstant element.
1498 return true;
1499 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001500
Scott Michel8efdca42007-12-04 22:23:35 +00001501 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1502 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001503
1504 //printf("%llx %llx %llx %llx\n",
Scott Michel8efdca42007-12-04 22:23:35 +00001505 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1506 return false;
1507}
1508
1509/// If this is a splat (repetition) of a value across the whole vector, return
1510/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel4ec722e2008-07-16 17:17:29 +00001511/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel8efdca42007-12-04 22:23:35 +00001512/// SplatSize = 1 byte.
Scott Michel4ec722e2008-07-16 17:17:29 +00001513static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel8efdca42007-12-04 22:23:35 +00001514 const uint64_t Undef128[2],
Scott Michel5a6f17b2008-01-30 02:55:46 +00001515 int MinSplatBits,
Scott Michel8efdca42007-12-04 22:23:35 +00001516 uint64_t &SplatBits, uint64_t &SplatUndef,
1517 int &SplatSize) {
1518 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1519 // the same as the lower 64-bits, ignoring undefs.
1520 uint64_t Bits64 = Bits128[0] | Bits128[1];
1521 uint64_t Undef64 = Undef128[0] & Undef128[1];
1522 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1523 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1524 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1525 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1526
1527 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1528 if (MinSplatBits < 64) {
Scott Michel4ec722e2008-07-16 17:17:29 +00001529
Scott Michel8efdca42007-12-04 22:23:35 +00001530 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1531 // undefs.
1532 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001533 if (MinSplatBits < 32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001534
Scott Michel5a6f17b2008-01-30 02:55:46 +00001535 // If the top 16-bits are different than the lower 16-bits, ignoring
1536 // undefs, we have an i32 splat.
1537 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1538 if (MinSplatBits < 16) {
1539 // If the top 8-bits are different than the lower 8-bits, ignoring
1540 // undefs, we have an i16 splat.
Gabor Greife9f7f582008-08-31 15:37:04 +00001541 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1542 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001543 // Otherwise, we have an 8-bit splat.
1544 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1545 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1546 SplatSize = 1;
1547 return true;
1548 }
1549 } else {
1550 SplatBits = Bits16;
1551 SplatUndef = Undef16;
1552 SplatSize = 2;
1553 return true;
1554 }
1555 }
1556 } else {
1557 SplatBits = Bits32;
1558 SplatUndef = Undef32;
1559 SplatSize = 4;
1560 return true;
1561 }
Scott Michel8efdca42007-12-04 22:23:35 +00001562 }
1563 } else {
1564 SplatBits = Bits128[0];
1565 SplatUndef = Undef128[0];
1566 SplatSize = 8;
1567 return true;
1568 }
1569 }
1570
1571 return false; // Can't be a splat if two pieces don't match.
1572}
1573
1574// If this is a case we can't handle, return null and let the default
1575// expansion code take care of it. If we CAN select this case, and if it
1576// selects to a single instruction, return Op. Otherwise, if we can codegen
1577// this case more efficiently than a constant pool load, lower it to the
1578// sequence of ops that should be used.
Dan Gohman8181bd12008-07-27 21:46:04 +00001579static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001580 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00001581 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001582 // UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001583 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel4ec722e2008-07-16 17:17:29 +00001584 // zero.
Scott Michel8efdca42007-12-04 22:23:35 +00001585 uint64_t VectorBits[2];
1586 uint64_t UndefBits[2];
1587 uint64_t SplatBits, SplatUndef;
1588 int SplatSize;
Gabor Greif1c80d112008-08-28 21:40:38 +00001589 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel8efdca42007-12-04 22:23:35 +00001590 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00001591 VT.getVectorElementType().getSizeInBits(),
Scott Michel8efdca42007-12-04 22:23:35 +00001592 SplatBits, SplatUndef, SplatSize))
Dan Gohman8181bd12008-07-27 21:46:04 +00001593 return SDValue(); // Not a constant vector, not a splat.
Scott Michel4ec722e2008-07-16 17:17:29 +00001594
Duncan Sands92c43912008-06-06 12:08:01 +00001595 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001596 default:
1597 case MVT::v4f32: {
1598 uint32_t Value32 = SplatBits;
1599 assert(SplatSize == 4
Scott Michel5a6f17b2008-01-30 02:55:46 +00001600 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel8efdca42007-12-04 22:23:35 +00001601 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001602 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001603 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001604 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001605 break;
1606 }
1607 case MVT::v2f64: {
1608 uint64_t f64val = SplatBits;
1609 assert(SplatSize == 8
Scott Michelc630c412008-11-24 17:11:17 +00001610 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel8efdca42007-12-04 22:23:35 +00001611 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001612 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001613 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001614 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001615 break;
1616 }
1617 case MVT::v16i8: {
1618 // 8-bit constants have to be expanded to 16-bits
1619 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman8181bd12008-07-27 21:46:04 +00001620 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001621 for (int i = 0; i < 8; ++i)
1622 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1623 return DAG.getNode(ISD::BIT_CONVERT, VT,
1624 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1625 }
1626 case MVT::v8i16: {
1627 unsigned short Value16;
Scott Michel4ec722e2008-07-16 17:17:29 +00001628 if (SplatSize == 2)
Scott Michel8efdca42007-12-04 22:23:35 +00001629 Value16 = (unsigned short) (SplatBits & 0xffff);
1630 else
1631 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman8181bd12008-07-27 21:46:04 +00001632 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1633 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001634 for (int i = 0; i < 8; ++i) Ops[i] = T;
1635 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1636 }
1637 case MVT::v4i32: {
1638 unsigned int Value = SplatBits;
Dan Gohman8181bd12008-07-27 21:46:04 +00001639 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel8efdca42007-12-04 22:23:35 +00001640 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1641 }
1642 case MVT::v2i64: {
1643 uint64_t val = SplatBits;
1644 uint32_t upper = uint32_t(val >> 32);
1645 uint32_t lower = uint32_t(val);
1646
Scott Michelbcc7b672008-03-06 04:02:54 +00001647 if (upper == lower) {
1648 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman8181bd12008-07-27 21:46:04 +00001649 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michelbcc7b672008-03-06 04:02:54 +00001650 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michel6baba072008-03-05 23:02:02 +00001651 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +00001652 SDValue LO32;
1653 SDValue HI32;
1654 SmallVector<SDValue, 16> ShufBytes;
1655 SDValue Result;
Scott Michel8efdca42007-12-04 22:23:35 +00001656 bool upper_special, lower_special;
1657
1658 // NOTE: This code creates common-case shuffle masks that can be easily
1659 // detected as common expressions. It is not attempting to create highly
1660 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1661
1662 // Detect if the upper or lower half is a special shuffle mask pattern:
Scott Michelc630c412008-11-24 17:11:17 +00001663 upper_special = (upper == 0||upper == 0xffffffff||upper == 0x80000000);
1664 lower_special = (lower == 0||lower == 0xffffffff||lower == 0x80000000);
Scott Michel8efdca42007-12-04 22:23:35 +00001665
1666 // Create lower vector if not a special pattern
1667 if (!lower_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001668 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001669 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1670 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1671 LO32C, LO32C, LO32C, LO32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001672 }
1673
1674 // Create upper vector if not a special pattern
1675 if (!upper_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001676 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001677 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1678 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1679 HI32C, HI32C, HI32C, HI32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001680 }
1681
1682 // If either upper or lower are special, then the two input operands are
1683 // the same (basically, one of them is a "don't care")
1684 if (lower_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001685 LO32 = HI32;
Scott Michel8efdca42007-12-04 22:23:35 +00001686 if (upper_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001687 HI32 = LO32;
Scott Michel8efdca42007-12-04 22:23:35 +00001688 if (lower_special && upper_special) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001689 // Unhappy situation... both upper and lower are special, so punt with
1690 // a target constant:
Dan Gohman8181bd12008-07-27 21:46:04 +00001691 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001692 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel8efdca42007-12-04 22:23:35 +00001693 Zero, Zero);
1694 }
1695
1696 for (int i = 0; i < 4; ++i) {
Scott Michel67224b22008-06-02 22:18:03 +00001697 uint64_t val = 0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001698 for (int j = 0; j < 4; ++j) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001699 SDValue V;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001700 bool process_upper, process_lower;
Scott Michel67224b22008-06-02 22:18:03 +00001701 val <<= 8;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001702 process_upper = (upper_special && (i & 1) == 0);
1703 process_lower = (lower_special && (i & 1) == 1);
Scott Michel8efdca42007-12-04 22:23:35 +00001704
Scott Michel5a6f17b2008-01-30 02:55:46 +00001705 if (process_upper || process_lower) {
1706 if ((process_upper && upper == 0)
1707 || (process_lower && lower == 0))
Scott Michel67224b22008-06-02 22:18:03 +00001708 val |= 0x80;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001709 else if ((process_upper && upper == 0xffffffff)
1710 || (process_lower && lower == 0xffffffff))
Scott Michel67224b22008-06-02 22:18:03 +00001711 val |= 0xc0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001712 else if ((process_upper && upper == 0x80000000)
1713 || (process_lower && lower == 0x80000000))
Scott Michel67224b22008-06-02 22:18:03 +00001714 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001715 } else
Scott Michel67224b22008-06-02 22:18:03 +00001716 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001717 }
Scott Michel67224b22008-06-02 22:18:03 +00001718
1719 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001720 }
1721
1722 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel67224b22008-06-02 22:18:03 +00001723 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001724 &ShufBytes[0], ShufBytes.size()));
Scott Michel8efdca42007-12-04 22:23:35 +00001725 }
1726 }
1727 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001728
Dan Gohman8181bd12008-07-27 21:46:04 +00001729 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001730}
1731
1732/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1733/// which the Cell can operate. The code inspects V3 to ascertain whether the
1734/// permutation vector, V3, is monotonically increasing with one "exception"
1735/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel56a125e2008-11-22 23:50:42 +00001736/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel8efdca42007-12-04 22:23:35 +00001737/// In either case, the net result is going to eventually invoke SHUFB to
1738/// permute/shuffle the bytes from V1 and V2.
1739/// \note
Scott Michel56a125e2008-11-22 23:50:42 +00001740/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel8efdca42007-12-04 22:23:35 +00001741/// control word for byte/halfword/word insertion. This takes care of a single
1742/// element move from V2 into V1.
1743/// \note
1744/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman8181bd12008-07-27 21:46:04 +00001745static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1746 SDValue V1 = Op.getOperand(0);
1747 SDValue V2 = Op.getOperand(1);
1748 SDValue PermMask = Op.getOperand(2);
Scott Michel4ec722e2008-07-16 17:17:29 +00001749
Scott Michel8efdca42007-12-04 22:23:35 +00001750 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel4ec722e2008-07-16 17:17:29 +00001751
Scott Michel8efdca42007-12-04 22:23:35 +00001752 // If we have a single element being moved from V1 to V2, this can be handled
1753 // using the C*[DX] compute mask instructions, but the vector elements have
1754 // to be monotonically increasing with one exception element.
Scott Michele2641a12008-12-04 21:01:44 +00001755 MVT VecVT = V1.getValueType();
1756 MVT EltVT = VecVT.getVectorElementType();
Scott Michel8efdca42007-12-04 22:23:35 +00001757 unsigned EltsFromV2 = 0;
1758 unsigned V2Elt = 0;
1759 unsigned V2EltIdx0 = 0;
1760 unsigned CurrElt = 0;
Scott Michele2641a12008-12-04 21:01:44 +00001761 unsigned MaxElts = VecVT.getVectorNumElements();
1762 unsigned PrevElt = 0;
1763 unsigned V0Elt = 0;
Scott Michel8efdca42007-12-04 22:23:35 +00001764 bool monotonic = true;
Scott Michele2641a12008-12-04 21:01:44 +00001765 bool rotate = true;
1766
1767 if (EltVT == MVT::i8) {
Scott Michel8efdca42007-12-04 22:23:35 +00001768 V2EltIdx0 = 16;
Scott Michele2641a12008-12-04 21:01:44 +00001769 } else if (EltVT == MVT::i16) {
Scott Michel8efdca42007-12-04 22:23:35 +00001770 V2EltIdx0 = 8;
Scott Michele2641a12008-12-04 21:01:44 +00001771 } else if (EltVT == MVT::i32 || EltVT == MVT::f32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001772 V2EltIdx0 = 4;
Scott Michele2641a12008-12-04 21:01:44 +00001773 } else if (EltVT == MVT::i64 || EltVT == MVT::f64) {
1774 V2EltIdx0 = 2;
1775 } else
Scott Michel8efdca42007-12-04 22:23:35 +00001776 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1777
Scott Michele2641a12008-12-04 21:01:44 +00001778 for (unsigned i = 0; i != PermMask.getNumOperands(); ++i) {
1779 if (PermMask.getOperand(i).getOpcode() != ISD::UNDEF) {
1780 unsigned SrcElt = cast<ConstantSDNode > (PermMask.getOperand(i))->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001781
Scott Michele2641a12008-12-04 21:01:44 +00001782 if (monotonic) {
1783 if (SrcElt >= V2EltIdx0) {
1784 if (1 >= (++EltsFromV2)) {
1785 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1786 }
1787 } else if (CurrElt != SrcElt) {
1788 monotonic = false;
1789 }
1790
1791 ++CurrElt;
1792 }
1793
1794 if (rotate) {
1795 if (PrevElt > 0 && SrcElt < MaxElts) {
1796 if ((PrevElt == SrcElt - 1)
1797 || (PrevElt == MaxElts - 1 && SrcElt == 0)) {
1798 PrevElt = SrcElt;
1799 if (SrcElt == 0)
1800 V0Elt = i;
1801 } else {
1802 rotate = false;
1803 }
1804 } else if (PrevElt == 0) {
1805 // First time through, need to keep track of previous element
1806 PrevElt = SrcElt;
1807 } else {
1808 // This isn't a rotation, takes elements from vector 2
1809 rotate = false;
1810 }
1811 }
Scott Michel8efdca42007-12-04 22:23:35 +00001812 }
Scott Michel8efdca42007-12-04 22:23:35 +00001813 }
1814
1815 if (EltsFromV2 == 1 && monotonic) {
1816 // Compute mask and shuffle
1817 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001818 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1819 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands92c43912008-06-06 12:08:01 +00001820 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00001821 // Initialize temporary register to 0
Dan Gohman8181bd12008-07-27 21:46:04 +00001822 SDValue InitTempReg =
Scott Michel8efdca42007-12-04 22:23:35 +00001823 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel56a125e2008-11-22 23:50:42 +00001824 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman8181bd12008-07-27 21:46:04 +00001825 SDValue ShufMaskOp =
Scott Michel0718cd82008-12-01 17:56:02 +00001826 DAG.getNode(SPUISD::SHUFFLE_MASK, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001827 DAG.getTargetConstant(V2Elt, MVT::i32),
1828 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +00001829 // Use shuffle mask in SHUFB synthetic instruction:
1830 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
Scott Michele2641a12008-12-04 21:01:44 +00001831 } else if (rotate) {
1832 int rotamt = (MaxElts - V0Elt) * EltVT.getSizeInBits()/8;
Scott Michelae5cbf52008-12-29 03:23:36 +00001833
Scott Michele2641a12008-12-04 21:01:44 +00001834 return DAG.getNode(SPUISD::ROTBYTES_LEFT, V1.getValueType(),
1835 V1, DAG.getConstant(rotamt, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001836 } else {
Gabor Greife9f7f582008-08-31 15:37:04 +00001837 // Convert the SHUFFLE_VECTOR mask's input element units to the
1838 // actual bytes.
Duncan Sands92c43912008-06-06 12:08:01 +00001839 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel4ec722e2008-07-16 17:17:29 +00001840
Dan Gohman8181bd12008-07-27 21:46:04 +00001841 SmallVector<SDValue, 16> ResultMask;
Scott Michel8efdca42007-12-04 22:23:35 +00001842 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1843 unsigned SrcElt;
1844 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001845 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001846 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001847 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel4ec722e2008-07-16 17:17:29 +00001848
Scott Michel97872d32008-02-23 18:41:37 +00001849 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001850 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1851 MVT::i8));
Scott Michel8efdca42007-12-04 22:23:35 +00001852 }
1853 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001854
Dan Gohman8181bd12008-07-27 21:46:04 +00001855 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel0718cd82008-12-01 17:56:02 +00001856 &ResultMask[0], ResultMask.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001857 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1858 }
1859}
1860
Dan Gohman8181bd12008-07-27 21:46:04 +00001861static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1862 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel8efdca42007-12-04 22:23:35 +00001863
Gabor Greif1c80d112008-08-28 21:40:38 +00001864 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel8efdca42007-12-04 22:23:35 +00001865 // For a constant, build the appropriate constant vector, which will
1866 // eventually simplify to a vector register load.
1867
Gabor Greif1c80d112008-08-28 21:40:38 +00001868 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman8181bd12008-07-27 21:46:04 +00001869 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands92c43912008-06-06 12:08:01 +00001870 MVT VT;
Scott Michel8efdca42007-12-04 22:23:35 +00001871 size_t n_copies;
1872
1873 // Create a constant vector:
Duncan Sands92c43912008-06-06 12:08:01 +00001874 switch (Op.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001875 default: assert(0 && "Unexpected constant value type in "
Scott Michel5a6f17b2008-01-30 02:55:46 +00001876 "LowerSCALAR_TO_VECTOR");
Scott Michel8efdca42007-12-04 22:23:35 +00001877 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1878 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1879 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1880 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1881 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1882 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1883 }
1884
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001885 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel8efdca42007-12-04 22:23:35 +00001886 for (size_t j = 0; j < n_copies; ++j)
1887 ConstVecValues.push_back(CValue);
1888
1889 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001890 &ConstVecValues[0], ConstVecValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001891 } else {
1892 // Otherwise, copy the value from one register to another:
Duncan Sands92c43912008-06-06 12:08:01 +00001893 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001894 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1895 case MVT::i8:
1896 case MVT::i16:
1897 case MVT::i32:
1898 case MVT::i64:
1899 case MVT::f32:
1900 case MVT::f64:
Scott Michel06eabde2008-12-27 04:51:36 +00001901 return DAG.getNode(SPUISD::PREFSLOT2VEC, Op.getValueType(), Op0, Op0);
Scott Michel8efdca42007-12-04 22:23:35 +00001902 }
1903 }
1904
Dan Gohman8181bd12008-07-27 21:46:04 +00001905 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001906}
1907
Dan Gohman8181bd12008-07-27 21:46:04 +00001908static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001909 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001910 SDValue N = Op.getOperand(0);
1911 SDValue Elt = Op.getOperand(1);
Scott Michel56a125e2008-11-22 23:50:42 +00001912 SDValue retval;
Scott Michel8efdca42007-12-04 22:23:35 +00001913
Scott Michel56a125e2008-11-22 23:50:42 +00001914 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
1915 // Constant argument:
1916 int EltNo = (int) C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001917
Scott Michel56a125e2008-11-22 23:50:42 +00001918 // sanity checks:
1919 if (VT == MVT::i8 && EltNo >= 16)
1920 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
1921 else if (VT == MVT::i16 && EltNo >= 8)
1922 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
1923 else if (VT == MVT::i32 && EltNo >= 4)
1924 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
1925 else if (VT == MVT::i64 && EltNo >= 2)
1926 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel8efdca42007-12-04 22:23:35 +00001927
Scott Michel56a125e2008-11-22 23:50:42 +00001928 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
1929 // i32 and i64: Element 0 is the preferred slot
Scott Michelc630c412008-11-24 17:11:17 +00001930 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel56a125e2008-11-22 23:50:42 +00001931 }
Scott Michel8efdca42007-12-04 22:23:35 +00001932
Scott Michel56a125e2008-11-22 23:50:42 +00001933 // Need to generate shuffle mask and extract:
1934 int prefslot_begin = -1, prefslot_end = -1;
1935 int elt_byte = EltNo * VT.getSizeInBits() / 8;
1936
1937 switch (VT.getSimpleVT()) {
1938 default:
1939 assert(false && "Invalid value type!");
1940 case MVT::i8: {
1941 prefslot_begin = prefslot_end = 3;
1942 break;
1943 }
1944 case MVT::i16: {
1945 prefslot_begin = 2; prefslot_end = 3;
1946 break;
1947 }
1948 case MVT::i32:
1949 case MVT::f32: {
1950 prefslot_begin = 0; prefslot_end = 3;
1951 break;
1952 }
1953 case MVT::i64:
1954 case MVT::f64: {
1955 prefslot_begin = 0; prefslot_end = 7;
1956 break;
1957 }
1958 }
1959
1960 assert(prefslot_begin != -1 && prefslot_end != -1 &&
1961 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
1962
1963 unsigned int ShufBytes[16];
1964 for (int i = 0; i < 16; ++i) {
1965 // zero fill uppper part of preferred slot, don't care about the
1966 // other slots:
1967 unsigned int mask_val;
1968 if (i <= prefslot_end) {
1969 mask_val =
1970 ((i < prefslot_begin)
1971 ? 0x80
1972 : elt_byte + (i - prefslot_begin));
1973
1974 ShufBytes[i] = mask_val;
1975 } else
1976 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
1977 }
1978
1979 SDValue ShufMask[4];
1980 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
Scott Michele2641a12008-12-04 21:01:44 +00001981 unsigned bidx = i * 4;
Scott Michel56a125e2008-11-22 23:50:42 +00001982 unsigned int bits = ((ShufBytes[bidx] << 24) |
1983 (ShufBytes[bidx+1] << 16) |
1984 (ShufBytes[bidx+2] << 8) |
1985 ShufBytes[bidx+3]);
1986 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
1987 }
1988
1989 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1990 &ShufMask[0],
1991 sizeof(ShufMask) / sizeof(ShufMask[0]));
1992
Scott Michelc630c412008-11-24 17:11:17 +00001993 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel56a125e2008-11-22 23:50:42 +00001994 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
1995 N, N, ShufMaskVec));
1996 } else {
1997 // Variable index: Rotate the requested element into slot 0, then replicate
1998 // slot 0 across the vector
1999 MVT VecVT = N.getValueType();
2000 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2001 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2002 abort();
2003 }
2004
2005 // Make life easier by making sure the index is zero-extended to i32
2006 if (Elt.getValueType() != MVT::i32)
2007 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2008
2009 // Scale the index to a bit/byte shift quantity
2010 APInt scaleFactor =
Scott Michelc630c412008-11-24 17:11:17 +00002011 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2012 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel56a125e2008-11-22 23:50:42 +00002013 SDValue vecShift;
Scott Michel56a125e2008-11-22 23:50:42 +00002014
Scott Michelc630c412008-11-24 17:11:17 +00002015 if (scaleShift > 0) {
2016 // Scale the shift factor:
Scott Michel56a125e2008-11-22 23:50:42 +00002017 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel0718cd82008-12-01 17:56:02 +00002018 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel56a125e2008-11-22 23:50:42 +00002019 }
2020
Scott Michelc630c412008-11-24 17:11:17 +00002021 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2022
2023 // Replicate the bytes starting at byte 0 across the entire vector (for
2024 // consistency with the notion of a unified register set)
Scott Michel56a125e2008-11-22 23:50:42 +00002025 SDValue replicate;
2026
2027 switch (VT.getSimpleVT()) {
2028 default:
2029 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2030 abort();
2031 /*NOTREACHED*/
2032 case MVT::i8: {
Scott Michelc630c412008-11-24 17:11:17 +00002033 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002034 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2035 factor, factor);
2036 break;
2037 }
2038 case MVT::i16: {
Scott Michelc630c412008-11-24 17:11:17 +00002039 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002040 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2041 factor, factor);
2042 break;
2043 }
2044 case MVT::i32:
2045 case MVT::f32: {
2046 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2047 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2048 factor, factor);
2049 break;
2050 }
2051 case MVT::i64:
2052 case MVT::f64: {
2053 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2054 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2055 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2056 loFactor, hiFactor);
2057 break;
2058 }
2059 }
2060
Scott Michelc630c412008-11-24 17:11:17 +00002061 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel0718cd82008-12-01 17:56:02 +00002062 DAG.getNode(SPUISD::SHUFB, VecVT,
2063 vecShift, vecShift, replicate));
Scott Michel8efdca42007-12-04 22:23:35 +00002064 }
2065
Scott Michel56a125e2008-11-22 23:50:42 +00002066 return retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002067}
2068
Dan Gohman8181bd12008-07-27 21:46:04 +00002069static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2070 SDValue VecOp = Op.getOperand(0);
2071 SDValue ValOp = Op.getOperand(1);
2072 SDValue IdxOp = Op.getOperand(2);
Duncan Sands92c43912008-06-06 12:08:01 +00002073 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002074
2075 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2076 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2077
Duncan Sands92c43912008-06-06 12:08:01 +00002078 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel0718cd82008-12-01 17:56:02 +00002079 // Use $sp ($1) because it's always 16-byte aligned and it's available:
2080 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
2081 DAG.getRegister(SPU::R1, PtrVT),
2082 DAG.getConstant(CN->getSExtValue(), PtrVT));
2083 SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, VT, Pointer);
Scott Michel8efdca42007-12-04 22:23:35 +00002084
Dan Gohman8181bd12008-07-27 21:46:04 +00002085 SDValue result =
Scott Michel8efdca42007-12-04 22:23:35 +00002086 DAG.getNode(SPUISD::SHUFB, VT,
2087 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
Scott Michelae5cbf52008-12-29 03:23:36 +00002088 VecOp,
Scott Michel0718cd82008-12-01 17:56:02 +00002089 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, ShufMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002090
2091 return result;
2092}
2093
Scott Michel06eabde2008-12-27 04:51:36 +00002094static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc,
2095 const TargetLowering &TLI)
Scott Michel97872d32008-02-23 18:41:37 +00002096{
Dan Gohman8181bd12008-07-27 21:46:04 +00002097 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel06eabde2008-12-27 04:51:36 +00002098 MVT ShiftVT = TLI.getShiftAmountTy();
Scott Michel8efdca42007-12-04 22:23:35 +00002099
2100 assert(Op.getValueType() == MVT::i8);
2101 switch (Opc) {
2102 default:
2103 assert(0 && "Unhandled i8 math operator");
2104 /*NOTREACHED*/
2105 break;
Scott Michel4d07fb72008-12-30 23:28:25 +00002106 case ISD::ADD: {
2107 // 8-bit addition: Promote the arguments up to 16-bits and truncate
2108 // the result:
2109 SDValue N1 = Op.getOperand(1);
2110 N0 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0);
2111 N1 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1);
2112 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
2113 DAG.getNode(Opc, MVT::i16, N0, N1));
2114
2115 }
2116
Scott Michel8efdca42007-12-04 22:23:35 +00002117 case ISD::SUB: {
2118 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2119 // the result:
Dan Gohman8181bd12008-07-27 21:46:04 +00002120 SDValue N1 = Op.getOperand(1);
Scott Michel4d07fb72008-12-30 23:28:25 +00002121 N0 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0);
2122 N1 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1);
Scott Michel4ec722e2008-07-16 17:17:29 +00002123 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002124 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel4ec722e2008-07-16 17:17:29 +00002125 }
Scott Michel8efdca42007-12-04 22:23:35 +00002126 case ISD::ROTR:
2127 case ISD::ROTL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002128 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002129 unsigned N1Opc;
2130 N0 = (N0.getOpcode() != ISD::Constant
2131 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002132 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2133 MVT::i16));
Scott Michel06eabde2008-12-27 04:51:36 +00002134 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greife9f7f582008-08-31 15:37:04 +00002135 ? ISD::ZERO_EXTEND
2136 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002137 N1 = (N1.getOpcode() != ISD::Constant
Scott Michel06eabde2008-12-27 04:51:36 +00002138 ? DAG.getNode(N1Opc, ShiftVT, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002139 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Scott Michel06eabde2008-12-27 04:51:36 +00002140 TLI.getShiftAmountTy()));
Dan Gohman8181bd12008-07-27 21:46:04 +00002141 SDValue ExpandArg =
Scott Michel8efdca42007-12-04 22:23:35 +00002142 DAG.getNode(ISD::OR, MVT::i16, N0,
2143 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sands7aef60d2008-10-30 19:24:28 +00002144 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002145 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002146 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2147 }
2148 case ISD::SRL:
2149 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002150 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002151 unsigned N1Opc;
2152 N0 = (N0.getOpcode() != ISD::Constant
2153 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002154 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
Scott Michel06eabde2008-12-27 04:51:36 +00002155 MVT::i32));
2156 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greife9f7f582008-08-31 15:37:04 +00002157 ? ISD::ZERO_EXTEND
2158 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002159 N1 = (N1.getOpcode() != ISD::Constant
Scott Michel06eabde2008-12-27 04:51:36 +00002160 ? DAG.getNode(N1Opc, ShiftVT, N1)
2161 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(), ShiftVT));
Scott Michel4ec722e2008-07-16 17:17:29 +00002162 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002163 DAG.getNode(Opc, MVT::i16, N0, N1));
2164 }
2165 case ISD::SRA: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002166 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002167 unsigned N1Opc;
2168 N0 = (N0.getOpcode() != ISD::Constant
2169 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Scott Michel06eabde2008-12-27 04:51:36 +00002170 : DAG.getConstant(cast<ConstantSDNode>(N0)->getSExtValue(),
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002171 MVT::i16));
Scott Michel06eabde2008-12-27 04:51:36 +00002172 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greife9f7f582008-08-31 15:37:04 +00002173 ? ISD::SIGN_EXTEND
2174 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002175 N1 = (N1.getOpcode() != ISD::Constant
Scott Michel06eabde2008-12-27 04:51:36 +00002176 ? DAG.getNode(N1Opc, ShiftVT, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002177 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Scott Michel06eabde2008-12-27 04:51:36 +00002178 ShiftVT));
Scott Michel4ec722e2008-07-16 17:17:29 +00002179 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002180 DAG.getNode(Opc, MVT::i16, N0, N1));
2181 }
2182 case ISD::MUL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002183 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002184 unsigned N1Opc;
2185 N0 = (N0.getOpcode() != ISD::Constant
2186 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002187 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2188 MVT::i16));
Duncan Sandsec142ee2008-06-08 20:54:56 +00002189 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002190 N1 = (N1.getOpcode() != ISD::Constant
2191 ? DAG.getNode(N1Opc, MVT::i16, N1)
Scott Michel06eabde2008-12-27 04:51:36 +00002192 : DAG.getConstant(cast<ConstantSDNode>(N1)->getSExtValue(),
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002193 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002194 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002195 DAG.getNode(Opc, MVT::i16, N0, N1));
2196 break;
2197 }
2198 }
2199
Dan Gohman8181bd12008-07-27 21:46:04 +00002200 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002201}
2202
Dan Gohman8181bd12008-07-27 21:46:04 +00002203static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002204{
Duncan Sands92c43912008-06-06 12:08:01 +00002205 MVT VT = Op.getValueType();
2206 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002207
Dan Gohman8181bd12008-07-27 21:46:04 +00002208 SDValue Op0 = Op.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002209
2210 switch (Opc) {
2211 case ISD::ZERO_EXTEND:
Scott Michel97872d32008-02-23 18:41:37 +00002212 case ISD::ANY_EXTEND: {
Duncan Sands92c43912008-06-06 12:08:01 +00002213 MVT Op0VT = Op0.getValueType();
2214 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002215
2216 assert(Op0VT == MVT::i32
2217 && "CellSPU: Zero/sign extending something other than i32");
2218
Scott Michelc630c412008-11-24 17:11:17 +00002219 DEBUG(cerr << "CellSPU.LowerI64Math: lowering zero/sign/any extend\n");
2220
Dan Gohman8181bd12008-07-27 21:46:04 +00002221 SDValue PromoteScalar =
Scott Michel06eabde2008-12-27 04:51:36 +00002222 DAG.getNode(SPUISD::PREFSLOT2VEC, Op0VecVT, Op0);
Scott Michel97872d32008-02-23 18:41:37 +00002223
Scott Michel4d07fb72008-12-30 23:28:25 +00002224 // Use a shuffle to zero extend the i32 to i64 directly:
2225 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, Op0VecVT,
2226 DAG.getConstant(0x80808080, MVT::i32), DAG.getConstant(0x00010203,
2227 MVT::i32), DAG.getConstant(0x80808080, MVT::i32), DAG.getConstant(
2228 0x08090a0b, MVT::i32));
2229 SDValue zextShuffle = DAG.getNode(SPUISD::SHUFB, Op0VecVT, PromoteScalar,
2230 PromoteScalar, shufMask);
Scott Michelf2df6cb2008-11-24 18:20:46 +00002231
Scott Michel4d07fb72008-12-30 23:28:25 +00002232 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, DAG.getNode(ISD::BIT_CONVERT,
2233 VecVT, zextShuffle));
Scott Michel97872d32008-02-23 18:41:37 +00002234 }
2235
Scott Michel67224b22008-06-02 22:18:03 +00002236 case ISD::ADD: {
2237 // Turn operands into vectors to satisfy type checking (shufb works on
2238 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002239 SDValue Op0 =
Scott Michel06eabde2008-12-27 04:51:36 +00002240 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002241 SDValue Op1 =
Scott Michel06eabde2008-12-27 04:51:36 +00002242 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002243 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002244
2245 // Create the shuffle mask for "rotating" the borrow up one register slot
2246 // once the borrow is generated.
2247 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2248 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2249 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2250 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2251
Dan Gohman8181bd12008-07-27 21:46:04 +00002252 SDValue CarryGen =
Scott Michel67224b22008-06-02 22:18:03 +00002253 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002254 SDValue ShiftedCarry =
Scott Michel67224b22008-06-02 22:18:03 +00002255 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2256 CarryGen, CarryGen,
2257 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2258 &ShufBytes[0], ShufBytes.size()));
2259
Scott Michelc630c412008-11-24 17:11:17 +00002260 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002261 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2262 Op0, Op1, ShiftedCarry));
2263 }
2264
2265 case ISD::SUB: {
2266 // Turn operands into vectors to satisfy type checking (shufb works on
2267 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002268 SDValue Op0 =
Scott Michel06eabde2008-12-27 04:51:36 +00002269 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002270 SDValue Op1 =
Scott Michel06eabde2008-12-27 04:51:36 +00002271 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002272 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002273
2274 // Create the shuffle mask for "rotating" the borrow up one register slot
2275 // once the borrow is generated.
2276 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2277 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2278 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2279 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2280
Dan Gohman8181bd12008-07-27 21:46:04 +00002281 SDValue BorrowGen =
Scott Michel67224b22008-06-02 22:18:03 +00002282 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002283 SDValue ShiftedBorrow =
Scott Michel67224b22008-06-02 22:18:03 +00002284 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2285 BorrowGen, BorrowGen,
2286 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2287 &ShufBytes[0], ShufBytes.size()));
2288
Scott Michelc630c412008-11-24 17:11:17 +00002289 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002290 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2291 Op0, Op1, ShiftedBorrow));
2292 }
Scott Michel97872d32008-02-23 18:41:37 +00002293 }
2294
Dan Gohman8181bd12008-07-27 21:46:04 +00002295 return SDValue();
Scott Michel97872d32008-02-23 18:41:37 +00002296}
2297
Scott Michel8efdca42007-12-04 22:23:35 +00002298//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman8181bd12008-07-27 21:46:04 +00002299static SDValue
2300LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2301 SDValue ConstVec;
2302 SDValue Arg;
Duncan Sands92c43912008-06-06 12:08:01 +00002303 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002304
2305 ConstVec = Op.getOperand(0);
2306 Arg = Op.getOperand(1);
Gabor Greif1c80d112008-08-28 21:40:38 +00002307 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2308 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel8efdca42007-12-04 22:23:35 +00002309 ConstVec = ConstVec.getOperand(0);
2310 } else {
2311 ConstVec = Op.getOperand(1);
2312 Arg = Op.getOperand(0);
Gabor Greif1c80d112008-08-28 21:40:38 +00002313 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00002314 ConstVec = ConstVec.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00002315 }
2316 }
2317 }
2318
Gabor Greif1c80d112008-08-28 21:40:38 +00002319 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel8efdca42007-12-04 22:23:35 +00002320 uint64_t VectorBits[2];
2321 uint64_t UndefBits[2];
2322 uint64_t SplatBits, SplatUndef;
2323 int SplatSize;
2324
Gabor Greif1c80d112008-08-28 21:40:38 +00002325 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002326 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00002327 VT.getVectorElementType().getSizeInBits(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002328 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002329 SDValue tcVec[16];
2330 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel8efdca42007-12-04 22:23:35 +00002331 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2332
2333 // Turn the BUILD_VECTOR into a set of target constants:
2334 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002335 tcVec[i] = tc;
Scott Michel8efdca42007-12-04 22:23:35 +00002336
Gabor Greif1c80d112008-08-28 21:40:38 +00002337 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002338 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel8efdca42007-12-04 22:23:35 +00002339 }
2340 }
Nate Begeman7569e762008-07-29 19:07:27 +00002341 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2342 // lowered. Return the operation, rather than a null SDValue.
2343 return Op;
Scott Michel8efdca42007-12-04 22:23:35 +00002344}
2345
Scott Michel8efdca42007-12-04 22:23:35 +00002346//! Custom lowering for CTPOP (count population)
2347/*!
2348 Custom lowering code that counts the number ones in the input
2349 operand. SPU has such an instruction, but it counts the number of
2350 ones per byte, which then have to be accumulated.
2351*/
Dan Gohman8181bd12008-07-27 21:46:04 +00002352static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002353 MVT VT = Op.getValueType();
2354 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +00002355
Duncan Sands92c43912008-06-06 12:08:01 +00002356 switch (VT.getSimpleVT()) {
2357 default:
2358 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002359 case MVT::i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002360 SDValue N = Op.getOperand(0);
2361 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002362
Scott Michel06eabde2008-12-27 04:51:36 +00002363 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman8181bd12008-07-27 21:46:04 +00002364 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002365
2366 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2367 }
2368
2369 case MVT::i16: {
2370 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002371 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002372
Chris Lattner1b989192007-12-31 04:13:23 +00002373 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002374
Dan Gohman8181bd12008-07-27 21:46:04 +00002375 SDValue N = Op.getOperand(0);
2376 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2377 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sands7aef60d2008-10-30 19:24:28 +00002378 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002379
Scott Michel06eabde2008-12-27 04:51:36 +00002380 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman8181bd12008-07-27 21:46:04 +00002381 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002382
2383 // CNTB_result becomes the chain to which all of the virtual registers
2384 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002385 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002386 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002387
Dan Gohman8181bd12008-07-27 21:46:04 +00002388 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002389 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2390
Dan Gohman8181bd12008-07-27 21:46:04 +00002391 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002392
2393 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002394 DAG.getNode(ISD::ADD, MVT::i16,
2395 DAG.getNode(ISD::SRL, MVT::i16,
2396 Tmp1, Shift1),
2397 Tmp1),
2398 Mask0);
Scott Michel8efdca42007-12-04 22:23:35 +00002399 }
2400
2401 case MVT::i32: {
2402 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002403 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002404
Chris Lattner1b989192007-12-31 04:13:23 +00002405 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2406 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002407
Dan Gohman8181bd12008-07-27 21:46:04 +00002408 SDValue N = Op.getOperand(0);
2409 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2410 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2411 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2412 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002413
Scott Michel06eabde2008-12-27 04:51:36 +00002414 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman8181bd12008-07-27 21:46:04 +00002415 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002416
2417 // CNTB_result becomes the chain to which all of the virtual registers
2418 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002419 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002420 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002421
Dan Gohman8181bd12008-07-27 21:46:04 +00002422 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002423 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2424
Dan Gohman8181bd12008-07-27 21:46:04 +00002425 SDValue Comp1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002426 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002427 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel8efdca42007-12-04 22:23:35 +00002428
Dan Gohman8181bd12008-07-27 21:46:04 +00002429 SDValue Sum1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002430 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002431 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002432
Dan Gohman8181bd12008-07-27 21:46:04 +00002433 SDValue Sum1_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002434 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2435
Dan Gohman8181bd12008-07-27 21:46:04 +00002436 SDValue Comp2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002437 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002438 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2439 Shift2);
Dan Gohman8181bd12008-07-27 21:46:04 +00002440 SDValue Sum2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002441 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002442 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002443
2444 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2445 }
2446
2447 case MVT::i64:
2448 break;
2449 }
2450
Dan Gohman8181bd12008-07-27 21:46:04 +00002451 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002452}
2453
Scott Michel06eabde2008-12-27 04:51:36 +00002454//! Lower ISD::SETCC
2455/*!
2456 Lower i64 condition code handling.
2457 */
2458
2459static SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) {
2460 MVT VT = Op.getValueType();
2461 SDValue lhs = Op.getOperand(0);
2462 SDValue rhs = Op.getOperand(1);
2463 SDValue condition = Op.getOperand(2);
2464
2465 if (VT == MVT::i32 && lhs.getValueType() == MVT::i64) {
2466 // Expand the i64 comparisons to what Cell can actually support,
2467 // which is eq, ugt and sgt:
2468#if 0
2469 CondCodeSDNode *ccvalue = dyn_cast<CondCodeSDValue>(condition);
2470
2471 switch (ccvalue->get()) {
2472 case
2473 }
2474#endif
2475 }
2476
2477 return SDValue();
2478}
2479
Scott Michel56a125e2008-11-22 23:50:42 +00002480//! Lower ISD::SELECT_CC
2481/*!
2482 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2483 SELB instruction.
2484
2485 \note Need to revisit this in the future: if the code path through the true
2486 and false value computations is longer than the latency of a branch (6
2487 cycles), then it would be more advantageous to branch and insert a new basic
2488 block and branch on the condition. However, this code does not make that
2489 assumption, given the simplisitc uses so far.
2490 */
2491
Scott Michel06eabde2008-12-27 04:51:36 +00002492static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
2493 const TargetLowering &TLI) {
Scott Michel56a125e2008-11-22 23:50:42 +00002494 MVT VT = Op.getValueType();
2495 SDValue lhs = Op.getOperand(0);
2496 SDValue rhs = Op.getOperand(1);
2497 SDValue trueval = Op.getOperand(2);
2498 SDValue falseval = Op.getOperand(3);
2499 SDValue condition = Op.getOperand(4);
2500
Scott Michel06eabde2008-12-27 04:51:36 +00002501 // NOTE: SELB's arguments: $rA, $rB, $mask
2502 //
2503 // SELB selects bits from $rA where bits in $mask are 0, bits from $rB
2504 // where bits in $mask are 1. CCond will be inverted, having 1s where the
2505 // condition was true and 0s where the condition was false. Hence, the
2506 // arguments to SELB get reversed.
2507
Scott Michel56a125e2008-11-22 23:50:42 +00002508 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2509 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2510 // with another "cannot select select_cc" assert:
2511
Duncan Sands4a361272009-01-01 15:52:00 +00002512 SDValue compare = DAG.getNode(ISD::SETCC,
2513 TLI.getSetCCResultType(Op.getValueType()),
Scott Michel06eabde2008-12-27 04:51:36 +00002514 lhs, rhs, condition);
2515 return DAG.getNode(SPUISD::SELB, VT, falseval, trueval, compare);
Scott Michel56a125e2008-11-22 23:50:42 +00002516}
2517
Scott Michelec8c82e2008-12-02 19:53:53 +00002518//! Custom lower ISD::TRUNCATE
2519static SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG)
2520{
2521 MVT VT = Op.getValueType();
2522 MVT::SimpleValueType simpleVT = VT.getSimpleVT();
2523 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
2524
2525 SDValue Op0 = Op.getOperand(0);
2526 MVT Op0VT = Op0.getValueType();
2527 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
2528
Scott Michelec8c82e2008-12-02 19:53:53 +00002529 // Create shuffle mask
Scott Michel06eabde2008-12-27 04:51:36 +00002530 if (Op0VT.getSimpleVT() == MVT::i128 && simpleVT == MVT::i64) {
2531 // least significant doubleword of quadword
2532 unsigned maskHigh = 0x08090a0b;
2533 unsigned maskLow = 0x0c0d0e0f;
2534 // Use a shuffle to perform the truncation
2535 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2536 DAG.getConstant(maskHigh, MVT::i32),
2537 DAG.getConstant(maskLow, MVT::i32),
2538 DAG.getConstant(maskHigh, MVT::i32),
2539 DAG.getConstant(maskLow, MVT::i32));
2540
2541
2542 SDValue PromoteScalar = DAG.getNode(SPUISD::PREFSLOT2VEC, Op0VecVT, Op0);
2543
2544 SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2545 PromoteScalar, PromoteScalar, shufMask);
2546
2547 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2548 DAG.getNode(ISD::BIT_CONVERT, VecVT, truncShuffle));
Scott Michelec8c82e2008-12-02 19:53:53 +00002549 }
2550
Scott Michel06eabde2008-12-27 04:51:36 +00002551 return SDValue(); // Leave the truncate unmolested
Scott Michelec8c82e2008-12-02 19:53:53 +00002552}
2553
Scott Michel56a125e2008-11-22 23:50:42 +00002554//! Custom (target-specific) lowering entry point
2555/*!
2556 This is where LLVM's DAG selection process calls to do target-specific
2557 lowering of nodes.
2558 */
Dan Gohman8181bd12008-07-27 21:46:04 +00002559SDValue
2560SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel8efdca42007-12-04 22:23:35 +00002561{
Scott Michel97872d32008-02-23 18:41:37 +00002562 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands92c43912008-06-06 12:08:01 +00002563 MVT VT = Op.getValueType();
Scott Michel97872d32008-02-23 18:41:37 +00002564
2565 switch (Opc) {
Scott Michel8efdca42007-12-04 22:23:35 +00002566 default: {
2567 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michel97872d32008-02-23 18:41:37 +00002568 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greif1c80d112008-08-28 21:40:38 +00002569 cerr << "*Op.getNode():\n";
2570 Op.getNode()->dump();
Scott Michel8efdca42007-12-04 22:23:35 +00002571 abort();
2572 }
2573 case ISD::LOAD:
Scott Michelec8c82e2008-12-02 19:53:53 +00002574 case ISD::EXTLOAD:
Scott Michel8efdca42007-12-04 22:23:35 +00002575 case ISD::SEXTLOAD:
2576 case ISD::ZEXTLOAD:
2577 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2578 case ISD::STORE:
2579 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2580 case ISD::ConstantPool:
2581 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2582 case ISD::GlobalAddress:
2583 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2584 case ISD::JumpTable:
2585 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2586 case ISD::Constant:
2587 return LowerConstant(Op, DAG);
2588 case ISD::ConstantFP:
2589 return LowerConstantFP(Op, DAG);
Scott Michel394e26d2008-01-17 20:38:41 +00002590 case ISD::BRCOND:
Scott Michel06eabde2008-12-27 04:51:36 +00002591 return LowerBRCOND(Op, DAG, *this);
Scott Michel8efdca42007-12-04 22:23:35 +00002592 case ISD::FORMAL_ARGUMENTS:
Scott Michel394e26d2008-01-17 20:38:41 +00002593 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel8efdca42007-12-04 22:23:35 +00002594 case ISD::CALL:
Scott Micheldbac4cf2008-01-11 02:53:15 +00002595 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel8efdca42007-12-04 22:23:35 +00002596 case ISD::RET:
2597 return LowerRET(Op, DAG, getTargetMachine());
2598
Scott Michel97872d32008-02-23 18:41:37 +00002599
Scott Michel97872d32008-02-23 18:41:37 +00002600 case ISD::ZERO_EXTEND:
Scott Michel97872d32008-02-23 18:41:37 +00002601 case ISD::ANY_EXTEND:
Scott Michel4d07fb72008-12-30 23:28:25 +00002602 return LowerI64Math(Op, DAG, Opc);
2603
2604 // i8, i64 math ops:
Scott Michel67224b22008-06-02 22:18:03 +00002605 case ISD::ADD:
Scott Michel8efdca42007-12-04 22:23:35 +00002606 case ISD::SUB:
2607 case ISD::ROTR:
2608 case ISD::ROTL:
2609 case ISD::SRL:
2610 case ISD::SHL:
Scott Michel67224b22008-06-02 22:18:03 +00002611 case ISD::SRA: {
Scott Michel97872d32008-02-23 18:41:37 +00002612 if (VT == MVT::i8)
Scott Michel06eabde2008-12-27 04:51:36 +00002613 return LowerI8Math(Op, DAG, Opc, *this);
Scott Michel97872d32008-02-23 18:41:37 +00002614 else if (VT == MVT::i64)
2615 return LowerI64Math(Op, DAG, Opc);
2616 break;
Scott Michel67224b22008-06-02 22:18:03 +00002617 }
Scott Michel8efdca42007-12-04 22:23:35 +00002618
2619 // Vector-related lowering.
2620 case ISD::BUILD_VECTOR:
2621 return LowerBUILD_VECTOR(Op, DAG);
2622 case ISD::SCALAR_TO_VECTOR:
2623 return LowerSCALAR_TO_VECTOR(Op, DAG);
2624 case ISD::VECTOR_SHUFFLE:
2625 return LowerVECTOR_SHUFFLE(Op, DAG);
2626 case ISD::EXTRACT_VECTOR_ELT:
2627 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2628 case ISD::INSERT_VECTOR_ELT:
2629 return LowerINSERT_VECTOR_ELT(Op, DAG);
2630
2631 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2632 case ISD::AND:
2633 case ISD::OR:
2634 case ISD::XOR:
2635 return LowerByteImmed(Op, DAG);
2636
2637 // Vector and i8 multiply:
2638 case ISD::MUL:
Scott Michel4d07fb72008-12-30 23:28:25 +00002639 if (VT == MVT::i8)
Scott Michel06eabde2008-12-27 04:51:36 +00002640 return LowerI8Math(Op, DAG, Opc, *this);
Scott Michel8efdca42007-12-04 22:23:35 +00002641
Scott Michel8efdca42007-12-04 22:23:35 +00002642 case ISD::CTPOP:
2643 return LowerCTPOP(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002644
2645 case ISD::SELECT_CC:
Scott Michel06eabde2008-12-27 04:51:36 +00002646 return LowerSELECT_CC(Op, DAG, *this);
Scott Michelec8c82e2008-12-02 19:53:53 +00002647
2648 case ISD::TRUNCATE:
2649 return LowerTRUNCATE(Op, DAG);
Scott Michel06eabde2008-12-27 04:51:36 +00002650
2651 case ISD::SETCC:
2652 return LowerSETCC(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002653 }
2654
Dan Gohman8181bd12008-07-27 21:46:04 +00002655 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002656}
2657
Duncan Sands7d9834b2008-12-01 11:39:25 +00002658void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
2659 SmallVectorImpl<SDValue>&Results,
2660 SelectionDAG &DAG)
Scott Michel6e2d68b2008-11-10 23:43:06 +00002661{
2662#if 0
2663 unsigned Opc = (unsigned) N->getOpcode();
2664 MVT OpVT = N->getValueType(0);
2665
2666 switch (Opc) {
2667 default: {
2668 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2669 cerr << "Op.getOpcode() = " << Opc << "\n";
2670 cerr << "*Op.getNode():\n";
2671 N->dump();
2672 abort();
2673 /*NOTREACHED*/
2674 }
2675 }
2676#endif
2677
2678 /* Otherwise, return unchanged */
Scott Michel6e2d68b2008-11-10 23:43:06 +00002679}
2680
Scott Michel8efdca42007-12-04 22:23:35 +00002681//===----------------------------------------------------------------------===//
Scott Michel8efdca42007-12-04 22:23:35 +00002682// Target Optimization Hooks
2683//===----------------------------------------------------------------------===//
2684
Dan Gohman8181bd12008-07-27 21:46:04 +00002685SDValue
Scott Michel8efdca42007-12-04 22:23:35 +00002686SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2687{
2688#if 0
2689 TargetMachine &TM = getTargetMachine();
Scott Michelf9f42e62008-01-29 02:16:57 +00002690#endif
2691 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel8efdca42007-12-04 22:23:35 +00002692 SelectionDAG &DAG = DCI.DAG;
Scott Michel0718cd82008-12-01 17:56:02 +00002693 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2694 MVT NodeVT = N->getValueType(0); // The node's value type
Scott Michel06eabde2008-12-27 04:51:36 +00002695 MVT Op0VT = Op0.getValueType(); // The first operand's result
Scott Michel0718cd82008-12-01 17:56:02 +00002696 SDValue Result; // Initially, empty result
Scott Michel8efdca42007-12-04 22:23:35 +00002697
2698 switch (N->getOpcode()) {
2699 default: break;
Scott Michelf9f42e62008-01-29 02:16:57 +00002700 case ISD::ADD: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002701 SDValue Op1 = N->getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002702
Scott Michel06eabde2008-12-27 04:51:36 +00002703 if (Op0.getOpcode() == SPUISD::IndirectAddr
2704 || Op1.getOpcode() == SPUISD::IndirectAddr) {
2705 // Normalize the operands to reduce repeated code
2706 SDValue IndirectArg = Op0, AddArg = Op1;
Scott Michelae5cbf52008-12-29 03:23:36 +00002707
Scott Michel06eabde2008-12-27 04:51:36 +00002708 if (Op1.getOpcode() == SPUISD::IndirectAddr) {
2709 IndirectArg = Op1;
2710 AddArg = Op0;
2711 }
2712
2713 if (isa<ConstantSDNode>(AddArg)) {
2714 ConstantSDNode *CN0 = cast<ConstantSDNode > (AddArg);
2715 SDValue IndOp1 = IndirectArg.getOperand(1);
2716
2717 if (CN0->isNullValue()) {
2718 // (add (SPUindirect <arg>, <arg>), 0) ->
2719 // (SPUindirect <arg>, <arg>)
Scott Michelf9f42e62008-01-29 02:16:57 +00002720
Scott Michel8c2746e2008-12-04 17:16:59 +00002721#if !defined(NDEBUG)
Scott Michel06eabde2008-12-27 04:51:36 +00002722 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel6ccefab2008-12-04 03:02:42 +00002723 cerr << "\n"
Scott Michel06eabde2008-12-27 04:51:36 +00002724 << "Replace: (add (SPUindirect <arg>, <arg>), 0)\n"
2725 << "With: (SPUindirect <arg>, <arg>)\n";
2726 }
Scott Michel6ccefab2008-12-04 03:02:42 +00002727#endif
2728
Scott Michel06eabde2008-12-27 04:51:36 +00002729 return IndirectArg;
2730 } else if (isa<ConstantSDNode>(IndOp1)) {
2731 // (add (SPUindirect <arg>, <const>), <const>) ->
2732 // (SPUindirect <arg>, <const + const>)
2733 ConstantSDNode *CN1 = cast<ConstantSDNode > (IndOp1);
2734 int64_t combinedConst = CN0->getSExtValue() + CN1->getSExtValue();
2735 SDValue combinedValue = DAG.getConstant(combinedConst, Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00002736
Scott Michel06eabde2008-12-27 04:51:36 +00002737#if !defined(NDEBUG)
2738 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
2739 cerr << "\n"
2740 << "Replace: (add (SPUindirect <arg>, " << CN1->getSExtValue()
2741 << "), " << CN0->getSExtValue() << ")\n"
2742 << "With: (SPUindirect <arg>, "
2743 << combinedConst << ")\n";
2744 }
2745#endif
Scott Michelf9f42e62008-01-29 02:16:57 +00002746
Scott Michel06eabde2008-12-27 04:51:36 +00002747 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
2748 IndirectArg, combinedValue);
2749 }
Scott Michelf9f42e62008-01-29 02:16:57 +00002750 }
2751 }
Scott Michel97872d32008-02-23 18:41:37 +00002752 break;
2753 }
2754 case ISD::SIGN_EXTEND:
2755 case ISD::ZERO_EXTEND:
2756 case ISD::ANY_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00002757 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT && NodeVT == Op0VT) {
Scott Michel97872d32008-02-23 18:41:37 +00002758 // (any_extend (SPUextract_elt0 <arg>)) ->
2759 // (SPUextract_elt0 <arg>)
2760 // Types must match, however...
Scott Michel8c2746e2008-12-04 17:16:59 +00002761#if !defined(NDEBUG)
2762 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel6ccefab2008-12-04 03:02:42 +00002763 cerr << "\nReplace: ";
2764 N->dump(&DAG);
2765 cerr << "\nWith: ";
2766 Op0.getNode()->dump(&DAG);
2767 cerr << "\n";
Scott Michel8c2746e2008-12-04 17:16:59 +00002768 }
Scott Michel6ccefab2008-12-04 03:02:42 +00002769#endif
Scott Michel97872d32008-02-23 18:41:37 +00002770
2771 return Op0;
2772 }
2773 break;
2774 }
2775 case SPUISD::IndirectAddr: {
2776 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2777 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002778 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00002779 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2780 // (SPUaform <addr>, 0)
2781
2782 DEBUG(cerr << "Replace: ");
2783 DEBUG(N->dump(&DAG));
2784 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002785 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002786 DEBUG(cerr << "\n");
2787
2788 return Op0;
2789 }
Scott Michel06eabde2008-12-27 04:51:36 +00002790 } else if (Op0.getOpcode() == ISD::ADD) {
2791 SDValue Op1 = N->getOperand(1);
2792 if (ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(Op1)) {
2793 // (SPUindirect (add <arg>, <arg>), 0) ->
2794 // (SPUindirect <arg>, <arg>)
2795 if (CN1->isNullValue()) {
2796
2797#if !defined(NDEBUG)
2798 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
2799 cerr << "\n"
2800 << "Replace: (SPUindirect (add <arg>, <arg>), 0)\n"
2801 << "With: (SPUindirect <arg>, <arg>)\n";
2802 }
2803#endif
2804
2805 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
2806 Op0.getOperand(0), Op0.getOperand(1));
2807 }
2808 }
Scott Michel97872d32008-02-23 18:41:37 +00002809 }
2810 break;
2811 }
2812 case SPUISD::SHLQUAD_L_BITS:
2813 case SPUISD::SHLQUAD_L_BYTES:
2814 case SPUISD::VEC_SHL:
2815 case SPUISD::VEC_SRL:
2816 case SPUISD::VEC_SRA:
Scott Michel06eabde2008-12-27 04:51:36 +00002817 case SPUISD::ROTBYTES_LEFT: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002818 SDValue Op1 = N->getOperand(1);
Scott Michel97872d32008-02-23 18:41:37 +00002819
Scott Michel06eabde2008-12-27 04:51:36 +00002820 // Kill degenerate vector shifts:
2821 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1)) {
2822 if (CN->isNullValue()) {
Scott Michel97872d32008-02-23 18:41:37 +00002823 Result = Op0;
2824 }
2825 }
2826 break;
2827 }
Scott Michel06eabde2008-12-27 04:51:36 +00002828 case SPUISD::PREFSLOT2VEC: {
Scott Michel97872d32008-02-23 18:41:37 +00002829 switch (Op0.getOpcode()) {
2830 default:
2831 break;
2832 case ISD::ANY_EXTEND:
2833 case ISD::ZERO_EXTEND:
2834 case ISD::SIGN_EXTEND: {
Scott Michelae5cbf52008-12-29 03:23:36 +00002835 // (SPUprefslot2vec (any|zero|sign_extend (SPUvec2prefslot <arg>))) ->
Scott Michel97872d32008-02-23 18:41:37 +00002836 // <arg>
Scott Michelae5cbf52008-12-29 03:23:36 +00002837 // but only if the SPUprefslot2vec and <arg> types match.
Dan Gohman8181bd12008-07-27 21:46:04 +00002838 SDValue Op00 = Op0.getOperand(0);
Scott Michelc630c412008-11-24 17:11:17 +00002839 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002840 SDValue Op000 = Op00.getOperand(0);
Scott Michel0718cd82008-12-01 17:56:02 +00002841 if (Op000.getValueType() == NodeVT) {
Scott Michel97872d32008-02-23 18:41:37 +00002842 Result = Op000;
2843 }
2844 }
2845 break;
2846 }
Scott Michelc630c412008-11-24 17:11:17 +00002847 case SPUISD::VEC2PREFSLOT: {
Scott Michelae5cbf52008-12-29 03:23:36 +00002848 // (SPUprefslot2vec (SPUvec2prefslot <arg>)) ->
Scott Michel97872d32008-02-23 18:41:37 +00002849 // <arg>
2850 Result = Op0.getOperand(0);
2851 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00002852 }
Scott Michel97872d32008-02-23 18:41:37 +00002853 }
2854 break;
Scott Michelf9f42e62008-01-29 02:16:57 +00002855 }
2856 }
Scott Michel394e26d2008-01-17 20:38:41 +00002857 // Otherwise, return unchanged.
Scott Michel0718cd82008-12-01 17:56:02 +00002858#ifndef NDEBUG
Gabor Greif1c80d112008-08-28 21:40:38 +00002859 if (Result.getNode()) {
Scott Michel97872d32008-02-23 18:41:37 +00002860 DEBUG(cerr << "\nReplace.SPU: ");
2861 DEBUG(N->dump(&DAG));
2862 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002863 DEBUG(Result.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002864 DEBUG(cerr << "\n");
2865 }
2866#endif
2867
2868 return Result;
Scott Michel8efdca42007-12-04 22:23:35 +00002869}
2870
2871//===----------------------------------------------------------------------===//
2872// Inline Assembly Support
2873//===----------------------------------------------------------------------===//
2874
2875/// getConstraintType - Given a constraint letter, return the type of
2876/// constraint it is for this target.
Scott Michel4ec722e2008-07-16 17:17:29 +00002877SPUTargetLowering::ConstraintType
Scott Michel8efdca42007-12-04 22:23:35 +00002878SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2879 if (ConstraintLetter.size() == 1) {
2880 switch (ConstraintLetter[0]) {
2881 default: break;
2882 case 'b':
2883 case 'r':
2884 case 'f':
2885 case 'v':
2886 case 'y':
2887 return C_RegisterClass;
Scott Michel4ec722e2008-07-16 17:17:29 +00002888 }
Scott Michel8efdca42007-12-04 22:23:35 +00002889 }
2890 return TargetLowering::getConstraintType(ConstraintLetter);
2891}
2892
Scott Michel4ec722e2008-07-16 17:17:29 +00002893std::pair<unsigned, const TargetRegisterClass*>
Scott Michel8efdca42007-12-04 22:23:35 +00002894SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands92c43912008-06-06 12:08:01 +00002895 MVT VT) const
Scott Michel8efdca42007-12-04 22:23:35 +00002896{
2897 if (Constraint.size() == 1) {
2898 // GCC RS6000 Constraint Letters
2899 switch (Constraint[0]) {
2900 case 'b': // R1-R31
2901 case 'r': // R0-R31
2902 if (VT == MVT::i64)
2903 return std::make_pair(0U, SPU::R64CRegisterClass);
2904 return std::make_pair(0U, SPU::R32CRegisterClass);
2905 case 'f':
2906 if (VT == MVT::f32)
2907 return std::make_pair(0U, SPU::R32FPRegisterClass);
2908 else if (VT == MVT::f64)
2909 return std::make_pair(0U, SPU::R64FPRegisterClass);
2910 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00002911 case 'v':
Scott Michel8efdca42007-12-04 22:23:35 +00002912 return std::make_pair(0U, SPU::GPRCRegisterClass);
2913 }
2914 }
Scott Michel4ec722e2008-07-16 17:17:29 +00002915
Scott Michel8efdca42007-12-04 22:23:35 +00002916 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2917}
2918
Scott Michel97872d32008-02-23 18:41:37 +00002919//! Compute used/known bits for a SPU operand
Scott Michel8efdca42007-12-04 22:23:35 +00002920void
Dan Gohman8181bd12008-07-27 21:46:04 +00002921SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohmand0dfc772008-02-13 22:28:48 +00002922 const APInt &Mask,
Scott Michel4ec722e2008-07-16 17:17:29 +00002923 APInt &KnownZero,
Dan Gohman229fa052008-02-13 00:35:47 +00002924 APInt &KnownOne,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002925 const SelectionDAG &DAG,
2926 unsigned Depth ) const {
Scott Michelbc5fbc12008-04-30 00:30:08 +00002927#if 0
Scott Michel97872d32008-02-23 18:41:37 +00002928 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michelbc5fbc12008-04-30 00:30:08 +00002929#endif
Scott Michel97872d32008-02-23 18:41:37 +00002930
2931 switch (Op.getOpcode()) {
2932 default:
2933 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2934 break;
2935
2936#if 0
2937 case CALL:
2938 case SHUFB:
Scott Michel56a125e2008-11-22 23:50:42 +00002939 case SHUFFLE_MASK:
Scott Michel97872d32008-02-23 18:41:37 +00002940 case CNTB:
2941#endif
2942
Scott Michel06eabde2008-12-27 04:51:36 +00002943 case SPUISD::PREFSLOT2VEC: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002944 SDValue Op0 = Op.getOperand(0);
Duncan Sands92c43912008-06-06 12:08:01 +00002945 MVT Op0VT = Op0.getValueType();
2946 unsigned Op0VTBits = Op0VT.getSizeInBits();
2947 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00002948 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2949 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00002950 break;
2951 }
Scott Michel4ec722e2008-07-16 17:17:29 +00002952
Scott Michel97872d32008-02-23 18:41:37 +00002953 case SPUISD::LDRESULT:
Scott Michel6ccefab2008-12-04 03:02:42 +00002954 case SPUISD::VEC2PREFSLOT: {
Duncan Sands92c43912008-06-06 12:08:01 +00002955 MVT OpVT = Op.getValueType();
2956 unsigned OpVTBits = OpVT.getSizeInBits();
2957 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00002958 KnownZero |= APInt(OpVTBits, ~InMask, false);
2959 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00002960 break;
2961 }
2962
2963#if 0
Scott Michelbc5fbc12008-04-30 00:30:08 +00002964 case SPUISD::SHLQUAD_L_BITS:
2965 case SPUISD::SHLQUAD_L_BYTES:
2966 case SPUISD::VEC_SHL:
2967 case SPUISD::VEC_SRL:
2968 case SPUISD::VEC_SRA:
2969 case SPUISD::VEC_ROTL:
2970 case SPUISD::VEC_ROTR:
Scott Michelbc5fbc12008-04-30 00:30:08 +00002971 case SPUISD::ROTBYTES_LEFT:
Scott Michel67224b22008-06-02 22:18:03 +00002972 case SPUISD::SELECT_MASK:
2973 case SPUISD::SELB:
Scott Michel67224b22008-06-02 22:18:03 +00002974 case SPUISD::SEXT32TO64:
Scott Michel97872d32008-02-23 18:41:37 +00002975#endif
2976 }
Scott Michel8efdca42007-12-04 22:23:35 +00002977}
Scott Michel4d07fb72008-12-30 23:28:25 +00002978
Scott Michel06eabde2008-12-27 04:51:36 +00002979unsigned
2980SPUTargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op,
2981 unsigned Depth) const {
2982 switch (Op.getOpcode()) {
2983 default:
2984 return 1;
Scott Michel8efdca42007-12-04 22:23:35 +00002985
Scott Michel06eabde2008-12-27 04:51:36 +00002986 case ISD::SETCC: {
2987 MVT VT = Op.getValueType();
2988
2989 if (VT != MVT::i8 && VT != MVT::i16 && VT != MVT::i32) {
2990 VT = MVT::i32;
2991 }
2992 return VT.getSizeInBits();
2993 }
2994 }
2995}
Scott Michelae5cbf52008-12-29 03:23:36 +00002996
Scott Michelbc5fbc12008-04-30 00:30:08 +00002997// LowerAsmOperandForConstraint
2998void
Dan Gohman8181bd12008-07-27 21:46:04 +00002999SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003000 char ConstraintLetter,
Evan Cheng7f250d62008-09-24 00:05:32 +00003001 bool hasMemory,
Dan Gohman8181bd12008-07-27 21:46:04 +00003002 std::vector<SDValue> &Ops,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003003 SelectionDAG &DAG) const {
3004 // Default, for the time being, to the base class handler
Evan Cheng7f250d62008-09-24 00:05:32 +00003005 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3006 Ops, DAG);
Scott Michelbc5fbc12008-04-30 00:30:08 +00003007}
3008
Scott Michel8efdca42007-12-04 22:23:35 +00003009/// isLegalAddressImmediate - Return true if the integer value can be used
3010/// as the offset of the target addressing mode.
Gabor Greife9f7f582008-08-31 15:37:04 +00003011bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3012 const Type *Ty) const {
Scott Michel8efdca42007-12-04 22:23:35 +00003013 // SPU's addresses are 256K:
3014 return (V > -(1 << 18) && V < (1 << 18) - 1);
3015}
3016
3017bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel4ec722e2008-07-16 17:17:29 +00003018 return false;
Scott Michel8efdca42007-12-04 22:23:35 +00003019}
Dan Gohman36322c72008-10-18 02:06:02 +00003020
3021bool
3022SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3023 // The SPU target isn't yet aware of offsets.
3024 return false;
3025}