blob: 5ccfd14aa4bb595861ad463c37ae1bd28c460498 [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
Dan Gohman8181bd12008-07-27 21:46:04 +0000436MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands92c43912008-06-06 12:08:01 +0000437 MVT VT = Op.getValueType();
Scott Michel06eabde2008-12-27 04:51:36 +0000438 // i16 and i32 are valid SETCC result types
439 return ((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) ? VT : MVT::i32);
Scott Michel53ab7792008-03-10 16:58:52 +0000440}
441
Scott Michel8efdca42007-12-04 22:23:35 +0000442//===----------------------------------------------------------------------===//
443// Calling convention code:
444//===----------------------------------------------------------------------===//
445
446#include "SPUGenCallingConv.inc"
447
448//===----------------------------------------------------------------------===//
449// LowerOperation implementation
450//===----------------------------------------------------------------------===//
451
452/// Custom lower loads for CellSPU
453/*!
454 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
455 within a 16-byte block, we have to rotate to extract the requested element.
Scott Michel6ccefab2008-12-04 03:02:42 +0000456
457 For extending loads, we also want to ensure that the following sequence is
458 emitted, e.g. for MVT::f32 extending load to MVT::f64:
459
460\verbatim
Scott Michelae5cbf52008-12-29 03:23:36 +0000461%1 v16i8,ch = load
Scott Michel6ccefab2008-12-04 03:02:42 +0000462%2 v16i8,ch = rotate %1
Scott Michelae5cbf52008-12-29 03:23:36 +0000463%3 v4f8, ch = bitconvert %2
Scott Michel6ccefab2008-12-04 03:02:42 +0000464%4 f32 = vec2perfslot %3
465%5 f64 = fp_extend %4
466\endverbatim
467*/
Dan Gohman8181bd12008-07-27 21:46:04 +0000468static SDValue
469LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000470 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000471 SDValue the_chain = LN->getChain();
Scott Michel06eabde2008-12-27 04:51:36 +0000472 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel6ccefab2008-12-04 03:02:42 +0000473 MVT InVT = LN->getMemoryVT();
474 MVT OutVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000475 ISD::LoadExtType ExtType = LN->getExtensionType();
476 unsigned alignment = LN->getAlignment();
Scott Michel06eabde2008-12-27 04:51:36 +0000477 const valtype_map_s *vtm = getValueTypeMapEntry(InVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000478
Scott Michel8efdca42007-12-04 22:23:35 +0000479 switch (LN->getAddressingMode()) {
480 case ISD::UNINDEXED: {
Scott Michel06eabde2008-12-27 04:51:36 +0000481 SDValue result;
482 SDValue basePtr = LN->getBasePtr();
483 SDValue rotate;
Scott Michel8efdca42007-12-04 22:23:35 +0000484
Scott Michel06eabde2008-12-27 04:51:36 +0000485 if (alignment == 16) {
486 ConstantSDNode *CN;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000487
Scott Michel06eabde2008-12-27 04:51:36 +0000488 // Special cases for a known aligned load to simplify the base pointer
489 // and the rotation amount:
490 if (basePtr.getOpcode() == ISD::ADD
491 && (CN = dyn_cast<ConstantSDNode > (basePtr.getOperand(1))) != 0) {
492 // Known offset into basePtr
493 int64_t offset = CN->getSExtValue();
494 int64_t rotamt = int64_t((offset & 0xf) - vtm->prefslot_byte);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000495
Scott Michel06eabde2008-12-27 04:51:36 +0000496 if (rotamt < 0)
497 rotamt += 16;
498
499 rotate = DAG.getConstant(rotamt, MVT::i16);
500
501 // Simplify the base pointer for this case:
502 basePtr = basePtr.getOperand(0);
503 if ((offset & ~0xf) > 0) {
504 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
505 basePtr,
506 DAG.getConstant((offset & ~0xf), PtrVT));
507 }
508 } else if ((basePtr.getOpcode() == SPUISD::AFormAddr)
509 || (basePtr.getOpcode() == SPUISD::IndirectAddr
510 && basePtr.getOperand(0).getOpcode() == SPUISD::Hi
511 && basePtr.getOperand(1).getOpcode() == SPUISD::Lo)) {
512 // Plain aligned a-form address: rotate into preferred slot
513 // Same for (SPUindirect (SPUhi ...), (SPUlo ...))
514 int64_t rotamt = -vtm->prefslot_byte;
515 if (rotamt < 0)
516 rotamt += 16;
517 rotate = DAG.getConstant(rotamt, MVT::i16);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000518 } else {
Scott Michel06eabde2008-12-27 04:51:36 +0000519 // Offset the rotate amount by the basePtr and the preferred slot
520 // byte offset
521 int64_t rotamt = -vtm->prefslot_byte;
522 if (rotamt < 0)
523 rotamt += 16;
524 rotate = DAG.getNode(ISD::ADD, PtrVT,
525 basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000526 DAG.getConstant(rotamt, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000527 }
Scott Michel06eabde2008-12-27 04:51:36 +0000528 } else {
529 // Unaligned load: must be more pessimistic about addressing modes:
530 if (basePtr.getOpcode() == ISD::ADD) {
531 MachineFunction &MF = DAG.getMachineFunction();
532 MachineRegisterInfo &RegInfo = MF.getRegInfo();
533 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
534 SDValue Flag;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000535
Scott Michel06eabde2008-12-27 04:51:36 +0000536 SDValue Op0 = basePtr.getOperand(0);
537 SDValue Op1 = basePtr.getOperand(1);
538
539 if (isa<ConstantSDNode>(Op1)) {
540 // Convert the (add <ptr>, <const>) to an indirect address contained
541 // in a register. Note that this is done because we need to avoid
542 // creating a 0(reg) d-form address due to the SPU's block loads.
543 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
544 the_chain = DAG.getCopyToReg(the_chain, VReg, basePtr, Flag);
545 basePtr = DAG.getCopyFromReg(the_chain, VReg, PtrVT);
546 } else {
547 // Convert the (add <arg1>, <arg2>) to an indirect address, which
548 // will likely be lowered as a reg(reg) x-form address.
549 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
550 }
551 } else {
552 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
553 basePtr,
554 DAG.getConstant(0, PtrVT));
555 }
556
557 // Offset the rotate amount by the basePtr and the preferred slot
558 // byte offset
559 rotate = DAG.getNode(ISD::ADD, PtrVT,
560 basePtr,
561 DAG.getConstant(-vtm->prefslot_byte, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +0000562 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000563
Scott Michel06eabde2008-12-27 04:51:36 +0000564 // Re-emit as a v16i8 vector load
565 result = DAG.getLoad(MVT::v16i8, the_chain, basePtr,
566 LN->getSrcValue(), LN->getSrcValueOffset(),
567 LN->isVolatile(), 16);
568
569 // Update the chain
570 the_chain = result.getValue(1);
571
572 // Rotate into the preferred slot:
573 result = DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v16i8,
574 result.getValue(0), rotate);
575
Scott Michel6ccefab2008-12-04 03:02:42 +0000576 // Convert the loaded v16i8 vector to the appropriate vector type
577 // specified by the operand:
578 MVT vecVT = MVT::getVectorVT(InVT, (128 / InVT.getSizeInBits()));
579 result = DAG.getNode(SPUISD::VEC2PREFSLOT, InVT,
580 DAG.getNode(ISD::BIT_CONVERT, vecVT, result));
Scott Michel4ec722e2008-07-16 17:17:29 +0000581
Scott Michel6ccefab2008-12-04 03:02:42 +0000582 // Handle extending loads by extending the scalar result:
583 if (ExtType == ISD::SEXTLOAD) {
584 result = DAG.getNode(ISD::SIGN_EXTEND, OutVT, result);
585 } else if (ExtType == ISD::ZEXTLOAD) {
586 result = DAG.getNode(ISD::ZERO_EXTEND, OutVT, result);
587 } else if (ExtType == ISD::EXTLOAD) {
588 unsigned NewOpc = ISD::ANY_EXTEND;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000589
Scott Michel6ccefab2008-12-04 03:02:42 +0000590 if (OutVT.isFloatingPoint())
591 NewOpc = ISD::FP_EXTEND;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000592
Scott Michel6ccefab2008-12-04 03:02:42 +0000593 result = DAG.getNode(NewOpc, OutVT, result);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000594 }
595
Scott Michel6ccefab2008-12-04 03:02:42 +0000596 SDVTList retvts = DAG.getVTList(OutVT, MVT::Other);
Dan Gohman8181bd12008-07-27 21:46:04 +0000597 SDValue retops[2] = {
Scott Michel394e26d2008-01-17 20:38:41 +0000598 result,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000599 the_chain
Scott Michel394e26d2008-01-17 20:38:41 +0000600 };
Scott Micheldbac4cf2008-01-11 02:53:15 +0000601
Scott Michel394e26d2008-01-17 20:38:41 +0000602 result = DAG.getNode(SPUISD::LDRESULT, retvts,
603 retops, sizeof(retops) / sizeof(retops[0]));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000604 return result;
Scott Michel8efdca42007-12-04 22:23:35 +0000605 }
606 case ISD::PRE_INC:
607 case ISD::PRE_DEC:
608 case ISD::POST_INC:
609 case ISD::POST_DEC:
610 case ISD::LAST_INDEXED_MODE:
611 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
612 "UNINDEXED\n";
613 cerr << (unsigned) LN->getAddressingMode() << "\n";
614 abort();
615 /*NOTREACHED*/
616 }
617
Dan Gohman8181bd12008-07-27 21:46:04 +0000618 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000619}
620
621/// Custom lower stores for CellSPU
622/*!
623 All CellSPU stores are aligned to 16-byte boundaries, so for elements
624 within a 16-byte block, we have to generate a shuffle to insert the
625 requested element into its place, then store the resulting block.
626 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000627static SDValue
628LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000629 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000630 SDValue Value = SN->getValue();
Duncan Sands92c43912008-06-06 12:08:01 +0000631 MVT VT = Value.getValueType();
632 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
633 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000634 unsigned alignment = SN->getAlignment();
Scott Michel8efdca42007-12-04 22:23:35 +0000635
636 switch (SN->getAddressingMode()) {
637 case ISD::UNINDEXED: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000638 // The vector type we really want to load from the 16-byte chunk.
Scott Michele1006032008-11-19 17:45:08 +0000639 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
640 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +0000641
Scott Michel06eabde2008-12-27 04:51:36 +0000642 SDValue alignLoadVec;
643 SDValue basePtr = SN->getBasePtr();
644 SDValue the_chain = SN->getChain();
645 SDValue insertEltOffs;
Scott Michel8efdca42007-12-04 22:23:35 +0000646
Scott Michel06eabde2008-12-27 04:51:36 +0000647 if (alignment == 16) {
648 ConstantSDNode *CN;
649
650 // Special cases for a known aligned load to simplify the base pointer
651 // and insertion byte:
652 if (basePtr.getOpcode() == ISD::ADD
653 && (CN = dyn_cast<ConstantSDNode>(basePtr.getOperand(1))) != 0) {
654 // Known offset into basePtr
655 int64_t offset = CN->getSExtValue();
656
657 // Simplify the base pointer for this case:
658 basePtr = basePtr.getOperand(0);
659 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
660 basePtr,
661 DAG.getConstant((offset & 0xf), PtrVT));
662
663 if ((offset & ~0xf) > 0) {
664 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
665 basePtr,
666 DAG.getConstant((offset & ~0xf), PtrVT));
667 }
668 } else {
669 // Otherwise, assume it's at byte 0 of basePtr
670 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
671 basePtr,
672 DAG.getConstant(0, PtrVT));
673 }
674 } else {
675 // Unaligned load: must be more pessimistic about addressing modes:
676 if (basePtr.getOpcode() == ISD::ADD) {
677 MachineFunction &MF = DAG.getMachineFunction();
678 MachineRegisterInfo &RegInfo = MF.getRegInfo();
679 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
680 SDValue Flag;
681
682 SDValue Op0 = basePtr.getOperand(0);
683 SDValue Op1 = basePtr.getOperand(1);
684
685 if (isa<ConstantSDNode>(Op1)) {
686 // Convert the (add <ptr>, <const>) to an indirect address contained
687 // in a register. Note that this is done because we need to avoid
688 // creating a 0(reg) d-form address due to the SPU's block loads.
689 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
690 the_chain = DAG.getCopyToReg(the_chain, VReg, basePtr, Flag);
691 basePtr = DAG.getCopyFromReg(the_chain, VReg, PtrVT);
692 } else {
693 // Convert the (add <arg1>, <arg2>) to an indirect address, which
694 // will likely be lowered as a reg(reg) x-form address.
695 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
696 }
697 } else {
698 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
699 basePtr,
700 DAG.getConstant(0, PtrVT));
701 }
702
703 // Insertion point is solely determined by basePtr's contents
704 insertEltOffs = DAG.getNode(ISD::ADD, PtrVT,
705 basePtr,
706 DAG.getConstant(0, PtrVT));
707 }
708
709 // Re-emit as a v16i8 vector load
710 alignLoadVec = DAG.getLoad(MVT::v16i8, the_chain, basePtr,
711 SN->getSrcValue(), SN->getSrcValueOffset(),
712 SN->isVolatile(), 16);
713
714 // Update the chain
715 the_chain = alignLoadVec.getValue(1);
Scott Michel8efdca42007-12-04 22:23:35 +0000716
Scott Micheldbac4cf2008-01-11 02:53:15 +0000717 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman8181bd12008-07-27 21:46:04 +0000718 SDValue theValue = SN->getValue();
719 SDValue result;
Scott Michel8efdca42007-12-04 22:23:35 +0000720
721 if (StVT != VT
Scott Michel5a6f17b2008-01-30 02:55:46 +0000722 && (theValue.getOpcode() == ISD::AssertZext
723 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel8efdca42007-12-04 22:23:35 +0000724 // Drill down and get the value for zero- and sign-extended
725 // quantities
Scott Michel4ec722e2008-07-16 17:17:29 +0000726 theValue = theValue.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000727 }
728
Scott Micheldbac4cf2008-01-11 02:53:15 +0000729 // If the base pointer is already a D-form address, then just create
730 // a new D-form address with a slot offset and the orignal base pointer.
731 // Otherwise generate a D-form address with the slot offset relative
732 // to the stack pointer, which is always aligned.
Scott Michel06eabde2008-12-27 04:51:36 +0000733#if !defined(NDEBUG)
734 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
735 cerr << "CellSPU LowerSTORE: basePtr = ";
736 basePtr.getNode()->dump(&DAG);
737 cerr << "\n";
738 }
739#endif
Scott Micheldbac4cf2008-01-11 02:53:15 +0000740
Scott Michelf65c8f02008-11-19 15:24:16 +0000741 SDValue insertEltOp =
Scott Michel06eabde2008-12-27 04:51:36 +0000742 DAG.getNode(SPUISD::SHUFFLE_MASK, vecVT, insertEltOffs);
Scott Michele1006032008-11-19 17:45:08 +0000743 SDValue vectorizeOp =
744 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michelf65c8f02008-11-19 15:24:16 +0000745
Scott Michel0718cd82008-12-01 17:56:02 +0000746 result = DAG.getNode(SPUISD::SHUFB, vecVT,
747 vectorizeOp, alignLoadVec,
748 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, insertEltOp));
Scott Michel8efdca42007-12-04 22:23:35 +0000749
Scott Micheldbac4cf2008-01-11 02:53:15 +0000750 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel8efdca42007-12-04 22:23:35 +0000751 LN->getSrcValue(), LN->getSrcValueOffset(),
752 LN->isVolatile(), LN->getAlignment());
753
Scott Michel8c2746e2008-12-04 17:16:59 +0000754#if 0 && !defined(NDEBUG)
Scott Michelf65c8f02008-11-19 15:24:16 +0000755 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
756 const SDValue &currentRoot = DAG.getRoot();
757
758 DAG.setRoot(result);
759 cerr << "------- CellSPU:LowerStore result:\n";
760 DAG.dump();
761 cerr << "-------\n";
762 DAG.setRoot(currentRoot);
763 }
764#endif
Scott Michelec8c82e2008-12-02 19:53:53 +0000765
Scott Michel8efdca42007-12-04 22:23:35 +0000766 return result;
767 /*UNREACHED*/
768 }
769 case ISD::PRE_INC:
770 case ISD::PRE_DEC:
771 case ISD::POST_INC:
772 case ISD::POST_DEC:
773 case ISD::LAST_INDEXED_MODE:
774 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
775 "UNINDEXED\n";
776 cerr << (unsigned) SN->getAddressingMode() << "\n";
777 abort();
778 /*NOTREACHED*/
779 }
780
Dan Gohman8181bd12008-07-27 21:46:04 +0000781 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000782}
783
784/// Generate the address of a constant pool entry.
Dan Gohman8181bd12008-07-27 21:46:04 +0000785static SDValue
786LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000787 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000788 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
789 Constant *C = CP->getConstVal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000790 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
791 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000792 const TargetMachine &TM = DAG.getTarget();
Scott Michel8efdca42007-12-04 22:23:35 +0000793
794 if (TM.getRelocationModel() == Reloc::Static) {
795 if (!ST->usingLargeMem()) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000796 // Just return the SDValue with the constant pool address in it.
Scott Michel394e26d2008-01-17 20:38:41 +0000797 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +0000798 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000799 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
800 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000801 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel8efdca42007-12-04 22:23:35 +0000802 }
803 }
804
805 assert(0 &&
Gabor Greife9f7f582008-08-31 15:37:04 +0000806 "LowerConstantPool: Relocation model other than static"
807 " not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000808 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000809}
810
Dan Gohman8181bd12008-07-27 21:46:04 +0000811static SDValue
812LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000813 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000814 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000815 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
816 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000817 const TargetMachine &TM = DAG.getTarget();
818
819 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel97872d32008-02-23 18:41:37 +0000820 if (!ST->usingLargeMem()) {
821 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
822 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000823 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
824 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000825 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
826 }
Scott Michel8efdca42007-12-04 22:23:35 +0000827 }
828
829 assert(0 &&
830 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000831 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000832}
833
Dan Gohman8181bd12008-07-27 21:46:04 +0000834static SDValue
835LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000836 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000837 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
838 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000839 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel8efdca42007-12-04 22:23:35 +0000840 const TargetMachine &TM = DAG.getTarget();
Dan Gohman8181bd12008-07-27 21:46:04 +0000841 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel4ec722e2008-07-16 17:17:29 +0000842
Scott Michel8efdca42007-12-04 22:23:35 +0000843 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michelf9f42e62008-01-29 02:16:57 +0000844 if (!ST->usingLargeMem()) {
845 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
846 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000847 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
848 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michelf9f42e62008-01-29 02:16:57 +0000849 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
850 }
Scott Michel8efdca42007-12-04 22:23:35 +0000851 } else {
852 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel5a6f17b2008-01-30 02:55:46 +0000853 << "supported.\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000854 abort();
855 /*NOTREACHED*/
856 }
857
Dan Gohman8181bd12008-07-27 21:46:04 +0000858 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000859}
860
861//! Custom lower i64 integer constants
862/*!
863 This code inserts all of the necessary juggling that needs to occur to load
864 a 64-bit constant into a register.
865 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000866static SDValue
867LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000868 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000869
870 if (VT == MVT::i64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000871 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
872 SDValue T = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michelc630c412008-11-24 17:11:17 +0000873 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000874 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +0000875 } else {
876 cerr << "LowerConstant: unhandled constant type "
Duncan Sands92c43912008-06-06 12:08:01 +0000877 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +0000878 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000879 abort();
880 /*NOTREACHED*/
881 }
882
Dan Gohman8181bd12008-07-27 21:46:04 +0000883 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000884}
885
Nate Begeman78125042008-02-14 18:43:04 +0000886//! Custom lower double precision floating point constants
Dan Gohman8181bd12008-07-27 21:46:04 +0000887static SDValue
888LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000889 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000890
Nate Begeman78125042008-02-14 18:43:04 +0000891 if (VT == MVT::f64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000892 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
893
894 assert((FP != 0) &&
895 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michelae5cbf52008-12-29 03:23:36 +0000896
Scott Michel11e88bb2007-12-19 20:15:47 +0000897 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel0718cd82008-12-01 17:56:02 +0000898 SDValue T = DAG.getConstant(dbits, MVT::i64);
899 SDValue Tvec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T);
900 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
901 DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64, Tvec));
Scott Michel8efdca42007-12-04 22:23:35 +0000902 }
903
Dan Gohman8181bd12008-07-27 21:46:04 +0000904 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000905}
906
Dan Gohman8181bd12008-07-27 21:46:04 +0000907static SDValue
Scott Michel06eabde2008-12-27 04:51:36 +0000908LowerBRCOND(SDValue Op, SelectionDAG &DAG, const TargetLowering &TLI) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000909 SDValue Cond = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +0000910 MVT CondVT = Cond.getValueType();
Scott Michel06eabde2008-12-27 04:51:36 +0000911 unsigned CondOpc;
Scott Michel394e26d2008-01-17 20:38:41 +0000912
Scott Michel33d73eb2008-11-21 02:56:16 +0000913 if (CondVT == MVT::i8) {
Scott Michel06eabde2008-12-27 04:51:36 +0000914 SDValue CondOp0 = Cond.getOperand(0);
915 if (Cond.getOpcode() == ISD::TRUNCATE) {
916 // Use the truncate's value type and ANY_EXTEND the condition (DAGcombine
917 // will then remove the truncate)
918 CondVT = CondOp0.getValueType();
919 CondOpc = ISD::ANY_EXTEND;
920 } else {
921 CondVT = MVT::i32; // default to something reasonable
922 CondOpc = ISD::ZERO_EXTEND;
923 }
924
925 Cond = DAG.getNode(CondOpc, CondVT, Op.getOperand(1));
926
Scott Michel394e26d2008-01-17 20:38:41 +0000927 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
Scott Michel06eabde2008-12-27 04:51:36 +0000928 Op.getOperand(0), Cond, Op.getOperand(2));
929 }
Scott Michelae5cbf52008-12-29 03:23:36 +0000930
Scott Michel06eabde2008-12-27 04:51:36 +0000931 return SDValue(); // Unchanged
Scott Michel394e26d2008-01-17 20:38:41 +0000932}
933
Dan Gohman8181bd12008-07-27 21:46:04 +0000934static SDValue
935LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel8efdca42007-12-04 22:23:35 +0000936{
937 MachineFunction &MF = DAG.getMachineFunction();
938 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner1b989192007-12-31 04:13:23 +0000939 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michela313fb02008-10-30 01:51:48 +0000940 SmallVector<SDValue, 48> ArgValues;
Dan Gohman8181bd12008-07-27 21:46:04 +0000941 SDValue Root = Op.getOperand(0);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000942 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel8efdca42007-12-04 22:23:35 +0000943
944 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
945 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel4ec722e2008-07-16 17:17:29 +0000946
Scott Michel8efdca42007-12-04 22:23:35 +0000947 unsigned ArgOffset = SPUFrameInfo::minStackSize();
948 unsigned ArgRegIdx = 0;
949 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel4ec722e2008-07-16 17:17:29 +0000950
Duncan Sands92c43912008-06-06 12:08:01 +0000951 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +0000952
Scott Michel8efdca42007-12-04 22:23:35 +0000953 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greife9f7f582008-08-31 15:37:04 +0000954 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
955 ArgNo != e; ++ArgNo) {
Duncan Sands92c43912008-06-06 12:08:01 +0000956 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
957 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michela313fb02008-10-30 01:51:48 +0000958 SDValue ArgVal;
Scott Michel8efdca42007-12-04 22:23:35 +0000959
Scott Michela313fb02008-10-30 01:51:48 +0000960 if (ArgRegIdx < NumArgRegs) {
961 const TargetRegisterClass *ArgRegClass;
Scott Michel4ec722e2008-07-16 17:17:29 +0000962
Scott Michela313fb02008-10-30 01:51:48 +0000963 switch (ObjectVT.getSimpleVT()) {
964 default: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000965 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
966 << ObjectVT.getMVTString()
967 << "\n";
968 abort();
Scott Michela313fb02008-10-30 01:51:48 +0000969 }
970 case MVT::i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000971 ArgRegClass = &SPU::R8CRegClass;
972 break;
Scott Michela313fb02008-10-30 01:51:48 +0000973 case MVT::i16:
Scott Michel33d73eb2008-11-21 02:56:16 +0000974 ArgRegClass = &SPU::R16CRegClass;
975 break;
Scott Michela313fb02008-10-30 01:51:48 +0000976 case MVT::i32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000977 ArgRegClass = &SPU::R32CRegClass;
978 break;
Scott Michela313fb02008-10-30 01:51:48 +0000979 case MVT::i64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000980 ArgRegClass = &SPU::R64CRegClass;
981 break;
Scott Michela313fb02008-10-30 01:51:48 +0000982 case MVT::f32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000983 ArgRegClass = &SPU::R32FPRegClass;
984 break;
Scott Michela313fb02008-10-30 01:51:48 +0000985 case MVT::f64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000986 ArgRegClass = &SPU::R64FPRegClass;
987 break;
Scott Michela313fb02008-10-30 01:51:48 +0000988 case MVT::v2f64:
989 case MVT::v4f32:
990 case MVT::v2i64:
991 case MVT::v4i32:
992 case MVT::v8i16:
993 case MVT::v16i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000994 ArgRegClass = &SPU::VECREGRegClass;
995 break;
Scott Michela313fb02008-10-30 01:51:48 +0000996 }
997
998 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
999 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
1000 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1001 ++ArgRegIdx;
1002 } else {
1003 // We need to load the argument to a virtual register if we determined
1004 // above that we ran out of physical registers of the appropriate type
1005 // or we're forced to do vararg
Chris Lattner60069452008-02-13 07:35:30 +00001006 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman8181bd12008-07-27 21:46:04 +00001007 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner60069452008-02-13 07:35:30 +00001008 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel8efdca42007-12-04 22:23:35 +00001009 ArgOffset += StackSlotSize;
1010 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001011
Scott Michel8efdca42007-12-04 22:23:35 +00001012 ArgValues.push_back(ArgVal);
Scott Michela313fb02008-10-30 01:51:48 +00001013 // Update the chain
1014 Root = ArgVal.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001015 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001016
Scott Michela313fb02008-10-30 01:51:48 +00001017 // vararg handling:
Scott Michel8efdca42007-12-04 22:23:35 +00001018 if (isVarArg) {
Scott Michela313fb02008-10-30 01:51:48 +00001019 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1020 // We will spill (79-3)+1 registers to the stack
1021 SmallVector<SDValue, 79-3+1> MemOps;
1022
1023 // Create the frame slot
1024
Scott Michel8efdca42007-12-04 22:23:35 +00001025 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Michela313fb02008-10-30 01:51:48 +00001026 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1027 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1028 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1029 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1030 Root = Store.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001031 MemOps.push_back(Store);
Scott Michela313fb02008-10-30 01:51:48 +00001032
1033 // Increment address by stack slot size for the next stored argument
1034 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001035 }
1036 if (!MemOps.empty())
Scott Michela313fb02008-10-30 01:51:48 +00001037 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001038 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001039
Scott Michel8efdca42007-12-04 22:23:35 +00001040 ArgValues.push_back(Root);
Scott Michel4ec722e2008-07-16 17:17:29 +00001041
Scott Michel8efdca42007-12-04 22:23:35 +00001042 // Return the new list of results.
Duncan Sands42d7bb82008-12-01 11:41:29 +00001043 return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(),
1044 &ArgValues[0], ArgValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001045}
1046
1047/// isLSAAddress - Return the immediate to use if the specified
1048/// value is representable as a LSA address.
Dan Gohman8181bd12008-07-27 21:46:04 +00001049static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel5974f432008-11-11 03:06:06 +00001050 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel8efdca42007-12-04 22:23:35 +00001051 if (!C) return 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001052
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001053 int Addr = C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001054 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1055 (Addr << 14 >> 14) != Addr)
1056 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel4ec722e2008-07-16 17:17:29 +00001057
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001058 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel8efdca42007-12-04 22:23:35 +00001059}
1060
1061static
Dan Gohman8181bd12008-07-27 21:46:04 +00001062SDValue
1063LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001064 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1065 SDValue Chain = TheCall->getChain();
Dan Gohman705e3f72008-09-13 01:54:27 +00001066 SDValue Callee = TheCall->getCallee();
1067 unsigned NumOps = TheCall->getNumArgs();
Scott Michel8efdca42007-12-04 22:23:35 +00001068 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1069 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1070 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1071
1072 // Handy pointer type
Duncan Sands92c43912008-06-06 12:08:01 +00001073 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +00001074
Scott Michel8efdca42007-12-04 22:23:35 +00001075 // Accumulate how many bytes are to be pushed on the stack, including the
1076 // linkage area, and parameter passing area. According to the SPU ABI,
1077 // we minimally need space for [LR] and [SP]
1078 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel4ec722e2008-07-16 17:17:29 +00001079
Scott Michel8efdca42007-12-04 22:23:35 +00001080 // Set up a copy of the stack pointer for use loading and storing any
1081 // arguments that may not fit in the registers available for argument
1082 // passing.
Dan Gohman8181bd12008-07-27 21:46:04 +00001083 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel4ec722e2008-07-16 17:17:29 +00001084
Scott Michel8efdca42007-12-04 22:23:35 +00001085 // Figure out which arguments are going to go in registers, and which in
1086 // memory.
1087 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1088 unsigned ArgRegIdx = 0;
1089
1090 // Keep track of registers passing arguments
Dan Gohman8181bd12008-07-27 21:46:04 +00001091 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel8efdca42007-12-04 22:23:35 +00001092 // And the arguments passed on the stack
Dan Gohman8181bd12008-07-27 21:46:04 +00001093 SmallVector<SDValue, 8> MemOpChains;
Scott Michel8efdca42007-12-04 22:23:35 +00001094
1095 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001096 SDValue Arg = TheCall->getArg(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001097
Scott Michel8efdca42007-12-04 22:23:35 +00001098 // PtrOff will be used to store the current argument to the stack if a
1099 // register cannot be found for it.
Dan Gohman8181bd12008-07-27 21:46:04 +00001100 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel8efdca42007-12-04 22:23:35 +00001101 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1102
Duncan Sands92c43912008-06-06 12:08:01 +00001103 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001104 default: assert(0 && "Unexpected ValueType for argument!");
1105 case MVT::i32:
1106 case MVT::i64:
1107 case MVT::i128:
1108 if (ArgRegIdx != NumArgRegs) {
1109 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1110 } else {
1111 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001112 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001113 }
1114 break;
1115 case MVT::f32:
1116 case MVT::f64:
1117 if (ArgRegIdx != NumArgRegs) {
1118 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1119 } else {
1120 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001121 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001122 }
1123 break;
Scott Michele2641a12008-12-04 21:01:44 +00001124 case MVT::v2i64:
1125 case MVT::v2f64:
Scott Michel8efdca42007-12-04 22:23:35 +00001126 case MVT::v4f32:
1127 case MVT::v4i32:
1128 case MVT::v8i16:
1129 case MVT::v16i8:
1130 if (ArgRegIdx != NumArgRegs) {
1131 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1132 } else {
1133 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001134 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001135 }
1136 break;
1137 }
1138 }
1139
1140 // Update number of stack bytes actually used, insert a call sequence start
1141 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001142 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1143 true));
Scott Michel8efdca42007-12-04 22:23:35 +00001144
1145 if (!MemOpChains.empty()) {
1146 // Adjust the stack pointer for the stack arguments.
1147 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1148 &MemOpChains[0], MemOpChains.size());
1149 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001150
Scott Michel8efdca42007-12-04 22:23:35 +00001151 // Build a sequence of copy-to-reg nodes chained together with token chain
1152 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman8181bd12008-07-27 21:46:04 +00001153 SDValue InFlag;
Scott Michel8efdca42007-12-04 22:23:35 +00001154 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1155 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1156 InFlag);
1157 InFlag = Chain.getValue(1);
1158 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001159
Dan Gohman8181bd12008-07-27 21:46:04 +00001160 SmallVector<SDValue, 8> Ops;
Scott Michel8efdca42007-12-04 22:23:35 +00001161 unsigned CallOpc = SPUISD::CALL;
Scott Michel4ec722e2008-07-16 17:17:29 +00001162
Bill Wendlingfef06052008-09-16 21:48:12 +00001163 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1164 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1165 // node so that legalize doesn't hack it.
Scott Michel5974f432008-11-11 03:06:06 +00001166 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001167 GlobalValue *GV = G->getGlobal();
Duncan Sands92c43912008-06-06 12:08:01 +00001168 MVT CalleeVT = Callee.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001169 SDValue Zero = DAG.getConstant(0, PtrVT);
1170 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001171
Scott Micheldbac4cf2008-01-11 02:53:15 +00001172 if (!ST->usingLargeMem()) {
1173 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1174 // style calls, otherwise, external symbols are BRASL calls. This assumes
1175 // that declared/defined symbols are in the same compilation unit and can
1176 // be reached through PC-relative jumps.
1177 //
1178 // NOTE:
1179 // This may be an unsafe assumption for JIT and really large compilation
1180 // units.
1181 if (GV->isDeclaration()) {
1182 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1183 } else {
1184 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1185 }
Scott Michel8efdca42007-12-04 22:23:35 +00001186 } else {
Scott Micheldbac4cf2008-01-11 02:53:15 +00001187 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1188 // address pairs:
Scott Michelf9f42e62008-01-29 02:16:57 +00001189 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +00001190 }
Scott Michelae5cbf52008-12-29 03:23:36 +00001191 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
1192 MVT CalleeVT = Callee.getValueType();
1193 SDValue Zero = DAG.getConstant(0, PtrVT);
1194 SDValue ExtSym = DAG.getTargetExternalSymbol(S->getSymbol(),
1195 Callee.getValueType());
1196
1197 if (!ST->usingLargeMem()) {
1198 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, ExtSym, Zero);
1199 } else {
1200 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, ExtSym, Zero);
1201 }
1202 } else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001203 // If this is an absolute destination address that appears to be a legal
1204 // local store address, use the munged value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001205 Callee = SDValue(Dest, 0);
Scott Micheldbac4cf2008-01-11 02:53:15 +00001206 }
Scott Michel8efdca42007-12-04 22:23:35 +00001207
1208 Ops.push_back(Chain);
1209 Ops.push_back(Callee);
Scott Michel4ec722e2008-07-16 17:17:29 +00001210
Scott Michel8efdca42007-12-04 22:23:35 +00001211 // Add argument registers to the end of the list so that they are known live
1212 // into the call.
1213 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel4ec722e2008-07-16 17:17:29 +00001214 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel8efdca42007-12-04 22:23:35 +00001215 RegsToPass[i].second.getValueType()));
Scott Michel4ec722e2008-07-16 17:17:29 +00001216
Gabor Greif1c80d112008-08-28 21:40:38 +00001217 if (InFlag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001218 Ops.push_back(InFlag);
Duncan Sands698842f2008-07-02 17:40:58 +00001219 // Returns a chain and a flag for retval copy to use.
1220 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1221 &Ops[0], Ops.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001222 InFlag = Chain.getValue(1);
1223
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001224 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1225 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman705e3f72008-09-13 01:54:27 +00001226 if (TheCall->getValueType(0) != MVT::Other)
Evan Cheng07322bb2008-02-05 22:44:06 +00001227 InFlag = Chain.getValue(1);
1228
Dan Gohman8181bd12008-07-27 21:46:04 +00001229 SDValue ResultVals[3];
Scott Michel8efdca42007-12-04 22:23:35 +00001230 unsigned NumResults = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001231
Scott Michel8efdca42007-12-04 22:23:35 +00001232 // If the call has results, copy the values out of the ret val registers.
Dan Gohman705e3f72008-09-13 01:54:27 +00001233 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001234 default: assert(0 && "Unexpected ret value!");
1235 case MVT::Other: break;
1236 case MVT::i32:
Dan Gohman705e3f72008-09-13 01:54:27 +00001237 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001238 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1239 ResultVals[0] = Chain.getValue(0);
1240 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1241 Chain.getValue(2)).getValue(1);
1242 ResultVals[1] = Chain.getValue(0);
1243 NumResults = 2;
Scott Michel8efdca42007-12-04 22:23:35 +00001244 } else {
1245 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1246 ResultVals[0] = Chain.getValue(0);
1247 NumResults = 1;
1248 }
Scott Michel8efdca42007-12-04 22:23:35 +00001249 break;
1250 case MVT::i64:
1251 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1252 ResultVals[0] = Chain.getValue(0);
1253 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001254 break;
1255 case MVT::f32:
1256 case MVT::f64:
Dan Gohman705e3f72008-09-13 01:54:27 +00001257 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001258 InFlag).getValue(1);
1259 ResultVals[0] = Chain.getValue(0);
1260 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001261 break;
1262 case MVT::v2f64:
Scott Michele2641a12008-12-04 21:01:44 +00001263 case MVT::v2i64:
Scott Michel8efdca42007-12-04 22:23:35 +00001264 case MVT::v4f32:
1265 case MVT::v4i32:
1266 case MVT::v8i16:
1267 case MVT::v16i8:
Dan Gohman705e3f72008-09-13 01:54:27 +00001268 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001269 InFlag).getValue(1);
1270 ResultVals[0] = Chain.getValue(0);
1271 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001272 break;
1273 }
Duncan Sands698842f2008-07-02 17:40:58 +00001274
Scott Michel8efdca42007-12-04 22:23:35 +00001275 // If the function returns void, just return the chain.
1276 if (NumResults == 0)
1277 return Chain;
Scott Michel4ec722e2008-07-16 17:17:29 +00001278
Scott Michel8efdca42007-12-04 22:23:35 +00001279 // Otherwise, merge everything together with a MERGE_VALUES node.
1280 ResultVals[NumResults++] = Chain;
Dan Gohman8181bd12008-07-27 21:46:04 +00001281 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif46bf5472008-08-26 22:36:50 +00001282 return Res.getValue(Op.getResNo());
Scott Michel8efdca42007-12-04 22:23:35 +00001283}
1284
Dan Gohman8181bd12008-07-27 21:46:04 +00001285static SDValue
1286LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel8efdca42007-12-04 22:23:35 +00001287 SmallVector<CCValAssign, 16> RVLocs;
1288 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1289 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1290 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greif1c80d112008-08-28 21:40:38 +00001291 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel4ec722e2008-07-16 17:17:29 +00001292
Scott Michel8efdca42007-12-04 22:23:35 +00001293 // If this is the first return lowered for this function, add the regs to the
1294 // liveout set for the function.
Chris Lattner1b989192007-12-31 04:13:23 +00001295 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001296 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner1b989192007-12-31 04:13:23 +00001297 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel8efdca42007-12-04 22:23:35 +00001298 }
1299
Dan Gohman8181bd12008-07-27 21:46:04 +00001300 SDValue Chain = Op.getOperand(0);
1301 SDValue Flag;
Scott Michel4ec722e2008-07-16 17:17:29 +00001302
Scott Michel8efdca42007-12-04 22:23:35 +00001303 // Copy the result values into the output registers.
1304 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1305 CCValAssign &VA = RVLocs[i];
1306 assert(VA.isRegLoc() && "Can only return in registers!");
1307 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1308 Flag = Chain.getValue(1);
1309 }
1310
Gabor Greif1c80d112008-08-28 21:40:38 +00001311 if (Flag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001312 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1313 else
1314 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1315}
1316
1317
1318//===----------------------------------------------------------------------===//
1319// Vector related lowering:
1320//===----------------------------------------------------------------------===//
1321
1322static ConstantSDNode *
1323getVecImm(SDNode *N) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001324 SDValue OpVal(0, 0);
Scott Michel4ec722e2008-07-16 17:17:29 +00001325
Scott Michel8efdca42007-12-04 22:23:35 +00001326 // Check to see if this buildvec has a single non-undef value in its elements.
1327 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1328 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greif1c80d112008-08-28 21:40:38 +00001329 if (OpVal.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +00001330 OpVal = N->getOperand(i);
1331 else if (OpVal != N->getOperand(i))
1332 return 0;
1333 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001334
Gabor Greif1c80d112008-08-28 21:40:38 +00001335 if (OpVal.getNode() != 0) {
Scott Michel5974f432008-11-11 03:06:06 +00001336 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001337 return CN;
1338 }
1339 }
1340
1341 return 0; // All UNDEF: use implicit def.; not Constant node
1342}
1343
1344/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1345/// and the value fits into an unsigned 18-bit constant, and if so, return the
1346/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001347SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001348 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001349 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001350 uint64_t Value = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001351 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001352 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001353 uint32_t upper = uint32_t(UValue >> 32);
1354 uint32_t lower = uint32_t(UValue);
1355 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001356 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001357 Value = Value >> 32;
1358 }
Scott Michel8efdca42007-12-04 22:23:35 +00001359 if (Value <= 0x3ffff)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001360 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001361 }
1362
Dan Gohman8181bd12008-07-27 21:46:04 +00001363 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001364}
1365
1366/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1367/// and the value fits into a signed 16-bit constant, and if so, return the
1368/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001369SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001370 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001371 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001372 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001373 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001374 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001375 uint32_t upper = uint32_t(UValue >> 32);
1376 uint32_t lower = uint32_t(UValue);
1377 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001378 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001379 Value = Value >> 32;
1380 }
Scott Michel6baba072008-03-05 23:02:02 +00001381 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001382 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001383 }
1384 }
1385
Dan Gohman8181bd12008-07-27 21:46:04 +00001386 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001387}
1388
1389/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1390/// and the value fits into a signed 10-bit constant, and if so, return the
1391/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001392SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001393 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001394 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001395 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001396 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001397 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001398 uint32_t upper = uint32_t(UValue >> 32);
1399 uint32_t lower = uint32_t(UValue);
1400 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001401 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001402 Value = Value >> 32;
1403 }
Scott Michel6baba072008-03-05 23:02:02 +00001404 if (isS10Constant(Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001405 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001406 }
1407
Dan Gohman8181bd12008-07-27 21:46:04 +00001408 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001409}
1410
1411/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1412/// and the value fits into a signed 8-bit constant, and if so, return the
1413/// constant.
1414///
1415/// @note: The incoming vector is v16i8 because that's the only way we can load
1416/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1417/// same value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001418SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001419 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001420 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001421 int Value = (int) CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001422 if (ValueType == MVT::i16
Scott Michel5a6f17b2008-01-30 02:55:46 +00001423 && Value <= 0xffff /* truncated from uint64_t */
1424 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001425 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001426 else if (ValueType == MVT::i8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001427 && (Value & 0xff) == Value)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001428 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001429 }
1430
Dan Gohman8181bd12008-07-27 21:46:04 +00001431 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001432}
1433
1434/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1435/// and the value fits into a signed 16-bit constant, and if so, return the
1436/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001437SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001438 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001439 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001440 uint64_t Value = CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001441 if ((ValueType == MVT::i32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001442 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1443 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001444 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001445 }
1446
Dan Gohman8181bd12008-07-27 21:46:04 +00001447 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001448}
1449
1450/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001451SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001452 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001453 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001454 }
1455
Dan Gohman8181bd12008-07-27 21:46:04 +00001456 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001457}
1458
1459/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001460SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001461 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001462 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001463 }
1464
Dan Gohman8181bd12008-07-27 21:46:04 +00001465 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001466}
1467
1468// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001469// UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001470// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1471// zero. Return true if this is not an array of constants, false if it is.
1472//
1473static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1474 uint64_t UndefBits[2]) {
1475 // Start with zero'd results.
1476 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001477
Duncan Sands92c43912008-06-06 12:08:01 +00001478 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel8efdca42007-12-04 22:23:35 +00001479 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001480 SDValue OpVal = BV->getOperand(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001481
Scott Michel8efdca42007-12-04 22:23:35 +00001482 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1483 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1484
1485 uint64_t EltBits = 0;
1486 if (OpVal.getOpcode() == ISD::UNDEF) {
1487 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1488 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1489 continue;
Scott Michel5974f432008-11-11 03:06:06 +00001490 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001491 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel5974f432008-11-11 03:06:06 +00001492 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001493 const APFloat &apf = CN->getValueAPF();
1494 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001495 ? FloatToBits(apf.convertToFloat())
1496 : DoubleToBits(apf.convertToDouble()));
Scott Michel8efdca42007-12-04 22:23:35 +00001497 } else {
1498 // Nonconstant element.
1499 return true;
1500 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001501
Scott Michel8efdca42007-12-04 22:23:35 +00001502 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1503 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001504
1505 //printf("%llx %llx %llx %llx\n",
Scott Michel8efdca42007-12-04 22:23:35 +00001506 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1507 return false;
1508}
1509
1510/// If this is a splat (repetition) of a value across the whole vector, return
1511/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel4ec722e2008-07-16 17:17:29 +00001512/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel8efdca42007-12-04 22:23:35 +00001513/// SplatSize = 1 byte.
Scott Michel4ec722e2008-07-16 17:17:29 +00001514static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel8efdca42007-12-04 22:23:35 +00001515 const uint64_t Undef128[2],
Scott Michel5a6f17b2008-01-30 02:55:46 +00001516 int MinSplatBits,
Scott Michel8efdca42007-12-04 22:23:35 +00001517 uint64_t &SplatBits, uint64_t &SplatUndef,
1518 int &SplatSize) {
1519 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1520 // the same as the lower 64-bits, ignoring undefs.
1521 uint64_t Bits64 = Bits128[0] | Bits128[1];
1522 uint64_t Undef64 = Undef128[0] & Undef128[1];
1523 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1524 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1525 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1526 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1527
1528 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1529 if (MinSplatBits < 64) {
Scott Michel4ec722e2008-07-16 17:17:29 +00001530
Scott Michel8efdca42007-12-04 22:23:35 +00001531 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1532 // undefs.
1533 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001534 if (MinSplatBits < 32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001535
Scott Michel5a6f17b2008-01-30 02:55:46 +00001536 // If the top 16-bits are different than the lower 16-bits, ignoring
1537 // undefs, we have an i32 splat.
1538 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1539 if (MinSplatBits < 16) {
1540 // If the top 8-bits are different than the lower 8-bits, ignoring
1541 // undefs, we have an i16 splat.
Gabor Greife9f7f582008-08-31 15:37:04 +00001542 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1543 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001544 // Otherwise, we have an 8-bit splat.
1545 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1546 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1547 SplatSize = 1;
1548 return true;
1549 }
1550 } else {
1551 SplatBits = Bits16;
1552 SplatUndef = Undef16;
1553 SplatSize = 2;
1554 return true;
1555 }
1556 }
1557 } else {
1558 SplatBits = Bits32;
1559 SplatUndef = Undef32;
1560 SplatSize = 4;
1561 return true;
1562 }
Scott Michel8efdca42007-12-04 22:23:35 +00001563 }
1564 } else {
1565 SplatBits = Bits128[0];
1566 SplatUndef = Undef128[0];
1567 SplatSize = 8;
1568 return true;
1569 }
1570 }
1571
1572 return false; // Can't be a splat if two pieces don't match.
1573}
1574
1575// If this is a case we can't handle, return null and let the default
1576// expansion code take care of it. If we CAN select this case, and if it
1577// selects to a single instruction, return Op. Otherwise, if we can codegen
1578// this case more efficiently than a constant pool load, lower it to the
1579// sequence of ops that should be used.
Dan Gohman8181bd12008-07-27 21:46:04 +00001580static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001581 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00001582 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001583 // UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001584 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel4ec722e2008-07-16 17:17:29 +00001585 // zero.
Scott Michel8efdca42007-12-04 22:23:35 +00001586 uint64_t VectorBits[2];
1587 uint64_t UndefBits[2];
1588 uint64_t SplatBits, SplatUndef;
1589 int SplatSize;
Gabor Greif1c80d112008-08-28 21:40:38 +00001590 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel8efdca42007-12-04 22:23:35 +00001591 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00001592 VT.getVectorElementType().getSizeInBits(),
Scott Michel8efdca42007-12-04 22:23:35 +00001593 SplatBits, SplatUndef, SplatSize))
Dan Gohman8181bd12008-07-27 21:46:04 +00001594 return SDValue(); // Not a constant vector, not a splat.
Scott Michel4ec722e2008-07-16 17:17:29 +00001595
Duncan Sands92c43912008-06-06 12:08:01 +00001596 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001597 default:
1598 case MVT::v4f32: {
1599 uint32_t Value32 = SplatBits;
1600 assert(SplatSize == 4
Scott Michel5a6f17b2008-01-30 02:55:46 +00001601 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel8efdca42007-12-04 22:23:35 +00001602 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001603 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001604 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001605 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001606 break;
1607 }
1608 case MVT::v2f64: {
1609 uint64_t f64val = SplatBits;
1610 assert(SplatSize == 8
Scott Michelc630c412008-11-24 17:11:17 +00001611 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel8efdca42007-12-04 22:23:35 +00001612 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001613 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001614 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001615 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001616 break;
1617 }
1618 case MVT::v16i8: {
1619 // 8-bit constants have to be expanded to 16-bits
1620 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman8181bd12008-07-27 21:46:04 +00001621 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001622 for (int i = 0; i < 8; ++i)
1623 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1624 return DAG.getNode(ISD::BIT_CONVERT, VT,
1625 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1626 }
1627 case MVT::v8i16: {
1628 unsigned short Value16;
Scott Michel4ec722e2008-07-16 17:17:29 +00001629 if (SplatSize == 2)
Scott Michel8efdca42007-12-04 22:23:35 +00001630 Value16 = (unsigned short) (SplatBits & 0xffff);
1631 else
1632 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman8181bd12008-07-27 21:46:04 +00001633 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1634 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001635 for (int i = 0; i < 8; ++i) Ops[i] = T;
1636 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1637 }
1638 case MVT::v4i32: {
1639 unsigned int Value = SplatBits;
Dan Gohman8181bd12008-07-27 21:46:04 +00001640 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel8efdca42007-12-04 22:23:35 +00001641 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1642 }
1643 case MVT::v2i64: {
1644 uint64_t val = SplatBits;
1645 uint32_t upper = uint32_t(val >> 32);
1646 uint32_t lower = uint32_t(val);
1647
Scott Michelbcc7b672008-03-06 04:02:54 +00001648 if (upper == lower) {
1649 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman8181bd12008-07-27 21:46:04 +00001650 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michelbcc7b672008-03-06 04:02:54 +00001651 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michel6baba072008-03-05 23:02:02 +00001652 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +00001653 SDValue LO32;
1654 SDValue HI32;
1655 SmallVector<SDValue, 16> ShufBytes;
1656 SDValue Result;
Scott Michel8efdca42007-12-04 22:23:35 +00001657 bool upper_special, lower_special;
1658
1659 // NOTE: This code creates common-case shuffle masks that can be easily
1660 // detected as common expressions. It is not attempting to create highly
1661 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1662
1663 // Detect if the upper or lower half is a special shuffle mask pattern:
Scott Michelc630c412008-11-24 17:11:17 +00001664 upper_special = (upper == 0||upper == 0xffffffff||upper == 0x80000000);
1665 lower_special = (lower == 0||lower == 0xffffffff||lower == 0x80000000);
Scott Michel8efdca42007-12-04 22:23:35 +00001666
1667 // Create lower vector if not a special pattern
1668 if (!lower_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001669 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001670 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1671 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1672 LO32C, LO32C, LO32C, LO32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001673 }
1674
1675 // Create upper vector if not a special pattern
1676 if (!upper_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001677 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001678 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1679 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1680 HI32C, HI32C, HI32C, HI32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001681 }
1682
1683 // If either upper or lower are special, then the two input operands are
1684 // the same (basically, one of them is a "don't care")
1685 if (lower_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001686 LO32 = HI32;
Scott Michel8efdca42007-12-04 22:23:35 +00001687 if (upper_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001688 HI32 = LO32;
Scott Michel8efdca42007-12-04 22:23:35 +00001689 if (lower_special && upper_special) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001690 // Unhappy situation... both upper and lower are special, so punt with
1691 // a target constant:
Dan Gohman8181bd12008-07-27 21:46:04 +00001692 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001693 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel8efdca42007-12-04 22:23:35 +00001694 Zero, Zero);
1695 }
1696
1697 for (int i = 0; i < 4; ++i) {
Scott Michel67224b22008-06-02 22:18:03 +00001698 uint64_t val = 0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001699 for (int j = 0; j < 4; ++j) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001700 SDValue V;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001701 bool process_upper, process_lower;
Scott Michel67224b22008-06-02 22:18:03 +00001702 val <<= 8;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001703 process_upper = (upper_special && (i & 1) == 0);
1704 process_lower = (lower_special && (i & 1) == 1);
Scott Michel8efdca42007-12-04 22:23:35 +00001705
Scott Michel5a6f17b2008-01-30 02:55:46 +00001706 if (process_upper || process_lower) {
1707 if ((process_upper && upper == 0)
1708 || (process_lower && lower == 0))
Scott Michel67224b22008-06-02 22:18:03 +00001709 val |= 0x80;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001710 else if ((process_upper && upper == 0xffffffff)
1711 || (process_lower && lower == 0xffffffff))
Scott Michel67224b22008-06-02 22:18:03 +00001712 val |= 0xc0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001713 else if ((process_upper && upper == 0x80000000)
1714 || (process_lower && lower == 0x80000000))
Scott Michel67224b22008-06-02 22:18:03 +00001715 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001716 } else
Scott Michel67224b22008-06-02 22:18:03 +00001717 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001718 }
Scott Michel67224b22008-06-02 22:18:03 +00001719
1720 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001721 }
1722
1723 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel67224b22008-06-02 22:18:03 +00001724 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001725 &ShufBytes[0], ShufBytes.size()));
Scott Michel8efdca42007-12-04 22:23:35 +00001726 }
1727 }
1728 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001729
Dan Gohman8181bd12008-07-27 21:46:04 +00001730 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001731}
1732
1733/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1734/// which the Cell can operate. The code inspects V3 to ascertain whether the
1735/// permutation vector, V3, is monotonically increasing with one "exception"
1736/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel56a125e2008-11-22 23:50:42 +00001737/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel8efdca42007-12-04 22:23:35 +00001738/// In either case, the net result is going to eventually invoke SHUFB to
1739/// permute/shuffle the bytes from V1 and V2.
1740/// \note
Scott Michel56a125e2008-11-22 23:50:42 +00001741/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel8efdca42007-12-04 22:23:35 +00001742/// control word for byte/halfword/word insertion. This takes care of a single
1743/// element move from V2 into V1.
1744/// \note
1745/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman8181bd12008-07-27 21:46:04 +00001746static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1747 SDValue V1 = Op.getOperand(0);
1748 SDValue V2 = Op.getOperand(1);
1749 SDValue PermMask = Op.getOperand(2);
Scott Michel4ec722e2008-07-16 17:17:29 +00001750
Scott Michel8efdca42007-12-04 22:23:35 +00001751 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel4ec722e2008-07-16 17:17:29 +00001752
Scott Michel8efdca42007-12-04 22:23:35 +00001753 // If we have a single element being moved from V1 to V2, this can be handled
1754 // using the C*[DX] compute mask instructions, but the vector elements have
1755 // to be monotonically increasing with one exception element.
Scott Michele2641a12008-12-04 21:01:44 +00001756 MVT VecVT = V1.getValueType();
1757 MVT EltVT = VecVT.getVectorElementType();
Scott Michel8efdca42007-12-04 22:23:35 +00001758 unsigned EltsFromV2 = 0;
1759 unsigned V2Elt = 0;
1760 unsigned V2EltIdx0 = 0;
1761 unsigned CurrElt = 0;
Scott Michele2641a12008-12-04 21:01:44 +00001762 unsigned MaxElts = VecVT.getVectorNumElements();
1763 unsigned PrevElt = 0;
1764 unsigned V0Elt = 0;
Scott Michel8efdca42007-12-04 22:23:35 +00001765 bool monotonic = true;
Scott Michele2641a12008-12-04 21:01:44 +00001766 bool rotate = true;
1767
1768 if (EltVT == MVT::i8) {
Scott Michel8efdca42007-12-04 22:23:35 +00001769 V2EltIdx0 = 16;
Scott Michele2641a12008-12-04 21:01:44 +00001770 } else if (EltVT == MVT::i16) {
Scott Michel8efdca42007-12-04 22:23:35 +00001771 V2EltIdx0 = 8;
Scott Michele2641a12008-12-04 21:01:44 +00001772 } else if (EltVT == MVT::i32 || EltVT == MVT::f32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001773 V2EltIdx0 = 4;
Scott Michele2641a12008-12-04 21:01:44 +00001774 } else if (EltVT == MVT::i64 || EltVT == MVT::f64) {
1775 V2EltIdx0 = 2;
1776 } else
Scott Michel8efdca42007-12-04 22:23:35 +00001777 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1778
Scott Michele2641a12008-12-04 21:01:44 +00001779 for (unsigned i = 0; i != PermMask.getNumOperands(); ++i) {
1780 if (PermMask.getOperand(i).getOpcode() != ISD::UNDEF) {
1781 unsigned SrcElt = cast<ConstantSDNode > (PermMask.getOperand(i))->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001782
Scott Michele2641a12008-12-04 21:01:44 +00001783 if (monotonic) {
1784 if (SrcElt >= V2EltIdx0) {
1785 if (1 >= (++EltsFromV2)) {
1786 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1787 }
1788 } else if (CurrElt != SrcElt) {
1789 monotonic = false;
1790 }
1791
1792 ++CurrElt;
1793 }
1794
1795 if (rotate) {
1796 if (PrevElt > 0 && SrcElt < MaxElts) {
1797 if ((PrevElt == SrcElt - 1)
1798 || (PrevElt == MaxElts - 1 && SrcElt == 0)) {
1799 PrevElt = SrcElt;
1800 if (SrcElt == 0)
1801 V0Elt = i;
1802 } else {
1803 rotate = false;
1804 }
1805 } else if (PrevElt == 0) {
1806 // First time through, need to keep track of previous element
1807 PrevElt = SrcElt;
1808 } else {
1809 // This isn't a rotation, takes elements from vector 2
1810 rotate = false;
1811 }
1812 }
Scott Michel8efdca42007-12-04 22:23:35 +00001813 }
Scott Michel8efdca42007-12-04 22:23:35 +00001814 }
1815
1816 if (EltsFromV2 == 1 && monotonic) {
1817 // Compute mask and shuffle
1818 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001819 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1820 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands92c43912008-06-06 12:08:01 +00001821 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00001822 // Initialize temporary register to 0
Dan Gohman8181bd12008-07-27 21:46:04 +00001823 SDValue InitTempReg =
Scott Michel8efdca42007-12-04 22:23:35 +00001824 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel56a125e2008-11-22 23:50:42 +00001825 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman8181bd12008-07-27 21:46:04 +00001826 SDValue ShufMaskOp =
Scott Michel0718cd82008-12-01 17:56:02 +00001827 DAG.getNode(SPUISD::SHUFFLE_MASK, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001828 DAG.getTargetConstant(V2Elt, MVT::i32),
1829 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +00001830 // Use shuffle mask in SHUFB synthetic instruction:
1831 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
Scott Michele2641a12008-12-04 21:01:44 +00001832 } else if (rotate) {
1833 int rotamt = (MaxElts - V0Elt) * EltVT.getSizeInBits()/8;
Scott Michelae5cbf52008-12-29 03:23:36 +00001834
Scott Michele2641a12008-12-04 21:01:44 +00001835 return DAG.getNode(SPUISD::ROTBYTES_LEFT, V1.getValueType(),
1836 V1, DAG.getConstant(rotamt, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001837 } else {
Gabor Greife9f7f582008-08-31 15:37:04 +00001838 // Convert the SHUFFLE_VECTOR mask's input element units to the
1839 // actual bytes.
Duncan Sands92c43912008-06-06 12:08:01 +00001840 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel4ec722e2008-07-16 17:17:29 +00001841
Dan Gohman8181bd12008-07-27 21:46:04 +00001842 SmallVector<SDValue, 16> ResultMask;
Scott Michel8efdca42007-12-04 22:23:35 +00001843 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1844 unsigned SrcElt;
1845 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001846 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001847 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001848 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel4ec722e2008-07-16 17:17:29 +00001849
Scott Michel97872d32008-02-23 18:41:37 +00001850 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001851 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1852 MVT::i8));
Scott Michel8efdca42007-12-04 22:23:35 +00001853 }
1854 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001855
Dan Gohman8181bd12008-07-27 21:46:04 +00001856 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel0718cd82008-12-01 17:56:02 +00001857 &ResultMask[0], ResultMask.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001858 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1859 }
1860}
1861
Dan Gohman8181bd12008-07-27 21:46:04 +00001862static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1863 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel8efdca42007-12-04 22:23:35 +00001864
Gabor Greif1c80d112008-08-28 21:40:38 +00001865 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel8efdca42007-12-04 22:23:35 +00001866 // For a constant, build the appropriate constant vector, which will
1867 // eventually simplify to a vector register load.
1868
Gabor Greif1c80d112008-08-28 21:40:38 +00001869 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman8181bd12008-07-27 21:46:04 +00001870 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands92c43912008-06-06 12:08:01 +00001871 MVT VT;
Scott Michel8efdca42007-12-04 22:23:35 +00001872 size_t n_copies;
1873
1874 // Create a constant vector:
Duncan Sands92c43912008-06-06 12:08:01 +00001875 switch (Op.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001876 default: assert(0 && "Unexpected constant value type in "
Scott Michel5a6f17b2008-01-30 02:55:46 +00001877 "LowerSCALAR_TO_VECTOR");
Scott Michel8efdca42007-12-04 22:23:35 +00001878 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1879 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1880 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1881 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1882 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1883 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1884 }
1885
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001886 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel8efdca42007-12-04 22:23:35 +00001887 for (size_t j = 0; j < n_copies; ++j)
1888 ConstVecValues.push_back(CValue);
1889
1890 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001891 &ConstVecValues[0], ConstVecValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001892 } else {
1893 // Otherwise, copy the value from one register to another:
Duncan Sands92c43912008-06-06 12:08:01 +00001894 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001895 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1896 case MVT::i8:
1897 case MVT::i16:
1898 case MVT::i32:
1899 case MVT::i64:
1900 case MVT::f32:
1901 case MVT::f64:
Scott Michel06eabde2008-12-27 04:51:36 +00001902 return DAG.getNode(SPUISD::PREFSLOT2VEC, Op.getValueType(), Op0, Op0);
Scott Michel8efdca42007-12-04 22:23:35 +00001903 }
1904 }
1905
Dan Gohman8181bd12008-07-27 21:46:04 +00001906 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001907}
1908
Dan Gohman8181bd12008-07-27 21:46:04 +00001909static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001910 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001911 SDValue N = Op.getOperand(0);
1912 SDValue Elt = Op.getOperand(1);
Scott Michel56a125e2008-11-22 23:50:42 +00001913 SDValue retval;
Scott Michel8efdca42007-12-04 22:23:35 +00001914
Scott Michel56a125e2008-11-22 23:50:42 +00001915 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
1916 // Constant argument:
1917 int EltNo = (int) C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001918
Scott Michel56a125e2008-11-22 23:50:42 +00001919 // sanity checks:
1920 if (VT == MVT::i8 && EltNo >= 16)
1921 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
1922 else if (VT == MVT::i16 && EltNo >= 8)
1923 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
1924 else if (VT == MVT::i32 && EltNo >= 4)
1925 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
1926 else if (VT == MVT::i64 && EltNo >= 2)
1927 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel8efdca42007-12-04 22:23:35 +00001928
Scott Michel56a125e2008-11-22 23:50:42 +00001929 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
1930 // i32 and i64: Element 0 is the preferred slot
Scott Michelc630c412008-11-24 17:11:17 +00001931 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel56a125e2008-11-22 23:50:42 +00001932 }
Scott Michel8efdca42007-12-04 22:23:35 +00001933
Scott Michel56a125e2008-11-22 23:50:42 +00001934 // Need to generate shuffle mask and extract:
1935 int prefslot_begin = -1, prefslot_end = -1;
1936 int elt_byte = EltNo * VT.getSizeInBits() / 8;
1937
1938 switch (VT.getSimpleVT()) {
1939 default:
1940 assert(false && "Invalid value type!");
1941 case MVT::i8: {
1942 prefslot_begin = prefslot_end = 3;
1943 break;
1944 }
1945 case MVT::i16: {
1946 prefslot_begin = 2; prefslot_end = 3;
1947 break;
1948 }
1949 case MVT::i32:
1950 case MVT::f32: {
1951 prefslot_begin = 0; prefslot_end = 3;
1952 break;
1953 }
1954 case MVT::i64:
1955 case MVT::f64: {
1956 prefslot_begin = 0; prefslot_end = 7;
1957 break;
1958 }
1959 }
1960
1961 assert(prefslot_begin != -1 && prefslot_end != -1 &&
1962 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
1963
1964 unsigned int ShufBytes[16];
1965 for (int i = 0; i < 16; ++i) {
1966 // zero fill uppper part of preferred slot, don't care about the
1967 // other slots:
1968 unsigned int mask_val;
1969 if (i <= prefslot_end) {
1970 mask_val =
1971 ((i < prefslot_begin)
1972 ? 0x80
1973 : elt_byte + (i - prefslot_begin));
1974
1975 ShufBytes[i] = mask_val;
1976 } else
1977 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
1978 }
1979
1980 SDValue ShufMask[4];
1981 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
Scott Michele2641a12008-12-04 21:01:44 +00001982 unsigned bidx = i * 4;
Scott Michel56a125e2008-11-22 23:50:42 +00001983 unsigned int bits = ((ShufBytes[bidx] << 24) |
1984 (ShufBytes[bidx+1] << 16) |
1985 (ShufBytes[bidx+2] << 8) |
1986 ShufBytes[bidx+3]);
1987 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
1988 }
1989
1990 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1991 &ShufMask[0],
1992 sizeof(ShufMask) / sizeof(ShufMask[0]));
1993
Scott Michelc630c412008-11-24 17:11:17 +00001994 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel56a125e2008-11-22 23:50:42 +00001995 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
1996 N, N, ShufMaskVec));
1997 } else {
1998 // Variable index: Rotate the requested element into slot 0, then replicate
1999 // slot 0 across the vector
2000 MVT VecVT = N.getValueType();
2001 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2002 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2003 abort();
2004 }
2005
2006 // Make life easier by making sure the index is zero-extended to i32
2007 if (Elt.getValueType() != MVT::i32)
2008 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2009
2010 // Scale the index to a bit/byte shift quantity
2011 APInt scaleFactor =
Scott Michelc630c412008-11-24 17:11:17 +00002012 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2013 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel56a125e2008-11-22 23:50:42 +00002014 SDValue vecShift;
Scott Michel56a125e2008-11-22 23:50:42 +00002015
Scott Michelc630c412008-11-24 17:11:17 +00002016 if (scaleShift > 0) {
2017 // Scale the shift factor:
Scott Michel56a125e2008-11-22 23:50:42 +00002018 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel0718cd82008-12-01 17:56:02 +00002019 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel56a125e2008-11-22 23:50:42 +00002020 }
2021
Scott Michelc630c412008-11-24 17:11:17 +00002022 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2023
2024 // Replicate the bytes starting at byte 0 across the entire vector (for
2025 // consistency with the notion of a unified register set)
Scott Michel56a125e2008-11-22 23:50:42 +00002026 SDValue replicate;
2027
2028 switch (VT.getSimpleVT()) {
2029 default:
2030 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2031 abort();
2032 /*NOTREACHED*/
2033 case MVT::i8: {
Scott Michelc630c412008-11-24 17:11:17 +00002034 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002035 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2036 factor, factor);
2037 break;
2038 }
2039 case MVT::i16: {
Scott Michelc630c412008-11-24 17:11:17 +00002040 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002041 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2042 factor, factor);
2043 break;
2044 }
2045 case MVT::i32:
2046 case MVT::f32: {
2047 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2048 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2049 factor, factor);
2050 break;
2051 }
2052 case MVT::i64:
2053 case MVT::f64: {
2054 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2055 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2056 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2057 loFactor, hiFactor);
2058 break;
2059 }
2060 }
2061
Scott Michelc630c412008-11-24 17:11:17 +00002062 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel0718cd82008-12-01 17:56:02 +00002063 DAG.getNode(SPUISD::SHUFB, VecVT,
2064 vecShift, vecShift, replicate));
Scott Michel8efdca42007-12-04 22:23:35 +00002065 }
2066
Scott Michel56a125e2008-11-22 23:50:42 +00002067 return retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002068}
2069
Dan Gohman8181bd12008-07-27 21:46:04 +00002070static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2071 SDValue VecOp = Op.getOperand(0);
2072 SDValue ValOp = Op.getOperand(1);
2073 SDValue IdxOp = Op.getOperand(2);
Duncan Sands92c43912008-06-06 12:08:01 +00002074 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002075
2076 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2077 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2078
Duncan Sands92c43912008-06-06 12:08:01 +00002079 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel0718cd82008-12-01 17:56:02 +00002080 // Use $sp ($1) because it's always 16-byte aligned and it's available:
2081 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
2082 DAG.getRegister(SPU::R1, PtrVT),
2083 DAG.getConstant(CN->getSExtValue(), PtrVT));
2084 SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, VT, Pointer);
Scott Michel8efdca42007-12-04 22:23:35 +00002085
Dan Gohman8181bd12008-07-27 21:46:04 +00002086 SDValue result =
Scott Michel8efdca42007-12-04 22:23:35 +00002087 DAG.getNode(SPUISD::SHUFB, VT,
2088 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
Scott Michelae5cbf52008-12-29 03:23:36 +00002089 VecOp,
Scott Michel0718cd82008-12-01 17:56:02 +00002090 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, ShufMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002091
2092 return result;
2093}
2094
Scott Michel06eabde2008-12-27 04:51:36 +00002095static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc,
2096 const TargetLowering &TLI)
Scott Michel97872d32008-02-23 18:41:37 +00002097{
Dan Gohman8181bd12008-07-27 21:46:04 +00002098 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel06eabde2008-12-27 04:51:36 +00002099 MVT ShiftVT = TLI.getShiftAmountTy();
Scott Michel8efdca42007-12-04 22:23:35 +00002100
2101 assert(Op.getValueType() == MVT::i8);
2102 switch (Opc) {
2103 default:
2104 assert(0 && "Unhandled i8 math operator");
2105 /*NOTREACHED*/
2106 break;
Scott Michel4d07fb72008-12-30 23:28:25 +00002107 case ISD::ADD: {
2108 // 8-bit addition: Promote the arguments up to 16-bits and truncate
2109 // the result:
2110 SDValue N1 = Op.getOperand(1);
2111 N0 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0);
2112 N1 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1);
2113 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
2114 DAG.getNode(Opc, MVT::i16, N0, N1));
2115
2116 }
2117
Scott Michel8efdca42007-12-04 22:23:35 +00002118 case ISD::SUB: {
2119 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2120 // the result:
Dan Gohman8181bd12008-07-27 21:46:04 +00002121 SDValue N1 = Op.getOperand(1);
Scott Michel4d07fb72008-12-30 23:28:25 +00002122 N0 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0);
2123 N1 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1);
Scott Michel4ec722e2008-07-16 17:17:29 +00002124 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002125 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel4ec722e2008-07-16 17:17:29 +00002126 }
Scott Michel8efdca42007-12-04 22:23:35 +00002127 case ISD::ROTR:
2128 case ISD::ROTL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002129 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002130 unsigned N1Opc;
2131 N0 = (N0.getOpcode() != ISD::Constant
2132 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002133 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2134 MVT::i16));
Scott Michel06eabde2008-12-27 04:51:36 +00002135 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greife9f7f582008-08-31 15:37:04 +00002136 ? ISD::ZERO_EXTEND
2137 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002138 N1 = (N1.getOpcode() != ISD::Constant
Scott Michel06eabde2008-12-27 04:51:36 +00002139 ? DAG.getNode(N1Opc, ShiftVT, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002140 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Scott Michel06eabde2008-12-27 04:51:36 +00002141 TLI.getShiftAmountTy()));
Dan Gohman8181bd12008-07-27 21:46:04 +00002142 SDValue ExpandArg =
Scott Michel8efdca42007-12-04 22:23:35 +00002143 DAG.getNode(ISD::OR, MVT::i16, N0,
2144 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sands7aef60d2008-10-30 19:24:28 +00002145 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002146 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002147 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2148 }
2149 case ISD::SRL:
2150 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002151 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002152 unsigned N1Opc;
2153 N0 = (N0.getOpcode() != ISD::Constant
2154 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002155 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
Scott Michel06eabde2008-12-27 04:51:36 +00002156 MVT::i32));
2157 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greife9f7f582008-08-31 15:37:04 +00002158 ? ISD::ZERO_EXTEND
2159 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002160 N1 = (N1.getOpcode() != ISD::Constant
Scott Michel06eabde2008-12-27 04:51:36 +00002161 ? DAG.getNode(N1Opc, ShiftVT, N1)
2162 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(), ShiftVT));
Scott Michel4ec722e2008-07-16 17:17:29 +00002163 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002164 DAG.getNode(Opc, MVT::i16, N0, N1));
2165 }
2166 case ISD::SRA: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002167 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002168 unsigned N1Opc;
2169 N0 = (N0.getOpcode() != ISD::Constant
2170 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Scott Michel06eabde2008-12-27 04:51:36 +00002171 : DAG.getConstant(cast<ConstantSDNode>(N0)->getSExtValue(),
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002172 MVT::i16));
Scott Michel06eabde2008-12-27 04:51:36 +00002173 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greife9f7f582008-08-31 15:37:04 +00002174 ? ISD::SIGN_EXTEND
2175 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002176 N1 = (N1.getOpcode() != ISD::Constant
Scott Michel06eabde2008-12-27 04:51:36 +00002177 ? DAG.getNode(N1Opc, ShiftVT, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002178 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Scott Michel06eabde2008-12-27 04:51:36 +00002179 ShiftVT));
Scott Michel4ec722e2008-07-16 17:17:29 +00002180 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002181 DAG.getNode(Opc, MVT::i16, N0, N1));
2182 }
2183 case ISD::MUL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002184 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002185 unsigned N1Opc;
2186 N0 = (N0.getOpcode() != ISD::Constant
2187 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002188 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2189 MVT::i16));
Duncan Sandsec142ee2008-06-08 20:54:56 +00002190 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002191 N1 = (N1.getOpcode() != ISD::Constant
2192 ? DAG.getNode(N1Opc, MVT::i16, N1)
Scott Michel06eabde2008-12-27 04:51:36 +00002193 : DAG.getConstant(cast<ConstantSDNode>(N1)->getSExtValue(),
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002194 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002195 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002196 DAG.getNode(Opc, MVT::i16, N0, N1));
2197 break;
2198 }
2199 }
2200
Dan Gohman8181bd12008-07-27 21:46:04 +00002201 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002202}
2203
Dan Gohman8181bd12008-07-27 21:46:04 +00002204static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002205{
Duncan Sands92c43912008-06-06 12:08:01 +00002206 MVT VT = Op.getValueType();
2207 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002208
Dan Gohman8181bd12008-07-27 21:46:04 +00002209 SDValue Op0 = Op.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002210
2211 switch (Opc) {
2212 case ISD::ZERO_EXTEND:
Scott Michel97872d32008-02-23 18:41:37 +00002213 case ISD::ANY_EXTEND: {
Duncan Sands92c43912008-06-06 12:08:01 +00002214 MVT Op0VT = Op0.getValueType();
2215 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002216
2217 assert(Op0VT == MVT::i32
2218 && "CellSPU: Zero/sign extending something other than i32");
2219
Scott Michelc630c412008-11-24 17:11:17 +00002220 DEBUG(cerr << "CellSPU.LowerI64Math: lowering zero/sign/any extend\n");
2221
Dan Gohman8181bd12008-07-27 21:46:04 +00002222 SDValue PromoteScalar =
Scott Michel06eabde2008-12-27 04:51:36 +00002223 DAG.getNode(SPUISD::PREFSLOT2VEC, Op0VecVT, Op0);
Scott Michel97872d32008-02-23 18:41:37 +00002224
Scott Michel4d07fb72008-12-30 23:28:25 +00002225 // Use a shuffle to zero extend the i32 to i64 directly:
2226 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, Op0VecVT,
2227 DAG.getConstant(0x80808080, MVT::i32), DAG.getConstant(0x00010203,
2228 MVT::i32), DAG.getConstant(0x80808080, MVT::i32), DAG.getConstant(
2229 0x08090a0b, MVT::i32));
2230 SDValue zextShuffle = DAG.getNode(SPUISD::SHUFB, Op0VecVT, PromoteScalar,
2231 PromoteScalar, shufMask);
Scott Michelf2df6cb2008-11-24 18:20:46 +00002232
Scott Michel4d07fb72008-12-30 23:28:25 +00002233 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, DAG.getNode(ISD::BIT_CONVERT,
2234 VecVT, zextShuffle));
Scott Michel97872d32008-02-23 18:41:37 +00002235 }
2236
Scott Michel67224b22008-06-02 22:18:03 +00002237 case ISD::ADD: {
2238 // Turn operands into vectors to satisfy type checking (shufb works on
2239 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002240 SDValue Op0 =
Scott Michel06eabde2008-12-27 04:51:36 +00002241 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002242 SDValue Op1 =
Scott Michel06eabde2008-12-27 04:51:36 +00002243 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002244 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002245
2246 // Create the shuffle mask for "rotating" the borrow up one register slot
2247 // once the borrow is generated.
2248 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2249 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2250 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2251 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2252
Dan Gohman8181bd12008-07-27 21:46:04 +00002253 SDValue CarryGen =
Scott Michel67224b22008-06-02 22:18:03 +00002254 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002255 SDValue ShiftedCarry =
Scott Michel67224b22008-06-02 22:18:03 +00002256 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2257 CarryGen, CarryGen,
2258 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2259 &ShufBytes[0], ShufBytes.size()));
2260
Scott Michelc630c412008-11-24 17:11:17 +00002261 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002262 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2263 Op0, Op1, ShiftedCarry));
2264 }
2265
2266 case ISD::SUB: {
2267 // Turn operands into vectors to satisfy type checking (shufb works on
2268 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002269 SDValue Op0 =
Scott Michel06eabde2008-12-27 04:51:36 +00002270 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002271 SDValue Op1 =
Scott Michel06eabde2008-12-27 04:51:36 +00002272 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002273 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002274
2275 // Create the shuffle mask for "rotating" the borrow up one register slot
2276 // once the borrow is generated.
2277 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2278 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2279 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2280 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2281
Dan Gohman8181bd12008-07-27 21:46:04 +00002282 SDValue BorrowGen =
Scott Michel67224b22008-06-02 22:18:03 +00002283 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002284 SDValue ShiftedBorrow =
Scott Michel67224b22008-06-02 22:18:03 +00002285 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2286 BorrowGen, BorrowGen,
2287 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2288 &ShufBytes[0], ShufBytes.size()));
2289
Scott Michelc630c412008-11-24 17:11:17 +00002290 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002291 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2292 Op0, Op1, ShiftedBorrow));
2293 }
Scott Michel97872d32008-02-23 18:41:37 +00002294 }
2295
Dan Gohman8181bd12008-07-27 21:46:04 +00002296 return SDValue();
Scott Michel97872d32008-02-23 18:41:37 +00002297}
2298
Scott Michel8efdca42007-12-04 22:23:35 +00002299//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman8181bd12008-07-27 21:46:04 +00002300static SDValue
2301LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2302 SDValue ConstVec;
2303 SDValue Arg;
Duncan Sands92c43912008-06-06 12:08:01 +00002304 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002305
2306 ConstVec = Op.getOperand(0);
2307 Arg = Op.getOperand(1);
Gabor Greif1c80d112008-08-28 21:40:38 +00002308 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2309 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel8efdca42007-12-04 22:23:35 +00002310 ConstVec = ConstVec.getOperand(0);
2311 } else {
2312 ConstVec = Op.getOperand(1);
2313 Arg = Op.getOperand(0);
Gabor Greif1c80d112008-08-28 21:40:38 +00002314 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00002315 ConstVec = ConstVec.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00002316 }
2317 }
2318 }
2319
Gabor Greif1c80d112008-08-28 21:40:38 +00002320 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel8efdca42007-12-04 22:23:35 +00002321 uint64_t VectorBits[2];
2322 uint64_t UndefBits[2];
2323 uint64_t SplatBits, SplatUndef;
2324 int SplatSize;
2325
Gabor Greif1c80d112008-08-28 21:40:38 +00002326 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002327 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00002328 VT.getVectorElementType().getSizeInBits(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002329 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002330 SDValue tcVec[16];
2331 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel8efdca42007-12-04 22:23:35 +00002332 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2333
2334 // Turn the BUILD_VECTOR into a set of target constants:
2335 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002336 tcVec[i] = tc;
Scott Michel8efdca42007-12-04 22:23:35 +00002337
Gabor Greif1c80d112008-08-28 21:40:38 +00002338 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002339 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel8efdca42007-12-04 22:23:35 +00002340 }
2341 }
Nate Begeman7569e762008-07-29 19:07:27 +00002342 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2343 // lowered. Return the operation, rather than a null SDValue.
2344 return Op;
Scott Michel8efdca42007-12-04 22:23:35 +00002345}
2346
Scott Michel8efdca42007-12-04 22:23:35 +00002347//! Custom lowering for CTPOP (count population)
2348/*!
2349 Custom lowering code that counts the number ones in the input
2350 operand. SPU has such an instruction, but it counts the number of
2351 ones per byte, which then have to be accumulated.
2352*/
Dan Gohman8181bd12008-07-27 21:46:04 +00002353static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002354 MVT VT = Op.getValueType();
2355 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +00002356
Duncan Sands92c43912008-06-06 12:08:01 +00002357 switch (VT.getSimpleVT()) {
2358 default:
2359 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002360 case MVT::i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002361 SDValue N = Op.getOperand(0);
2362 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002363
Scott Michel06eabde2008-12-27 04:51:36 +00002364 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman8181bd12008-07-27 21:46:04 +00002365 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002366
2367 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2368 }
2369
2370 case MVT::i16: {
2371 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002372 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002373
Chris Lattner1b989192007-12-31 04:13:23 +00002374 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002375
Dan Gohman8181bd12008-07-27 21:46:04 +00002376 SDValue N = Op.getOperand(0);
2377 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2378 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sands7aef60d2008-10-30 19:24:28 +00002379 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002380
Scott Michel06eabde2008-12-27 04:51:36 +00002381 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman8181bd12008-07-27 21:46:04 +00002382 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002383
2384 // CNTB_result becomes the chain to which all of the virtual registers
2385 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002386 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002387 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002388
Dan Gohman8181bd12008-07-27 21:46:04 +00002389 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002390 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2391
Dan Gohman8181bd12008-07-27 21:46:04 +00002392 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002393
2394 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002395 DAG.getNode(ISD::ADD, MVT::i16,
2396 DAG.getNode(ISD::SRL, MVT::i16,
2397 Tmp1, Shift1),
2398 Tmp1),
2399 Mask0);
Scott Michel8efdca42007-12-04 22:23:35 +00002400 }
2401
2402 case MVT::i32: {
2403 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002404 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002405
Chris Lattner1b989192007-12-31 04:13:23 +00002406 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2407 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002408
Dan Gohman8181bd12008-07-27 21:46:04 +00002409 SDValue N = Op.getOperand(0);
2410 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2411 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2412 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2413 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002414
Scott Michel06eabde2008-12-27 04:51:36 +00002415 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman8181bd12008-07-27 21:46:04 +00002416 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002417
2418 // CNTB_result becomes the chain to which all of the virtual registers
2419 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002420 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002421 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002422
Dan Gohman8181bd12008-07-27 21:46:04 +00002423 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002424 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2425
Dan Gohman8181bd12008-07-27 21:46:04 +00002426 SDValue Comp1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002427 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002428 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel8efdca42007-12-04 22:23:35 +00002429
Dan Gohman8181bd12008-07-27 21:46:04 +00002430 SDValue Sum1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002431 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002432 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002433
Dan Gohman8181bd12008-07-27 21:46:04 +00002434 SDValue Sum1_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002435 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2436
Dan Gohman8181bd12008-07-27 21:46:04 +00002437 SDValue Comp2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002438 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002439 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2440 Shift2);
Dan Gohman8181bd12008-07-27 21:46:04 +00002441 SDValue Sum2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002442 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002443 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002444
2445 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2446 }
2447
2448 case MVT::i64:
2449 break;
2450 }
2451
Dan Gohman8181bd12008-07-27 21:46:04 +00002452 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002453}
2454
Scott Michel06eabde2008-12-27 04:51:36 +00002455//! Lower ISD::SETCC
2456/*!
2457 Lower i64 condition code handling.
2458 */
2459
2460static SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) {
2461 MVT VT = Op.getValueType();
2462 SDValue lhs = Op.getOperand(0);
2463 SDValue rhs = Op.getOperand(1);
2464 SDValue condition = Op.getOperand(2);
2465
2466 if (VT == MVT::i32 && lhs.getValueType() == MVT::i64) {
2467 // Expand the i64 comparisons to what Cell can actually support,
2468 // which is eq, ugt and sgt:
2469#if 0
2470 CondCodeSDNode *ccvalue = dyn_cast<CondCodeSDValue>(condition);
2471
2472 switch (ccvalue->get()) {
2473 case
2474 }
2475#endif
2476 }
2477
2478 return SDValue();
2479}
2480
Scott Michel56a125e2008-11-22 23:50:42 +00002481//! Lower ISD::SELECT_CC
2482/*!
2483 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2484 SELB instruction.
2485
2486 \note Need to revisit this in the future: if the code path through the true
2487 and false value computations is longer than the latency of a branch (6
2488 cycles), then it would be more advantageous to branch and insert a new basic
2489 block and branch on the condition. However, this code does not make that
2490 assumption, given the simplisitc uses so far.
2491 */
2492
Scott Michel06eabde2008-12-27 04:51:36 +00002493static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
2494 const TargetLowering &TLI) {
Scott Michel56a125e2008-11-22 23:50:42 +00002495 MVT VT = Op.getValueType();
2496 SDValue lhs = Op.getOperand(0);
2497 SDValue rhs = Op.getOperand(1);
2498 SDValue trueval = Op.getOperand(2);
2499 SDValue falseval = Op.getOperand(3);
2500 SDValue condition = Op.getOperand(4);
2501
Scott Michel06eabde2008-12-27 04:51:36 +00002502 // NOTE: SELB's arguments: $rA, $rB, $mask
2503 //
2504 // SELB selects bits from $rA where bits in $mask are 0, bits from $rB
2505 // where bits in $mask are 1. CCond will be inverted, having 1s where the
2506 // condition was true and 0s where the condition was false. Hence, the
2507 // arguments to SELB get reversed.
2508
Scott Michel56a125e2008-11-22 23:50:42 +00002509 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2510 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2511 // with another "cannot select select_cc" assert:
2512
Scott Michel06eabde2008-12-27 04:51:36 +00002513 SDValue compare = DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(Op),
2514 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}