blob: 0822181d3b73cf2527c7764c61e82f7f4ad3da64 [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
207 // SPU needs custom lowering for shift left/right for i64
Scott Michel97872d32008-02-23 18:41:37 +0000208 setOperationAction(ISD::SHL, MVT::i64, Custom);
209 setOperationAction(ISD::SRL, MVT::i64, Custom);
210 setOperationAction(ISD::SRA, MVT::i64, Custom);
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
218 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000219 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel67224b22008-06-02 22:18:03 +0000220 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000221
Scott Michel8efdca42007-12-04 22:23:35 +0000222 // SPU does not have BSWAP. It does have i32 support CTLZ.
223 // CTPOP has to be custom lowered.
224 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
225 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
226
227 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
228 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
229 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
230 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
231
232 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
233 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
234
235 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000236
Scott Michel67224b22008-06-02 22:18:03 +0000237 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel978b96f2008-03-10 23:49:09 +0000238 // select ought to work:
Scott Michel53ab7792008-03-10 16:58:52 +0000239 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000240 setOperationAction(ISD::SELECT, MVT::i16, Legal);
241 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel06eabde2008-12-27 04:51:36 +0000242 setOperationAction(ISD::SELECT, MVT::i64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000243
Scott Michel53ab7792008-03-10 16:58:52 +0000244 setOperationAction(ISD::SETCC, MVT::i8, Legal);
245 setOperationAction(ISD::SETCC, MVT::i16, Legal);
Scott Michelae5cbf52008-12-29 03:23:36 +0000246 setOperationAction(ISD::SETCC, MVT::i32, Legal);
247 setOperationAction(ISD::SETCC, MVT::i64, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000248
Scott Michel97872d32008-02-23 18:41:37 +0000249 // Zero extension and sign extension for i64 have to be
250 // custom legalized
251 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
252 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
253 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
265 setOperationAction(ISD::FDIV, MVT::f32, Custom);
Scott Michel06eabde2008-12-27 04:51:36 +0000266 setOperationAction(ISD::FDIV, MVT::f64, Expand); // libcall
Scott Michel8efdca42007-12-04 22:23:35 +0000267
268 // SPU has [U|S]INT_TO_FP
269 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
270 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
271 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
272 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
273 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
274 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
275 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
276 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
277
Scott Michel754d8662007-12-20 00:44:13 +0000278 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
279 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
280 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
281 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000282
283 // We cannot sextinreg(i1). Expand to shifts.
284 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000285
Scott Michel8efdca42007-12-04 22:23:35 +0000286 // Support label based line numbers.
Dan Gohman472d12c2008-06-30 20:59:49 +0000287 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000288 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000289
290 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel8efdca42007-12-04 22:23:35 +0000291 // appropriate instructions to materialize the address.
Scott Michel33d73eb2008-11-21 02:56:16 +0000292 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michelf9f42e62008-01-29 02:16:57 +0000293 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000294 MVT VT = (MVT::SimpleValueType)sctype;
295
Scott Michelae5cbf52008-12-29 03:23:36 +0000296 setOperationAction(ISD::GlobalAddress, VT, Custom);
297 setOperationAction(ISD::ConstantPool, VT, Custom);
298 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michelf9f42e62008-01-29 02:16:57 +0000299 }
Scott Michel8efdca42007-12-04 22:23:35 +0000300
301 // RET must be custom lowered, to meet ABI requirements
302 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000303
Scott Michel8efdca42007-12-04 22:23:35 +0000304 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
305 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000306
Scott Michel8efdca42007-12-04 22:23:35 +0000307 // Use the default implementation.
308 setOperationAction(ISD::VAARG , MVT::Other, Expand);
309 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
310 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000311 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000312 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
313 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
314 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
315
316 // Cell SPU has instructions for converting between i64 and fp.
317 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
318 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000319
Scott Michel8efdca42007-12-04 22:23:35 +0000320 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
321 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
322
323 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
324 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
325
326 // First set operation action for all vector types to expand. Then we
327 // will selectively turn on ones that can be effectively codegen'd.
328 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
329 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
330 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
331 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
332 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
333 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
334
Duncan Sands92c43912008-06-06 12:08:01 +0000335 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
336 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
337 MVT VT = (MVT::SimpleValueType)i;
Scott Michel8efdca42007-12-04 22:23:35 +0000338
Duncan Sands92c43912008-06-06 12:08:01 +0000339 // add/sub are legal for all supported vector VT's.
340 setOperationAction(ISD::ADD , VT, Legal);
341 setOperationAction(ISD::SUB , VT, Legal);
342 // mul has to be custom lowered.
343 setOperationAction(ISD::MUL , VT, Custom);
344
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);
357 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000358
359 // Custom lower build_vector, constant pool spills, insert and
360 // extract vector elements:
Duncan Sands92c43912008-06-06 12:08:01 +0000361 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
362 setOperationAction(ISD::ConstantPool, VT, Custom);
363 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
364 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
365 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
366 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000367 }
368
Scott Michel8efdca42007-12-04 22:23:35 +0000369 setOperationAction(ISD::AND, MVT::v16i8, Custom);
370 setOperationAction(ISD::OR, MVT::v16i8, Custom);
371 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
372 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000373
Scott Michelae5cbf52008-12-29 03:23:36 +0000374 // FIXME: This is only temporary until I put all vector multiplications in
375 // SPUInstrInfo.td:
376 setOperationAction(ISD::MUL, MVT::v4i32, Legal);
377
Scott Michel8efdca42007-12-04 22:23:35 +0000378 setShiftAmountType(MVT::i32);
Scott Michel06eabde2008-12-27 04:51:36 +0000379 setBooleanContents(ZeroOrNegativeOneBooleanContent);
Scott Michel4ec722e2008-07-16 17:17:29 +0000380
Scott Michel8efdca42007-12-04 22:23:35 +0000381 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel4ec722e2008-07-16 17:17:29 +0000382
Scott Michel8efdca42007-12-04 22:23:35 +0000383 // We have target-specific dag combine patterns for the following nodes:
Scott Michelf9f42e62008-01-29 02:16:57 +0000384 setTargetDAGCombine(ISD::ADD);
Scott Michel97872d32008-02-23 18:41:37 +0000385 setTargetDAGCombine(ISD::ZERO_EXTEND);
386 setTargetDAGCombine(ISD::SIGN_EXTEND);
387 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel4ec722e2008-07-16 17:17:29 +0000388
Scott Michel8efdca42007-12-04 22:23:35 +0000389 computeRegisterProperties();
Scott Michel56a125e2008-11-22 23:50:42 +0000390
Scott Michel2c261072008-12-09 03:37:19 +0000391 // Set pre-RA register scheduler default to BURR, which produces slightly
392 // better code than the default (could also be TDRR, but TargetLowering.h
393 // needs a mod to support that model):
394 setSchedulingPreference(SchedulingForRegPressure);
Scott Michel8efdca42007-12-04 22:23:35 +0000395}
396
397const char *
398SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
399{
400 if (node_names.empty()) {
401 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
402 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
403 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
404 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Micheldbac4cf2008-01-11 02:53:15 +0000405 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michelf9f42e62008-01-29 02:16:57 +0000406 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel8efdca42007-12-04 22:23:35 +0000407 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
408 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
409 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
Scott Michel56a125e2008-11-22 23:50:42 +0000410 node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000411 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
Scott Michelae5cbf52008-12-29 03:23:36 +0000412 node_names[(unsigned) SPUISD::PREFSLOT2VEC] = "SPUISD::PREFSLOT2VEC";
Scott Michelc630c412008-11-24 17:11:17 +0000413 node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
Scott Michel8efdca42007-12-04 22:23:35 +0000414 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
415 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
416 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
417 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michel97872d32008-02-23 18:41:37 +0000418 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
419 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel8efdca42007-12-04 22:23:35 +0000420 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
421 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
422 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
423 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
424 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michel97872d32008-02-23 18:41:37 +0000425 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
426 "SPUISD::ROTQUAD_RZ_BYTES";
427 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
428 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel8efdca42007-12-04 22:23:35 +0000429 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
Scott Michel67224b22008-06-02 22:18:03 +0000430 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
431 "SPUISD::ROTBYTES_LEFT_BITS";
432 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000433 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel67224b22008-06-02 22:18:03 +0000434 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
435 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
436 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
437 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel8efdca42007-12-04 22:23:35 +0000438 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
439 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
440 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
441 }
442
443 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
444
445 return ((i != node_names.end()) ? i->second : 0);
446}
447
Scott Michel06eabde2008-12-27 04:51:36 +0000448//===----------------------------------------------------------------------===//
449// Return the Cell SPU's SETCC result type
450//===----------------------------------------------------------------------===//
451
Dan Gohman8181bd12008-07-27 21:46:04 +0000452MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands92c43912008-06-06 12:08:01 +0000453 MVT VT = Op.getValueType();
Scott Michel06eabde2008-12-27 04:51:36 +0000454 // i16 and i32 are valid SETCC result types
455 return ((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) ? VT : MVT::i32);
Scott Michel53ab7792008-03-10 16:58:52 +0000456}
457
Scott Michel8efdca42007-12-04 22:23:35 +0000458//===----------------------------------------------------------------------===//
459// Calling convention code:
460//===----------------------------------------------------------------------===//
461
462#include "SPUGenCallingConv.inc"
463
464//===----------------------------------------------------------------------===//
465// LowerOperation implementation
466//===----------------------------------------------------------------------===//
467
468/// Custom lower loads for CellSPU
469/*!
470 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
471 within a 16-byte block, we have to rotate to extract the requested element.
Scott Michel6ccefab2008-12-04 03:02:42 +0000472
473 For extending loads, we also want to ensure that the following sequence is
474 emitted, e.g. for MVT::f32 extending load to MVT::f64:
475
476\verbatim
Scott Michelae5cbf52008-12-29 03:23:36 +0000477%1 v16i8,ch = load
Scott Michel6ccefab2008-12-04 03:02:42 +0000478%2 v16i8,ch = rotate %1
Scott Michelae5cbf52008-12-29 03:23:36 +0000479%3 v4f8, ch = bitconvert %2
Scott Michel6ccefab2008-12-04 03:02:42 +0000480%4 f32 = vec2perfslot %3
481%5 f64 = fp_extend %4
482\endverbatim
483*/
Dan Gohman8181bd12008-07-27 21:46:04 +0000484static SDValue
485LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000486 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000487 SDValue the_chain = LN->getChain();
Scott Michel06eabde2008-12-27 04:51:36 +0000488 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel6ccefab2008-12-04 03:02:42 +0000489 MVT InVT = LN->getMemoryVT();
490 MVT OutVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000491 ISD::LoadExtType ExtType = LN->getExtensionType();
492 unsigned alignment = LN->getAlignment();
Scott Michel06eabde2008-12-27 04:51:36 +0000493 const valtype_map_s *vtm = getValueTypeMapEntry(InVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000494
Scott Michel8efdca42007-12-04 22:23:35 +0000495 switch (LN->getAddressingMode()) {
496 case ISD::UNINDEXED: {
Scott Michel06eabde2008-12-27 04:51:36 +0000497 SDValue result;
498 SDValue basePtr = LN->getBasePtr();
499 SDValue rotate;
Scott Michel8efdca42007-12-04 22:23:35 +0000500
Scott Michel06eabde2008-12-27 04:51:36 +0000501 if (alignment == 16) {
502 ConstantSDNode *CN;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000503
Scott Michel06eabde2008-12-27 04:51:36 +0000504 // Special cases for a known aligned load to simplify the base pointer
505 // and the rotation amount:
506 if (basePtr.getOpcode() == ISD::ADD
507 && (CN = dyn_cast<ConstantSDNode > (basePtr.getOperand(1))) != 0) {
508 // Known offset into basePtr
509 int64_t offset = CN->getSExtValue();
510 int64_t rotamt = int64_t((offset & 0xf) - vtm->prefslot_byte);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000511
Scott Michel06eabde2008-12-27 04:51:36 +0000512 if (rotamt < 0)
513 rotamt += 16;
514
515 rotate = DAG.getConstant(rotamt, MVT::i16);
516
517 // Simplify the base pointer for this case:
518 basePtr = basePtr.getOperand(0);
519 if ((offset & ~0xf) > 0) {
520 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
521 basePtr,
522 DAG.getConstant((offset & ~0xf), PtrVT));
523 }
524 } else if ((basePtr.getOpcode() == SPUISD::AFormAddr)
525 || (basePtr.getOpcode() == SPUISD::IndirectAddr
526 && basePtr.getOperand(0).getOpcode() == SPUISD::Hi
527 && basePtr.getOperand(1).getOpcode() == SPUISD::Lo)) {
528 // Plain aligned a-form address: rotate into preferred slot
529 // Same for (SPUindirect (SPUhi ...), (SPUlo ...))
530 int64_t rotamt = -vtm->prefslot_byte;
531 if (rotamt < 0)
532 rotamt += 16;
533 rotate = DAG.getConstant(rotamt, MVT::i16);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000534 } else {
Scott Michel06eabde2008-12-27 04:51:36 +0000535 // Offset the rotate amount by the basePtr and the preferred slot
536 // byte offset
537 int64_t rotamt = -vtm->prefslot_byte;
538 if (rotamt < 0)
539 rotamt += 16;
540 rotate = DAG.getNode(ISD::ADD, PtrVT,
541 basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000542 DAG.getConstant(rotamt, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000543 }
Scott Michel06eabde2008-12-27 04:51:36 +0000544 } else {
545 // Unaligned load: must be more pessimistic about addressing modes:
546 if (basePtr.getOpcode() == ISD::ADD) {
547 MachineFunction &MF = DAG.getMachineFunction();
548 MachineRegisterInfo &RegInfo = MF.getRegInfo();
549 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
550 SDValue Flag;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000551
Scott Michel06eabde2008-12-27 04:51:36 +0000552 SDValue Op0 = basePtr.getOperand(0);
553 SDValue Op1 = basePtr.getOperand(1);
554
555 if (isa<ConstantSDNode>(Op1)) {
556 // Convert the (add <ptr>, <const>) to an indirect address contained
557 // in a register. Note that this is done because we need to avoid
558 // creating a 0(reg) d-form address due to the SPU's block loads.
559 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
560 the_chain = DAG.getCopyToReg(the_chain, VReg, basePtr, Flag);
561 basePtr = DAG.getCopyFromReg(the_chain, VReg, PtrVT);
562 } else {
563 // Convert the (add <arg1>, <arg2>) to an indirect address, which
564 // will likely be lowered as a reg(reg) x-form address.
565 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
566 }
567 } else {
568 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
569 basePtr,
570 DAG.getConstant(0, PtrVT));
571 }
572
573 // Offset the rotate amount by the basePtr and the preferred slot
574 // byte offset
575 rotate = DAG.getNode(ISD::ADD, PtrVT,
576 basePtr,
577 DAG.getConstant(-vtm->prefslot_byte, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +0000578 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000579
Scott Michel06eabde2008-12-27 04:51:36 +0000580 // Re-emit as a v16i8 vector load
581 result = DAG.getLoad(MVT::v16i8, the_chain, basePtr,
582 LN->getSrcValue(), LN->getSrcValueOffset(),
583 LN->isVolatile(), 16);
584
585 // Update the chain
586 the_chain = result.getValue(1);
587
588 // Rotate into the preferred slot:
589 result = DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v16i8,
590 result.getValue(0), rotate);
591
Scott Michel6ccefab2008-12-04 03:02:42 +0000592 // Convert the loaded v16i8 vector to the appropriate vector type
593 // specified by the operand:
594 MVT vecVT = MVT::getVectorVT(InVT, (128 / InVT.getSizeInBits()));
595 result = DAG.getNode(SPUISD::VEC2PREFSLOT, InVT,
596 DAG.getNode(ISD::BIT_CONVERT, vecVT, result));
Scott Michel4ec722e2008-07-16 17:17:29 +0000597
Scott Michel6ccefab2008-12-04 03:02:42 +0000598 // Handle extending loads by extending the scalar result:
599 if (ExtType == ISD::SEXTLOAD) {
600 result = DAG.getNode(ISD::SIGN_EXTEND, OutVT, result);
601 } else if (ExtType == ISD::ZEXTLOAD) {
602 result = DAG.getNode(ISD::ZERO_EXTEND, OutVT, result);
603 } else if (ExtType == ISD::EXTLOAD) {
604 unsigned NewOpc = ISD::ANY_EXTEND;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000605
Scott Michel6ccefab2008-12-04 03:02:42 +0000606 if (OutVT.isFloatingPoint())
607 NewOpc = ISD::FP_EXTEND;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000608
Scott Michel6ccefab2008-12-04 03:02:42 +0000609 result = DAG.getNode(NewOpc, OutVT, result);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000610 }
611
Scott Michel6ccefab2008-12-04 03:02:42 +0000612 SDVTList retvts = DAG.getVTList(OutVT, MVT::Other);
Dan Gohman8181bd12008-07-27 21:46:04 +0000613 SDValue retops[2] = {
Scott Michel394e26d2008-01-17 20:38:41 +0000614 result,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000615 the_chain
Scott Michel394e26d2008-01-17 20:38:41 +0000616 };
Scott Micheldbac4cf2008-01-11 02:53:15 +0000617
Scott Michel394e26d2008-01-17 20:38:41 +0000618 result = DAG.getNode(SPUISD::LDRESULT, retvts,
619 retops, sizeof(retops) / sizeof(retops[0]));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000620 return result;
Scott Michel8efdca42007-12-04 22:23:35 +0000621 }
622 case ISD::PRE_INC:
623 case ISD::PRE_DEC:
624 case ISD::POST_INC:
625 case ISD::POST_DEC:
626 case ISD::LAST_INDEXED_MODE:
627 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
628 "UNINDEXED\n";
629 cerr << (unsigned) LN->getAddressingMode() << "\n";
630 abort();
631 /*NOTREACHED*/
632 }
633
Dan Gohman8181bd12008-07-27 21:46:04 +0000634 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000635}
636
637/// Custom lower stores for CellSPU
638/*!
639 All CellSPU stores are aligned to 16-byte boundaries, so for elements
640 within a 16-byte block, we have to generate a shuffle to insert the
641 requested element into its place, then store the resulting block.
642 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000643static SDValue
644LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000645 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000646 SDValue Value = SN->getValue();
Duncan Sands92c43912008-06-06 12:08:01 +0000647 MVT VT = Value.getValueType();
648 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
649 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000650 unsigned alignment = SN->getAlignment();
Scott Michel8efdca42007-12-04 22:23:35 +0000651
652 switch (SN->getAddressingMode()) {
653 case ISD::UNINDEXED: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000654 // The vector type we really want to load from the 16-byte chunk.
Scott Michele1006032008-11-19 17:45:08 +0000655 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
656 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +0000657
Scott Michel06eabde2008-12-27 04:51:36 +0000658 SDValue alignLoadVec;
659 SDValue basePtr = SN->getBasePtr();
660 SDValue the_chain = SN->getChain();
661 SDValue insertEltOffs;
Scott Michel8efdca42007-12-04 22:23:35 +0000662
Scott Michel06eabde2008-12-27 04:51:36 +0000663 if (alignment == 16) {
664 ConstantSDNode *CN;
665
666 // Special cases for a known aligned load to simplify the base pointer
667 // and insertion byte:
668 if (basePtr.getOpcode() == ISD::ADD
669 && (CN = dyn_cast<ConstantSDNode>(basePtr.getOperand(1))) != 0) {
670 // Known offset into basePtr
671 int64_t offset = CN->getSExtValue();
672
673 // Simplify the base pointer for this case:
674 basePtr = basePtr.getOperand(0);
675 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
676 basePtr,
677 DAG.getConstant((offset & 0xf), PtrVT));
678
679 if ((offset & ~0xf) > 0) {
680 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
681 basePtr,
682 DAG.getConstant((offset & ~0xf), PtrVT));
683 }
684 } else {
685 // Otherwise, assume it's at byte 0 of basePtr
686 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
687 basePtr,
688 DAG.getConstant(0, PtrVT));
689 }
690 } else {
691 // Unaligned load: must be more pessimistic about addressing modes:
692 if (basePtr.getOpcode() == ISD::ADD) {
693 MachineFunction &MF = DAG.getMachineFunction();
694 MachineRegisterInfo &RegInfo = MF.getRegInfo();
695 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
696 SDValue Flag;
697
698 SDValue Op0 = basePtr.getOperand(0);
699 SDValue Op1 = basePtr.getOperand(1);
700
701 if (isa<ConstantSDNode>(Op1)) {
702 // Convert the (add <ptr>, <const>) to an indirect address contained
703 // in a register. Note that this is done because we need to avoid
704 // creating a 0(reg) d-form address due to the SPU's block loads.
705 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
706 the_chain = DAG.getCopyToReg(the_chain, VReg, basePtr, Flag);
707 basePtr = DAG.getCopyFromReg(the_chain, VReg, PtrVT);
708 } else {
709 // Convert the (add <arg1>, <arg2>) to an indirect address, which
710 // will likely be lowered as a reg(reg) x-form address.
711 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
712 }
713 } else {
714 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
715 basePtr,
716 DAG.getConstant(0, PtrVT));
717 }
718
719 // Insertion point is solely determined by basePtr's contents
720 insertEltOffs = DAG.getNode(ISD::ADD, PtrVT,
721 basePtr,
722 DAG.getConstant(0, PtrVT));
723 }
724
725 // Re-emit as a v16i8 vector load
726 alignLoadVec = DAG.getLoad(MVT::v16i8, the_chain, basePtr,
727 SN->getSrcValue(), SN->getSrcValueOffset(),
728 SN->isVolatile(), 16);
729
730 // Update the chain
731 the_chain = alignLoadVec.getValue(1);
Scott Michel8efdca42007-12-04 22:23:35 +0000732
Scott Micheldbac4cf2008-01-11 02:53:15 +0000733 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman8181bd12008-07-27 21:46:04 +0000734 SDValue theValue = SN->getValue();
735 SDValue result;
Scott Michel8efdca42007-12-04 22:23:35 +0000736
737 if (StVT != VT
Scott Michel5a6f17b2008-01-30 02:55:46 +0000738 && (theValue.getOpcode() == ISD::AssertZext
739 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel8efdca42007-12-04 22:23:35 +0000740 // Drill down and get the value for zero- and sign-extended
741 // quantities
Scott Michel4ec722e2008-07-16 17:17:29 +0000742 theValue = theValue.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000743 }
744
Scott Micheldbac4cf2008-01-11 02:53:15 +0000745 // If the base pointer is already a D-form address, then just create
746 // a new D-form address with a slot offset and the orignal base pointer.
747 // Otherwise generate a D-form address with the slot offset relative
748 // to the stack pointer, which is always aligned.
Scott Michel06eabde2008-12-27 04:51:36 +0000749#if !defined(NDEBUG)
750 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
751 cerr << "CellSPU LowerSTORE: basePtr = ";
752 basePtr.getNode()->dump(&DAG);
753 cerr << "\n";
754 }
755#endif
Scott Micheldbac4cf2008-01-11 02:53:15 +0000756
Scott Michelf65c8f02008-11-19 15:24:16 +0000757 SDValue insertEltOp =
Scott Michel06eabde2008-12-27 04:51:36 +0000758 DAG.getNode(SPUISD::SHUFFLE_MASK, vecVT, insertEltOffs);
Scott Michele1006032008-11-19 17:45:08 +0000759 SDValue vectorizeOp =
760 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michelf65c8f02008-11-19 15:24:16 +0000761
Scott Michel0718cd82008-12-01 17:56:02 +0000762 result = DAG.getNode(SPUISD::SHUFB, vecVT,
763 vectorizeOp, alignLoadVec,
764 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, insertEltOp));
Scott Michel8efdca42007-12-04 22:23:35 +0000765
Scott Micheldbac4cf2008-01-11 02:53:15 +0000766 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel8efdca42007-12-04 22:23:35 +0000767 LN->getSrcValue(), LN->getSrcValueOffset(),
768 LN->isVolatile(), LN->getAlignment());
769
Scott Michel8c2746e2008-12-04 17:16:59 +0000770#if 0 && !defined(NDEBUG)
Scott Michelf65c8f02008-11-19 15:24:16 +0000771 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
772 const SDValue &currentRoot = DAG.getRoot();
773
774 DAG.setRoot(result);
775 cerr << "------- CellSPU:LowerStore result:\n";
776 DAG.dump();
777 cerr << "-------\n";
778 DAG.setRoot(currentRoot);
779 }
780#endif
Scott Michelec8c82e2008-12-02 19:53:53 +0000781
Scott Michel8efdca42007-12-04 22:23:35 +0000782 return result;
783 /*UNREACHED*/
784 }
785 case ISD::PRE_INC:
786 case ISD::PRE_DEC:
787 case ISD::POST_INC:
788 case ISD::POST_DEC:
789 case ISD::LAST_INDEXED_MODE:
790 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
791 "UNINDEXED\n";
792 cerr << (unsigned) SN->getAddressingMode() << "\n";
793 abort();
794 /*NOTREACHED*/
795 }
796
Dan Gohman8181bd12008-07-27 21:46:04 +0000797 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000798}
799
800/// Generate the address of a constant pool entry.
Dan Gohman8181bd12008-07-27 21:46:04 +0000801static SDValue
802LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000803 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000804 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
805 Constant *C = CP->getConstVal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000806 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
807 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000808 const TargetMachine &TM = DAG.getTarget();
Scott Michel8efdca42007-12-04 22:23:35 +0000809
810 if (TM.getRelocationModel() == Reloc::Static) {
811 if (!ST->usingLargeMem()) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000812 // Just return the SDValue with the constant pool address in it.
Scott Michel394e26d2008-01-17 20:38:41 +0000813 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +0000814 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000815 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
816 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000817 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel8efdca42007-12-04 22:23:35 +0000818 }
819 }
820
821 assert(0 &&
Gabor Greife9f7f582008-08-31 15:37:04 +0000822 "LowerConstantPool: Relocation model other than static"
823 " not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000824 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000825}
826
Dan Gohman8181bd12008-07-27 21:46:04 +0000827static SDValue
828LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000829 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000830 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000831 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
832 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000833 const TargetMachine &TM = DAG.getTarget();
834
835 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel97872d32008-02-23 18:41:37 +0000836 if (!ST->usingLargeMem()) {
837 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
838 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000839 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
840 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000841 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
842 }
Scott Michel8efdca42007-12-04 22:23:35 +0000843 }
844
845 assert(0 &&
846 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000847 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000848}
849
Dan Gohman8181bd12008-07-27 21:46:04 +0000850static SDValue
851LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000852 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000853 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
854 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000855 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel8efdca42007-12-04 22:23:35 +0000856 const TargetMachine &TM = DAG.getTarget();
Dan Gohman8181bd12008-07-27 21:46:04 +0000857 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel4ec722e2008-07-16 17:17:29 +0000858
Scott Michel8efdca42007-12-04 22:23:35 +0000859 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michelf9f42e62008-01-29 02:16:57 +0000860 if (!ST->usingLargeMem()) {
861 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
862 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000863 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
864 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michelf9f42e62008-01-29 02:16:57 +0000865 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
866 }
Scott Michel8efdca42007-12-04 22:23:35 +0000867 } else {
868 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel5a6f17b2008-01-30 02:55:46 +0000869 << "supported.\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000870 abort();
871 /*NOTREACHED*/
872 }
873
Dan Gohman8181bd12008-07-27 21:46:04 +0000874 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000875}
876
877//! Custom lower i64 integer constants
878/*!
879 This code inserts all of the necessary juggling that needs to occur to load
880 a 64-bit constant into a register.
881 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000882static SDValue
883LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000884 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000885
886 if (VT == MVT::i64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000887 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
888 SDValue T = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michelc630c412008-11-24 17:11:17 +0000889 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000890 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +0000891 } else {
892 cerr << "LowerConstant: unhandled constant type "
Duncan Sands92c43912008-06-06 12:08:01 +0000893 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +0000894 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000895 abort();
896 /*NOTREACHED*/
897 }
898
Dan Gohman8181bd12008-07-27 21:46:04 +0000899 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000900}
901
Nate Begeman78125042008-02-14 18:43:04 +0000902//! Custom lower double precision floating point constants
Dan Gohman8181bd12008-07-27 21:46:04 +0000903static SDValue
904LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000905 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000906
Nate Begeman78125042008-02-14 18:43:04 +0000907 if (VT == MVT::f64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000908 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
909
910 assert((FP != 0) &&
911 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michelae5cbf52008-12-29 03:23:36 +0000912
Scott Michel11e88bb2007-12-19 20:15:47 +0000913 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel0718cd82008-12-01 17:56:02 +0000914 SDValue T = DAG.getConstant(dbits, MVT::i64);
915 SDValue Tvec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T);
916 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
917 DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64, Tvec));
Scott Michel8efdca42007-12-04 22:23:35 +0000918 }
919
Dan Gohman8181bd12008-07-27 21:46:04 +0000920 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000921}
922
Dan Gohman8181bd12008-07-27 21:46:04 +0000923static SDValue
Scott Michel06eabde2008-12-27 04:51:36 +0000924LowerBRCOND(SDValue Op, SelectionDAG &DAG, const TargetLowering &TLI) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000925 SDValue Cond = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +0000926 MVT CondVT = Cond.getValueType();
Scott Michel06eabde2008-12-27 04:51:36 +0000927 unsigned CondOpc;
Scott Michel394e26d2008-01-17 20:38:41 +0000928
Scott Michel33d73eb2008-11-21 02:56:16 +0000929 if (CondVT == MVT::i8) {
Scott Michel06eabde2008-12-27 04:51:36 +0000930 SDValue CondOp0 = Cond.getOperand(0);
931 if (Cond.getOpcode() == ISD::TRUNCATE) {
932 // Use the truncate's value type and ANY_EXTEND the condition (DAGcombine
933 // will then remove the truncate)
934 CondVT = CondOp0.getValueType();
935 CondOpc = ISD::ANY_EXTEND;
936 } else {
937 CondVT = MVT::i32; // default to something reasonable
938 CondOpc = ISD::ZERO_EXTEND;
939 }
940
941 Cond = DAG.getNode(CondOpc, CondVT, Op.getOperand(1));
942
Scott Michel394e26d2008-01-17 20:38:41 +0000943 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
Scott Michel06eabde2008-12-27 04:51:36 +0000944 Op.getOperand(0), Cond, Op.getOperand(2));
945 }
Scott Michelae5cbf52008-12-29 03:23:36 +0000946
Scott Michel06eabde2008-12-27 04:51:36 +0000947 return SDValue(); // Unchanged
Scott Michel394e26d2008-01-17 20:38:41 +0000948}
949
Dan Gohman8181bd12008-07-27 21:46:04 +0000950static SDValue
951LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel8efdca42007-12-04 22:23:35 +0000952{
953 MachineFunction &MF = DAG.getMachineFunction();
954 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner1b989192007-12-31 04:13:23 +0000955 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michela313fb02008-10-30 01:51:48 +0000956 SmallVector<SDValue, 48> ArgValues;
Dan Gohman8181bd12008-07-27 21:46:04 +0000957 SDValue Root = Op.getOperand(0);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000958 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel8efdca42007-12-04 22:23:35 +0000959
960 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
961 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel4ec722e2008-07-16 17:17:29 +0000962
Scott Michel8efdca42007-12-04 22:23:35 +0000963 unsigned ArgOffset = SPUFrameInfo::minStackSize();
964 unsigned ArgRegIdx = 0;
965 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel4ec722e2008-07-16 17:17:29 +0000966
Duncan Sands92c43912008-06-06 12:08:01 +0000967 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +0000968
Scott Michel8efdca42007-12-04 22:23:35 +0000969 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greife9f7f582008-08-31 15:37:04 +0000970 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
971 ArgNo != e; ++ArgNo) {
Duncan Sands92c43912008-06-06 12:08:01 +0000972 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
973 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michela313fb02008-10-30 01:51:48 +0000974 SDValue ArgVal;
Scott Michel8efdca42007-12-04 22:23:35 +0000975
Scott Michela313fb02008-10-30 01:51:48 +0000976 if (ArgRegIdx < NumArgRegs) {
977 const TargetRegisterClass *ArgRegClass;
Scott Michel4ec722e2008-07-16 17:17:29 +0000978
Scott Michela313fb02008-10-30 01:51:48 +0000979 switch (ObjectVT.getSimpleVT()) {
980 default: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000981 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
982 << ObjectVT.getMVTString()
983 << "\n";
984 abort();
Scott Michela313fb02008-10-30 01:51:48 +0000985 }
986 case MVT::i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000987 ArgRegClass = &SPU::R8CRegClass;
988 break;
Scott Michela313fb02008-10-30 01:51:48 +0000989 case MVT::i16:
Scott Michel33d73eb2008-11-21 02:56:16 +0000990 ArgRegClass = &SPU::R16CRegClass;
991 break;
Scott Michela313fb02008-10-30 01:51:48 +0000992 case MVT::i32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000993 ArgRegClass = &SPU::R32CRegClass;
994 break;
Scott Michela313fb02008-10-30 01:51:48 +0000995 case MVT::i64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000996 ArgRegClass = &SPU::R64CRegClass;
997 break;
Scott Michela313fb02008-10-30 01:51:48 +0000998 case MVT::f32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000999 ArgRegClass = &SPU::R32FPRegClass;
1000 break;
Scott Michela313fb02008-10-30 01:51:48 +00001001 case MVT::f64:
Scott Michel33d73eb2008-11-21 02:56:16 +00001002 ArgRegClass = &SPU::R64FPRegClass;
1003 break;
Scott Michela313fb02008-10-30 01:51:48 +00001004 case MVT::v2f64:
1005 case MVT::v4f32:
1006 case MVT::v2i64:
1007 case MVT::v4i32:
1008 case MVT::v8i16:
1009 case MVT::v16i8:
Scott Michel33d73eb2008-11-21 02:56:16 +00001010 ArgRegClass = &SPU::VECREGRegClass;
1011 break;
Scott Michela313fb02008-10-30 01:51:48 +00001012 }
1013
1014 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
1015 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
1016 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1017 ++ArgRegIdx;
1018 } else {
1019 // We need to load the argument to a virtual register if we determined
1020 // above that we ran out of physical registers of the appropriate type
1021 // or we're forced to do vararg
Chris Lattner60069452008-02-13 07:35:30 +00001022 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman8181bd12008-07-27 21:46:04 +00001023 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner60069452008-02-13 07:35:30 +00001024 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel8efdca42007-12-04 22:23:35 +00001025 ArgOffset += StackSlotSize;
1026 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001027
Scott Michel8efdca42007-12-04 22:23:35 +00001028 ArgValues.push_back(ArgVal);
Scott Michela313fb02008-10-30 01:51:48 +00001029 // Update the chain
1030 Root = ArgVal.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001031 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001032
Scott Michela313fb02008-10-30 01:51:48 +00001033 // vararg handling:
Scott Michel8efdca42007-12-04 22:23:35 +00001034 if (isVarArg) {
Scott Michela313fb02008-10-30 01:51:48 +00001035 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1036 // We will spill (79-3)+1 registers to the stack
1037 SmallVector<SDValue, 79-3+1> MemOps;
1038
1039 // Create the frame slot
1040
Scott Michel8efdca42007-12-04 22:23:35 +00001041 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Michela313fb02008-10-30 01:51:48 +00001042 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1043 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1044 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1045 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1046 Root = Store.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001047 MemOps.push_back(Store);
Scott Michela313fb02008-10-30 01:51:48 +00001048
1049 // Increment address by stack slot size for the next stored argument
1050 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001051 }
1052 if (!MemOps.empty())
Scott Michela313fb02008-10-30 01:51:48 +00001053 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001054 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001055
Scott Michel8efdca42007-12-04 22:23:35 +00001056 ArgValues.push_back(Root);
Scott Michel4ec722e2008-07-16 17:17:29 +00001057
Scott Michel8efdca42007-12-04 22:23:35 +00001058 // Return the new list of results.
Duncan Sands42d7bb82008-12-01 11:41:29 +00001059 return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(),
1060 &ArgValues[0], ArgValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001061}
1062
1063/// isLSAAddress - Return the immediate to use if the specified
1064/// value is representable as a LSA address.
Dan Gohman8181bd12008-07-27 21:46:04 +00001065static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel5974f432008-11-11 03:06:06 +00001066 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel8efdca42007-12-04 22:23:35 +00001067 if (!C) return 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001068
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001069 int Addr = C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001070 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1071 (Addr << 14 >> 14) != Addr)
1072 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel4ec722e2008-07-16 17:17:29 +00001073
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001074 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel8efdca42007-12-04 22:23:35 +00001075}
1076
1077static
Dan Gohman8181bd12008-07-27 21:46:04 +00001078SDValue
1079LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001080 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1081 SDValue Chain = TheCall->getChain();
Dan Gohman705e3f72008-09-13 01:54:27 +00001082 SDValue Callee = TheCall->getCallee();
1083 unsigned NumOps = TheCall->getNumArgs();
Scott Michel8efdca42007-12-04 22:23:35 +00001084 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1085 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1086 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1087
1088 // Handy pointer type
Duncan Sands92c43912008-06-06 12:08:01 +00001089 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +00001090
Scott Michel8efdca42007-12-04 22:23:35 +00001091 // Accumulate how many bytes are to be pushed on the stack, including the
1092 // linkage area, and parameter passing area. According to the SPU ABI,
1093 // we minimally need space for [LR] and [SP]
1094 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel4ec722e2008-07-16 17:17:29 +00001095
Scott Michel8efdca42007-12-04 22:23:35 +00001096 // Set up a copy of the stack pointer for use loading and storing any
1097 // arguments that may not fit in the registers available for argument
1098 // passing.
Dan Gohman8181bd12008-07-27 21:46:04 +00001099 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel4ec722e2008-07-16 17:17:29 +00001100
Scott Michel8efdca42007-12-04 22:23:35 +00001101 // Figure out which arguments are going to go in registers, and which in
1102 // memory.
1103 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1104 unsigned ArgRegIdx = 0;
1105
1106 // Keep track of registers passing arguments
Dan Gohman8181bd12008-07-27 21:46:04 +00001107 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel8efdca42007-12-04 22:23:35 +00001108 // And the arguments passed on the stack
Dan Gohman8181bd12008-07-27 21:46:04 +00001109 SmallVector<SDValue, 8> MemOpChains;
Scott Michel8efdca42007-12-04 22:23:35 +00001110
1111 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001112 SDValue Arg = TheCall->getArg(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001113
Scott Michel8efdca42007-12-04 22:23:35 +00001114 // PtrOff will be used to store the current argument to the stack if a
1115 // register cannot be found for it.
Dan Gohman8181bd12008-07-27 21:46:04 +00001116 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel8efdca42007-12-04 22:23:35 +00001117 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1118
Duncan Sands92c43912008-06-06 12:08:01 +00001119 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001120 default: assert(0 && "Unexpected ValueType for argument!");
1121 case MVT::i32:
1122 case MVT::i64:
1123 case MVT::i128:
1124 if (ArgRegIdx != NumArgRegs) {
1125 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1126 } else {
1127 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001128 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001129 }
1130 break;
1131 case MVT::f32:
1132 case MVT::f64:
1133 if (ArgRegIdx != NumArgRegs) {
1134 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1135 } else {
1136 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001137 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001138 }
1139 break;
Scott Michele2641a12008-12-04 21:01:44 +00001140 case MVT::v2i64:
1141 case MVT::v2f64:
Scott Michel8efdca42007-12-04 22:23:35 +00001142 case MVT::v4f32:
1143 case MVT::v4i32:
1144 case MVT::v8i16:
1145 case MVT::v16i8:
1146 if (ArgRegIdx != NumArgRegs) {
1147 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1148 } else {
1149 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001150 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001151 }
1152 break;
1153 }
1154 }
1155
1156 // Update number of stack bytes actually used, insert a call sequence start
1157 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001158 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1159 true));
Scott Michel8efdca42007-12-04 22:23:35 +00001160
1161 if (!MemOpChains.empty()) {
1162 // Adjust the stack pointer for the stack arguments.
1163 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1164 &MemOpChains[0], MemOpChains.size());
1165 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001166
Scott Michel8efdca42007-12-04 22:23:35 +00001167 // Build a sequence of copy-to-reg nodes chained together with token chain
1168 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman8181bd12008-07-27 21:46:04 +00001169 SDValue InFlag;
Scott Michel8efdca42007-12-04 22:23:35 +00001170 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1171 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1172 InFlag);
1173 InFlag = Chain.getValue(1);
1174 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001175
Dan Gohman8181bd12008-07-27 21:46:04 +00001176 SmallVector<SDValue, 8> Ops;
Scott Michel8efdca42007-12-04 22:23:35 +00001177 unsigned CallOpc = SPUISD::CALL;
Scott Michel4ec722e2008-07-16 17:17:29 +00001178
Bill Wendlingfef06052008-09-16 21:48:12 +00001179 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1180 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1181 // node so that legalize doesn't hack it.
Scott Michel5974f432008-11-11 03:06:06 +00001182 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001183 GlobalValue *GV = G->getGlobal();
Duncan Sands92c43912008-06-06 12:08:01 +00001184 MVT CalleeVT = Callee.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001185 SDValue Zero = DAG.getConstant(0, PtrVT);
1186 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001187
Scott Micheldbac4cf2008-01-11 02:53:15 +00001188 if (!ST->usingLargeMem()) {
1189 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1190 // style calls, otherwise, external symbols are BRASL calls. This assumes
1191 // that declared/defined symbols are in the same compilation unit and can
1192 // be reached through PC-relative jumps.
1193 //
1194 // NOTE:
1195 // This may be an unsafe assumption for JIT and really large compilation
1196 // units.
1197 if (GV->isDeclaration()) {
1198 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1199 } else {
1200 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1201 }
Scott Michel8efdca42007-12-04 22:23:35 +00001202 } else {
Scott Micheldbac4cf2008-01-11 02:53:15 +00001203 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1204 // address pairs:
Scott Michelf9f42e62008-01-29 02:16:57 +00001205 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +00001206 }
Scott Michelae5cbf52008-12-29 03:23:36 +00001207 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
1208 MVT CalleeVT = Callee.getValueType();
1209 SDValue Zero = DAG.getConstant(0, PtrVT);
1210 SDValue ExtSym = DAG.getTargetExternalSymbol(S->getSymbol(),
1211 Callee.getValueType());
1212
1213 if (!ST->usingLargeMem()) {
1214 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, ExtSym, Zero);
1215 } else {
1216 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, ExtSym, Zero);
1217 }
1218 } else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001219 // If this is an absolute destination address that appears to be a legal
1220 // local store address, use the munged value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001221 Callee = SDValue(Dest, 0);
Scott Micheldbac4cf2008-01-11 02:53:15 +00001222 }
Scott Michel8efdca42007-12-04 22:23:35 +00001223
1224 Ops.push_back(Chain);
1225 Ops.push_back(Callee);
Scott Michel4ec722e2008-07-16 17:17:29 +00001226
Scott Michel8efdca42007-12-04 22:23:35 +00001227 // Add argument registers to the end of the list so that they are known live
1228 // into the call.
1229 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel4ec722e2008-07-16 17:17:29 +00001230 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel8efdca42007-12-04 22:23:35 +00001231 RegsToPass[i].second.getValueType()));
Scott Michel4ec722e2008-07-16 17:17:29 +00001232
Gabor Greif1c80d112008-08-28 21:40:38 +00001233 if (InFlag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001234 Ops.push_back(InFlag);
Duncan Sands698842f2008-07-02 17:40:58 +00001235 // Returns a chain and a flag for retval copy to use.
1236 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1237 &Ops[0], Ops.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001238 InFlag = Chain.getValue(1);
1239
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001240 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1241 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman705e3f72008-09-13 01:54:27 +00001242 if (TheCall->getValueType(0) != MVT::Other)
Evan Cheng07322bb2008-02-05 22:44:06 +00001243 InFlag = Chain.getValue(1);
1244
Dan Gohman8181bd12008-07-27 21:46:04 +00001245 SDValue ResultVals[3];
Scott Michel8efdca42007-12-04 22:23:35 +00001246 unsigned NumResults = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001247
Scott Michel8efdca42007-12-04 22:23:35 +00001248 // If the call has results, copy the values out of the ret val registers.
Dan Gohman705e3f72008-09-13 01:54:27 +00001249 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001250 default: assert(0 && "Unexpected ret value!");
1251 case MVT::Other: break;
1252 case MVT::i32:
Dan Gohman705e3f72008-09-13 01:54:27 +00001253 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001254 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1255 ResultVals[0] = Chain.getValue(0);
1256 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1257 Chain.getValue(2)).getValue(1);
1258 ResultVals[1] = Chain.getValue(0);
1259 NumResults = 2;
Scott Michel8efdca42007-12-04 22:23:35 +00001260 } else {
1261 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1262 ResultVals[0] = Chain.getValue(0);
1263 NumResults = 1;
1264 }
Scott Michel8efdca42007-12-04 22:23:35 +00001265 break;
1266 case MVT::i64:
1267 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1268 ResultVals[0] = Chain.getValue(0);
1269 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001270 break;
1271 case MVT::f32:
1272 case MVT::f64:
Dan Gohman705e3f72008-09-13 01:54:27 +00001273 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001274 InFlag).getValue(1);
1275 ResultVals[0] = Chain.getValue(0);
1276 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001277 break;
1278 case MVT::v2f64:
Scott Michele2641a12008-12-04 21:01:44 +00001279 case MVT::v2i64:
Scott Michel8efdca42007-12-04 22:23:35 +00001280 case MVT::v4f32:
1281 case MVT::v4i32:
1282 case MVT::v8i16:
1283 case MVT::v16i8:
Dan Gohman705e3f72008-09-13 01:54:27 +00001284 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001285 InFlag).getValue(1);
1286 ResultVals[0] = Chain.getValue(0);
1287 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001288 break;
1289 }
Duncan Sands698842f2008-07-02 17:40:58 +00001290
Scott Michel8efdca42007-12-04 22:23:35 +00001291 // If the function returns void, just return the chain.
1292 if (NumResults == 0)
1293 return Chain;
Scott Michel4ec722e2008-07-16 17:17:29 +00001294
Scott Michel8efdca42007-12-04 22:23:35 +00001295 // Otherwise, merge everything together with a MERGE_VALUES node.
1296 ResultVals[NumResults++] = Chain;
Dan Gohman8181bd12008-07-27 21:46:04 +00001297 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif46bf5472008-08-26 22:36:50 +00001298 return Res.getValue(Op.getResNo());
Scott Michel8efdca42007-12-04 22:23:35 +00001299}
1300
Dan Gohman8181bd12008-07-27 21:46:04 +00001301static SDValue
1302LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel8efdca42007-12-04 22:23:35 +00001303 SmallVector<CCValAssign, 16> RVLocs;
1304 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1305 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1306 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greif1c80d112008-08-28 21:40:38 +00001307 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel4ec722e2008-07-16 17:17:29 +00001308
Scott Michel8efdca42007-12-04 22:23:35 +00001309 // If this is the first return lowered for this function, add the regs to the
1310 // liveout set for the function.
Chris Lattner1b989192007-12-31 04:13:23 +00001311 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001312 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner1b989192007-12-31 04:13:23 +00001313 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel8efdca42007-12-04 22:23:35 +00001314 }
1315
Dan Gohman8181bd12008-07-27 21:46:04 +00001316 SDValue Chain = Op.getOperand(0);
1317 SDValue Flag;
Scott Michel4ec722e2008-07-16 17:17:29 +00001318
Scott Michel8efdca42007-12-04 22:23:35 +00001319 // Copy the result values into the output registers.
1320 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1321 CCValAssign &VA = RVLocs[i];
1322 assert(VA.isRegLoc() && "Can only return in registers!");
1323 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1324 Flag = Chain.getValue(1);
1325 }
1326
Gabor Greif1c80d112008-08-28 21:40:38 +00001327 if (Flag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001328 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1329 else
1330 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1331}
1332
1333
1334//===----------------------------------------------------------------------===//
1335// Vector related lowering:
1336//===----------------------------------------------------------------------===//
1337
1338static ConstantSDNode *
1339getVecImm(SDNode *N) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001340 SDValue OpVal(0, 0);
Scott Michel4ec722e2008-07-16 17:17:29 +00001341
Scott Michel8efdca42007-12-04 22:23:35 +00001342 // Check to see if this buildvec has a single non-undef value in its elements.
1343 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1344 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greif1c80d112008-08-28 21:40:38 +00001345 if (OpVal.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +00001346 OpVal = N->getOperand(i);
1347 else if (OpVal != N->getOperand(i))
1348 return 0;
1349 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001350
Gabor Greif1c80d112008-08-28 21:40:38 +00001351 if (OpVal.getNode() != 0) {
Scott Michel5974f432008-11-11 03:06:06 +00001352 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001353 return CN;
1354 }
1355 }
1356
1357 return 0; // All UNDEF: use implicit def.; not Constant node
1358}
1359
1360/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1361/// and the value fits into an unsigned 18-bit constant, and if so, return the
1362/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001363SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001364 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001365 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001366 uint64_t Value = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001367 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001368 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001369 uint32_t upper = uint32_t(UValue >> 32);
1370 uint32_t lower = uint32_t(UValue);
1371 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001372 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001373 Value = Value >> 32;
1374 }
Scott Michel8efdca42007-12-04 22:23:35 +00001375 if (Value <= 0x3ffff)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001376 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001377 }
1378
Dan Gohman8181bd12008-07-27 21:46:04 +00001379 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001380}
1381
1382/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1383/// and the value fits into a signed 16-bit constant, and if so, return the
1384/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001385SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001386 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001387 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001388 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001389 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001390 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001391 uint32_t upper = uint32_t(UValue >> 32);
1392 uint32_t lower = uint32_t(UValue);
1393 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001394 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001395 Value = Value >> 32;
1396 }
Scott Michel6baba072008-03-05 23:02:02 +00001397 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001398 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001399 }
1400 }
1401
Dan Gohman8181bd12008-07-27 21:46:04 +00001402 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001403}
1404
1405/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1406/// and the value fits into a signed 10-bit constant, and if so, return the
1407/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001408SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001409 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001410 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001411 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001412 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001413 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001414 uint32_t upper = uint32_t(UValue >> 32);
1415 uint32_t lower = uint32_t(UValue);
1416 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001417 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001418 Value = Value >> 32;
1419 }
Scott Michel6baba072008-03-05 23:02:02 +00001420 if (isS10Constant(Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001421 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001422 }
1423
Dan Gohman8181bd12008-07-27 21:46:04 +00001424 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001425}
1426
1427/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1428/// and the value fits into a signed 8-bit constant, and if so, return the
1429/// constant.
1430///
1431/// @note: The incoming vector is v16i8 because that's the only way we can load
1432/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1433/// same value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001434SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001435 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001436 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001437 int Value = (int) CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001438 if (ValueType == MVT::i16
Scott Michel5a6f17b2008-01-30 02:55:46 +00001439 && Value <= 0xffff /* truncated from uint64_t */
1440 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001441 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001442 else if (ValueType == MVT::i8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001443 && (Value & 0xff) == Value)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001444 return DAG.getTargetConstant(Value, 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_ILHUvec_imm - Test if this vector is a vector filled with the same value
1451/// and the value fits into a signed 16-bit constant, and if so, return the
1452/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001453SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001454 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001455 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001456 uint64_t Value = CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001457 if ((ValueType == MVT::i32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001458 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1459 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001460 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001461 }
1462
Dan Gohman8181bd12008-07-27 21:46:04 +00001463 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001464}
1465
1466/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001467SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001468 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001469 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001470 }
1471
Dan Gohman8181bd12008-07-27 21:46:04 +00001472 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001473}
1474
1475/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001476SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001477 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001478 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001479 }
1480
Dan Gohman8181bd12008-07-27 21:46:04 +00001481 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001482}
1483
1484// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001485// UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001486// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1487// zero. Return true if this is not an array of constants, false if it is.
1488//
1489static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1490 uint64_t UndefBits[2]) {
1491 // Start with zero'd results.
1492 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001493
Duncan Sands92c43912008-06-06 12:08:01 +00001494 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel8efdca42007-12-04 22:23:35 +00001495 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001496 SDValue OpVal = BV->getOperand(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001497
Scott Michel8efdca42007-12-04 22:23:35 +00001498 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1499 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1500
1501 uint64_t EltBits = 0;
1502 if (OpVal.getOpcode() == ISD::UNDEF) {
1503 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1504 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1505 continue;
Scott Michel5974f432008-11-11 03:06:06 +00001506 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001507 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel5974f432008-11-11 03:06:06 +00001508 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001509 const APFloat &apf = CN->getValueAPF();
1510 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001511 ? FloatToBits(apf.convertToFloat())
1512 : DoubleToBits(apf.convertToDouble()));
Scott Michel8efdca42007-12-04 22:23:35 +00001513 } else {
1514 // Nonconstant element.
1515 return true;
1516 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001517
Scott Michel8efdca42007-12-04 22:23:35 +00001518 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1519 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001520
1521 //printf("%llx %llx %llx %llx\n",
Scott Michel8efdca42007-12-04 22:23:35 +00001522 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1523 return false;
1524}
1525
1526/// If this is a splat (repetition) of a value across the whole vector, return
1527/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel4ec722e2008-07-16 17:17:29 +00001528/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel8efdca42007-12-04 22:23:35 +00001529/// SplatSize = 1 byte.
Scott Michel4ec722e2008-07-16 17:17:29 +00001530static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel8efdca42007-12-04 22:23:35 +00001531 const uint64_t Undef128[2],
Scott Michel5a6f17b2008-01-30 02:55:46 +00001532 int MinSplatBits,
Scott Michel8efdca42007-12-04 22:23:35 +00001533 uint64_t &SplatBits, uint64_t &SplatUndef,
1534 int &SplatSize) {
1535 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1536 // the same as the lower 64-bits, ignoring undefs.
1537 uint64_t Bits64 = Bits128[0] | Bits128[1];
1538 uint64_t Undef64 = Undef128[0] & Undef128[1];
1539 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1540 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1541 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1542 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1543
1544 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1545 if (MinSplatBits < 64) {
Scott Michel4ec722e2008-07-16 17:17:29 +00001546
Scott Michel8efdca42007-12-04 22:23:35 +00001547 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1548 // undefs.
1549 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001550 if (MinSplatBits < 32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001551
Scott Michel5a6f17b2008-01-30 02:55:46 +00001552 // If the top 16-bits are different than the lower 16-bits, ignoring
1553 // undefs, we have an i32 splat.
1554 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1555 if (MinSplatBits < 16) {
1556 // If the top 8-bits are different than the lower 8-bits, ignoring
1557 // undefs, we have an i16 splat.
Gabor Greife9f7f582008-08-31 15:37:04 +00001558 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1559 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001560 // Otherwise, we have an 8-bit splat.
1561 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1562 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1563 SplatSize = 1;
1564 return true;
1565 }
1566 } else {
1567 SplatBits = Bits16;
1568 SplatUndef = Undef16;
1569 SplatSize = 2;
1570 return true;
1571 }
1572 }
1573 } else {
1574 SplatBits = Bits32;
1575 SplatUndef = Undef32;
1576 SplatSize = 4;
1577 return true;
1578 }
Scott Michel8efdca42007-12-04 22:23:35 +00001579 }
1580 } else {
1581 SplatBits = Bits128[0];
1582 SplatUndef = Undef128[0];
1583 SplatSize = 8;
1584 return true;
1585 }
1586 }
1587
1588 return false; // Can't be a splat if two pieces don't match.
1589}
1590
1591// If this is a case we can't handle, return null and let the default
1592// expansion code take care of it. If we CAN select this case, and if it
1593// selects to a single instruction, return Op. Otherwise, if we can codegen
1594// this case more efficiently than a constant pool load, lower it to the
1595// sequence of ops that should be used.
Dan Gohman8181bd12008-07-27 21:46:04 +00001596static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001597 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00001598 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001599 // UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001600 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel4ec722e2008-07-16 17:17:29 +00001601 // zero.
Scott Michel8efdca42007-12-04 22:23:35 +00001602 uint64_t VectorBits[2];
1603 uint64_t UndefBits[2];
1604 uint64_t SplatBits, SplatUndef;
1605 int SplatSize;
Gabor Greif1c80d112008-08-28 21:40:38 +00001606 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel8efdca42007-12-04 22:23:35 +00001607 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00001608 VT.getVectorElementType().getSizeInBits(),
Scott Michel8efdca42007-12-04 22:23:35 +00001609 SplatBits, SplatUndef, SplatSize))
Dan Gohman8181bd12008-07-27 21:46:04 +00001610 return SDValue(); // Not a constant vector, not a splat.
Scott Michel4ec722e2008-07-16 17:17:29 +00001611
Duncan Sands92c43912008-06-06 12:08:01 +00001612 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001613 default:
1614 case MVT::v4f32: {
1615 uint32_t Value32 = SplatBits;
1616 assert(SplatSize == 4
Scott Michel5a6f17b2008-01-30 02:55:46 +00001617 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel8efdca42007-12-04 22:23:35 +00001618 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001619 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001620 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001621 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001622 break;
1623 }
1624 case MVT::v2f64: {
1625 uint64_t f64val = SplatBits;
1626 assert(SplatSize == 8
Scott Michelc630c412008-11-24 17:11:17 +00001627 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel8efdca42007-12-04 22:23:35 +00001628 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001629 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001630 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001631 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001632 break;
1633 }
1634 case MVT::v16i8: {
1635 // 8-bit constants have to be expanded to 16-bits
1636 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman8181bd12008-07-27 21:46:04 +00001637 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001638 for (int i = 0; i < 8; ++i)
1639 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1640 return DAG.getNode(ISD::BIT_CONVERT, VT,
1641 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1642 }
1643 case MVT::v8i16: {
1644 unsigned short Value16;
Scott Michel4ec722e2008-07-16 17:17:29 +00001645 if (SplatSize == 2)
Scott Michel8efdca42007-12-04 22:23:35 +00001646 Value16 = (unsigned short) (SplatBits & 0xffff);
1647 else
1648 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman8181bd12008-07-27 21:46:04 +00001649 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1650 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001651 for (int i = 0; i < 8; ++i) Ops[i] = T;
1652 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1653 }
1654 case MVT::v4i32: {
1655 unsigned int Value = SplatBits;
Dan Gohman8181bd12008-07-27 21:46:04 +00001656 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel8efdca42007-12-04 22:23:35 +00001657 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1658 }
1659 case MVT::v2i64: {
1660 uint64_t val = SplatBits;
1661 uint32_t upper = uint32_t(val >> 32);
1662 uint32_t lower = uint32_t(val);
1663
Scott Michelbcc7b672008-03-06 04:02:54 +00001664 if (upper == lower) {
1665 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman8181bd12008-07-27 21:46:04 +00001666 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michelbcc7b672008-03-06 04:02:54 +00001667 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michel6baba072008-03-05 23:02:02 +00001668 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +00001669 SDValue LO32;
1670 SDValue HI32;
1671 SmallVector<SDValue, 16> ShufBytes;
1672 SDValue Result;
Scott Michel8efdca42007-12-04 22:23:35 +00001673 bool upper_special, lower_special;
1674
1675 // NOTE: This code creates common-case shuffle masks that can be easily
1676 // detected as common expressions. It is not attempting to create highly
1677 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1678
1679 // Detect if the upper or lower half is a special shuffle mask pattern:
Scott Michelc630c412008-11-24 17:11:17 +00001680 upper_special = (upper == 0||upper == 0xffffffff||upper == 0x80000000);
1681 lower_special = (lower == 0||lower == 0xffffffff||lower == 0x80000000);
Scott Michel8efdca42007-12-04 22:23:35 +00001682
1683 // Create lower vector if not a special pattern
1684 if (!lower_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001685 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001686 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1687 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1688 LO32C, LO32C, LO32C, LO32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001689 }
1690
1691 // Create upper vector if not a special pattern
1692 if (!upper_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001693 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001694 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1695 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1696 HI32C, HI32C, HI32C, HI32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001697 }
1698
1699 // If either upper or lower are special, then the two input operands are
1700 // the same (basically, one of them is a "don't care")
1701 if (lower_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001702 LO32 = HI32;
Scott Michel8efdca42007-12-04 22:23:35 +00001703 if (upper_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001704 HI32 = LO32;
Scott Michel8efdca42007-12-04 22:23:35 +00001705 if (lower_special && upper_special) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001706 // Unhappy situation... both upper and lower are special, so punt with
1707 // a target constant:
Dan Gohman8181bd12008-07-27 21:46:04 +00001708 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001709 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel8efdca42007-12-04 22:23:35 +00001710 Zero, Zero);
1711 }
1712
1713 for (int i = 0; i < 4; ++i) {
Scott Michel67224b22008-06-02 22:18:03 +00001714 uint64_t val = 0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001715 for (int j = 0; j < 4; ++j) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001716 SDValue V;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001717 bool process_upper, process_lower;
Scott Michel67224b22008-06-02 22:18:03 +00001718 val <<= 8;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001719 process_upper = (upper_special && (i & 1) == 0);
1720 process_lower = (lower_special && (i & 1) == 1);
Scott Michel8efdca42007-12-04 22:23:35 +00001721
Scott Michel5a6f17b2008-01-30 02:55:46 +00001722 if (process_upper || process_lower) {
1723 if ((process_upper && upper == 0)
1724 || (process_lower && lower == 0))
Scott Michel67224b22008-06-02 22:18:03 +00001725 val |= 0x80;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001726 else if ((process_upper && upper == 0xffffffff)
1727 || (process_lower && lower == 0xffffffff))
Scott Michel67224b22008-06-02 22:18:03 +00001728 val |= 0xc0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001729 else if ((process_upper && upper == 0x80000000)
1730 || (process_lower && lower == 0x80000000))
Scott Michel67224b22008-06-02 22:18:03 +00001731 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001732 } else
Scott Michel67224b22008-06-02 22:18:03 +00001733 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001734 }
Scott Michel67224b22008-06-02 22:18:03 +00001735
1736 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001737 }
1738
1739 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel67224b22008-06-02 22:18:03 +00001740 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001741 &ShufBytes[0], ShufBytes.size()));
Scott Michel8efdca42007-12-04 22:23:35 +00001742 }
1743 }
1744 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001745
Dan Gohman8181bd12008-07-27 21:46:04 +00001746 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001747}
1748
1749/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1750/// which the Cell can operate. The code inspects V3 to ascertain whether the
1751/// permutation vector, V3, is monotonically increasing with one "exception"
1752/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel56a125e2008-11-22 23:50:42 +00001753/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel8efdca42007-12-04 22:23:35 +00001754/// In either case, the net result is going to eventually invoke SHUFB to
1755/// permute/shuffle the bytes from V1 and V2.
1756/// \note
Scott Michel56a125e2008-11-22 23:50:42 +00001757/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel8efdca42007-12-04 22:23:35 +00001758/// control word for byte/halfword/word insertion. This takes care of a single
1759/// element move from V2 into V1.
1760/// \note
1761/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman8181bd12008-07-27 21:46:04 +00001762static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1763 SDValue V1 = Op.getOperand(0);
1764 SDValue V2 = Op.getOperand(1);
1765 SDValue PermMask = Op.getOperand(2);
Scott Michel4ec722e2008-07-16 17:17:29 +00001766
Scott Michel8efdca42007-12-04 22:23:35 +00001767 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel4ec722e2008-07-16 17:17:29 +00001768
Scott Michel8efdca42007-12-04 22:23:35 +00001769 // If we have a single element being moved from V1 to V2, this can be handled
1770 // using the C*[DX] compute mask instructions, but the vector elements have
1771 // to be monotonically increasing with one exception element.
Scott Michele2641a12008-12-04 21:01:44 +00001772 MVT VecVT = V1.getValueType();
1773 MVT EltVT = VecVT.getVectorElementType();
Scott Michel8efdca42007-12-04 22:23:35 +00001774 unsigned EltsFromV2 = 0;
1775 unsigned V2Elt = 0;
1776 unsigned V2EltIdx0 = 0;
1777 unsigned CurrElt = 0;
Scott Michele2641a12008-12-04 21:01:44 +00001778 unsigned MaxElts = VecVT.getVectorNumElements();
1779 unsigned PrevElt = 0;
1780 unsigned V0Elt = 0;
Scott Michel8efdca42007-12-04 22:23:35 +00001781 bool monotonic = true;
Scott Michele2641a12008-12-04 21:01:44 +00001782 bool rotate = true;
1783
1784 if (EltVT == MVT::i8) {
Scott Michel8efdca42007-12-04 22:23:35 +00001785 V2EltIdx0 = 16;
Scott Michele2641a12008-12-04 21:01:44 +00001786 } else if (EltVT == MVT::i16) {
Scott Michel8efdca42007-12-04 22:23:35 +00001787 V2EltIdx0 = 8;
Scott Michele2641a12008-12-04 21:01:44 +00001788 } else if (EltVT == MVT::i32 || EltVT == MVT::f32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001789 V2EltIdx0 = 4;
Scott Michele2641a12008-12-04 21:01:44 +00001790 } else if (EltVT == MVT::i64 || EltVT == MVT::f64) {
1791 V2EltIdx0 = 2;
1792 } else
Scott Michel8efdca42007-12-04 22:23:35 +00001793 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1794
Scott Michele2641a12008-12-04 21:01:44 +00001795 for (unsigned i = 0; i != PermMask.getNumOperands(); ++i) {
1796 if (PermMask.getOperand(i).getOpcode() != ISD::UNDEF) {
1797 unsigned SrcElt = cast<ConstantSDNode > (PermMask.getOperand(i))->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001798
Scott Michele2641a12008-12-04 21:01:44 +00001799 if (monotonic) {
1800 if (SrcElt >= V2EltIdx0) {
1801 if (1 >= (++EltsFromV2)) {
1802 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1803 }
1804 } else if (CurrElt != SrcElt) {
1805 monotonic = false;
1806 }
1807
1808 ++CurrElt;
1809 }
1810
1811 if (rotate) {
1812 if (PrevElt > 0 && SrcElt < MaxElts) {
1813 if ((PrevElt == SrcElt - 1)
1814 || (PrevElt == MaxElts - 1 && SrcElt == 0)) {
1815 PrevElt = SrcElt;
1816 if (SrcElt == 0)
1817 V0Elt = i;
1818 } else {
1819 rotate = false;
1820 }
1821 } else if (PrevElt == 0) {
1822 // First time through, need to keep track of previous element
1823 PrevElt = SrcElt;
1824 } else {
1825 // This isn't a rotation, takes elements from vector 2
1826 rotate = false;
1827 }
1828 }
Scott Michel8efdca42007-12-04 22:23:35 +00001829 }
Scott Michel8efdca42007-12-04 22:23:35 +00001830 }
1831
1832 if (EltsFromV2 == 1 && monotonic) {
1833 // Compute mask and shuffle
1834 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001835 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1836 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands92c43912008-06-06 12:08:01 +00001837 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00001838 // Initialize temporary register to 0
Dan Gohman8181bd12008-07-27 21:46:04 +00001839 SDValue InitTempReg =
Scott Michel8efdca42007-12-04 22:23:35 +00001840 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel56a125e2008-11-22 23:50:42 +00001841 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman8181bd12008-07-27 21:46:04 +00001842 SDValue ShufMaskOp =
Scott Michel0718cd82008-12-01 17:56:02 +00001843 DAG.getNode(SPUISD::SHUFFLE_MASK, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001844 DAG.getTargetConstant(V2Elt, MVT::i32),
1845 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +00001846 // Use shuffle mask in SHUFB synthetic instruction:
1847 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
Scott Michele2641a12008-12-04 21:01:44 +00001848 } else if (rotate) {
1849 int rotamt = (MaxElts - V0Elt) * EltVT.getSizeInBits()/8;
Scott Michelae5cbf52008-12-29 03:23:36 +00001850
Scott Michele2641a12008-12-04 21:01:44 +00001851 return DAG.getNode(SPUISD::ROTBYTES_LEFT, V1.getValueType(),
1852 V1, DAG.getConstant(rotamt, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001853 } else {
Gabor Greife9f7f582008-08-31 15:37:04 +00001854 // Convert the SHUFFLE_VECTOR mask's input element units to the
1855 // actual bytes.
Duncan Sands92c43912008-06-06 12:08:01 +00001856 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel4ec722e2008-07-16 17:17:29 +00001857
Dan Gohman8181bd12008-07-27 21:46:04 +00001858 SmallVector<SDValue, 16> ResultMask;
Scott Michel8efdca42007-12-04 22:23:35 +00001859 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1860 unsigned SrcElt;
1861 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001862 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001863 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001864 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel4ec722e2008-07-16 17:17:29 +00001865
Scott Michel97872d32008-02-23 18:41:37 +00001866 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001867 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1868 MVT::i8));
Scott Michel8efdca42007-12-04 22:23:35 +00001869 }
1870 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001871
Dan Gohman8181bd12008-07-27 21:46:04 +00001872 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel0718cd82008-12-01 17:56:02 +00001873 &ResultMask[0], ResultMask.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001874 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1875 }
1876}
1877
Dan Gohman8181bd12008-07-27 21:46:04 +00001878static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1879 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel8efdca42007-12-04 22:23:35 +00001880
Gabor Greif1c80d112008-08-28 21:40:38 +00001881 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel8efdca42007-12-04 22:23:35 +00001882 // For a constant, build the appropriate constant vector, which will
1883 // eventually simplify to a vector register load.
1884
Gabor Greif1c80d112008-08-28 21:40:38 +00001885 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman8181bd12008-07-27 21:46:04 +00001886 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands92c43912008-06-06 12:08:01 +00001887 MVT VT;
Scott Michel8efdca42007-12-04 22:23:35 +00001888 size_t n_copies;
1889
1890 // Create a constant vector:
Duncan Sands92c43912008-06-06 12:08:01 +00001891 switch (Op.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001892 default: assert(0 && "Unexpected constant value type in "
Scott Michel5a6f17b2008-01-30 02:55:46 +00001893 "LowerSCALAR_TO_VECTOR");
Scott Michel8efdca42007-12-04 22:23:35 +00001894 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1895 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1896 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1897 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1898 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1899 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1900 }
1901
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001902 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel8efdca42007-12-04 22:23:35 +00001903 for (size_t j = 0; j < n_copies; ++j)
1904 ConstVecValues.push_back(CValue);
1905
1906 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001907 &ConstVecValues[0], ConstVecValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001908 } else {
1909 // Otherwise, copy the value from one register to another:
Duncan Sands92c43912008-06-06 12:08:01 +00001910 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001911 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1912 case MVT::i8:
1913 case MVT::i16:
1914 case MVT::i32:
1915 case MVT::i64:
1916 case MVT::f32:
1917 case MVT::f64:
Scott Michel06eabde2008-12-27 04:51:36 +00001918 return DAG.getNode(SPUISD::PREFSLOT2VEC, Op.getValueType(), Op0, Op0);
Scott Michel8efdca42007-12-04 22:23:35 +00001919 }
1920 }
1921
Dan Gohman8181bd12008-07-27 21:46:04 +00001922 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001923}
1924
Dan Gohman8181bd12008-07-27 21:46:04 +00001925static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001926 switch (Op.getValueType().getSimpleVT()) {
1927 default:
1928 cerr << "CellSPU: Unknown vector multiplication, got "
1929 << Op.getValueType().getMVTString()
1930 << "\n";
1931 abort();
1932 /*NOTREACHED*/
1933
Scott Michelae5cbf52008-12-29 03:23:36 +00001934 case MVT::v4i32:
1935 break;
Scott Michel8efdca42007-12-04 22:23:35 +00001936
1937 // Multiply two v8i16 vectors (pipeline friendly version):
1938 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1939 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1940 // c) Use SELB to select upper and lower halves from the intermediate results
1941 //
Scott Michel67224b22008-06-02 22:18:03 +00001942 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel8efdca42007-12-04 22:23:35 +00001943 // dual-issue. This code does manage to do this, even if it's a little on
1944 // the wacky side
1945 case MVT::v8i16: {
1946 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001947 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman8181bd12008-07-27 21:46:04 +00001948 SDValue Chain = Op.getOperand(0);
1949 SDValue rA = Op.getOperand(0);
1950 SDValue rB = Op.getOperand(1);
Chris Lattner1b989192007-12-31 04:13:23 +00001951 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1952 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00001953
Dan Gohman8181bd12008-07-27 21:46:04 +00001954 SDValue FSMBOp =
Scott Michel8efdca42007-12-04 22:23:35 +00001955 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel67224b22008-06-02 22:18:03 +00001956 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001957 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel8efdca42007-12-04 22:23:35 +00001958
Dan Gohman8181bd12008-07-27 21:46:04 +00001959 SDValue HHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001960 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001961 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001962
Dan Gohman8181bd12008-07-27 21:46:04 +00001963 SDValue HHProd_v4i32 =
Scott Michel8efdca42007-12-04 22:23:35 +00001964 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001965 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001966
1967 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001968 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1969 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1970 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1971 HHProd_v4i32,
1972 DAG.getConstant(16, MVT::i16))),
1973 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001974 }
1975
1976 // This M00sE is N@stI! (apologies to Monty Python)
1977 //
1978 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1979 // is to break it all apart, sign extend, and reassemble the various
1980 // intermediate products.
1981 case MVT::v16i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001982 SDValue rA = Op.getOperand(0);
1983 SDValue rB = Op.getOperand(1);
1984 SDValue c8 = DAG.getConstant(8, MVT::i32);
1985 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001986
Dan Gohman8181bd12008-07-27 21:46:04 +00001987 SDValue LLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001988 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001989 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1990 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001991
Dan Gohman8181bd12008-07-27 21:46:04 +00001992 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001993
Dan Gohman8181bd12008-07-27 21:46:04 +00001994 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001995
Dan Gohman8181bd12008-07-27 21:46:04 +00001996 SDValue LHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001997 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001998 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001999
Dan Gohman8181bd12008-07-27 21:46:04 +00002000 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00002001 DAG.getConstant(0x2222, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00002002
Dan Gohman8181bd12008-07-27 21:46:04 +00002003 SDValue LoProdParts =
Scott Michel97872d32008-02-23 18:41:37 +00002004 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2005 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2006 LLProd, LHProd, FSMBmask));
Scott Michel8efdca42007-12-04 22:23:35 +00002007
Dan Gohman8181bd12008-07-27 21:46:04 +00002008 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002009
Dan Gohman8181bd12008-07-27 21:46:04 +00002010 SDValue LoProd =
Scott Michel8efdca42007-12-04 22:23:35 +00002011 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michel97872d32008-02-23 18:41:37 +00002012 LoProdParts,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002013 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2014 LoProdMask, LoProdMask,
2015 LoProdMask, LoProdMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002016
Dan Gohman8181bd12008-07-27 21:46:04 +00002017 SDValue rAH =
Scott Michel8efdca42007-12-04 22:23:35 +00002018 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002019 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002020
Dan Gohman8181bd12008-07-27 21:46:04 +00002021 SDValue rBH =
Scott Michel8efdca42007-12-04 22:23:35 +00002022 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002023 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002024
Dan Gohman8181bd12008-07-27 21:46:04 +00002025 SDValue HLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00002026 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002027 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2028 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel8efdca42007-12-04 22:23:35 +00002029
Dan Gohman8181bd12008-07-27 21:46:04 +00002030 SDValue HHProd_1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002031 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002032 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00002033 DAG.getNode(SPUISD::VEC_SRA,
2034 MVT::v4i32, rAH, c8)),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002035 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00002036 DAG.getNode(SPUISD::VEC_SRA,
2037 MVT::v4i32, rBH, c8)));
Scott Michel8efdca42007-12-04 22:23:35 +00002038
Dan Gohman8181bd12008-07-27 21:46:04 +00002039 SDValue HHProd =
Scott Michel97872d32008-02-23 18:41:37 +00002040 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2041 HLProd,
2042 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2043 FSMBmask);
Scott Michel8efdca42007-12-04 22:23:35 +00002044
Dan Gohman8181bd12008-07-27 21:46:04 +00002045 SDValue HiProd =
Scott Michel97872d32008-02-23 18:41:37 +00002046 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002047
2048 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002049 DAG.getNode(ISD::OR, MVT::v4i32,
2050 LoProd, HiProd));
Scott Michel8efdca42007-12-04 22:23:35 +00002051 }
Scott Michel8efdca42007-12-04 22:23:35 +00002052 }
2053
Dan Gohman8181bd12008-07-27 21:46:04 +00002054 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002055}
2056
Dan Gohman8181bd12008-07-27 21:46:04 +00002057static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00002058 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002059 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002060
Dan Gohman8181bd12008-07-27 21:46:04 +00002061 SDValue A = Op.getOperand(0);
2062 SDValue B = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002063 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002064
2065 unsigned VRegBR, VRegC;
2066
2067 if (VT == MVT::f32) {
Chris Lattner1b989192007-12-31 04:13:23 +00002068 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2069 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002070 } else {
Chris Lattner1b989192007-12-31 04:13:23 +00002071 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2072 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002073 }
2074 // TODO: make sure we're feeding FPInterp the right arguments
2075 // Right now: fi B, frest(B)
2076
2077 // Computes BRcpl =
2078 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman8181bd12008-07-27 21:46:04 +00002079 SDValue BRcpl =
Scott Michel4ec722e2008-07-16 17:17:29 +00002080 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2081 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002082 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002083
Scott Michel8efdca42007-12-04 22:23:35 +00002084 // Computes A * BRcpl and stores in a temporary register
Dan Gohman8181bd12008-07-27 21:46:04 +00002085 SDValue AxBRcpl =
Scott Michel8efdca42007-12-04 22:23:35 +00002086 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel4ec722e2008-07-16 17:17:29 +00002087 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002088 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel8efdca42007-12-04 22:23:35 +00002089 // What's the Chain variable do? It's magic!
2090 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel4ec722e2008-07-16 17:17:29 +00002091
2092 return DAG.getNode(ISD::FADD, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002093 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel4ec722e2008-07-16 17:17:29 +00002094 DAG.getNode(ISD::FMUL, VT,
2095 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002096 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel4ec722e2008-07-16 17:17:29 +00002097 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002098 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel8efdca42007-12-04 22:23:35 +00002099}
2100
Dan Gohman8181bd12008-07-27 21:46:04 +00002101static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002102 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002103 SDValue N = Op.getOperand(0);
2104 SDValue Elt = Op.getOperand(1);
Scott Michel56a125e2008-11-22 23:50:42 +00002105 SDValue retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002106
Scott Michel56a125e2008-11-22 23:50:42 +00002107 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
2108 // Constant argument:
2109 int EltNo = (int) C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002110
Scott Michel56a125e2008-11-22 23:50:42 +00002111 // sanity checks:
2112 if (VT == MVT::i8 && EltNo >= 16)
2113 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2114 else if (VT == MVT::i16 && EltNo >= 8)
2115 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2116 else if (VT == MVT::i32 && EltNo >= 4)
2117 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2118 else if (VT == MVT::i64 && EltNo >= 2)
2119 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel8efdca42007-12-04 22:23:35 +00002120
Scott Michel56a125e2008-11-22 23:50:42 +00002121 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2122 // i32 and i64: Element 0 is the preferred slot
Scott Michelc630c412008-11-24 17:11:17 +00002123 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel56a125e2008-11-22 23:50:42 +00002124 }
Scott Michel8efdca42007-12-04 22:23:35 +00002125
Scott Michel56a125e2008-11-22 23:50:42 +00002126 // Need to generate shuffle mask and extract:
2127 int prefslot_begin = -1, prefslot_end = -1;
2128 int elt_byte = EltNo * VT.getSizeInBits() / 8;
2129
2130 switch (VT.getSimpleVT()) {
2131 default:
2132 assert(false && "Invalid value type!");
2133 case MVT::i8: {
2134 prefslot_begin = prefslot_end = 3;
2135 break;
2136 }
2137 case MVT::i16: {
2138 prefslot_begin = 2; prefslot_end = 3;
2139 break;
2140 }
2141 case MVT::i32:
2142 case MVT::f32: {
2143 prefslot_begin = 0; prefslot_end = 3;
2144 break;
2145 }
2146 case MVT::i64:
2147 case MVT::f64: {
2148 prefslot_begin = 0; prefslot_end = 7;
2149 break;
2150 }
2151 }
2152
2153 assert(prefslot_begin != -1 && prefslot_end != -1 &&
2154 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
2155
2156 unsigned int ShufBytes[16];
2157 for (int i = 0; i < 16; ++i) {
2158 // zero fill uppper part of preferred slot, don't care about the
2159 // other slots:
2160 unsigned int mask_val;
2161 if (i <= prefslot_end) {
2162 mask_val =
2163 ((i < prefslot_begin)
2164 ? 0x80
2165 : elt_byte + (i - prefslot_begin));
2166
2167 ShufBytes[i] = mask_val;
2168 } else
2169 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
2170 }
2171
2172 SDValue ShufMask[4];
2173 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
Scott Michele2641a12008-12-04 21:01:44 +00002174 unsigned bidx = i * 4;
Scott Michel56a125e2008-11-22 23:50:42 +00002175 unsigned int bits = ((ShufBytes[bidx] << 24) |
2176 (ShufBytes[bidx+1] << 16) |
2177 (ShufBytes[bidx+2] << 8) |
2178 ShufBytes[bidx+3]);
2179 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
2180 }
2181
2182 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2183 &ShufMask[0],
2184 sizeof(ShufMask) / sizeof(ShufMask[0]));
2185
Scott Michelc630c412008-11-24 17:11:17 +00002186 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel56a125e2008-11-22 23:50:42 +00002187 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2188 N, N, ShufMaskVec));
2189 } else {
2190 // Variable index: Rotate the requested element into slot 0, then replicate
2191 // slot 0 across the vector
2192 MVT VecVT = N.getValueType();
2193 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2194 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2195 abort();
2196 }
2197
2198 // Make life easier by making sure the index is zero-extended to i32
2199 if (Elt.getValueType() != MVT::i32)
2200 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2201
2202 // Scale the index to a bit/byte shift quantity
2203 APInt scaleFactor =
Scott Michelc630c412008-11-24 17:11:17 +00002204 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2205 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel56a125e2008-11-22 23:50:42 +00002206 SDValue vecShift;
Scott Michel56a125e2008-11-22 23:50:42 +00002207
Scott Michelc630c412008-11-24 17:11:17 +00002208 if (scaleShift > 0) {
2209 // Scale the shift factor:
Scott Michel56a125e2008-11-22 23:50:42 +00002210 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel0718cd82008-12-01 17:56:02 +00002211 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel56a125e2008-11-22 23:50:42 +00002212 }
2213
Scott Michelc630c412008-11-24 17:11:17 +00002214 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2215
2216 // Replicate the bytes starting at byte 0 across the entire vector (for
2217 // consistency with the notion of a unified register set)
Scott Michel56a125e2008-11-22 23:50:42 +00002218 SDValue replicate;
2219
2220 switch (VT.getSimpleVT()) {
2221 default:
2222 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2223 abort();
2224 /*NOTREACHED*/
2225 case MVT::i8: {
Scott Michelc630c412008-11-24 17:11:17 +00002226 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002227 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2228 factor, factor);
2229 break;
2230 }
2231 case MVT::i16: {
Scott Michelc630c412008-11-24 17:11:17 +00002232 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002233 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2234 factor, factor);
2235 break;
2236 }
2237 case MVT::i32:
2238 case MVT::f32: {
2239 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2240 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2241 factor, factor);
2242 break;
2243 }
2244 case MVT::i64:
2245 case MVT::f64: {
2246 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2247 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2248 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2249 loFactor, hiFactor);
2250 break;
2251 }
2252 }
2253
Scott Michelc630c412008-11-24 17:11:17 +00002254 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel0718cd82008-12-01 17:56:02 +00002255 DAG.getNode(SPUISD::SHUFB, VecVT,
2256 vecShift, vecShift, replicate));
Scott Michel8efdca42007-12-04 22:23:35 +00002257 }
2258
Scott Michel56a125e2008-11-22 23:50:42 +00002259 return retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002260}
2261
Dan Gohman8181bd12008-07-27 21:46:04 +00002262static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2263 SDValue VecOp = Op.getOperand(0);
2264 SDValue ValOp = Op.getOperand(1);
2265 SDValue IdxOp = Op.getOperand(2);
Duncan Sands92c43912008-06-06 12:08:01 +00002266 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002267
2268 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2269 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2270
Duncan Sands92c43912008-06-06 12:08:01 +00002271 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel0718cd82008-12-01 17:56:02 +00002272 // Use $sp ($1) because it's always 16-byte aligned and it's available:
2273 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
2274 DAG.getRegister(SPU::R1, PtrVT),
2275 DAG.getConstant(CN->getSExtValue(), PtrVT));
2276 SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, VT, Pointer);
Scott Michel8efdca42007-12-04 22:23:35 +00002277
Dan Gohman8181bd12008-07-27 21:46:04 +00002278 SDValue result =
Scott Michel8efdca42007-12-04 22:23:35 +00002279 DAG.getNode(SPUISD::SHUFB, VT,
2280 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
Scott Michelae5cbf52008-12-29 03:23:36 +00002281 VecOp,
Scott Michel0718cd82008-12-01 17:56:02 +00002282 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, ShufMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002283
2284 return result;
2285}
2286
Scott Michel06eabde2008-12-27 04:51:36 +00002287static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc,
2288 const TargetLowering &TLI)
Scott Michel97872d32008-02-23 18:41:37 +00002289{
Dan Gohman8181bd12008-07-27 21:46:04 +00002290 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel06eabde2008-12-27 04:51:36 +00002291 MVT ShiftVT = TLI.getShiftAmountTy();
Scott Michel8efdca42007-12-04 22:23:35 +00002292
2293 assert(Op.getValueType() == MVT::i8);
2294 switch (Opc) {
2295 default:
2296 assert(0 && "Unhandled i8 math operator");
2297 /*NOTREACHED*/
2298 break;
2299 case ISD::SUB: {
2300 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2301 // the result:
Dan Gohman8181bd12008-07-27 21:46:04 +00002302 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002303 N0 = (N0.getOpcode() != ISD::Constant
2304 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Scott Michel06eabde2008-12-27 04:51:36 +00002305 : DAG.getConstant(cast<ConstantSDNode>(N0)->getSExtValue(),
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002306 MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00002307 N1 = (N1.getOpcode() != ISD::Constant
2308 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Scott Michel06eabde2008-12-27 04:51:36 +00002309 : DAG.getConstant(cast<ConstantSDNode>(N1)->getSExtValue(),
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002310 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002311 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002312 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel4ec722e2008-07-16 17:17:29 +00002313 }
Scott Michel8efdca42007-12-04 22:23:35 +00002314 case ISD::ROTR:
2315 case ISD::ROTL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002316 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002317 unsigned N1Opc;
2318 N0 = (N0.getOpcode() != ISD::Constant
2319 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002320 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2321 MVT::i16));
Scott Michel06eabde2008-12-27 04:51:36 +00002322 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greife9f7f582008-08-31 15:37:04 +00002323 ? ISD::ZERO_EXTEND
2324 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002325 N1 = (N1.getOpcode() != ISD::Constant
Scott Michel06eabde2008-12-27 04:51:36 +00002326 ? DAG.getNode(N1Opc, ShiftVT, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002327 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Scott Michel06eabde2008-12-27 04:51:36 +00002328 TLI.getShiftAmountTy()));
Dan Gohman8181bd12008-07-27 21:46:04 +00002329 SDValue ExpandArg =
Scott Michel8efdca42007-12-04 22:23:35 +00002330 DAG.getNode(ISD::OR, MVT::i16, N0,
2331 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sands7aef60d2008-10-30 19:24:28 +00002332 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002333 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002334 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2335 }
2336 case ISD::SRL:
2337 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002338 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002339 unsigned N1Opc;
2340 N0 = (N0.getOpcode() != ISD::Constant
2341 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002342 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
Scott Michel06eabde2008-12-27 04:51:36 +00002343 MVT::i32));
2344 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greife9f7f582008-08-31 15:37:04 +00002345 ? ISD::ZERO_EXTEND
2346 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002347 N1 = (N1.getOpcode() != ISD::Constant
Scott Michel06eabde2008-12-27 04:51:36 +00002348 ? DAG.getNode(N1Opc, ShiftVT, N1)
2349 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(), ShiftVT));
Scott Michel4ec722e2008-07-16 17:17:29 +00002350 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002351 DAG.getNode(Opc, MVT::i16, N0, N1));
2352 }
2353 case ISD::SRA: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002354 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002355 unsigned N1Opc;
2356 N0 = (N0.getOpcode() != ISD::Constant
2357 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Scott Michel06eabde2008-12-27 04:51:36 +00002358 : DAG.getConstant(cast<ConstantSDNode>(N0)->getSExtValue(),
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002359 MVT::i16));
Scott Michel06eabde2008-12-27 04:51:36 +00002360 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greife9f7f582008-08-31 15:37:04 +00002361 ? ISD::SIGN_EXTEND
2362 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002363 N1 = (N1.getOpcode() != ISD::Constant
Scott Michel06eabde2008-12-27 04:51:36 +00002364 ? DAG.getNode(N1Opc, ShiftVT, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002365 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Scott Michel06eabde2008-12-27 04:51:36 +00002366 ShiftVT));
Scott Michel4ec722e2008-07-16 17:17:29 +00002367 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002368 DAG.getNode(Opc, MVT::i16, N0, N1));
2369 }
2370 case ISD::MUL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002371 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002372 unsigned N1Opc;
2373 N0 = (N0.getOpcode() != ISD::Constant
2374 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002375 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2376 MVT::i16));
Duncan Sandsec142ee2008-06-08 20:54:56 +00002377 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002378 N1 = (N1.getOpcode() != ISD::Constant
2379 ? DAG.getNode(N1Opc, MVT::i16, N1)
Scott Michel06eabde2008-12-27 04:51:36 +00002380 : DAG.getConstant(cast<ConstantSDNode>(N1)->getSExtValue(),
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002381 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002382 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002383 DAG.getNode(Opc, MVT::i16, N0, N1));
2384 break;
2385 }
2386 }
2387
Dan Gohman8181bd12008-07-27 21:46:04 +00002388 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002389}
2390
Dan Gohman8181bd12008-07-27 21:46:04 +00002391static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002392{
Duncan Sands92c43912008-06-06 12:08:01 +00002393 MVT VT = Op.getValueType();
2394 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002395
Dan Gohman8181bd12008-07-27 21:46:04 +00002396 SDValue Op0 = Op.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002397
2398 switch (Opc) {
2399 case ISD::ZERO_EXTEND:
2400 case ISD::SIGN_EXTEND:
2401 case ISD::ANY_EXTEND: {
Duncan Sands92c43912008-06-06 12:08:01 +00002402 MVT Op0VT = Op0.getValueType();
2403 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002404
2405 assert(Op0VT == MVT::i32
2406 && "CellSPU: Zero/sign extending something other than i32");
2407
Scott Michelc630c412008-11-24 17:11:17 +00002408 DEBUG(cerr << "CellSPU.LowerI64Math: lowering zero/sign/any extend\n");
2409
Dan Gohman8181bd12008-07-27 21:46:04 +00002410 SDValue PromoteScalar =
Scott Michel06eabde2008-12-27 04:51:36 +00002411 DAG.getNode(SPUISD::PREFSLOT2VEC, Op0VecVT, Op0);
Scott Michel97872d32008-02-23 18:41:37 +00002412
Scott Michelc630c412008-11-24 17:11:17 +00002413 if (Opc != ISD::SIGN_EXTEND) {
Scott Michelf2df6cb2008-11-24 18:20:46 +00002414 // Use a shuffle to zero extend the i32 to i64 directly:
2415 SDValue shufMask =
2416 DAG.getNode(ISD::BUILD_VECTOR, Op0VecVT,
2417 DAG.getConstant(0x80808080, MVT::i32),
2418 DAG.getConstant(0x00010203, MVT::i32),
2419 DAG.getConstant(0x80808080, MVT::i32),
2420 DAG.getConstant(0x08090a0b, MVT::i32));
2421 SDValue zextShuffle =
2422 DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2423 PromoteScalar, PromoteScalar, shufMask);
2424
Scott Michelc630c412008-11-24 17:11:17 +00002425 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michelf2df6cb2008-11-24 18:20:46 +00002426 DAG.getNode(ISD::BIT_CONVERT, VecVT, zextShuffle));
Scott Michelc630c412008-11-24 17:11:17 +00002427 } else {
2428 // SPU has no "rotate quadword and replicate bit 0" (i.e. rotate/shift
2429 // right and propagate the sign bit) instruction.
Scott Michelf2df6cb2008-11-24 18:20:46 +00002430 SDValue RotQuad =
2431 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, Op0VecVT,
2432 PromoteScalar, DAG.getConstant(4, MVT::i32));
Scott Michelc630c412008-11-24 17:11:17 +00002433 SDValue SignQuad =
2434 DAG.getNode(SPUISD::VEC_SRA, Op0VecVT,
2435 PromoteScalar, DAG.getConstant(32, MVT::i32));
2436 SDValue SelMask =
2437 DAG.getNode(SPUISD::SELECT_MASK, Op0VecVT,
2438 DAG.getConstant(0xf0f0, MVT::i16));
2439 SDValue CombineQuad =
2440 DAG.getNode(SPUISD::SELB, Op0VecVT,
2441 SignQuad, RotQuad, SelMask);
2442
2443 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2444 DAG.getNode(ISD::BIT_CONVERT, VecVT, CombineQuad));
2445 }
Scott Michel97872d32008-02-23 18:41:37 +00002446 }
2447
Scott Michel67224b22008-06-02 22:18:03 +00002448 case ISD::ADD: {
2449 // Turn operands into vectors to satisfy type checking (shufb works on
2450 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002451 SDValue Op0 =
Scott Michel06eabde2008-12-27 04:51:36 +00002452 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002453 SDValue Op1 =
Scott Michel06eabde2008-12-27 04:51:36 +00002454 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002455 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002456
2457 // Create the shuffle mask for "rotating" the borrow up one register slot
2458 // once the borrow is generated.
2459 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2460 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2461 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2462 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2463
Dan Gohman8181bd12008-07-27 21:46:04 +00002464 SDValue CarryGen =
Scott Michel67224b22008-06-02 22:18:03 +00002465 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002466 SDValue ShiftedCarry =
Scott Michel67224b22008-06-02 22:18:03 +00002467 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2468 CarryGen, CarryGen,
2469 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2470 &ShufBytes[0], ShufBytes.size()));
2471
Scott Michelc630c412008-11-24 17:11:17 +00002472 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002473 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2474 Op0, Op1, ShiftedCarry));
2475 }
2476
2477 case ISD::SUB: {
2478 // Turn operands into vectors to satisfy type checking (shufb works on
2479 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002480 SDValue Op0 =
Scott Michel06eabde2008-12-27 04:51:36 +00002481 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002482 SDValue Op1 =
Scott Michel06eabde2008-12-27 04:51:36 +00002483 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002484 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002485
2486 // Create the shuffle mask for "rotating" the borrow up one register slot
2487 // once the borrow is generated.
2488 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2489 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2490 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2491 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2492
Dan Gohman8181bd12008-07-27 21:46:04 +00002493 SDValue BorrowGen =
Scott Michel67224b22008-06-02 22:18:03 +00002494 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002495 SDValue ShiftedBorrow =
Scott Michel67224b22008-06-02 22:18:03 +00002496 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2497 BorrowGen, BorrowGen,
2498 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2499 &ShufBytes[0], ShufBytes.size()));
2500
Scott Michelc630c412008-11-24 17:11:17 +00002501 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002502 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2503 Op0, Op1, ShiftedBorrow));
2504 }
2505
Scott Michel97872d32008-02-23 18:41:37 +00002506 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002507 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002508 MVT ShiftAmtVT = ShiftAmt.getValueType();
Scott Michel06eabde2008-12-27 04:51:36 +00002509 SDValue Op0Vec = DAG.getNode(SPUISD::PREFSLOT2VEC, VecVT, Op0);
Dan Gohman8181bd12008-07-27 21:46:04 +00002510 SDValue MaskLower =
Scott Michel97872d32008-02-23 18:41:37 +00002511 DAG.getNode(SPUISD::SELB, VecVT,
2512 Op0Vec,
2513 DAG.getConstant(0, VecVT),
Scott Michel67224b22008-06-02 22:18:03 +00002514 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michel97872d32008-02-23 18:41:37 +00002515 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman8181bd12008-07-27 21:46:04 +00002516 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002517 DAG.getNode(ISD::SRL, ShiftAmtVT,
2518 ShiftAmt,
2519 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002520 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002521 DAG.getNode(ISD::AND, ShiftAmtVT,
2522 ShiftAmt,
2523 DAG.getConstant(7, ShiftAmtVT));
2524
Scott Michelc630c412008-11-24 17:11:17 +00002525 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel97872d32008-02-23 18:41:37 +00002526 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2527 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2528 MaskLower, ShiftAmtBytes),
2529 ShiftAmtBits));
2530 }
2531
2532 case ISD::SRL: {
Duncan Sands92c43912008-06-06 12:08:01 +00002533 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002534 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002535 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002536 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002537 DAG.getNode(ISD::SRL, ShiftAmtVT,
2538 ShiftAmt,
2539 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002540 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002541 DAG.getNode(ISD::AND, ShiftAmtVT,
2542 ShiftAmt,
2543 DAG.getConstant(7, ShiftAmtVT));
2544
2545 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2546 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2547 Op0, ShiftAmtBytes),
2548 ShiftAmtBits);
2549 }
Scott Michel67224b22008-06-02 22:18:03 +00002550
2551 case ISD::SRA: {
2552 // Promote Op0 to vector
Dan Gohman8181bd12008-07-27 21:46:04 +00002553 SDValue Op0 =
Scott Michel06eabde2008-12-27 04:51:36 +00002554 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002555 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002556 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel67224b22008-06-02 22:18:03 +00002557
2558 // Negate variable shift amounts
2559 if (!isa<ConstantSDNode>(ShiftAmt)) {
2560 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2561 DAG.getConstant(0, ShiftVT), ShiftAmt);
2562 }
2563
Dan Gohman8181bd12008-07-27 21:46:04 +00002564 SDValue UpperHalfSign =
Scott Michelc630c412008-11-24 17:11:17 +00002565 DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i32,
Scott Michel67224b22008-06-02 22:18:03 +00002566 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2567 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2568 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman8181bd12008-07-27 21:46:04 +00002569 SDValue UpperHalfSignMask =
Scott Michel67224b22008-06-02 22:18:03 +00002570 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman8181bd12008-07-27 21:46:04 +00002571 SDValue UpperLowerMask =
Scott Michel67224b22008-06-02 22:18:03 +00002572 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2573 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman8181bd12008-07-27 21:46:04 +00002574 SDValue UpperLowerSelect =
Scott Michel67224b22008-06-02 22:18:03 +00002575 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2576 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman8181bd12008-07-27 21:46:04 +00002577 SDValue RotateLeftBytes =
Scott Michel67224b22008-06-02 22:18:03 +00002578 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2579 UpperLowerSelect, ShiftAmt);
Dan Gohman8181bd12008-07-27 21:46:04 +00002580 SDValue RotateLeftBits =
Scott Michel67224b22008-06-02 22:18:03 +00002581 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2582 RotateLeftBytes, ShiftAmt);
2583
Scott Michelc630c412008-11-24 17:11:17 +00002584 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002585 RotateLeftBits);
2586 }
Scott Michel97872d32008-02-23 18:41:37 +00002587 }
2588
Dan Gohman8181bd12008-07-27 21:46:04 +00002589 return SDValue();
Scott Michel97872d32008-02-23 18:41:37 +00002590}
2591
Scott Michel8efdca42007-12-04 22:23:35 +00002592//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman8181bd12008-07-27 21:46:04 +00002593static SDValue
2594LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2595 SDValue ConstVec;
2596 SDValue Arg;
Duncan Sands92c43912008-06-06 12:08:01 +00002597 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002598
2599 ConstVec = Op.getOperand(0);
2600 Arg = Op.getOperand(1);
Gabor Greif1c80d112008-08-28 21:40:38 +00002601 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2602 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel8efdca42007-12-04 22:23:35 +00002603 ConstVec = ConstVec.getOperand(0);
2604 } else {
2605 ConstVec = Op.getOperand(1);
2606 Arg = Op.getOperand(0);
Gabor Greif1c80d112008-08-28 21:40:38 +00002607 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00002608 ConstVec = ConstVec.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00002609 }
2610 }
2611 }
2612
Gabor Greif1c80d112008-08-28 21:40:38 +00002613 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel8efdca42007-12-04 22:23:35 +00002614 uint64_t VectorBits[2];
2615 uint64_t UndefBits[2];
2616 uint64_t SplatBits, SplatUndef;
2617 int SplatSize;
2618
Gabor Greif1c80d112008-08-28 21:40:38 +00002619 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002620 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00002621 VT.getVectorElementType().getSizeInBits(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002622 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002623 SDValue tcVec[16];
2624 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel8efdca42007-12-04 22:23:35 +00002625 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2626
2627 // Turn the BUILD_VECTOR into a set of target constants:
2628 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002629 tcVec[i] = tc;
Scott Michel8efdca42007-12-04 22:23:35 +00002630
Gabor Greif1c80d112008-08-28 21:40:38 +00002631 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002632 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel8efdca42007-12-04 22:23:35 +00002633 }
2634 }
Nate Begeman7569e762008-07-29 19:07:27 +00002635 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2636 // lowered. Return the operation, rather than a null SDValue.
2637 return Op;
Scott Michel8efdca42007-12-04 22:23:35 +00002638}
2639
Scott Michel8efdca42007-12-04 22:23:35 +00002640//! Custom lowering for CTPOP (count population)
2641/*!
2642 Custom lowering code that counts the number ones in the input
2643 operand. SPU has such an instruction, but it counts the number of
2644 ones per byte, which then have to be accumulated.
2645*/
Dan Gohman8181bd12008-07-27 21:46:04 +00002646static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002647 MVT VT = Op.getValueType();
2648 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +00002649
Duncan Sands92c43912008-06-06 12:08:01 +00002650 switch (VT.getSimpleVT()) {
2651 default:
2652 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002653 case MVT::i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002654 SDValue N = Op.getOperand(0);
2655 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002656
Scott Michel06eabde2008-12-27 04:51:36 +00002657 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman8181bd12008-07-27 21:46:04 +00002658 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002659
2660 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2661 }
2662
2663 case MVT::i16: {
2664 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002665 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002666
Chris Lattner1b989192007-12-31 04:13:23 +00002667 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002668
Dan Gohman8181bd12008-07-27 21:46:04 +00002669 SDValue N = Op.getOperand(0);
2670 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2671 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sands7aef60d2008-10-30 19:24:28 +00002672 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002673
Scott Michel06eabde2008-12-27 04:51:36 +00002674 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman8181bd12008-07-27 21:46:04 +00002675 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002676
2677 // CNTB_result becomes the chain to which all of the virtual registers
2678 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002679 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002680 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002681
Dan Gohman8181bd12008-07-27 21:46:04 +00002682 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002683 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2684
Dan Gohman8181bd12008-07-27 21:46:04 +00002685 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002686
2687 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002688 DAG.getNode(ISD::ADD, MVT::i16,
2689 DAG.getNode(ISD::SRL, MVT::i16,
2690 Tmp1, Shift1),
2691 Tmp1),
2692 Mask0);
Scott Michel8efdca42007-12-04 22:23:35 +00002693 }
2694
2695 case MVT::i32: {
2696 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002697 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002698
Chris Lattner1b989192007-12-31 04:13:23 +00002699 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2700 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002701
Dan Gohman8181bd12008-07-27 21:46:04 +00002702 SDValue N = Op.getOperand(0);
2703 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2704 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2705 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2706 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002707
Scott Michel06eabde2008-12-27 04:51:36 +00002708 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman8181bd12008-07-27 21:46:04 +00002709 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002710
2711 // CNTB_result becomes the chain to which all of the virtual registers
2712 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002713 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002714 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002715
Dan Gohman8181bd12008-07-27 21:46:04 +00002716 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002717 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2718
Dan Gohman8181bd12008-07-27 21:46:04 +00002719 SDValue Comp1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002720 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002721 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel8efdca42007-12-04 22:23:35 +00002722
Dan Gohman8181bd12008-07-27 21:46:04 +00002723 SDValue Sum1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002724 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002725 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002726
Dan Gohman8181bd12008-07-27 21:46:04 +00002727 SDValue Sum1_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002728 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2729
Dan Gohman8181bd12008-07-27 21:46:04 +00002730 SDValue Comp2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002731 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002732 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2733 Shift2);
Dan Gohman8181bd12008-07-27 21:46:04 +00002734 SDValue Sum2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002735 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002736 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002737
2738 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2739 }
2740
2741 case MVT::i64:
2742 break;
2743 }
2744
Dan Gohman8181bd12008-07-27 21:46:04 +00002745 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002746}
2747
Scott Michel06eabde2008-12-27 04:51:36 +00002748//! Lower ISD::SETCC
2749/*!
2750 Lower i64 condition code handling.
2751 */
2752
2753static SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) {
2754 MVT VT = Op.getValueType();
2755 SDValue lhs = Op.getOperand(0);
2756 SDValue rhs = Op.getOperand(1);
2757 SDValue condition = Op.getOperand(2);
2758
2759 if (VT == MVT::i32 && lhs.getValueType() == MVT::i64) {
2760 // Expand the i64 comparisons to what Cell can actually support,
2761 // which is eq, ugt and sgt:
2762#if 0
2763 CondCodeSDNode *ccvalue = dyn_cast<CondCodeSDValue>(condition);
2764
2765 switch (ccvalue->get()) {
2766 case
2767 }
2768#endif
2769 }
2770
2771 return SDValue();
2772}
2773
Scott Michel56a125e2008-11-22 23:50:42 +00002774//! Lower ISD::SELECT_CC
2775/*!
2776 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2777 SELB instruction.
2778
2779 \note Need to revisit this in the future: if the code path through the true
2780 and false value computations is longer than the latency of a branch (6
2781 cycles), then it would be more advantageous to branch and insert a new basic
2782 block and branch on the condition. However, this code does not make that
2783 assumption, given the simplisitc uses so far.
2784 */
2785
Scott Michel06eabde2008-12-27 04:51:36 +00002786static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
2787 const TargetLowering &TLI) {
Scott Michel56a125e2008-11-22 23:50:42 +00002788 MVT VT = Op.getValueType();
2789 SDValue lhs = Op.getOperand(0);
2790 SDValue rhs = Op.getOperand(1);
2791 SDValue trueval = Op.getOperand(2);
2792 SDValue falseval = Op.getOperand(3);
2793 SDValue condition = Op.getOperand(4);
2794
Scott Michel06eabde2008-12-27 04:51:36 +00002795 // NOTE: SELB's arguments: $rA, $rB, $mask
2796 //
2797 // SELB selects bits from $rA where bits in $mask are 0, bits from $rB
2798 // where bits in $mask are 1. CCond will be inverted, having 1s where the
2799 // condition was true and 0s where the condition was false. Hence, the
2800 // arguments to SELB get reversed.
2801
Scott Michel56a125e2008-11-22 23:50:42 +00002802 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2803 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2804 // with another "cannot select select_cc" assert:
2805
Scott Michel06eabde2008-12-27 04:51:36 +00002806 SDValue compare = DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(Op),
2807 lhs, rhs, condition);
2808 return DAG.getNode(SPUISD::SELB, VT, falseval, trueval, compare);
Scott Michel56a125e2008-11-22 23:50:42 +00002809}
2810
Scott Michelec8c82e2008-12-02 19:53:53 +00002811//! Custom lower ISD::TRUNCATE
2812static SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG)
2813{
2814 MVT VT = Op.getValueType();
2815 MVT::SimpleValueType simpleVT = VT.getSimpleVT();
2816 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
2817
2818 SDValue Op0 = Op.getOperand(0);
2819 MVT Op0VT = Op0.getValueType();
2820 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
2821
Scott Michelec8c82e2008-12-02 19:53:53 +00002822 // Create shuffle mask
Scott Michel06eabde2008-12-27 04:51:36 +00002823 if (Op0VT.getSimpleVT() == MVT::i128 && simpleVT == MVT::i64) {
2824 // least significant doubleword of quadword
2825 unsigned maskHigh = 0x08090a0b;
2826 unsigned maskLow = 0x0c0d0e0f;
2827 // Use a shuffle to perform the truncation
2828 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2829 DAG.getConstant(maskHigh, MVT::i32),
2830 DAG.getConstant(maskLow, MVT::i32),
2831 DAG.getConstant(maskHigh, MVT::i32),
2832 DAG.getConstant(maskLow, MVT::i32));
2833
2834
2835 SDValue PromoteScalar = DAG.getNode(SPUISD::PREFSLOT2VEC, Op0VecVT, Op0);
2836
2837 SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2838 PromoteScalar, PromoteScalar, shufMask);
2839
2840 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2841 DAG.getNode(ISD::BIT_CONVERT, VecVT, truncShuffle));
Scott Michelec8c82e2008-12-02 19:53:53 +00002842 }
2843
Scott Michel06eabde2008-12-27 04:51:36 +00002844 return SDValue(); // Leave the truncate unmolested
Scott Michelec8c82e2008-12-02 19:53:53 +00002845}
2846
Scott Michel56a125e2008-11-22 23:50:42 +00002847//! Custom (target-specific) lowering entry point
2848/*!
2849 This is where LLVM's DAG selection process calls to do target-specific
2850 lowering of nodes.
2851 */
Dan Gohman8181bd12008-07-27 21:46:04 +00002852SDValue
2853SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel8efdca42007-12-04 22:23:35 +00002854{
Scott Michel97872d32008-02-23 18:41:37 +00002855 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands92c43912008-06-06 12:08:01 +00002856 MVT VT = Op.getValueType();
Scott Michel97872d32008-02-23 18:41:37 +00002857
2858 switch (Opc) {
Scott Michel8efdca42007-12-04 22:23:35 +00002859 default: {
2860 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michel97872d32008-02-23 18:41:37 +00002861 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greif1c80d112008-08-28 21:40:38 +00002862 cerr << "*Op.getNode():\n";
2863 Op.getNode()->dump();
Scott Michel8efdca42007-12-04 22:23:35 +00002864 abort();
2865 }
2866 case ISD::LOAD:
Scott Michelec8c82e2008-12-02 19:53:53 +00002867 case ISD::EXTLOAD:
Scott Michel8efdca42007-12-04 22:23:35 +00002868 case ISD::SEXTLOAD:
2869 case ISD::ZEXTLOAD:
2870 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2871 case ISD::STORE:
2872 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2873 case ISD::ConstantPool:
2874 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2875 case ISD::GlobalAddress:
2876 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2877 case ISD::JumpTable:
2878 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2879 case ISD::Constant:
2880 return LowerConstant(Op, DAG);
2881 case ISD::ConstantFP:
2882 return LowerConstantFP(Op, DAG);
Scott Michel394e26d2008-01-17 20:38:41 +00002883 case ISD::BRCOND:
Scott Michel06eabde2008-12-27 04:51:36 +00002884 return LowerBRCOND(Op, DAG, *this);
Scott Michel8efdca42007-12-04 22:23:35 +00002885 case ISD::FORMAL_ARGUMENTS:
Scott Michel394e26d2008-01-17 20:38:41 +00002886 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel8efdca42007-12-04 22:23:35 +00002887 case ISD::CALL:
Scott Micheldbac4cf2008-01-11 02:53:15 +00002888 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel8efdca42007-12-04 22:23:35 +00002889 case ISD::RET:
2890 return LowerRET(Op, DAG, getTargetMachine());
2891
Scott Michel97872d32008-02-23 18:41:37 +00002892
2893 // i8, i64 math ops:
2894 case ISD::ZERO_EXTEND:
2895 case ISD::SIGN_EXTEND:
2896 case ISD::ANY_EXTEND:
Scott Michel67224b22008-06-02 22:18:03 +00002897 case ISD::ADD:
Scott Michel8efdca42007-12-04 22:23:35 +00002898 case ISD::SUB:
2899 case ISD::ROTR:
2900 case ISD::ROTL:
2901 case ISD::SRL:
2902 case ISD::SHL:
Scott Michel67224b22008-06-02 22:18:03 +00002903 case ISD::SRA: {
Scott Michel97872d32008-02-23 18:41:37 +00002904 if (VT == MVT::i8)
Scott Michel06eabde2008-12-27 04:51:36 +00002905 return LowerI8Math(Op, DAG, Opc, *this);
Scott Michel97872d32008-02-23 18:41:37 +00002906 else if (VT == MVT::i64)
2907 return LowerI64Math(Op, DAG, Opc);
2908 break;
Scott Michel67224b22008-06-02 22:18:03 +00002909 }
Scott Michel8efdca42007-12-04 22:23:35 +00002910
2911 // Vector-related lowering.
2912 case ISD::BUILD_VECTOR:
2913 return LowerBUILD_VECTOR(Op, DAG);
2914 case ISD::SCALAR_TO_VECTOR:
2915 return LowerSCALAR_TO_VECTOR(Op, DAG);
2916 case ISD::VECTOR_SHUFFLE:
2917 return LowerVECTOR_SHUFFLE(Op, DAG);
2918 case ISD::EXTRACT_VECTOR_ELT:
2919 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2920 case ISD::INSERT_VECTOR_ELT:
2921 return LowerINSERT_VECTOR_ELT(Op, DAG);
2922
2923 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2924 case ISD::AND:
2925 case ISD::OR:
2926 case ISD::XOR:
2927 return LowerByteImmed(Op, DAG);
2928
2929 // Vector and i8 multiply:
2930 case ISD::MUL:
Duncan Sands92c43912008-06-06 12:08:01 +00002931 if (VT.isVector())
Scott Michel8efdca42007-12-04 22:23:35 +00002932 return LowerVectorMUL(Op, DAG);
Scott Michel97872d32008-02-23 18:41:37 +00002933 else if (VT == MVT::i8)
Scott Michel06eabde2008-12-27 04:51:36 +00002934 return LowerI8Math(Op, DAG, Opc, *this);
Scott Michel8efdca42007-12-04 22:23:35 +00002935
2936 case ISD::FDIV:
Scott Michel97872d32008-02-23 18:41:37 +00002937 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel8efdca42007-12-04 22:23:35 +00002938 return LowerFDIVf32(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002939#if 0
2940 // This is probably a libcall
2941 else if (Op.getValueType() == MVT::f64)
2942 return LowerFDIVf64(Op, DAG);
2943#endif
Scott Michel8efdca42007-12-04 22:23:35 +00002944 else
2945 assert(0 && "Calling FDIV on unsupported MVT");
2946
2947 case ISD::CTPOP:
2948 return LowerCTPOP(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002949
2950 case ISD::SELECT_CC:
Scott Michel06eabde2008-12-27 04:51:36 +00002951 return LowerSELECT_CC(Op, DAG, *this);
Scott Michelec8c82e2008-12-02 19:53:53 +00002952
2953 case ISD::TRUNCATE:
2954 return LowerTRUNCATE(Op, DAG);
Scott Michel06eabde2008-12-27 04:51:36 +00002955
2956 case ISD::SETCC:
2957 return LowerSETCC(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002958 }
2959
Dan Gohman8181bd12008-07-27 21:46:04 +00002960 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002961}
2962
Duncan Sands7d9834b2008-12-01 11:39:25 +00002963void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
2964 SmallVectorImpl<SDValue>&Results,
2965 SelectionDAG &DAG)
Scott Michel6e2d68b2008-11-10 23:43:06 +00002966{
2967#if 0
2968 unsigned Opc = (unsigned) N->getOpcode();
2969 MVT OpVT = N->getValueType(0);
2970
2971 switch (Opc) {
2972 default: {
2973 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2974 cerr << "Op.getOpcode() = " << Opc << "\n";
2975 cerr << "*Op.getNode():\n";
2976 N->dump();
2977 abort();
2978 /*NOTREACHED*/
2979 }
2980 }
2981#endif
2982
2983 /* Otherwise, return unchanged */
Scott Michel6e2d68b2008-11-10 23:43:06 +00002984}
2985
Scott Michel8efdca42007-12-04 22:23:35 +00002986//===----------------------------------------------------------------------===//
Scott Michel8efdca42007-12-04 22:23:35 +00002987// Target Optimization Hooks
2988//===----------------------------------------------------------------------===//
2989
Dan Gohman8181bd12008-07-27 21:46:04 +00002990SDValue
Scott Michel8efdca42007-12-04 22:23:35 +00002991SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2992{
2993#if 0
2994 TargetMachine &TM = getTargetMachine();
Scott Michelf9f42e62008-01-29 02:16:57 +00002995#endif
2996 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel8efdca42007-12-04 22:23:35 +00002997 SelectionDAG &DAG = DCI.DAG;
Scott Michel0718cd82008-12-01 17:56:02 +00002998 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2999 MVT NodeVT = N->getValueType(0); // The node's value type
Scott Michel06eabde2008-12-27 04:51:36 +00003000 MVT Op0VT = Op0.getValueType(); // The first operand's result
Scott Michel0718cd82008-12-01 17:56:02 +00003001 SDValue Result; // Initially, empty result
Scott Michel8efdca42007-12-04 22:23:35 +00003002
3003 switch (N->getOpcode()) {
3004 default: break;
Scott Michelf9f42e62008-01-29 02:16:57 +00003005 case ISD::ADD: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003006 SDValue Op1 = N->getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003007
Scott Michel06eabde2008-12-27 04:51:36 +00003008 if (Op0.getOpcode() == SPUISD::IndirectAddr
3009 || Op1.getOpcode() == SPUISD::IndirectAddr) {
3010 // Normalize the operands to reduce repeated code
3011 SDValue IndirectArg = Op0, AddArg = Op1;
Scott Michelae5cbf52008-12-29 03:23:36 +00003012
Scott Michel06eabde2008-12-27 04:51:36 +00003013 if (Op1.getOpcode() == SPUISD::IndirectAddr) {
3014 IndirectArg = Op1;
3015 AddArg = Op0;
3016 }
3017
3018 if (isa<ConstantSDNode>(AddArg)) {
3019 ConstantSDNode *CN0 = cast<ConstantSDNode > (AddArg);
3020 SDValue IndOp1 = IndirectArg.getOperand(1);
3021
3022 if (CN0->isNullValue()) {
3023 // (add (SPUindirect <arg>, <arg>), 0) ->
3024 // (SPUindirect <arg>, <arg>)
Scott Michelf9f42e62008-01-29 02:16:57 +00003025
Scott Michel8c2746e2008-12-04 17:16:59 +00003026#if !defined(NDEBUG)
Scott Michel06eabde2008-12-27 04:51:36 +00003027 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel6ccefab2008-12-04 03:02:42 +00003028 cerr << "\n"
Scott Michel06eabde2008-12-27 04:51:36 +00003029 << "Replace: (add (SPUindirect <arg>, <arg>), 0)\n"
3030 << "With: (SPUindirect <arg>, <arg>)\n";
3031 }
Scott Michel6ccefab2008-12-04 03:02:42 +00003032#endif
3033
Scott Michel06eabde2008-12-27 04:51:36 +00003034 return IndirectArg;
3035 } else if (isa<ConstantSDNode>(IndOp1)) {
3036 // (add (SPUindirect <arg>, <const>), <const>) ->
3037 // (SPUindirect <arg>, <const + const>)
3038 ConstantSDNode *CN1 = cast<ConstantSDNode > (IndOp1);
3039 int64_t combinedConst = CN0->getSExtValue() + CN1->getSExtValue();
3040 SDValue combinedValue = DAG.getConstant(combinedConst, Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00003041
Scott Michel06eabde2008-12-27 04:51:36 +00003042#if !defined(NDEBUG)
3043 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
3044 cerr << "\n"
3045 << "Replace: (add (SPUindirect <arg>, " << CN1->getSExtValue()
3046 << "), " << CN0->getSExtValue() << ")\n"
3047 << "With: (SPUindirect <arg>, "
3048 << combinedConst << ")\n";
3049 }
3050#endif
Scott Michelf9f42e62008-01-29 02:16:57 +00003051
Scott Michel06eabde2008-12-27 04:51:36 +00003052 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
3053 IndirectArg, combinedValue);
3054 }
Scott Michelf9f42e62008-01-29 02:16:57 +00003055 }
3056 }
Scott Michel97872d32008-02-23 18:41:37 +00003057 break;
3058 }
3059 case ISD::SIGN_EXTEND:
3060 case ISD::ZERO_EXTEND:
3061 case ISD::ANY_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00003062 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT && NodeVT == Op0VT) {
Scott Michel97872d32008-02-23 18:41:37 +00003063 // (any_extend (SPUextract_elt0 <arg>)) ->
3064 // (SPUextract_elt0 <arg>)
3065 // Types must match, however...
Scott Michel8c2746e2008-12-04 17:16:59 +00003066#if !defined(NDEBUG)
3067 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel6ccefab2008-12-04 03:02:42 +00003068 cerr << "\nReplace: ";
3069 N->dump(&DAG);
3070 cerr << "\nWith: ";
3071 Op0.getNode()->dump(&DAG);
3072 cerr << "\n";
Scott Michel8c2746e2008-12-04 17:16:59 +00003073 }
Scott Michel6ccefab2008-12-04 03:02:42 +00003074#endif
Scott Michel97872d32008-02-23 18:41:37 +00003075
3076 return Op0;
3077 }
3078 break;
3079 }
3080 case SPUISD::IndirectAddr: {
3081 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
3082 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003083 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00003084 // (SPUindirect (SPUaform <addr>, 0), 0) ->
3085 // (SPUaform <addr>, 0)
3086
3087 DEBUG(cerr << "Replace: ");
3088 DEBUG(N->dump(&DAG));
3089 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00003090 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00003091 DEBUG(cerr << "\n");
3092
3093 return Op0;
3094 }
Scott Michel06eabde2008-12-27 04:51:36 +00003095 } else if (Op0.getOpcode() == ISD::ADD) {
3096 SDValue Op1 = N->getOperand(1);
3097 if (ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(Op1)) {
3098 // (SPUindirect (add <arg>, <arg>), 0) ->
3099 // (SPUindirect <arg>, <arg>)
3100 if (CN1->isNullValue()) {
3101
3102#if !defined(NDEBUG)
3103 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
3104 cerr << "\n"
3105 << "Replace: (SPUindirect (add <arg>, <arg>), 0)\n"
3106 << "With: (SPUindirect <arg>, <arg>)\n";
3107 }
3108#endif
3109
3110 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
3111 Op0.getOperand(0), Op0.getOperand(1));
3112 }
3113 }
Scott Michel97872d32008-02-23 18:41:37 +00003114 }
3115 break;
3116 }
3117 case SPUISD::SHLQUAD_L_BITS:
3118 case SPUISD::SHLQUAD_L_BYTES:
3119 case SPUISD::VEC_SHL:
3120 case SPUISD::VEC_SRL:
3121 case SPUISD::VEC_SRA:
3122 case SPUISD::ROTQUAD_RZ_BYTES:
Scott Michel06eabde2008-12-27 04:51:36 +00003123 case SPUISD::ROTQUAD_RZ_BITS:
3124 case SPUISD::ROTBYTES_LEFT: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003125 SDValue Op1 = N->getOperand(1);
Scott Michel97872d32008-02-23 18:41:37 +00003126
Scott Michel06eabde2008-12-27 04:51:36 +00003127 // Kill degenerate vector shifts:
3128 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1)) {
3129 if (CN->isNullValue()) {
Scott Michel97872d32008-02-23 18:41:37 +00003130 Result = Op0;
3131 }
3132 }
3133 break;
3134 }
Scott Michel06eabde2008-12-27 04:51:36 +00003135 case SPUISD::PREFSLOT2VEC: {
Scott Michel97872d32008-02-23 18:41:37 +00003136 switch (Op0.getOpcode()) {
3137 default:
3138 break;
3139 case ISD::ANY_EXTEND:
3140 case ISD::ZERO_EXTEND:
3141 case ISD::SIGN_EXTEND: {
Scott Michelae5cbf52008-12-29 03:23:36 +00003142 // (SPUprefslot2vec (any|zero|sign_extend (SPUvec2prefslot <arg>))) ->
Scott Michel97872d32008-02-23 18:41:37 +00003143 // <arg>
Scott Michelae5cbf52008-12-29 03:23:36 +00003144 // but only if the SPUprefslot2vec and <arg> types match.
Dan Gohman8181bd12008-07-27 21:46:04 +00003145 SDValue Op00 = Op0.getOperand(0);
Scott Michelc630c412008-11-24 17:11:17 +00003146 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003147 SDValue Op000 = Op00.getOperand(0);
Scott Michel0718cd82008-12-01 17:56:02 +00003148 if (Op000.getValueType() == NodeVT) {
Scott Michel97872d32008-02-23 18:41:37 +00003149 Result = Op000;
3150 }
3151 }
3152 break;
3153 }
Scott Michelc630c412008-11-24 17:11:17 +00003154 case SPUISD::VEC2PREFSLOT: {
Scott Michelae5cbf52008-12-29 03:23:36 +00003155 // (SPUprefslot2vec (SPUvec2prefslot <arg>)) ->
Scott Michel97872d32008-02-23 18:41:37 +00003156 // <arg>
3157 Result = Op0.getOperand(0);
3158 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00003159 }
Scott Michel97872d32008-02-23 18:41:37 +00003160 }
3161 break;
Scott Michelf9f42e62008-01-29 02:16:57 +00003162 }
3163 }
Scott Michel394e26d2008-01-17 20:38:41 +00003164 // Otherwise, return unchanged.
Scott Michel0718cd82008-12-01 17:56:02 +00003165#ifndef NDEBUG
Gabor Greif1c80d112008-08-28 21:40:38 +00003166 if (Result.getNode()) {
Scott Michel97872d32008-02-23 18:41:37 +00003167 DEBUG(cerr << "\nReplace.SPU: ");
3168 DEBUG(N->dump(&DAG));
3169 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00003170 DEBUG(Result.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00003171 DEBUG(cerr << "\n");
3172 }
3173#endif
3174
3175 return Result;
Scott Michel8efdca42007-12-04 22:23:35 +00003176}
3177
3178//===----------------------------------------------------------------------===//
3179// Inline Assembly Support
3180//===----------------------------------------------------------------------===//
3181
3182/// getConstraintType - Given a constraint letter, return the type of
3183/// constraint it is for this target.
Scott Michel4ec722e2008-07-16 17:17:29 +00003184SPUTargetLowering::ConstraintType
Scott Michel8efdca42007-12-04 22:23:35 +00003185SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
3186 if (ConstraintLetter.size() == 1) {
3187 switch (ConstraintLetter[0]) {
3188 default: break;
3189 case 'b':
3190 case 'r':
3191 case 'f':
3192 case 'v':
3193 case 'y':
3194 return C_RegisterClass;
Scott Michel4ec722e2008-07-16 17:17:29 +00003195 }
Scott Michel8efdca42007-12-04 22:23:35 +00003196 }
3197 return TargetLowering::getConstraintType(ConstraintLetter);
3198}
3199
Scott Michel4ec722e2008-07-16 17:17:29 +00003200std::pair<unsigned, const TargetRegisterClass*>
Scott Michel8efdca42007-12-04 22:23:35 +00003201SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands92c43912008-06-06 12:08:01 +00003202 MVT VT) const
Scott Michel8efdca42007-12-04 22:23:35 +00003203{
3204 if (Constraint.size() == 1) {
3205 // GCC RS6000 Constraint Letters
3206 switch (Constraint[0]) {
3207 case 'b': // R1-R31
3208 case 'r': // R0-R31
3209 if (VT == MVT::i64)
3210 return std::make_pair(0U, SPU::R64CRegisterClass);
3211 return std::make_pair(0U, SPU::R32CRegisterClass);
3212 case 'f':
3213 if (VT == MVT::f32)
3214 return std::make_pair(0U, SPU::R32FPRegisterClass);
3215 else if (VT == MVT::f64)
3216 return std::make_pair(0U, SPU::R64FPRegisterClass);
3217 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00003218 case 'v':
Scott Michel8efdca42007-12-04 22:23:35 +00003219 return std::make_pair(0U, SPU::GPRCRegisterClass);
3220 }
3221 }
Scott Michel4ec722e2008-07-16 17:17:29 +00003222
Scott Michel8efdca42007-12-04 22:23:35 +00003223 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3224}
3225
Scott Michel97872d32008-02-23 18:41:37 +00003226//! Compute used/known bits for a SPU operand
Scott Michel8efdca42007-12-04 22:23:35 +00003227void
Dan Gohman8181bd12008-07-27 21:46:04 +00003228SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohmand0dfc772008-02-13 22:28:48 +00003229 const APInt &Mask,
Scott Michel4ec722e2008-07-16 17:17:29 +00003230 APInt &KnownZero,
Dan Gohman229fa052008-02-13 00:35:47 +00003231 APInt &KnownOne,
Scott Michel5a6f17b2008-01-30 02:55:46 +00003232 const SelectionDAG &DAG,
3233 unsigned Depth ) const {
Scott Michelbc5fbc12008-04-30 00:30:08 +00003234#if 0
Scott Michel97872d32008-02-23 18:41:37 +00003235 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michelbc5fbc12008-04-30 00:30:08 +00003236#endif
Scott Michel97872d32008-02-23 18:41:37 +00003237
3238 switch (Op.getOpcode()) {
3239 default:
3240 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3241 break;
3242
3243#if 0
3244 case CALL:
3245 case SHUFB:
Scott Michel56a125e2008-11-22 23:50:42 +00003246 case SHUFFLE_MASK:
Scott Michel97872d32008-02-23 18:41:37 +00003247 case CNTB:
3248#endif
3249
Scott Michel06eabde2008-12-27 04:51:36 +00003250 case SPUISD::PREFSLOT2VEC: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003251 SDValue Op0 = Op.getOperand(0);
Duncan Sands92c43912008-06-06 12:08:01 +00003252 MVT Op0VT = Op0.getValueType();
3253 unsigned Op0VTBits = Op0VT.getSizeInBits();
3254 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003255 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3256 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003257 break;
3258 }
Scott Michel4ec722e2008-07-16 17:17:29 +00003259
Scott Michel97872d32008-02-23 18:41:37 +00003260 case SPUISD::LDRESULT:
Scott Michel6ccefab2008-12-04 03:02:42 +00003261 case SPUISD::VEC2PREFSLOT: {
Duncan Sands92c43912008-06-06 12:08:01 +00003262 MVT OpVT = Op.getValueType();
3263 unsigned OpVTBits = OpVT.getSizeInBits();
3264 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003265 KnownZero |= APInt(OpVTBits, ~InMask, false);
3266 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003267 break;
3268 }
3269
3270#if 0
Scott Michel97872d32008-02-23 18:41:37 +00003271 case MPY:
3272 case MPYU:
3273 case MPYH:
3274 case MPYHH:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003275 case SPUISD::SHLQUAD_L_BITS:
3276 case SPUISD::SHLQUAD_L_BYTES:
3277 case SPUISD::VEC_SHL:
3278 case SPUISD::VEC_SRL:
3279 case SPUISD::VEC_SRA:
3280 case SPUISD::VEC_ROTL:
3281 case SPUISD::VEC_ROTR:
3282 case SPUISD::ROTQUAD_RZ_BYTES:
3283 case SPUISD::ROTQUAD_RZ_BITS:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003284 case SPUISD::ROTBYTES_LEFT:
Scott Michel67224b22008-06-02 22:18:03 +00003285 case SPUISD::SELECT_MASK:
3286 case SPUISD::SELB:
3287 case SPUISD::FPInterp:
3288 case SPUISD::FPRecipEst:
3289 case SPUISD::SEXT32TO64:
Scott Michel97872d32008-02-23 18:41:37 +00003290#endif
3291 }
Scott Michel8efdca42007-12-04 22:23:35 +00003292}
Scott Michel06eabde2008-12-27 04:51:36 +00003293
3294unsigned
3295SPUTargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op,
3296 unsigned Depth) const {
3297 switch (Op.getOpcode()) {
3298 default:
3299 return 1;
Scott Michel8efdca42007-12-04 22:23:35 +00003300
Scott Michel06eabde2008-12-27 04:51:36 +00003301 case ISD::SETCC: {
3302 MVT VT = Op.getValueType();
3303
3304 if (VT != MVT::i8 && VT != MVT::i16 && VT != MVT::i32) {
3305 VT = MVT::i32;
3306 }
3307 return VT.getSizeInBits();
3308 }
3309 }
3310}
Scott Michelae5cbf52008-12-29 03:23:36 +00003311
Scott Michelbc5fbc12008-04-30 00:30:08 +00003312// LowerAsmOperandForConstraint
3313void
Dan Gohman8181bd12008-07-27 21:46:04 +00003314SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003315 char ConstraintLetter,
Evan Cheng7f250d62008-09-24 00:05:32 +00003316 bool hasMemory,
Dan Gohman8181bd12008-07-27 21:46:04 +00003317 std::vector<SDValue> &Ops,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003318 SelectionDAG &DAG) const {
3319 // Default, for the time being, to the base class handler
Evan Cheng7f250d62008-09-24 00:05:32 +00003320 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3321 Ops, DAG);
Scott Michelbc5fbc12008-04-30 00:30:08 +00003322}
3323
Scott Michel8efdca42007-12-04 22:23:35 +00003324/// isLegalAddressImmediate - Return true if the integer value can be used
3325/// as the offset of the target addressing mode.
Gabor Greife9f7f582008-08-31 15:37:04 +00003326bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3327 const Type *Ty) const {
Scott Michel8efdca42007-12-04 22:23:35 +00003328 // SPU's addresses are 256K:
3329 return (V > -(1 << 18) && V < (1 << 18) - 1);
3330}
3331
3332bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel4ec722e2008-07-16 17:17:29 +00003333 return false;
Scott Michel8efdca42007-12-04 22:23:35 +00003334}
Dan Gohman36322c72008-10-18 02:06:02 +00003335
3336bool
3337SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3338 // The SPU target isn't yet aware of offsets.
3339 return false;
3340}