blob: e975d0d039cac633f4b4c024b1b9cf726bd36c21 [file] [log] [blame]
Scott Michel266bc8f2007-12-04 22:23:35 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-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 Michel266bc8f2007-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 Michel203b2d62008-04-30 00:30:08 +000017#include "SPUFrameInfo.h"
Scott Michelf0569be2008-12-27 04:51:36 +000018#include "llvm/ADT/APInt.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000019#include "llvm/ADT/VectorExtras.h"
Scott Michel266bc8f2007-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 Lattner84bc5422007-12-31 04:13:23 +000024#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000025#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel266bc8f2007-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 Sands83ec4b62008-06-06 12:08:01 +000041 //! MVT mapping to useful data for Cell SPU
Scott Michel266bc8f2007-12-04 22:23:35 +000042 struct valtype_map_s {
Scott Michel7a1c9e92008-11-22 23:50:42 +000043 const MVT valtype;
44 const int prefslot_byte;
Scott Michel266bc8f2007-12-04 22:23:35 +000045 };
Scott Michel5af8f0e2008-07-16 17:17:29 +000046
Scott Michel266bc8f2007-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 Sands83ec4b62008-06-06 12:08:01 +000060 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel266bc8f2007-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 Michel7f9ba9b2008-01-30 02:55:46 +000065 retval = valtype_map + i;
66 break;
Scott Michel266bc8f2007-12-04 22:23:35 +000067 }
68 }
69
70#ifndef NDEBUG
71 if (retval == 0) {
72 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands83ec4b62008-06-06 12:08:01 +000073 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +000074 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +000075 abort();
76 }
77#endif
78
79 return retval;
80 }
Scott Michel266bc8f2007-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 Michel5af8f0e2008-07-16 17:17:29 +000093
Scott Michel266bc8f2007-12-04 22:23:35 +000094 // Set up the SPU's register classes:
Scott Michel504c3692007-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 Michel266bc8f2007-12-04 22:23:35 +0000101 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000102
Scott Michel266bc8f2007-12-04 22:23:35 +0000103 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng03294662008-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 Michel266bc8f2007-12-04 22:23:35 +0000107
Scott Michelf0569be2008-12-27 04:51:36 +0000108 setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
109 setLoadExtAction(ISD::EXTLOAD, MVT::f64, Expand);
Scott Michelb30e8f62008-12-02 19:53:53 +0000110
Scott Michel266bc8f2007-12-04 22:23:35 +0000111 // SPU constant load actions are custom lowered:
112 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begemanccef5802008-02-14 18:43:04 +0000113 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel266bc8f2007-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 Michel719b0e12008-11-19 17:45:08 +0000117 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel266bc8f2007-12-04 22:23:35 +0000118 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000119 MVT VT = (MVT::SimpleValueType)sctype;
120
Scott Michelf0569be2008-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
127 for (unsigned stype = sctype - 1; stype >= (unsigned) MVT::i8; --stype) {
128 MVT StoreVT = (MVT::SimpleValueType) stype;
129 setTruncStoreAction(VT, StoreVT, Expand);
130 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000131 }
132
Scott Michelf0569be2008-12-27 04:51:36 +0000133 for (unsigned sctype = (unsigned) MVT::f32; sctype < (unsigned) MVT::f64;
134 ++sctype) {
135 MVT VT = (MVT::SimpleValueType) sctype;
136
137 setOperationAction(ISD::LOAD, VT, Custom);
138 setOperationAction(ISD::STORE, VT, Custom);
139
140 for (unsigned stype = sctype - 1; stype >= (unsigned) MVT::f32; --stype) {
141 MVT StoreVT = (MVT::SimpleValueType) stype;
142 setTruncStoreAction(VT, StoreVT, Expand);
143 }
144 }
145
146 // Custom lower BRCOND for i8 to "promote" the result to whatever the result
147 // operand happens to be:
Scott Michel58c58182008-01-17 20:38:41 +0000148 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000149
150 // Expand the jumptable branches
151 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
152 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel7a1c9e92008-11-22 23:50:42 +0000153
154 // Custom lower SELECT_CC for most cases, but expand by default
Scott Michel5af8f0e2008-07-16 17:17:29 +0000155 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel7a1c9e92008-11-22 23:50:42 +0000156 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
157 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
158 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
159 setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000160
161 // SPU has no intrinsics for these particular operations:
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000162 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
163
Scott Michelf0569be2008-12-27 04:51:36 +0000164 // SPU has no SREM/UREM instructions
Scott Michel266bc8f2007-12-04 22:23:35 +0000165 setOperationAction(ISD::SREM, MVT::i32, Expand);
166 setOperationAction(ISD::UREM, MVT::i32, Expand);
167 setOperationAction(ISD::SREM, MVT::i64, Expand);
168 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000169
Scott Michel266bc8f2007-12-04 22:23:35 +0000170 // We don't support sin/cos/sqrt/fmod
171 setOperationAction(ISD::FSIN , MVT::f64, Expand);
172 setOperationAction(ISD::FCOS , MVT::f64, Expand);
173 setOperationAction(ISD::FREM , MVT::f64, Expand);
174 setOperationAction(ISD::FSIN , MVT::f32, Expand);
175 setOperationAction(ISD::FCOS , MVT::f32, Expand);
176 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000177
Scott Michel266bc8f2007-12-04 22:23:35 +0000178 // If we're enabling GP optimizations, use hardware square root
179 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
180 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000181
Scott Michel266bc8f2007-12-04 22:23:35 +0000182 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
183 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
184
185 // SPU can do rotate right and left, so legalize it... but customize for i8
186 // because instructions don't exist.
Bill Wendling9440e352008-08-31 02:59:23 +0000187
188 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
189 // .td files.
190 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
191 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
192 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
193
Scott Michel266bc8f2007-12-04 22:23:35 +0000194 setOperationAction(ISD::ROTL, MVT::i32, Legal);
195 setOperationAction(ISD::ROTL, MVT::i16, Legal);
196 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Micheldc91bea2008-11-20 16:36:33 +0000197
Scott Michel266bc8f2007-12-04 22:23:35 +0000198 // SPU has no native version of shift left/right for i8
199 setOperationAction(ISD::SHL, MVT::i8, Custom);
200 setOperationAction(ISD::SRL, MVT::i8, Custom);
201 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel9c0c6b22008-11-21 02:56:16 +0000202
203 // SPU needs custom lowering for shift left/right for i64
Scott Michela59d4692008-02-23 18:41:37 +0000204 setOperationAction(ISD::SHL, MVT::i64, Custom);
205 setOperationAction(ISD::SRL, MVT::i64, Custom);
206 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000207
Scott Michel5af8f0e2008-07-16 17:17:29 +0000208 // Custom lower i8, i32 and i64 multiplications
209 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000210 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel9c0c6b22008-11-21 02:56:16 +0000211 setOperationAction(ISD::MUL, MVT::i64, Expand); // libcall
212
Scott Michel8bf61e82008-06-02 22:18:03 +0000213 // Need to custom handle (some) common i8, i64 math ops
214 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000215 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel8bf61e82008-06-02 22:18:03 +0000216 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000217
Scott Michel266bc8f2007-12-04 22:23:35 +0000218 // SPU does not have BSWAP. It does have i32 support CTLZ.
219 // CTPOP has to be custom lowered.
220 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
221 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
222
223 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
224 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
225 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
226 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
227
228 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
229 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
230
231 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000232
Scott Michel8bf61e82008-06-02 22:18:03 +0000233 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000234 // select ought to work:
Scott Michel78c47fa2008-03-10 16:58:52 +0000235 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michelad2715e2008-03-05 23:02:02 +0000236 setOperationAction(ISD::SELECT, MVT::i16, Legal);
237 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michelf0569be2008-12-27 04:51:36 +0000238 setOperationAction(ISD::SELECT, MVT::i64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000239
Scott Michel78c47fa2008-03-10 16:58:52 +0000240 setOperationAction(ISD::SETCC, MVT::i8, Legal);
241 setOperationAction(ISD::SETCC, MVT::i16, Legal);
Scott Michelf0569be2008-12-27 04:51:36 +0000242 setOperationAction(ISD::SETCC, MVT::i32, Custom);
243 setOperationAction(ISD::SETCC, MVT::i64, Custom);
Scott Michelad2715e2008-03-05 23:02:02 +0000244
Scott Michela59d4692008-02-23 18:41:37 +0000245 // Zero extension and sign extension for i64 have to be
246 // custom legalized
247 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
248 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
249 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000250
Scott Michelf0569be2008-12-27 04:51:36 +0000251 // Custom lower i128 -> i64 truncates
Scott Michelb30e8f62008-12-02 19:53:53 +0000252 setOperationAction(ISD::TRUNCATE, MVT::i64, Custom);
253
Scott Michel266bc8f2007-12-04 22:23:35 +0000254 // SPU has a legal FP -> signed INT instruction
255 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
256 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
257 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
258 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
259
260 // FDIV on SPU requires custom lowering
261 setOperationAction(ISD::FDIV, MVT::f32, Custom);
Scott Michelf0569be2008-12-27 04:51:36 +0000262 setOperationAction(ISD::FDIV, MVT::f64, Expand); // libcall
Scott Michel266bc8f2007-12-04 22:23:35 +0000263
264 // SPU has [U|S]INT_TO_FP
265 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
266 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
267 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
268 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
269 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
270 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
271 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
272 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
273
Scott Michel86c041f2007-12-20 00:44:13 +0000274 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
275 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
276 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
277 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000278
279 // We cannot sextinreg(i1). Expand to shifts.
280 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000281
Scott Michel266bc8f2007-12-04 22:23:35 +0000282 // Support label based line numbers.
Dan Gohman7f460202008-06-30 20:59:49 +0000283 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000284 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000285
286 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000287 // appropriate instructions to materialize the address.
Scott Michel9c0c6b22008-11-21 02:56:16 +0000288 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel053c1da2008-01-29 02:16:57 +0000289 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000290 MVT VT = (MVT::SimpleValueType)sctype;
291
292 setOperationAction(ISD::GlobalAddress, VT, Custom);
293 setOperationAction(ISD::ConstantPool, VT, Custom);
294 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000295 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000296
297 // RET must be custom lowered, to meet ABI requirements
298 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000299
Scott Michel266bc8f2007-12-04 22:23:35 +0000300 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
301 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000302
Scott Michel266bc8f2007-12-04 22:23:35 +0000303 // Use the default implementation.
304 setOperationAction(ISD::VAARG , MVT::Other, Expand);
305 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
306 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000307 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000308 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
309 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
310 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
311
312 // Cell SPU has instructions for converting between i64 and fp.
313 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
314 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000315
Scott Michel266bc8f2007-12-04 22:23:35 +0000316 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
317 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
318
319 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
320 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
321
322 // First set operation action for all vector types to expand. Then we
323 // will selectively turn on ones that can be effectively codegen'd.
324 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
325 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
326 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
327 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
328 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
329 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
330
Duncan Sands83ec4b62008-06-06 12:08:01 +0000331 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
332 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
333 MVT VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000334
Duncan Sands83ec4b62008-06-06 12:08:01 +0000335 // add/sub are legal for all supported vector VT's.
336 setOperationAction(ISD::ADD , VT, Legal);
337 setOperationAction(ISD::SUB , VT, Legal);
338 // mul has to be custom lowered.
339 setOperationAction(ISD::MUL , VT, Custom);
340
341 setOperationAction(ISD::AND , VT, Legal);
342 setOperationAction(ISD::OR , VT, Legal);
343 setOperationAction(ISD::XOR , VT, Legal);
344 setOperationAction(ISD::LOAD , VT, Legal);
345 setOperationAction(ISD::SELECT, VT, Legal);
346 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000347
Scott Michel266bc8f2007-12-04 22:23:35 +0000348 // These operations need to be expanded:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000349 setOperationAction(ISD::SDIV, VT, Expand);
350 setOperationAction(ISD::SREM, VT, Expand);
351 setOperationAction(ISD::UDIV, VT, Expand);
352 setOperationAction(ISD::UREM, VT, Expand);
353 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000354
355 // Custom lower build_vector, constant pool spills, insert and
356 // extract vector elements:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000357 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
358 setOperationAction(ISD::ConstantPool, VT, Custom);
359 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
360 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
361 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
362 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000363 }
364
365 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
366 setOperationAction(ISD::AND, MVT::v16i8, Custom);
367 setOperationAction(ISD::OR, MVT::v16i8, Custom);
368 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
369 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000370
Scott Michel266bc8f2007-12-04 22:23:35 +0000371 setShiftAmountType(MVT::i32);
Scott Michelf0569be2008-12-27 04:51:36 +0000372 setBooleanContents(ZeroOrNegativeOneBooleanContent);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000373
Scott Michel266bc8f2007-12-04 22:23:35 +0000374 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000375
Scott Michel266bc8f2007-12-04 22:23:35 +0000376 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000377 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000378 setTargetDAGCombine(ISD::ZERO_EXTEND);
379 setTargetDAGCombine(ISD::SIGN_EXTEND);
380 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000381
Scott Michel266bc8f2007-12-04 22:23:35 +0000382 computeRegisterProperties();
Scott Michel7a1c9e92008-11-22 23:50:42 +0000383
Scott Michele07d3de2008-12-09 03:37:19 +0000384 // Set pre-RA register scheduler default to BURR, which produces slightly
385 // better code than the default (could also be TDRR, but TargetLowering.h
386 // needs a mod to support that model):
387 setSchedulingPreference(SchedulingForRegPressure);
Scott Michel266bc8f2007-12-04 22:23:35 +0000388}
389
390const char *
391SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
392{
393 if (node_names.empty()) {
394 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
395 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
396 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
397 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000398 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000399 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000400 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
401 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
402 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
Scott Michel7a1c9e92008-11-22 23:50:42 +0000403 node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000404 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
Scott Michelf0569be2008-12-27 04:51:36 +0000405 node_names[(unsigned) SPUISD::PREFSLOT2VEC] = "SPUISD::PROMOTE_SCALAR";
Scott Michel104de432008-11-24 17:11:17 +0000406 node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
Scott Michel266bc8f2007-12-04 22:23:35 +0000407 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
408 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
409 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
410 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michela59d4692008-02-23 18:41:37 +0000411 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
412 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000413 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
414 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
415 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
416 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
417 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michela59d4692008-02-23 18:41:37 +0000418 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
419 "SPUISD::ROTQUAD_RZ_BYTES";
420 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
421 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel266bc8f2007-12-04 22:23:35 +0000422 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
Scott Michel8bf61e82008-06-02 22:18:03 +0000423 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
424 "SPUISD::ROTBYTES_LEFT_BITS";
425 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000426 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel8bf61e82008-06-02 22:18:03 +0000427 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
428 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
429 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
430 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel266bc8f2007-12-04 22:23:35 +0000431 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
432 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
433 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
434 }
435
436 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
437
438 return ((i != node_names.end()) ? i->second : 0);
439}
440
Scott Michelf0569be2008-12-27 04:51:36 +0000441//===----------------------------------------------------------------------===//
442// Return the Cell SPU's SETCC result type
443//===----------------------------------------------------------------------===//
444
Dan Gohman475871a2008-07-27 21:46:04 +0000445MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000446 MVT VT = Op.getValueType();
Scott Michelf0569be2008-12-27 04:51:36 +0000447 // i16 and i32 are valid SETCC result types
448 return ((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) ? VT : MVT::i32);
Scott Michel78c47fa2008-03-10 16:58:52 +0000449}
450
Scott Michel266bc8f2007-12-04 22:23:35 +0000451//===----------------------------------------------------------------------===//
452// Calling convention code:
453//===----------------------------------------------------------------------===//
454
455#include "SPUGenCallingConv.inc"
456
457//===----------------------------------------------------------------------===//
458// LowerOperation implementation
459//===----------------------------------------------------------------------===//
460
461/// Custom lower loads for CellSPU
462/*!
463 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
464 within a 16-byte block, we have to rotate to extract the requested element.
Scott Michel30ee7df2008-12-04 03:02:42 +0000465
466 For extending loads, we also want to ensure that the following sequence is
467 emitted, e.g. for MVT::f32 extending load to MVT::f64:
468
469\verbatim
470%1 v16i8,ch = load
471%2 v16i8,ch = rotate %1
472%3 v4f8, ch = bitconvert %2
473%4 f32 = vec2perfslot %3
474%5 f64 = fp_extend %4
475\endverbatim
476*/
Dan Gohman475871a2008-07-27 21:46:04 +0000477static SDValue
478LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000479 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000480 SDValue the_chain = LN->getChain();
Scott Michelf0569be2008-12-27 04:51:36 +0000481 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel30ee7df2008-12-04 03:02:42 +0000482 MVT InVT = LN->getMemoryVT();
483 MVT OutVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000484 ISD::LoadExtType ExtType = LN->getExtensionType();
485 unsigned alignment = LN->getAlignment();
Scott Michelf0569be2008-12-27 04:51:36 +0000486 const valtype_map_s *vtm = getValueTypeMapEntry(InVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000487
Scott Michel266bc8f2007-12-04 22:23:35 +0000488 switch (LN->getAddressingMode()) {
489 case ISD::UNINDEXED: {
Scott Michelf0569be2008-12-27 04:51:36 +0000490 SDValue result;
491 SDValue basePtr = LN->getBasePtr();
492 SDValue rotate;
Scott Michel266bc8f2007-12-04 22:23:35 +0000493
Scott Michelf0569be2008-12-27 04:51:36 +0000494 if (alignment == 16) {
495 ConstantSDNode *CN;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000496
Scott Michelf0569be2008-12-27 04:51:36 +0000497 // Special cases for a known aligned load to simplify the base pointer
498 // and the rotation amount:
499 if (basePtr.getOpcode() == ISD::ADD
500 && (CN = dyn_cast<ConstantSDNode > (basePtr.getOperand(1))) != 0) {
501 // Known offset into basePtr
502 int64_t offset = CN->getSExtValue();
503 int64_t rotamt = int64_t((offset & 0xf) - vtm->prefslot_byte);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000504
Scott Michelf0569be2008-12-27 04:51:36 +0000505 if (rotamt < 0)
506 rotamt += 16;
507
508 rotate = DAG.getConstant(rotamt, MVT::i16);
509
510 // Simplify the base pointer for this case:
511 basePtr = basePtr.getOperand(0);
512 if ((offset & ~0xf) > 0) {
513 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
514 basePtr,
515 DAG.getConstant((offset & ~0xf), PtrVT));
516 }
517 } else if ((basePtr.getOpcode() == SPUISD::AFormAddr)
518 || (basePtr.getOpcode() == SPUISD::IndirectAddr
519 && basePtr.getOperand(0).getOpcode() == SPUISD::Hi
520 && basePtr.getOperand(1).getOpcode() == SPUISD::Lo)) {
521 // Plain aligned a-form address: rotate into preferred slot
522 // Same for (SPUindirect (SPUhi ...), (SPUlo ...))
523 int64_t rotamt = -vtm->prefslot_byte;
524 if (rotamt < 0)
525 rotamt += 16;
526 rotate = DAG.getConstant(rotamt, MVT::i16);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000527 } else {
Scott Michelf0569be2008-12-27 04:51:36 +0000528 // Offset the rotate amount by the basePtr and the preferred slot
529 // byte offset
530 int64_t rotamt = -vtm->prefslot_byte;
531 if (rotamt < 0)
532 rotamt += 16;
533 rotate = DAG.getNode(ISD::ADD, PtrVT,
534 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000535 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000536 }
Scott Michelf0569be2008-12-27 04:51:36 +0000537 } else {
538 // Unaligned load: must be more pessimistic about addressing modes:
539 if (basePtr.getOpcode() == ISD::ADD) {
540 MachineFunction &MF = DAG.getMachineFunction();
541 MachineRegisterInfo &RegInfo = MF.getRegInfo();
542 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
543 SDValue Flag;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000544
Scott Michelf0569be2008-12-27 04:51:36 +0000545 SDValue Op0 = basePtr.getOperand(0);
546 SDValue Op1 = basePtr.getOperand(1);
547
548 if (isa<ConstantSDNode>(Op1)) {
549 // Convert the (add <ptr>, <const>) to an indirect address contained
550 // in a register. Note that this is done because we need to avoid
551 // creating a 0(reg) d-form address due to the SPU's block loads.
552 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
553 the_chain = DAG.getCopyToReg(the_chain, VReg, basePtr, Flag);
554 basePtr = DAG.getCopyFromReg(the_chain, VReg, PtrVT);
555 } else {
556 // Convert the (add <arg1>, <arg2>) to an indirect address, which
557 // will likely be lowered as a reg(reg) x-form address.
558 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
559 }
560 } else {
561 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
562 basePtr,
563 DAG.getConstant(0, PtrVT));
564 }
565
566 // Offset the rotate amount by the basePtr and the preferred slot
567 // byte offset
568 rotate = DAG.getNode(ISD::ADD, PtrVT,
569 basePtr,
570 DAG.getConstant(-vtm->prefslot_byte, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +0000571 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000572
Scott Michelf0569be2008-12-27 04:51:36 +0000573 // Re-emit as a v16i8 vector load
574 result = DAG.getLoad(MVT::v16i8, the_chain, basePtr,
575 LN->getSrcValue(), LN->getSrcValueOffset(),
576 LN->isVolatile(), 16);
577
578 // Update the chain
579 the_chain = result.getValue(1);
580
581 // Rotate into the preferred slot:
582 result = DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v16i8,
583 result.getValue(0), rotate);
584
Scott Michel30ee7df2008-12-04 03:02:42 +0000585 // Convert the loaded v16i8 vector to the appropriate vector type
586 // specified by the operand:
587 MVT vecVT = MVT::getVectorVT(InVT, (128 / InVT.getSizeInBits()));
588 result = DAG.getNode(SPUISD::VEC2PREFSLOT, InVT,
589 DAG.getNode(ISD::BIT_CONVERT, vecVT, result));
Scott Michel5af8f0e2008-07-16 17:17:29 +0000590
Scott Michel30ee7df2008-12-04 03:02:42 +0000591 // Handle extending loads by extending the scalar result:
592 if (ExtType == ISD::SEXTLOAD) {
593 result = DAG.getNode(ISD::SIGN_EXTEND, OutVT, result);
594 } else if (ExtType == ISD::ZEXTLOAD) {
595 result = DAG.getNode(ISD::ZERO_EXTEND, OutVT, result);
596 } else if (ExtType == ISD::EXTLOAD) {
597 unsigned NewOpc = ISD::ANY_EXTEND;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000598
Scott Michel30ee7df2008-12-04 03:02:42 +0000599 if (OutVT.isFloatingPoint())
600 NewOpc = ISD::FP_EXTEND;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000601
Scott Michel30ee7df2008-12-04 03:02:42 +0000602 result = DAG.getNode(NewOpc, OutVT, result);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000603 }
604
Scott Michel30ee7df2008-12-04 03:02:42 +0000605 SDVTList retvts = DAG.getVTList(OutVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000606 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000607 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000608 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000609 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000610
Scott Michel58c58182008-01-17 20:38:41 +0000611 result = DAG.getNode(SPUISD::LDRESULT, retvts,
612 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000613 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000614 }
615 case ISD::PRE_INC:
616 case ISD::PRE_DEC:
617 case ISD::POST_INC:
618 case ISD::POST_DEC:
619 case ISD::LAST_INDEXED_MODE:
620 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
621 "UNINDEXED\n";
622 cerr << (unsigned) LN->getAddressingMode() << "\n";
623 abort();
624 /*NOTREACHED*/
625 }
626
Dan Gohman475871a2008-07-27 21:46:04 +0000627 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000628}
629
630/// Custom lower stores for CellSPU
631/*!
632 All CellSPU stores are aligned to 16-byte boundaries, so for elements
633 within a 16-byte block, we have to generate a shuffle to insert the
634 requested element into its place, then store the resulting block.
635 */
Dan Gohman475871a2008-07-27 21:46:04 +0000636static SDValue
637LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000638 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000639 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000640 MVT VT = Value.getValueType();
641 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
642 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000643 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000644
645 switch (SN->getAddressingMode()) {
646 case ISD::UNINDEXED: {
Scott Michel9c0c6b22008-11-21 02:56:16 +0000647 // The vector type we really want to load from the 16-byte chunk.
Scott Michel719b0e12008-11-19 17:45:08 +0000648 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
649 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000650
Scott Michelf0569be2008-12-27 04:51:36 +0000651 SDValue alignLoadVec;
652 SDValue basePtr = SN->getBasePtr();
653 SDValue the_chain = SN->getChain();
654 SDValue insertEltOffs;
Scott Michel266bc8f2007-12-04 22:23:35 +0000655
Scott Michelf0569be2008-12-27 04:51:36 +0000656 if (alignment == 16) {
657 ConstantSDNode *CN;
658
659 // Special cases for a known aligned load to simplify the base pointer
660 // and insertion byte:
661 if (basePtr.getOpcode() == ISD::ADD
662 && (CN = dyn_cast<ConstantSDNode>(basePtr.getOperand(1))) != 0) {
663 // Known offset into basePtr
664 int64_t offset = CN->getSExtValue();
665
666 // Simplify the base pointer for this case:
667 basePtr = basePtr.getOperand(0);
668 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
669 basePtr,
670 DAG.getConstant((offset & 0xf), PtrVT));
671
672 if ((offset & ~0xf) > 0) {
673 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
674 basePtr,
675 DAG.getConstant((offset & ~0xf), PtrVT));
676 }
677 } else {
678 // Otherwise, assume it's at byte 0 of basePtr
679 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
680 basePtr,
681 DAG.getConstant(0, PtrVT));
682 }
683 } else {
684 // Unaligned load: must be more pessimistic about addressing modes:
685 if (basePtr.getOpcode() == ISD::ADD) {
686 MachineFunction &MF = DAG.getMachineFunction();
687 MachineRegisterInfo &RegInfo = MF.getRegInfo();
688 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
689 SDValue Flag;
690
691 SDValue Op0 = basePtr.getOperand(0);
692 SDValue Op1 = basePtr.getOperand(1);
693
694 if (isa<ConstantSDNode>(Op1)) {
695 // Convert the (add <ptr>, <const>) to an indirect address contained
696 // in a register. Note that this is done because we need to avoid
697 // creating a 0(reg) d-form address due to the SPU's block loads.
698 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
699 the_chain = DAG.getCopyToReg(the_chain, VReg, basePtr, Flag);
700 basePtr = DAG.getCopyFromReg(the_chain, VReg, PtrVT);
701 } else {
702 // Convert the (add <arg1>, <arg2>) to an indirect address, which
703 // will likely be lowered as a reg(reg) x-form address.
704 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
705 }
706 } else {
707 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
708 basePtr,
709 DAG.getConstant(0, PtrVT));
710 }
711
712 // Insertion point is solely determined by basePtr's contents
713 insertEltOffs = DAG.getNode(ISD::ADD, PtrVT,
714 basePtr,
715 DAG.getConstant(0, PtrVT));
716 }
717
718 // Re-emit as a v16i8 vector load
719 alignLoadVec = DAG.getLoad(MVT::v16i8, the_chain, basePtr,
720 SN->getSrcValue(), SN->getSrcValueOffset(),
721 SN->isVolatile(), 16);
722
723 // Update the chain
724 the_chain = alignLoadVec.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000725
Scott Michel9de5d0d2008-01-11 02:53:15 +0000726 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000727 SDValue theValue = SN->getValue();
728 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000729
730 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000731 && (theValue.getOpcode() == ISD::AssertZext
732 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000733 // Drill down and get the value for zero- and sign-extended
734 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000735 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000736 }
737
Scott Michel9de5d0d2008-01-11 02:53:15 +0000738 // If the base pointer is already a D-form address, then just create
739 // a new D-form address with a slot offset and the orignal base pointer.
740 // Otherwise generate a D-form address with the slot offset relative
741 // to the stack pointer, which is always aligned.
Scott Michelf0569be2008-12-27 04:51:36 +0000742#if !defined(NDEBUG)
743 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
744 cerr << "CellSPU LowerSTORE: basePtr = ";
745 basePtr.getNode()->dump(&DAG);
746 cerr << "\n";
747 }
748#endif
Scott Michel9de5d0d2008-01-11 02:53:15 +0000749
Scott Michel430a5552008-11-19 15:24:16 +0000750 SDValue insertEltOp =
Scott Michelf0569be2008-12-27 04:51:36 +0000751 DAG.getNode(SPUISD::SHUFFLE_MASK, vecVT, insertEltOffs);
Scott Michel719b0e12008-11-19 17:45:08 +0000752 SDValue vectorizeOp =
753 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michel430a5552008-11-19 15:24:16 +0000754
Scott Michel1a6cdb62008-12-01 17:56:02 +0000755 result = DAG.getNode(SPUISD::SHUFB, vecVT,
756 vectorizeOp, alignLoadVec,
757 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000758
Scott Michel9de5d0d2008-01-11 02:53:15 +0000759 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000760 LN->getSrcValue(), LN->getSrcValueOffset(),
761 LN->isVolatile(), LN->getAlignment());
762
Scott Michel23f2ff72008-12-04 17:16:59 +0000763#if 0 && !defined(NDEBUG)
Scott Michel430a5552008-11-19 15:24:16 +0000764 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
765 const SDValue &currentRoot = DAG.getRoot();
766
767 DAG.setRoot(result);
768 cerr << "------- CellSPU:LowerStore result:\n";
769 DAG.dump();
770 cerr << "-------\n";
771 DAG.setRoot(currentRoot);
772 }
773#endif
Scott Michelb30e8f62008-12-02 19:53:53 +0000774
Scott Michel266bc8f2007-12-04 22:23:35 +0000775 return result;
776 /*UNREACHED*/
777 }
778 case ISD::PRE_INC:
779 case ISD::PRE_DEC:
780 case ISD::POST_INC:
781 case ISD::POST_DEC:
782 case ISD::LAST_INDEXED_MODE:
783 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
784 "UNINDEXED\n";
785 cerr << (unsigned) SN->getAddressingMode() << "\n";
786 abort();
787 /*NOTREACHED*/
788 }
789
Dan Gohman475871a2008-07-27 21:46:04 +0000790 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000791}
792
793/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000794static SDValue
795LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000796 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000797 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
798 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000799 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
800 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000801 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000802
803 if (TM.getRelocationModel() == Reloc::Static) {
804 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000805 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000806 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000807 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000808 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
809 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000810 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000811 }
812 }
813
814 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000815 "LowerConstantPool: Relocation model other than static"
816 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000817 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000818}
819
Dan Gohman475871a2008-07-27 21:46:04 +0000820static SDValue
821LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000822 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000823 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000824 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
825 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000826 const TargetMachine &TM = DAG.getTarget();
827
828 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000829 if (!ST->usingLargeMem()) {
830 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
831 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000832 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
833 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000834 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
835 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000836 }
837
838 assert(0 &&
839 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000840 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000841}
842
Dan Gohman475871a2008-07-27 21:46:04 +0000843static SDValue
844LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000845 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000846 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
847 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000848 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000849 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000850 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000851
Scott Michel266bc8f2007-12-04 22:23:35 +0000852 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000853 if (!ST->usingLargeMem()) {
854 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
855 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000856 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
857 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000858 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
859 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000860 } else {
861 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000862 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000863 abort();
864 /*NOTREACHED*/
865 }
866
Dan Gohman475871a2008-07-27 21:46:04 +0000867 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000868}
869
870//! Custom lower i64 integer constants
871/*!
872 This code inserts all of the necessary juggling that needs to occur to load
873 a 64-bit constant into a register.
874 */
Dan Gohman475871a2008-07-27 21:46:04 +0000875static SDValue
876LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000877 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000878
879 if (VT == MVT::i64) {
Scott Michel1a6cdb62008-12-01 17:56:02 +0000880 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
881 SDValue T = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel104de432008-11-24 17:11:17 +0000882 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000883 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000884 } else {
885 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000886 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000887 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000888 abort();
889 /*NOTREACHED*/
890 }
891
Dan Gohman475871a2008-07-27 21:46:04 +0000892 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000893}
894
Nate Begemanccef5802008-02-14 18:43:04 +0000895//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000896static SDValue
897LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000898 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000899
Nate Begemanccef5802008-02-14 18:43:04 +0000900 if (VT == MVT::f64) {
Scott Michel1a6cdb62008-12-01 17:56:02 +0000901 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
902
903 assert((FP != 0) &&
904 "LowerConstantFP: Node is not ConstantFPSDNode");
905
Scott Michel170783a2007-12-19 20:15:47 +0000906 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel1a6cdb62008-12-01 17:56:02 +0000907 SDValue T = DAG.getConstant(dbits, MVT::i64);
908 SDValue Tvec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T);
909 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
910 DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64, Tvec));
Scott Michel266bc8f2007-12-04 22:23:35 +0000911 }
912
Dan Gohman475871a2008-07-27 21:46:04 +0000913 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000914}
915
Dan Gohman475871a2008-07-27 21:46:04 +0000916static SDValue
Scott Michelf0569be2008-12-27 04:51:36 +0000917LowerBRCOND(SDValue Op, SelectionDAG &DAG, const TargetLowering &TLI) {
Dan Gohman475871a2008-07-27 21:46:04 +0000918 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000919 MVT CondVT = Cond.getValueType();
Scott Michelf0569be2008-12-27 04:51:36 +0000920 unsigned CondOpc;
Scott Michel58c58182008-01-17 20:38:41 +0000921
Scott Michel9c0c6b22008-11-21 02:56:16 +0000922 if (CondVT == MVT::i8) {
Scott Michelf0569be2008-12-27 04:51:36 +0000923 SDValue CondOp0 = Cond.getOperand(0);
924 if (Cond.getOpcode() == ISD::TRUNCATE) {
925 // Use the truncate's value type and ANY_EXTEND the condition (DAGcombine
926 // will then remove the truncate)
927 CondVT = CondOp0.getValueType();
928 CondOpc = ISD::ANY_EXTEND;
929 } else {
930 CondVT = MVT::i32; // default to something reasonable
931 CondOpc = ISD::ZERO_EXTEND;
932 }
933
934 Cond = DAG.getNode(CondOpc, CondVT, Op.getOperand(1));
935
Scott Michel58c58182008-01-17 20:38:41 +0000936 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
Scott Michelf0569be2008-12-27 04:51:36 +0000937 Op.getOperand(0), Cond, Op.getOperand(2));
938 }
939
940 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000941}
942
Dan Gohman475871a2008-07-27 21:46:04 +0000943static SDValue
944LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000945{
946 MachineFunction &MF = DAG.getMachineFunction();
947 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000948 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Micheld976c212008-10-30 01:51:48 +0000949 SmallVector<SDValue, 48> ArgValues;
Dan Gohman475871a2008-07-27 21:46:04 +0000950 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000951 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000952
953 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
954 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000955
Scott Michel266bc8f2007-12-04 22:23:35 +0000956 unsigned ArgOffset = SPUFrameInfo::minStackSize();
957 unsigned ArgRegIdx = 0;
958 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000959
Duncan Sands83ec4b62008-06-06 12:08:01 +0000960 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000961
Scott Michel266bc8f2007-12-04 22:23:35 +0000962 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000963 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
964 ArgNo != e; ++ArgNo) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000965 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
966 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Micheld976c212008-10-30 01:51:48 +0000967 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000968
Scott Micheld976c212008-10-30 01:51:48 +0000969 if (ArgRegIdx < NumArgRegs) {
970 const TargetRegisterClass *ArgRegClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000971
Scott Micheld976c212008-10-30 01:51:48 +0000972 switch (ObjectVT.getSimpleVT()) {
973 default: {
Scott Michel9c0c6b22008-11-21 02:56:16 +0000974 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
975 << ObjectVT.getMVTString()
976 << "\n";
977 abort();
Scott Micheld976c212008-10-30 01:51:48 +0000978 }
979 case MVT::i8:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000980 ArgRegClass = &SPU::R8CRegClass;
981 break;
Scott Micheld976c212008-10-30 01:51:48 +0000982 case MVT::i16:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000983 ArgRegClass = &SPU::R16CRegClass;
984 break;
Scott Micheld976c212008-10-30 01:51:48 +0000985 case MVT::i32:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000986 ArgRegClass = &SPU::R32CRegClass;
987 break;
Scott Micheld976c212008-10-30 01:51:48 +0000988 case MVT::i64:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000989 ArgRegClass = &SPU::R64CRegClass;
990 break;
Scott Micheld976c212008-10-30 01:51:48 +0000991 case MVT::f32:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000992 ArgRegClass = &SPU::R32FPRegClass;
993 break;
Scott Micheld976c212008-10-30 01:51:48 +0000994 case MVT::f64:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000995 ArgRegClass = &SPU::R64FPRegClass;
996 break;
Scott Micheld976c212008-10-30 01:51:48 +0000997 case MVT::v2f64:
998 case MVT::v4f32:
999 case MVT::v2i64:
1000 case MVT::v4i32:
1001 case MVT::v8i16:
1002 case MVT::v16i8:
Scott Michel9c0c6b22008-11-21 02:56:16 +00001003 ArgRegClass = &SPU::VECREGRegClass;
1004 break;
Scott Micheld976c212008-10-30 01:51:48 +00001005 }
1006
1007 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
1008 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
1009 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1010 ++ArgRegIdx;
1011 } else {
1012 // We need to load the argument to a virtual register if we determined
1013 // above that we ran out of physical registers of the appropriate type
1014 // or we're forced to do vararg
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001015 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001016 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001017 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001018 ArgOffset += StackSlotSize;
1019 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001020
Scott Michel266bc8f2007-12-04 22:23:35 +00001021 ArgValues.push_back(ArgVal);
Scott Micheld976c212008-10-30 01:51:48 +00001022 // Update the chain
1023 Root = ArgVal.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001024 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001025
Scott Micheld976c212008-10-30 01:51:48 +00001026 // vararg handling:
Scott Michel266bc8f2007-12-04 22:23:35 +00001027 if (isVarArg) {
Scott Micheld976c212008-10-30 01:51:48 +00001028 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1029 // We will spill (79-3)+1 registers to the stack
1030 SmallVector<SDValue, 79-3+1> MemOps;
1031
1032 // Create the frame slot
1033
Scott Michel266bc8f2007-12-04 22:23:35 +00001034 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Micheld976c212008-10-30 01:51:48 +00001035 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1036 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1037 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1038 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1039 Root = Store.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001040 MemOps.push_back(Store);
Scott Micheld976c212008-10-30 01:51:48 +00001041
1042 // Increment address by stack slot size for the next stored argument
1043 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001044 }
1045 if (!MemOps.empty())
Scott Micheld976c212008-10-30 01:51:48 +00001046 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001047 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001048
Scott Michel266bc8f2007-12-04 22:23:35 +00001049 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001050
Scott Michel266bc8f2007-12-04 22:23:35 +00001051 // Return the new list of results.
Duncan Sandsaaffa052008-12-01 11:41:29 +00001052 return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(),
1053 &ArgValues[0], ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001054}
1055
1056/// isLSAAddress - Return the immediate to use if the specified
1057/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001058static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001059 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel266bc8f2007-12-04 22:23:35 +00001060 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001061
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001062 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001063 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1064 (Addr << 14 >> 14) != Addr)
1065 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001066
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001067 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001068}
1069
1070static
Dan Gohman475871a2008-07-27 21:46:04 +00001071SDValue
1072LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman095cc292008-09-13 01:54:27 +00001073 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1074 SDValue Chain = TheCall->getChain();
Dan Gohman095cc292008-09-13 01:54:27 +00001075 SDValue Callee = TheCall->getCallee();
1076 unsigned NumOps = TheCall->getNumArgs();
Scott Michel266bc8f2007-12-04 22:23:35 +00001077 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1078 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1079 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1080
1081 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001082 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001083
Scott Michel266bc8f2007-12-04 22:23:35 +00001084 // Accumulate how many bytes are to be pushed on the stack, including the
1085 // linkage area, and parameter passing area. According to the SPU ABI,
1086 // we minimally need space for [LR] and [SP]
1087 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001088
Scott Michel266bc8f2007-12-04 22:23:35 +00001089 // Set up a copy of the stack pointer for use loading and storing any
1090 // arguments that may not fit in the registers available for argument
1091 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001092 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001093
Scott Michel266bc8f2007-12-04 22:23:35 +00001094 // Figure out which arguments are going to go in registers, and which in
1095 // memory.
1096 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1097 unsigned ArgRegIdx = 0;
1098
1099 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001100 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001101 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001102 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001103
1104 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman095cc292008-09-13 01:54:27 +00001105 SDValue Arg = TheCall->getArg(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001106
Scott Michel266bc8f2007-12-04 22:23:35 +00001107 // PtrOff will be used to store the current argument to the stack if a
1108 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001109 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001110 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1111
Duncan Sands83ec4b62008-06-06 12:08:01 +00001112 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001113 default: assert(0 && "Unexpected ValueType for argument!");
1114 case MVT::i32:
1115 case MVT::i64:
1116 case MVT::i128:
1117 if (ArgRegIdx != NumArgRegs) {
1118 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1119 } else {
1120 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001121 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001122 }
1123 break;
1124 case MVT::f32:
1125 case MVT::f64:
1126 if (ArgRegIdx != NumArgRegs) {
1127 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1128 } else {
1129 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001130 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001131 }
1132 break;
Scott Michelcc188272008-12-04 21:01:44 +00001133 case MVT::v2i64:
1134 case MVT::v2f64:
Scott Michel266bc8f2007-12-04 22:23:35 +00001135 case MVT::v4f32:
1136 case MVT::v4i32:
1137 case MVT::v8i16:
1138 case MVT::v16i8:
1139 if (ArgRegIdx != NumArgRegs) {
1140 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1141 } else {
1142 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001143 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001144 }
1145 break;
1146 }
1147 }
1148
1149 // Update number of stack bytes actually used, insert a call sequence start
1150 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnere563bbc2008-10-11 22:08:30 +00001151 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1152 true));
Scott Michel266bc8f2007-12-04 22:23:35 +00001153
1154 if (!MemOpChains.empty()) {
1155 // Adjust the stack pointer for the stack arguments.
1156 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1157 &MemOpChains[0], MemOpChains.size());
1158 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001159
Scott Michel266bc8f2007-12-04 22:23:35 +00001160 // Build a sequence of copy-to-reg nodes chained together with token chain
1161 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001162 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001163 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1164 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1165 InFlag);
1166 InFlag = Chain.getValue(1);
1167 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001168
Dan Gohman475871a2008-07-27 21:46:04 +00001169 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001170 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001171
Bill Wendling056292f2008-09-16 21:48:12 +00001172 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1173 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1174 // node so that legalize doesn't hack it.
Scott Michel19fd42a2008-11-11 03:06:06 +00001175 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001176 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001177 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001178 SDValue Zero = DAG.getConstant(0, PtrVT);
1179 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001180
Scott Michel9de5d0d2008-01-11 02:53:15 +00001181 if (!ST->usingLargeMem()) {
1182 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1183 // style calls, otherwise, external symbols are BRASL calls. This assumes
1184 // that declared/defined symbols are in the same compilation unit and can
1185 // be reached through PC-relative jumps.
1186 //
1187 // NOTE:
1188 // This may be an unsafe assumption for JIT and really large compilation
1189 // units.
1190 if (GV->isDeclaration()) {
1191 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1192 } else {
1193 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1194 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001195 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001196 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1197 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001198 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001199 }
Scott Michel19fd42a2008-11-11 03:06:06 +00001200 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendling056292f2008-09-16 21:48:12 +00001201 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001202 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001203 // If this is an absolute destination address that appears to be a legal
1204 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001205 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001206 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001207
1208 Ops.push_back(Chain);
1209 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001210
Scott Michel266bc8f2007-12-04 22:23:35 +00001211 // Add argument registers to the end of the list so that they are known live
1212 // into the call.
1213 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001214 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001215 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001216
Gabor Greifba36cb52008-08-28 21:40:38 +00001217 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001218 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001219 // Returns a chain and a flag for retval copy to use.
1220 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1221 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001222 InFlag = Chain.getValue(1);
1223
Chris Lattnere563bbc2008-10-11 22:08:30 +00001224 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1225 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001226 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001227 InFlag = Chain.getValue(1);
1228
Dan Gohman475871a2008-07-27 21:46:04 +00001229 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001230 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001231
Scott Michel266bc8f2007-12-04 22:23:35 +00001232 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001233 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001234 default: assert(0 && "Unexpected ret value!");
1235 case MVT::Other: break;
1236 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001237 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001238 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1239 ResultVals[0] = Chain.getValue(0);
1240 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1241 Chain.getValue(2)).getValue(1);
1242 ResultVals[1] = Chain.getValue(0);
1243 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001244 } else {
1245 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1246 ResultVals[0] = Chain.getValue(0);
1247 NumResults = 1;
1248 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001249 break;
1250 case MVT::i64:
1251 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1252 ResultVals[0] = Chain.getValue(0);
1253 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001254 break;
1255 case MVT::f32:
1256 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001257 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001258 InFlag).getValue(1);
1259 ResultVals[0] = Chain.getValue(0);
1260 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001261 break;
1262 case MVT::v2f64:
Scott Michelcc188272008-12-04 21:01:44 +00001263 case MVT::v2i64:
Scott Michel266bc8f2007-12-04 22:23:35 +00001264 case MVT::v4f32:
1265 case MVT::v4i32:
1266 case MVT::v8i16:
1267 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001268 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001269 InFlag).getValue(1);
1270 ResultVals[0] = Chain.getValue(0);
1271 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001272 break;
1273 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001274
Scott Michel266bc8f2007-12-04 22:23:35 +00001275 // If the function returns void, just return the chain.
1276 if (NumResults == 0)
1277 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001278
Scott Michel266bc8f2007-12-04 22:23:35 +00001279 // Otherwise, merge everything together with a MERGE_VALUES node.
1280 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001281 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001282 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001283}
1284
Dan Gohman475871a2008-07-27 21:46:04 +00001285static SDValue
1286LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001287 SmallVector<CCValAssign, 16> RVLocs;
1288 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1289 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1290 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001291 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001292
Scott Michel266bc8f2007-12-04 22:23:35 +00001293 // If this is the first return lowered for this function, add the regs to the
1294 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001295 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001296 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001297 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001298 }
1299
Dan Gohman475871a2008-07-27 21:46:04 +00001300 SDValue Chain = Op.getOperand(0);
1301 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001302
Scott Michel266bc8f2007-12-04 22:23:35 +00001303 // Copy the result values into the output registers.
1304 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1305 CCValAssign &VA = RVLocs[i];
1306 assert(VA.isRegLoc() && "Can only return in registers!");
1307 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1308 Flag = Chain.getValue(1);
1309 }
1310
Gabor Greifba36cb52008-08-28 21:40:38 +00001311 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001312 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1313 else
1314 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1315}
1316
1317
1318//===----------------------------------------------------------------------===//
1319// Vector related lowering:
1320//===----------------------------------------------------------------------===//
1321
1322static ConstantSDNode *
1323getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001324 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001325
Scott Michel266bc8f2007-12-04 22:23:35 +00001326 // Check to see if this buildvec has a single non-undef value in its elements.
1327 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1328 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001329 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001330 OpVal = N->getOperand(i);
1331 else if (OpVal != N->getOperand(i))
1332 return 0;
1333 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001334
Gabor Greifba36cb52008-08-28 21:40:38 +00001335 if (OpVal.getNode() != 0) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001336 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001337 return CN;
1338 }
1339 }
1340
1341 return 0; // All UNDEF: use implicit def.; not Constant node
1342}
1343
1344/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1345/// and the value fits into an unsigned 18-bit constant, and if so, return the
1346/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001347SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001348 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001349 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001350 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001351 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001352 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001353 uint32_t upper = uint32_t(UValue >> 32);
1354 uint32_t lower = uint32_t(UValue);
1355 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001356 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001357 Value = Value >> 32;
1358 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001359 if (Value <= 0x3ffff)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001360 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001361 }
1362
Dan Gohman475871a2008-07-27 21:46:04 +00001363 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001364}
1365
1366/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1367/// and the value fits into a signed 16-bit constant, and if so, return the
1368/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001369SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001370 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001371 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001372 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001373 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001374 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001375 uint32_t upper = uint32_t(UValue >> 32);
1376 uint32_t lower = uint32_t(UValue);
1377 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001378 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001379 Value = Value >> 32;
1380 }
Scott Michelad2715e2008-03-05 23:02:02 +00001381 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001382 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001383 }
1384 }
1385
Dan Gohman475871a2008-07-27 21:46:04 +00001386 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001387}
1388
1389/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1390/// and the value fits into a signed 10-bit constant, and if so, return the
1391/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001392SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001393 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001394 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001395 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001396 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001397 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001398 uint32_t upper = uint32_t(UValue >> 32);
1399 uint32_t lower = uint32_t(UValue);
1400 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001401 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001402 Value = Value >> 32;
1403 }
Scott Michelad2715e2008-03-05 23:02:02 +00001404 if (isS10Constant(Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001405 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001406 }
1407
Dan Gohman475871a2008-07-27 21:46:04 +00001408 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001409}
1410
1411/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1412/// and the value fits into a signed 8-bit constant, and if so, return the
1413/// constant.
1414///
1415/// @note: The incoming vector is v16i8 because that's the only way we can load
1416/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1417/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001418SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001419 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001420 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001421 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001422 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001423 && Value <= 0xffff /* truncated from uint64_t */
1424 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001425 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001426 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001427 && (Value & 0xff) == Value)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001428 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001429 }
1430
Dan Gohman475871a2008-07-27 21:46:04 +00001431 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001432}
1433
1434/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1435/// and the value fits into a signed 16-bit constant, and if so, return the
1436/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001437SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001438 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001439 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001440 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001441 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001442 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1443 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001444 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001445 }
1446
Dan Gohman475871a2008-07-27 21:46:04 +00001447 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001448}
1449
1450/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001451SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001452 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001453 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001454 }
1455
Dan Gohman475871a2008-07-27 21:46:04 +00001456 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001457}
1458
1459/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001460SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001461 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001462 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001463 }
1464
Dan Gohman475871a2008-07-27 21:46:04 +00001465 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001466}
1467
1468// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001469// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001470// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1471// zero. Return true if this is not an array of constants, false if it is.
1472//
1473static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1474 uint64_t UndefBits[2]) {
1475 // Start with zero'd results.
1476 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001477
Duncan Sands83ec4b62008-06-06 12:08:01 +00001478 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001479 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001480 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001481
Scott Michel266bc8f2007-12-04 22:23:35 +00001482 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1483 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1484
1485 uint64_t EltBits = 0;
1486 if (OpVal.getOpcode() == ISD::UNDEF) {
1487 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1488 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1489 continue;
Scott Michel19fd42a2008-11-11 03:06:06 +00001490 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001491 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel19fd42a2008-11-11 03:06:06 +00001492 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001493 const APFloat &apf = CN->getValueAPF();
1494 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001495 ? FloatToBits(apf.convertToFloat())
1496 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001497 } else {
1498 // Nonconstant element.
1499 return true;
1500 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001501
Scott Michel266bc8f2007-12-04 22:23:35 +00001502 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1503 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001504
1505 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001506 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1507 return false;
1508}
1509
1510/// If this is a splat (repetition) of a value across the whole vector, return
1511/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001512/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001513/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001514static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001515 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001516 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001517 uint64_t &SplatBits, uint64_t &SplatUndef,
1518 int &SplatSize) {
1519 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1520 // the same as the lower 64-bits, ignoring undefs.
1521 uint64_t Bits64 = Bits128[0] | Bits128[1];
1522 uint64_t Undef64 = Undef128[0] & Undef128[1];
1523 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1524 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1525 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1526 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1527
1528 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1529 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001530
Scott Michel266bc8f2007-12-04 22:23:35 +00001531 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1532 // undefs.
1533 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001534 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001535
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001536 // If the top 16-bits are different than the lower 16-bits, ignoring
1537 // undefs, we have an i32 splat.
1538 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1539 if (MinSplatBits < 16) {
1540 // If the top 8-bits are different than the lower 8-bits, ignoring
1541 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001542 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1543 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001544 // Otherwise, we have an 8-bit splat.
1545 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1546 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1547 SplatSize = 1;
1548 return true;
1549 }
1550 } else {
1551 SplatBits = Bits16;
1552 SplatUndef = Undef16;
1553 SplatSize = 2;
1554 return true;
1555 }
1556 }
1557 } else {
1558 SplatBits = Bits32;
1559 SplatUndef = Undef32;
1560 SplatSize = 4;
1561 return true;
1562 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001563 }
1564 } else {
1565 SplatBits = Bits128[0];
1566 SplatUndef = Undef128[0];
1567 SplatSize = 8;
1568 return true;
1569 }
1570 }
1571
1572 return false; // Can't be a splat if two pieces don't match.
1573}
1574
1575// If this is a case we can't handle, return null and let the default
1576// expansion code take care of it. If we CAN select this case, and if it
1577// selects to a single instruction, return Op. Otherwise, if we can codegen
1578// this case more efficiently than a constant pool load, lower it to the
1579// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001580static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001581 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001582 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001583 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001584 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001585 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001586 uint64_t VectorBits[2];
1587 uint64_t UndefBits[2];
1588 uint64_t SplatBits, SplatUndef;
1589 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001590 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001591 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001592 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001593 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001594 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001595
Duncan Sands83ec4b62008-06-06 12:08:01 +00001596 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001597 default:
1598 case MVT::v4f32: {
1599 uint32_t Value32 = SplatBits;
1600 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001601 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001602 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001603 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001604 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001605 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001606 break;
1607 }
1608 case MVT::v2f64: {
1609 uint64_t f64val = SplatBits;
1610 assert(SplatSize == 8
Scott Michel104de432008-11-24 17:11:17 +00001611 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001612 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001613 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001614 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001615 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001616 break;
1617 }
1618 case MVT::v16i8: {
1619 // 8-bit constants have to be expanded to 16-bits
1620 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001621 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001622 for (int i = 0; i < 8; ++i)
1623 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1624 return DAG.getNode(ISD::BIT_CONVERT, VT,
1625 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1626 }
1627 case MVT::v8i16: {
1628 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001629 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001630 Value16 = (unsigned short) (SplatBits & 0xffff);
1631 else
1632 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001633 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1634 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001635 for (int i = 0; i < 8; ++i) Ops[i] = T;
1636 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1637 }
1638 case MVT::v4i32: {
1639 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001640 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001641 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1642 }
1643 case MVT::v2i64: {
1644 uint64_t val = SplatBits;
1645 uint32_t upper = uint32_t(val >> 32);
1646 uint32_t lower = uint32_t(val);
1647
Scott Michel4cb8bd82008-03-06 04:02:54 +00001648 if (upper == lower) {
1649 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001650 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001651 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001652 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001653 SDValue LO32;
1654 SDValue HI32;
1655 SmallVector<SDValue, 16> ShufBytes;
1656 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001657 bool upper_special, lower_special;
1658
1659 // NOTE: This code creates common-case shuffle masks that can be easily
1660 // detected as common expressions. It is not attempting to create highly
1661 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1662
1663 // Detect if the upper or lower half is a special shuffle mask pattern:
Scott Michel104de432008-11-24 17:11:17 +00001664 upper_special = (upper == 0||upper == 0xffffffff||upper == 0x80000000);
1665 lower_special = (lower == 0||lower == 0xffffffff||lower == 0x80000000);
Scott Michel266bc8f2007-12-04 22:23:35 +00001666
1667 // Create lower vector if not a special pattern
1668 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001669 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001670 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1671 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1672 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001673 }
1674
1675 // Create upper vector if not a special pattern
1676 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001677 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001678 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1679 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1680 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001681 }
1682
1683 // If either upper or lower are special, then the two input operands are
1684 // the same (basically, one of them is a "don't care")
1685 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001686 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001687 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001688 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001689 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001690 // Unhappy situation... both upper and lower are special, so punt with
1691 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001692 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001693 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001694 Zero, Zero);
1695 }
1696
1697 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001698 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001699 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001700 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001701 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001702 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001703 process_upper = (upper_special && (i & 1) == 0);
1704 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001705
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001706 if (process_upper || process_lower) {
1707 if ((process_upper && upper == 0)
1708 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001709 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001710 else if ((process_upper && upper == 0xffffffff)
1711 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001712 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001713 else if ((process_upper && upper == 0x80000000)
1714 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001715 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001716 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001717 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001718 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001719
1720 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001721 }
1722
1723 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001724 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001725 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001726 }
1727 }
1728 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001729
Dan Gohman475871a2008-07-27 21:46:04 +00001730 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001731}
1732
1733/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1734/// which the Cell can operate. The code inspects V3 to ascertain whether the
1735/// permutation vector, V3, is monotonically increasing with one "exception"
1736/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel7a1c9e92008-11-22 23:50:42 +00001737/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel266bc8f2007-12-04 22:23:35 +00001738/// In either case, the net result is going to eventually invoke SHUFB to
1739/// permute/shuffle the bytes from V1 and V2.
1740/// \note
Scott Michel7a1c9e92008-11-22 23:50:42 +00001741/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel266bc8f2007-12-04 22:23:35 +00001742/// control word for byte/halfword/word insertion. This takes care of a single
1743/// element move from V2 into V1.
1744/// \note
1745/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001746static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1747 SDValue V1 = Op.getOperand(0);
1748 SDValue V2 = Op.getOperand(1);
1749 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001750
Scott Michel266bc8f2007-12-04 22:23:35 +00001751 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001752
Scott Michel266bc8f2007-12-04 22:23:35 +00001753 // If we have a single element being moved from V1 to V2, this can be handled
1754 // using the C*[DX] compute mask instructions, but the vector elements have
1755 // to be monotonically increasing with one exception element.
Scott Michelcc188272008-12-04 21:01:44 +00001756 MVT VecVT = V1.getValueType();
1757 MVT EltVT = VecVT.getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001758 unsigned EltsFromV2 = 0;
1759 unsigned V2Elt = 0;
1760 unsigned V2EltIdx0 = 0;
1761 unsigned CurrElt = 0;
Scott Michelcc188272008-12-04 21:01:44 +00001762 unsigned MaxElts = VecVT.getVectorNumElements();
1763 unsigned PrevElt = 0;
1764 unsigned V0Elt = 0;
Scott Michel266bc8f2007-12-04 22:23:35 +00001765 bool monotonic = true;
Scott Michelcc188272008-12-04 21:01:44 +00001766 bool rotate = true;
1767
1768 if (EltVT == MVT::i8) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001769 V2EltIdx0 = 16;
Scott Michelcc188272008-12-04 21:01:44 +00001770 } else if (EltVT == MVT::i16) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001771 V2EltIdx0 = 8;
Scott Michelcc188272008-12-04 21:01:44 +00001772 } else if (EltVT == MVT::i32 || EltVT == MVT::f32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001773 V2EltIdx0 = 4;
Scott Michelcc188272008-12-04 21:01:44 +00001774 } else if (EltVT == MVT::i64 || EltVT == MVT::f64) {
1775 V2EltIdx0 = 2;
1776 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00001777 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1778
Scott Michelcc188272008-12-04 21:01:44 +00001779 for (unsigned i = 0; i != PermMask.getNumOperands(); ++i) {
1780 if (PermMask.getOperand(i).getOpcode() != ISD::UNDEF) {
1781 unsigned SrcElt = cast<ConstantSDNode > (PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001782
Scott Michelcc188272008-12-04 21:01:44 +00001783 if (monotonic) {
1784 if (SrcElt >= V2EltIdx0) {
1785 if (1 >= (++EltsFromV2)) {
1786 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1787 }
1788 } else if (CurrElt != SrcElt) {
1789 monotonic = false;
1790 }
1791
1792 ++CurrElt;
1793 }
1794
1795 if (rotate) {
1796 if (PrevElt > 0 && SrcElt < MaxElts) {
1797 if ((PrevElt == SrcElt - 1)
1798 || (PrevElt == MaxElts - 1 && SrcElt == 0)) {
1799 PrevElt = SrcElt;
1800 if (SrcElt == 0)
1801 V0Elt = i;
1802 } else {
1803 rotate = false;
1804 }
1805 } else if (PrevElt == 0) {
1806 // First time through, need to keep track of previous element
1807 PrevElt = SrcElt;
1808 } else {
1809 // This isn't a rotation, takes elements from vector 2
1810 rotate = false;
1811 }
1812 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001813 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001814 }
1815
1816 if (EltsFromV2 == 1 && monotonic) {
1817 // Compute mask and shuffle
1818 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001819 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1820 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001821 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001822 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001823 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001824 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel7a1c9e92008-11-22 23:50:42 +00001825 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001826 SDValue ShufMaskOp =
Scott Michel1a6cdb62008-12-01 17:56:02 +00001827 DAG.getNode(SPUISD::SHUFFLE_MASK, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001828 DAG.getTargetConstant(V2Elt, MVT::i32),
1829 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001830 // Use shuffle mask in SHUFB synthetic instruction:
1831 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
Scott Michelcc188272008-12-04 21:01:44 +00001832 } else if (rotate) {
1833 int rotamt = (MaxElts - V0Elt) * EltVT.getSizeInBits()/8;
1834
1835 return DAG.getNode(SPUISD::ROTBYTES_LEFT, V1.getValueType(),
1836 V1, DAG.getConstant(rotamt, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001837 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001838 // Convert the SHUFFLE_VECTOR mask's input element units to the
1839 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001840 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001841
Dan Gohman475871a2008-07-27 21:46:04 +00001842 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001843 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1844 unsigned SrcElt;
1845 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001846 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001847 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001848 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001849
Scott Michela59d4692008-02-23 18:41:37 +00001850 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001851 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1852 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001853 }
1854 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001855
Dan Gohman475871a2008-07-27 21:46:04 +00001856 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel1a6cdb62008-12-01 17:56:02 +00001857 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001858 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1859 }
1860}
1861
Dan Gohman475871a2008-07-27 21:46:04 +00001862static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1863 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001864
Gabor Greifba36cb52008-08-28 21:40:38 +00001865 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001866 // For a constant, build the appropriate constant vector, which will
1867 // eventually simplify to a vector register load.
1868
Gabor Greifba36cb52008-08-28 21:40:38 +00001869 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001870 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001871 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001872 size_t n_copies;
1873
1874 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001875 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001876 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001877 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001878 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1879 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1880 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1881 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1882 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1883 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1884 }
1885
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001886 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001887 for (size_t j = 0; j < n_copies; ++j)
1888 ConstVecValues.push_back(CValue);
1889
1890 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001891 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001892 } else {
1893 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001894 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001895 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1896 case MVT::i8:
1897 case MVT::i16:
1898 case MVT::i32:
1899 case MVT::i64:
1900 case MVT::f32:
1901 case MVT::f64:
Scott Michelf0569be2008-12-27 04:51:36 +00001902 return DAG.getNode(SPUISD::PREFSLOT2VEC, Op.getValueType(), Op0, Op0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001903 }
1904 }
1905
Dan Gohman475871a2008-07-27 21:46:04 +00001906 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001907}
1908
Dan Gohman475871a2008-07-27 21:46:04 +00001909static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001910 switch (Op.getValueType().getSimpleVT()) {
1911 default:
1912 cerr << "CellSPU: Unknown vector multiplication, got "
1913 << Op.getValueType().getMVTString()
1914 << "\n";
1915 abort();
1916 /*NOTREACHED*/
1917
Scott Michel266bc8f2007-12-04 22:23:35 +00001918 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001919 SDValue rA = Op.getOperand(0);
1920 SDValue rB = Op.getOperand(1);
1921 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1922 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1923 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1924 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001925
1926 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1927 break;
1928 }
1929
1930 // Multiply two v8i16 vectors (pipeline friendly version):
1931 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1932 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1933 // c) Use SELB to select upper and lower halves from the intermediate results
1934 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001935 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001936 // dual-issue. This code does manage to do this, even if it's a little on
1937 // the wacky side
1938 case MVT::v8i16: {
1939 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001940 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001941 SDValue Chain = Op.getOperand(0);
1942 SDValue rA = Op.getOperand(0);
1943 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001944 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1945 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001946
Dan Gohman475871a2008-07-27 21:46:04 +00001947 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001948 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001949 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001950 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001951
Dan Gohman475871a2008-07-27 21:46:04 +00001952 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001953 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001954 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001955
Dan Gohman475871a2008-07-27 21:46:04 +00001956 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001957 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001958 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001959
1960 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001961 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1962 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1963 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1964 HHProd_v4i32,
1965 DAG.getConstant(16, MVT::i16))),
1966 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001967 }
1968
1969 // This M00sE is N@stI! (apologies to Monty Python)
1970 //
1971 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1972 // is to break it all apart, sign extend, and reassemble the various
1973 // intermediate products.
1974 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001975 SDValue rA = Op.getOperand(0);
1976 SDValue rB = Op.getOperand(1);
1977 SDValue c8 = DAG.getConstant(8, MVT::i32);
1978 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001979
Dan Gohman475871a2008-07-27 21:46:04 +00001980 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001981 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001982 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1983 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001984
Dan Gohman475871a2008-07-27 21:46:04 +00001985 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001986
Dan Gohman475871a2008-07-27 21:46:04 +00001987 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001988
Dan Gohman475871a2008-07-27 21:46:04 +00001989 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001990 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001991 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001992
Dan Gohman475871a2008-07-27 21:46:04 +00001993 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001994 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001995
Dan Gohman475871a2008-07-27 21:46:04 +00001996 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001997 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1998 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1999 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002000
Dan Gohman475871a2008-07-27 21:46:04 +00002001 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002002
Dan Gohman475871a2008-07-27 21:46:04 +00002003 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00002004 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00002005 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002006 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2007 LoProdMask, LoProdMask,
2008 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002009
Dan Gohman475871a2008-07-27 21:46:04 +00002010 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002011 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002012 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002013
Dan Gohman475871a2008-07-27 21:46:04 +00002014 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002015 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002016 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002017
Dan Gohman475871a2008-07-27 21:46:04 +00002018 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00002019 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002020 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2021 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00002022
Dan Gohman475871a2008-07-27 21:46:04 +00002023 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002024 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002025 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002026 DAG.getNode(SPUISD::VEC_SRA,
2027 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002028 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002029 DAG.getNode(SPUISD::VEC_SRA,
2030 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002031
Dan Gohman475871a2008-07-27 21:46:04 +00002032 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00002033 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2034 HLProd,
2035 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2036 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00002037
Dan Gohman475871a2008-07-27 21:46:04 +00002038 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002039 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002040
2041 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002042 DAG.getNode(ISD::OR, MVT::v4i32,
2043 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002044 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002045 }
2046
Dan Gohman475871a2008-07-27 21:46:04 +00002047 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002048}
2049
Dan Gohman475871a2008-07-27 21:46:04 +00002050static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002051 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002052 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002053
Dan Gohman475871a2008-07-27 21:46:04 +00002054 SDValue A = Op.getOperand(0);
2055 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002056 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002057
2058 unsigned VRegBR, VRegC;
2059
2060 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002061 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2062 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002063 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002064 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2065 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002066 }
2067 // TODO: make sure we're feeding FPInterp the right arguments
2068 // Right now: fi B, frest(B)
2069
2070 // Computes BRcpl =
2071 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002072 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002073 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2074 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002075 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002076
Scott Michel266bc8f2007-12-04 22:23:35 +00002077 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002078 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002079 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002080 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002081 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002082 // What's the Chain variable do? It's magic!
2083 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002084
2085 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002086 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002087 DAG.getNode(ISD::FMUL, VT,
2088 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002089 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002090 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002091 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002092}
2093
Dan Gohman475871a2008-07-27 21:46:04 +00002094static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002095 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002096 SDValue N = Op.getOperand(0);
2097 SDValue Elt = Op.getOperand(1);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002098 SDValue retval;
Scott Michel266bc8f2007-12-04 22:23:35 +00002099
Scott Michel7a1c9e92008-11-22 23:50:42 +00002100 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
2101 // Constant argument:
2102 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002103
Scott Michel7a1c9e92008-11-22 23:50:42 +00002104 // sanity checks:
2105 if (VT == MVT::i8 && EltNo >= 16)
2106 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2107 else if (VT == MVT::i16 && EltNo >= 8)
2108 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2109 else if (VT == MVT::i32 && EltNo >= 4)
2110 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2111 else if (VT == MVT::i64 && EltNo >= 2)
2112 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel266bc8f2007-12-04 22:23:35 +00002113
Scott Michel7a1c9e92008-11-22 23:50:42 +00002114 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2115 // i32 and i64: Element 0 is the preferred slot
Scott Michel104de432008-11-24 17:11:17 +00002116 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002117 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002118
Scott Michel7a1c9e92008-11-22 23:50:42 +00002119 // Need to generate shuffle mask and extract:
2120 int prefslot_begin = -1, prefslot_end = -1;
2121 int elt_byte = EltNo * VT.getSizeInBits() / 8;
2122
2123 switch (VT.getSimpleVT()) {
2124 default:
2125 assert(false && "Invalid value type!");
2126 case MVT::i8: {
2127 prefslot_begin = prefslot_end = 3;
2128 break;
2129 }
2130 case MVT::i16: {
2131 prefslot_begin = 2; prefslot_end = 3;
2132 break;
2133 }
2134 case MVT::i32:
2135 case MVT::f32: {
2136 prefslot_begin = 0; prefslot_end = 3;
2137 break;
2138 }
2139 case MVT::i64:
2140 case MVT::f64: {
2141 prefslot_begin = 0; prefslot_end = 7;
2142 break;
2143 }
2144 }
2145
2146 assert(prefslot_begin != -1 && prefslot_end != -1 &&
2147 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
2148
2149 unsigned int ShufBytes[16];
2150 for (int i = 0; i < 16; ++i) {
2151 // zero fill uppper part of preferred slot, don't care about the
2152 // other slots:
2153 unsigned int mask_val;
2154 if (i <= prefslot_end) {
2155 mask_val =
2156 ((i < prefslot_begin)
2157 ? 0x80
2158 : elt_byte + (i - prefslot_begin));
2159
2160 ShufBytes[i] = mask_val;
2161 } else
2162 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
2163 }
2164
2165 SDValue ShufMask[4];
2166 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
Scott Michelcc188272008-12-04 21:01:44 +00002167 unsigned bidx = i * 4;
Scott Michel7a1c9e92008-11-22 23:50:42 +00002168 unsigned int bits = ((ShufBytes[bidx] << 24) |
2169 (ShufBytes[bidx+1] << 16) |
2170 (ShufBytes[bidx+2] << 8) |
2171 ShufBytes[bidx+3]);
2172 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
2173 }
2174
2175 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2176 &ShufMask[0],
2177 sizeof(ShufMask) / sizeof(ShufMask[0]));
2178
Scott Michel104de432008-11-24 17:11:17 +00002179 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel7a1c9e92008-11-22 23:50:42 +00002180 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2181 N, N, ShufMaskVec));
2182 } else {
2183 // Variable index: Rotate the requested element into slot 0, then replicate
2184 // slot 0 across the vector
2185 MVT VecVT = N.getValueType();
2186 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2187 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2188 abort();
2189 }
2190
2191 // Make life easier by making sure the index is zero-extended to i32
2192 if (Elt.getValueType() != MVT::i32)
2193 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2194
2195 // Scale the index to a bit/byte shift quantity
2196 APInt scaleFactor =
Scott Michel104de432008-11-24 17:11:17 +00002197 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2198 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel7a1c9e92008-11-22 23:50:42 +00002199 SDValue vecShift;
Scott Michel7a1c9e92008-11-22 23:50:42 +00002200
Scott Michel104de432008-11-24 17:11:17 +00002201 if (scaleShift > 0) {
2202 // Scale the shift factor:
Scott Michel7a1c9e92008-11-22 23:50:42 +00002203 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel1a6cdb62008-12-01 17:56:02 +00002204 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel7a1c9e92008-11-22 23:50:42 +00002205 }
2206
Scott Michel104de432008-11-24 17:11:17 +00002207 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2208
2209 // Replicate the bytes starting at byte 0 across the entire vector (for
2210 // consistency with the notion of a unified register set)
Scott Michel7a1c9e92008-11-22 23:50:42 +00002211 SDValue replicate;
2212
2213 switch (VT.getSimpleVT()) {
2214 default:
2215 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2216 abort();
2217 /*NOTREACHED*/
2218 case MVT::i8: {
Scott Michel104de432008-11-24 17:11:17 +00002219 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002220 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2221 factor, factor);
2222 break;
2223 }
2224 case MVT::i16: {
Scott Michel104de432008-11-24 17:11:17 +00002225 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002226 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2227 factor, factor);
2228 break;
2229 }
2230 case MVT::i32:
2231 case MVT::f32: {
2232 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2233 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2234 factor, factor);
2235 break;
2236 }
2237 case MVT::i64:
2238 case MVT::f64: {
2239 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2240 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2241 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2242 loFactor, hiFactor);
2243 break;
2244 }
2245 }
2246
Scott Michel104de432008-11-24 17:11:17 +00002247 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel1a6cdb62008-12-01 17:56:02 +00002248 DAG.getNode(SPUISD::SHUFB, VecVT,
2249 vecShift, vecShift, replicate));
Scott Michel266bc8f2007-12-04 22:23:35 +00002250 }
2251
Scott Michel7a1c9e92008-11-22 23:50:42 +00002252 return retval;
Scott Michel266bc8f2007-12-04 22:23:35 +00002253}
2254
Dan Gohman475871a2008-07-27 21:46:04 +00002255static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2256 SDValue VecOp = Op.getOperand(0);
2257 SDValue ValOp = Op.getOperand(1);
2258 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002259 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002260
2261 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2262 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2263
Duncan Sands83ec4b62008-06-06 12:08:01 +00002264 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel1a6cdb62008-12-01 17:56:02 +00002265 // Use $sp ($1) because it's always 16-byte aligned and it's available:
2266 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
2267 DAG.getRegister(SPU::R1, PtrVT),
2268 DAG.getConstant(CN->getSExtValue(), PtrVT));
2269 SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, VT, Pointer);
Scott Michel266bc8f2007-12-04 22:23:35 +00002270
Dan Gohman475871a2008-07-27 21:46:04 +00002271 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002272 DAG.getNode(SPUISD::SHUFB, VT,
2273 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
Scott Michel1a6cdb62008-12-01 17:56:02 +00002274 VecOp,
2275 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, ShufMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002276
2277 return result;
2278}
2279
Scott Michelf0569be2008-12-27 04:51:36 +00002280static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc,
2281 const TargetLowering &TLI)
Scott Michela59d4692008-02-23 18:41:37 +00002282{
Dan Gohman475871a2008-07-27 21:46:04 +00002283 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michelf0569be2008-12-27 04:51:36 +00002284 MVT ShiftVT = TLI.getShiftAmountTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002285
2286 assert(Op.getValueType() == MVT::i8);
2287 switch (Opc) {
2288 default:
2289 assert(0 && "Unhandled i8 math operator");
2290 /*NOTREACHED*/
2291 break;
2292 case ISD::SUB: {
2293 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2294 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002295 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002296 N0 = (N0.getOpcode() != ISD::Constant
2297 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Scott Michelf0569be2008-12-27 04:51:36 +00002298 : DAG.getConstant(cast<ConstantSDNode>(N0)->getSExtValue(),
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002299 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002300 N1 = (N1.getOpcode() != ISD::Constant
2301 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Scott Michelf0569be2008-12-27 04:51:36 +00002302 : DAG.getConstant(cast<ConstantSDNode>(N1)->getSExtValue(),
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002303 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002304 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002305 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002306 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002307 case ISD::ROTR:
2308 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002309 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002310 unsigned N1Opc;
2311 N0 = (N0.getOpcode() != ISD::Constant
2312 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002313 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2314 MVT::i16));
Scott Michelf0569be2008-12-27 04:51:36 +00002315 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greif93c53e52008-08-31 15:37:04 +00002316 ? ISD::ZERO_EXTEND
2317 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002318 N1 = (N1.getOpcode() != ISD::Constant
Scott Michelf0569be2008-12-27 04:51:36 +00002319 ? DAG.getNode(N1Opc, ShiftVT, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002320 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Scott Michelf0569be2008-12-27 04:51:36 +00002321 TLI.getShiftAmountTy()));
Dan Gohman475871a2008-07-27 21:46:04 +00002322 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002323 DAG.getNode(ISD::OR, MVT::i16, N0,
2324 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002325 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002326 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002327 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2328 }
2329 case ISD::SRL:
2330 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002331 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002332 unsigned N1Opc;
2333 N0 = (N0.getOpcode() != ISD::Constant
2334 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002335 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
Scott Michelf0569be2008-12-27 04:51:36 +00002336 MVT::i32));
2337 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greif93c53e52008-08-31 15:37:04 +00002338 ? ISD::ZERO_EXTEND
2339 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002340 N1 = (N1.getOpcode() != ISD::Constant
Scott Michelf0569be2008-12-27 04:51:36 +00002341 ? DAG.getNode(N1Opc, ShiftVT, N1)
2342 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(), ShiftVT));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002343 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002344 DAG.getNode(Opc, MVT::i16, N0, N1));
2345 }
2346 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002347 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002348 unsigned N1Opc;
2349 N0 = (N0.getOpcode() != ISD::Constant
2350 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Scott Michelf0569be2008-12-27 04:51:36 +00002351 : DAG.getConstant(cast<ConstantSDNode>(N0)->getSExtValue(),
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002352 MVT::i16));
Scott Michelf0569be2008-12-27 04:51:36 +00002353 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greif93c53e52008-08-31 15:37:04 +00002354 ? ISD::SIGN_EXTEND
2355 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002356 N1 = (N1.getOpcode() != ISD::Constant
Scott Michelf0569be2008-12-27 04:51:36 +00002357 ? DAG.getNode(N1Opc, ShiftVT, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002358 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Scott Michelf0569be2008-12-27 04:51:36 +00002359 ShiftVT));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002360 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002361 DAG.getNode(Opc, MVT::i16, N0, N1));
2362 }
2363 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002364 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002365 unsigned N1Opc;
2366 N0 = (N0.getOpcode() != ISD::Constant
2367 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002368 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2369 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002370 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002371 N1 = (N1.getOpcode() != ISD::Constant
2372 ? DAG.getNode(N1Opc, MVT::i16, N1)
Scott Michelf0569be2008-12-27 04:51:36 +00002373 : DAG.getConstant(cast<ConstantSDNode>(N1)->getSExtValue(),
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002374 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002375 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002376 DAG.getNode(Opc, MVT::i16, N0, N1));
2377 break;
2378 }
2379 }
2380
Dan Gohman475871a2008-07-27 21:46:04 +00002381 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002382}
2383
Dan Gohman475871a2008-07-27 21:46:04 +00002384static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002385{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002386 MVT VT = Op.getValueType();
2387 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002388
Dan Gohman475871a2008-07-27 21:46:04 +00002389 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002390
2391 switch (Opc) {
2392 case ISD::ZERO_EXTEND:
2393 case ISD::SIGN_EXTEND:
2394 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002395 MVT Op0VT = Op0.getValueType();
2396 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002397
2398 assert(Op0VT == MVT::i32
2399 && "CellSPU: Zero/sign extending something other than i32");
2400
Scott Michel104de432008-11-24 17:11:17 +00002401 DEBUG(cerr << "CellSPU.LowerI64Math: lowering zero/sign/any extend\n");
2402
Dan Gohman475871a2008-07-27 21:46:04 +00002403 SDValue PromoteScalar =
Scott Michelf0569be2008-12-27 04:51:36 +00002404 DAG.getNode(SPUISD::PREFSLOT2VEC, Op0VecVT, Op0);
Scott Michela59d4692008-02-23 18:41:37 +00002405
Scott Michel104de432008-11-24 17:11:17 +00002406 if (Opc != ISD::SIGN_EXTEND) {
Scott Michel045a1452008-11-24 18:20:46 +00002407 // Use a shuffle to zero extend the i32 to i64 directly:
2408 SDValue shufMask =
2409 DAG.getNode(ISD::BUILD_VECTOR, Op0VecVT,
2410 DAG.getConstant(0x80808080, MVT::i32),
2411 DAG.getConstant(0x00010203, MVT::i32),
2412 DAG.getConstant(0x80808080, MVT::i32),
2413 DAG.getConstant(0x08090a0b, MVT::i32));
2414 SDValue zextShuffle =
2415 DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2416 PromoteScalar, PromoteScalar, shufMask);
2417
Scott Michel104de432008-11-24 17:11:17 +00002418 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel045a1452008-11-24 18:20:46 +00002419 DAG.getNode(ISD::BIT_CONVERT, VecVT, zextShuffle));
Scott Michel104de432008-11-24 17:11:17 +00002420 } else {
2421 // SPU has no "rotate quadword and replicate bit 0" (i.e. rotate/shift
2422 // right and propagate the sign bit) instruction.
Scott Michel045a1452008-11-24 18:20:46 +00002423 SDValue RotQuad =
2424 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, Op0VecVT,
2425 PromoteScalar, DAG.getConstant(4, MVT::i32));
Scott Michel104de432008-11-24 17:11:17 +00002426 SDValue SignQuad =
2427 DAG.getNode(SPUISD::VEC_SRA, Op0VecVT,
2428 PromoteScalar, DAG.getConstant(32, MVT::i32));
2429 SDValue SelMask =
2430 DAG.getNode(SPUISD::SELECT_MASK, Op0VecVT,
2431 DAG.getConstant(0xf0f0, MVT::i16));
2432 SDValue CombineQuad =
2433 DAG.getNode(SPUISD::SELB, Op0VecVT,
2434 SignQuad, RotQuad, SelMask);
2435
2436 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2437 DAG.getNode(ISD::BIT_CONVERT, VecVT, CombineQuad));
2438 }
Scott Michela59d4692008-02-23 18:41:37 +00002439 }
2440
Scott Michel8bf61e82008-06-02 22:18:03 +00002441 case ISD::ADD: {
2442 // Turn operands into vectors to satisfy type checking (shufb works on
2443 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002444 SDValue Op0 =
Scott Michelf0569be2008-12-27 04:51:36 +00002445 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002446 SDValue Op1 =
Scott Michelf0569be2008-12-27 04:51:36 +00002447 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002448 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002449
2450 // Create the shuffle mask for "rotating" the borrow up one register slot
2451 // once the borrow is generated.
2452 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2453 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2454 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2455 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2456
Dan Gohman475871a2008-07-27 21:46:04 +00002457 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002458 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002459 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002460 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2461 CarryGen, CarryGen,
2462 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2463 &ShufBytes[0], ShufBytes.size()));
2464
Scott Michel104de432008-11-24 17:11:17 +00002465 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel8bf61e82008-06-02 22:18:03 +00002466 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2467 Op0, Op1, ShiftedCarry));
2468 }
2469
2470 case ISD::SUB: {
2471 // Turn operands into vectors to satisfy type checking (shufb works on
2472 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002473 SDValue Op0 =
Scott Michelf0569be2008-12-27 04:51:36 +00002474 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002475 SDValue Op1 =
Scott Michelf0569be2008-12-27 04:51:36 +00002476 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002477 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002478
2479 // Create the shuffle mask for "rotating" the borrow up one register slot
2480 // once the borrow is generated.
2481 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2482 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2483 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2484 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2485
Dan Gohman475871a2008-07-27 21:46:04 +00002486 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002487 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002488 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002489 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2490 BorrowGen, BorrowGen,
2491 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2492 &ShufBytes[0], ShufBytes.size()));
2493
Scott Michel104de432008-11-24 17:11:17 +00002494 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel8bf61e82008-06-02 22:18:03 +00002495 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2496 Op0, Op1, ShiftedBorrow));
2497 }
2498
Scott Michela59d4692008-02-23 18:41:37 +00002499 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002500 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002501 MVT ShiftAmtVT = ShiftAmt.getValueType();
Scott Michelf0569be2008-12-27 04:51:36 +00002502 SDValue Op0Vec = DAG.getNode(SPUISD::PREFSLOT2VEC, VecVT, Op0);
Dan Gohman475871a2008-07-27 21:46:04 +00002503 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002504 DAG.getNode(SPUISD::SELB, VecVT,
2505 Op0Vec,
2506 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002507 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002508 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002509 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002510 DAG.getNode(ISD::SRL, ShiftAmtVT,
2511 ShiftAmt,
2512 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002513 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002514 DAG.getNode(ISD::AND, ShiftAmtVT,
2515 ShiftAmt,
2516 DAG.getConstant(7, ShiftAmtVT));
2517
Scott Michel104de432008-11-24 17:11:17 +00002518 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michela59d4692008-02-23 18:41:37 +00002519 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2520 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2521 MaskLower, ShiftAmtBytes),
2522 ShiftAmtBits));
2523 }
2524
2525 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002526 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002527 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002528 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002529 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002530 DAG.getNode(ISD::SRL, ShiftAmtVT,
2531 ShiftAmt,
2532 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002533 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002534 DAG.getNode(ISD::AND, ShiftAmtVT,
2535 ShiftAmt,
2536 DAG.getConstant(7, ShiftAmtVT));
2537
2538 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2539 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2540 Op0, ShiftAmtBytes),
2541 ShiftAmtBits);
2542 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002543
2544 case ISD::SRA: {
2545 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002546 SDValue Op0 =
Scott Michelf0569be2008-12-27 04:51:36 +00002547 DAG.getNode(SPUISD::PREFSLOT2VEC, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002548 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002549 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002550
2551 // Negate variable shift amounts
2552 if (!isa<ConstantSDNode>(ShiftAmt)) {
2553 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2554 DAG.getConstant(0, ShiftVT), ShiftAmt);
2555 }
2556
Dan Gohman475871a2008-07-27 21:46:04 +00002557 SDValue UpperHalfSign =
Scott Michel104de432008-11-24 17:11:17 +00002558 DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i32,
Scott Michel8bf61e82008-06-02 22:18:03 +00002559 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2560 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2561 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002562 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002563 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002564 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002565 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2566 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002567 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002568 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2569 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002570 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002571 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2572 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002573 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002574 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2575 RotateLeftBytes, ShiftAmt);
2576
Scott Michel104de432008-11-24 17:11:17 +00002577 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel8bf61e82008-06-02 22:18:03 +00002578 RotateLeftBits);
2579 }
Scott Michela59d4692008-02-23 18:41:37 +00002580 }
2581
Dan Gohman475871a2008-07-27 21:46:04 +00002582 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002583}
2584
Scott Michel266bc8f2007-12-04 22:23:35 +00002585//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002586static SDValue
2587LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2588 SDValue ConstVec;
2589 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002590 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002591
2592 ConstVec = Op.getOperand(0);
2593 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002594 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2595 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002596 ConstVec = ConstVec.getOperand(0);
2597 } else {
2598 ConstVec = Op.getOperand(1);
2599 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002600 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002601 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002602 }
2603 }
2604 }
2605
Gabor Greifba36cb52008-08-28 21:40:38 +00002606 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002607 uint64_t VectorBits[2];
2608 uint64_t UndefBits[2];
2609 uint64_t SplatBits, SplatUndef;
2610 int SplatSize;
2611
Gabor Greifba36cb52008-08-28 21:40:38 +00002612 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002613 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002614 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002615 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002616 SDValue tcVec[16];
2617 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002618 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2619
2620 // Turn the BUILD_VECTOR into a set of target constants:
2621 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002622 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002623
Gabor Greifba36cb52008-08-28 21:40:38 +00002624 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002625 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002626 }
2627 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002628 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2629 // lowered. Return the operation, rather than a null SDValue.
2630 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002631}
2632
2633//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002634static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002635 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002636 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002637 default:
2638 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002639 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002640 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002641 abort();
2642 /*NOTREACHED*/
2643
2644 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002645 SDValue rA = Op.getOperand(0);
2646 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002647
2648 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002649 DAG.getNode(ISD::ADD, MVT::i32,
2650 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2651 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2652 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002653 }
2654 }
2655
Dan Gohman475871a2008-07-27 21:46:04 +00002656 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002657}
2658
2659//! Custom lowering for CTPOP (count population)
2660/*!
2661 Custom lowering code that counts the number ones in the input
2662 operand. SPU has such an instruction, but it counts the number of
2663 ones per byte, which then have to be accumulated.
2664*/
Dan Gohman475871a2008-07-27 21:46:04 +00002665static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002666 MVT VT = Op.getValueType();
2667 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002668
Duncan Sands83ec4b62008-06-06 12:08:01 +00002669 switch (VT.getSimpleVT()) {
2670 default:
2671 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002672 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002673 SDValue N = Op.getOperand(0);
2674 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002675
Scott Michelf0569be2008-12-27 04:51:36 +00002676 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman475871a2008-07-27 21:46:04 +00002677 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002678
2679 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2680 }
2681
2682 case MVT::i16: {
2683 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002684 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002685
Chris Lattner84bc5422007-12-31 04:13:23 +00002686 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002687
Dan Gohman475871a2008-07-27 21:46:04 +00002688 SDValue N = Op.getOperand(0);
2689 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2690 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002691 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002692
Scott Michelf0569be2008-12-27 04:51:36 +00002693 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman475871a2008-07-27 21:46:04 +00002694 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002695
2696 // CNTB_result becomes the chain to which all of the virtual registers
2697 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002698 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002699 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002700
Dan Gohman475871a2008-07-27 21:46:04 +00002701 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002702 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2703
Dan Gohman475871a2008-07-27 21:46:04 +00002704 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002705
2706 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002707 DAG.getNode(ISD::ADD, MVT::i16,
2708 DAG.getNode(ISD::SRL, MVT::i16,
2709 Tmp1, Shift1),
2710 Tmp1),
2711 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002712 }
2713
2714 case MVT::i32: {
2715 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002716 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002717
Chris Lattner84bc5422007-12-31 04:13:23 +00002718 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2719 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002720
Dan Gohman475871a2008-07-27 21:46:04 +00002721 SDValue N = Op.getOperand(0);
2722 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2723 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2724 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2725 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002726
Scott Michelf0569be2008-12-27 04:51:36 +00002727 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman475871a2008-07-27 21:46:04 +00002728 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002729
2730 // CNTB_result becomes the chain to which all of the virtual registers
2731 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002732 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002733 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002734
Dan Gohman475871a2008-07-27 21:46:04 +00002735 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002736 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2737
Dan Gohman475871a2008-07-27 21:46:04 +00002738 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002739 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002740 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002741
Dan Gohman475871a2008-07-27 21:46:04 +00002742 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002743 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002744 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002745
Dan Gohman475871a2008-07-27 21:46:04 +00002746 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002747 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2748
Dan Gohman475871a2008-07-27 21:46:04 +00002749 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002750 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002751 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2752 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002753 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002754 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002755 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002756
2757 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2758 }
2759
2760 case MVT::i64:
2761 break;
2762 }
2763
Dan Gohman475871a2008-07-27 21:46:04 +00002764 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002765}
2766
Scott Michelf0569be2008-12-27 04:51:36 +00002767//! Lower ISD::SETCC
2768/*!
2769 Lower i64 condition code handling.
2770 */
2771
2772static SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) {
2773 MVT VT = Op.getValueType();
2774 SDValue lhs = Op.getOperand(0);
2775 SDValue rhs = Op.getOperand(1);
2776 SDValue condition = Op.getOperand(2);
2777
2778 if (VT == MVT::i32 && lhs.getValueType() == MVT::i64) {
2779 // Expand the i64 comparisons to what Cell can actually support,
2780 // which is eq, ugt and sgt:
2781#if 0
2782 CondCodeSDNode *ccvalue = dyn_cast<CondCodeSDValue>(condition);
2783
2784 switch (ccvalue->get()) {
2785 case
2786 }
2787#endif
2788 }
2789
2790 return SDValue();
2791}
2792
Scott Michel7a1c9e92008-11-22 23:50:42 +00002793//! Lower ISD::SELECT_CC
2794/*!
2795 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2796 SELB instruction.
2797
2798 \note Need to revisit this in the future: if the code path through the true
2799 and false value computations is longer than the latency of a branch (6
2800 cycles), then it would be more advantageous to branch and insert a new basic
2801 block and branch on the condition. However, this code does not make that
2802 assumption, given the simplisitc uses so far.
2803 */
2804
Scott Michelf0569be2008-12-27 04:51:36 +00002805static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
2806 const TargetLowering &TLI) {
Scott Michel7a1c9e92008-11-22 23:50:42 +00002807 MVT VT = Op.getValueType();
2808 SDValue lhs = Op.getOperand(0);
2809 SDValue rhs = Op.getOperand(1);
2810 SDValue trueval = Op.getOperand(2);
2811 SDValue falseval = Op.getOperand(3);
2812 SDValue condition = Op.getOperand(4);
2813
Scott Michelf0569be2008-12-27 04:51:36 +00002814 // NOTE: SELB's arguments: $rA, $rB, $mask
2815 //
2816 // SELB selects bits from $rA where bits in $mask are 0, bits from $rB
2817 // where bits in $mask are 1. CCond will be inverted, having 1s where the
2818 // condition was true and 0s where the condition was false. Hence, the
2819 // arguments to SELB get reversed.
2820
Scott Michel7a1c9e92008-11-22 23:50:42 +00002821 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2822 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2823 // with another "cannot select select_cc" assert:
2824
Scott Michelf0569be2008-12-27 04:51:36 +00002825 SDValue compare = DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(Op),
2826 lhs, rhs, condition);
2827 return DAG.getNode(SPUISD::SELB, VT, falseval, trueval, compare);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002828}
2829
Scott Michelb30e8f62008-12-02 19:53:53 +00002830//! Custom lower ISD::TRUNCATE
2831static SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG)
2832{
2833 MVT VT = Op.getValueType();
2834 MVT::SimpleValueType simpleVT = VT.getSimpleVT();
2835 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
2836
2837 SDValue Op0 = Op.getOperand(0);
2838 MVT Op0VT = Op0.getValueType();
2839 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
2840
Scott Michelb30e8f62008-12-02 19:53:53 +00002841 // Create shuffle mask
Scott Michelf0569be2008-12-27 04:51:36 +00002842 if (Op0VT.getSimpleVT() == MVT::i128 && simpleVT == MVT::i64) {
2843 // least significant doubleword of quadword
2844 unsigned maskHigh = 0x08090a0b;
2845 unsigned maskLow = 0x0c0d0e0f;
2846 // Use a shuffle to perform the truncation
2847 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2848 DAG.getConstant(maskHigh, MVT::i32),
2849 DAG.getConstant(maskLow, MVT::i32),
2850 DAG.getConstant(maskHigh, MVT::i32),
2851 DAG.getConstant(maskLow, MVT::i32));
2852
2853
2854 SDValue PromoteScalar = DAG.getNode(SPUISD::PREFSLOT2VEC, Op0VecVT, Op0);
2855
2856 SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2857 PromoteScalar, PromoteScalar, shufMask);
2858
2859 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2860 DAG.getNode(ISD::BIT_CONVERT, VecVT, truncShuffle));
Scott Michelb30e8f62008-12-02 19:53:53 +00002861 }
2862
Scott Michelf0569be2008-12-27 04:51:36 +00002863 return SDValue(); // Leave the truncate unmolested
Scott Michelb30e8f62008-12-02 19:53:53 +00002864}
2865
Scott Michel7a1c9e92008-11-22 23:50:42 +00002866//! Custom (target-specific) lowering entry point
2867/*!
2868 This is where LLVM's DAG selection process calls to do target-specific
2869 lowering of nodes.
2870 */
Dan Gohman475871a2008-07-27 21:46:04 +00002871SDValue
2872SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002873{
Scott Michela59d4692008-02-23 18:41:37 +00002874 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002875 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002876
2877 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002878 default: {
2879 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002880 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002881 cerr << "*Op.getNode():\n";
2882 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002883 abort();
2884 }
2885 case ISD::LOAD:
Scott Michelb30e8f62008-12-02 19:53:53 +00002886 case ISD::EXTLOAD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002887 case ISD::SEXTLOAD:
2888 case ISD::ZEXTLOAD:
2889 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2890 case ISD::STORE:
2891 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2892 case ISD::ConstantPool:
2893 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2894 case ISD::GlobalAddress:
2895 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2896 case ISD::JumpTable:
2897 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2898 case ISD::Constant:
2899 return LowerConstant(Op, DAG);
2900 case ISD::ConstantFP:
2901 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002902 case ISD::BRCOND:
Scott Michelf0569be2008-12-27 04:51:36 +00002903 return LowerBRCOND(Op, DAG, *this);
Scott Michel266bc8f2007-12-04 22:23:35 +00002904 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002905 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002906 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002907 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002908 case ISD::RET:
2909 return LowerRET(Op, DAG, getTargetMachine());
2910
Scott Michela59d4692008-02-23 18:41:37 +00002911
2912 // i8, i64 math ops:
2913 case ISD::ZERO_EXTEND:
2914 case ISD::SIGN_EXTEND:
2915 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002916 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002917 case ISD::SUB:
2918 case ISD::ROTR:
2919 case ISD::ROTL:
2920 case ISD::SRL:
2921 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002922 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002923 if (VT == MVT::i8)
Scott Michelf0569be2008-12-27 04:51:36 +00002924 return LowerI8Math(Op, DAG, Opc, *this);
Scott Michela59d4692008-02-23 18:41:37 +00002925 else if (VT == MVT::i64)
2926 return LowerI64Math(Op, DAG, Opc);
2927 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002928 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002929
2930 // Vector-related lowering.
2931 case ISD::BUILD_VECTOR:
2932 return LowerBUILD_VECTOR(Op, DAG);
2933 case ISD::SCALAR_TO_VECTOR:
2934 return LowerSCALAR_TO_VECTOR(Op, DAG);
2935 case ISD::VECTOR_SHUFFLE:
2936 return LowerVECTOR_SHUFFLE(Op, DAG);
2937 case ISD::EXTRACT_VECTOR_ELT:
2938 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2939 case ISD::INSERT_VECTOR_ELT:
2940 return LowerINSERT_VECTOR_ELT(Op, DAG);
2941
2942 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2943 case ISD::AND:
2944 case ISD::OR:
2945 case ISD::XOR:
2946 return LowerByteImmed(Op, DAG);
2947
2948 // Vector and i8 multiply:
2949 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002950 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002951 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002952 else if (VT == MVT::i8)
Scott Michelf0569be2008-12-27 04:51:36 +00002953 return LowerI8Math(Op, DAG, Opc, *this);
Scott Michel266bc8f2007-12-04 22:23:35 +00002954 else
Scott Michela59d4692008-02-23 18:41:37 +00002955 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002956
2957 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002958 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002959 return LowerFDIVf32(Op, DAG);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002960#if 0
2961 // This is probably a libcall
2962 else if (Op.getValueType() == MVT::f64)
2963 return LowerFDIVf64(Op, DAG);
2964#endif
Scott Michel266bc8f2007-12-04 22:23:35 +00002965 else
2966 assert(0 && "Calling FDIV on unsupported MVT");
2967
2968 case ISD::CTPOP:
2969 return LowerCTPOP(Op, DAG);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002970
2971 case ISD::SELECT_CC:
Scott Michelf0569be2008-12-27 04:51:36 +00002972 return LowerSELECT_CC(Op, DAG, *this);
Scott Michelb30e8f62008-12-02 19:53:53 +00002973
2974 case ISD::TRUNCATE:
2975 return LowerTRUNCATE(Op, DAG);
Scott Michelf0569be2008-12-27 04:51:36 +00002976
2977 case ISD::SETCC:
2978 return LowerSETCC(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002979 }
2980
Dan Gohman475871a2008-07-27 21:46:04 +00002981 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002982}
2983
Duncan Sands1607f052008-12-01 11:39:25 +00002984void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
2985 SmallVectorImpl<SDValue>&Results,
2986 SelectionDAG &DAG)
Scott Michel73ce1c52008-11-10 23:43:06 +00002987{
2988#if 0
2989 unsigned Opc = (unsigned) N->getOpcode();
2990 MVT OpVT = N->getValueType(0);
2991
2992 switch (Opc) {
2993 default: {
2994 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2995 cerr << "Op.getOpcode() = " << Opc << "\n";
2996 cerr << "*Op.getNode():\n";
2997 N->dump();
2998 abort();
2999 /*NOTREACHED*/
3000 }
3001 }
3002#endif
3003
3004 /* Otherwise, return unchanged */
Scott Michel73ce1c52008-11-10 23:43:06 +00003005}
3006
Scott Michel266bc8f2007-12-04 22:23:35 +00003007//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00003008// Target Optimization Hooks
3009//===----------------------------------------------------------------------===//
3010
Dan Gohman475871a2008-07-27 21:46:04 +00003011SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00003012SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
3013{
3014#if 0
3015 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00003016#endif
3017 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00003018 SelectionDAG &DAG = DCI.DAG;
Scott Michel1a6cdb62008-12-01 17:56:02 +00003019 SDValue Op0 = N->getOperand(0); // everything has at least one operand
3020 MVT NodeVT = N->getValueType(0); // The node's value type
Scott Michelf0569be2008-12-27 04:51:36 +00003021 MVT Op0VT = Op0.getValueType(); // The first operand's result
Scott Michel1a6cdb62008-12-01 17:56:02 +00003022 SDValue Result; // Initially, empty result
Scott Michel266bc8f2007-12-04 22:23:35 +00003023
3024 switch (N->getOpcode()) {
3025 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00003026 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00003027 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00003028
Scott Michelf0569be2008-12-27 04:51:36 +00003029 if (Op0.getOpcode() == SPUISD::IndirectAddr
3030 || Op1.getOpcode() == SPUISD::IndirectAddr) {
3031 // Normalize the operands to reduce repeated code
3032 SDValue IndirectArg = Op0, AddArg = Op1;
3033
3034 if (Op1.getOpcode() == SPUISD::IndirectAddr) {
3035 IndirectArg = Op1;
3036 AddArg = Op0;
3037 }
3038
3039 if (isa<ConstantSDNode>(AddArg)) {
3040 ConstantSDNode *CN0 = cast<ConstantSDNode > (AddArg);
3041 SDValue IndOp1 = IndirectArg.getOperand(1);
3042
3043 if (CN0->isNullValue()) {
3044 // (add (SPUindirect <arg>, <arg>), 0) ->
3045 // (SPUindirect <arg>, <arg>)
Scott Michel053c1da2008-01-29 02:16:57 +00003046
Scott Michel23f2ff72008-12-04 17:16:59 +00003047#if !defined(NDEBUG)
Scott Michelf0569be2008-12-27 04:51:36 +00003048 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel30ee7df2008-12-04 03:02:42 +00003049 cerr << "\n"
Scott Michelf0569be2008-12-27 04:51:36 +00003050 << "Replace: (add (SPUindirect <arg>, <arg>), 0)\n"
3051 << "With: (SPUindirect <arg>, <arg>)\n";
3052 }
Scott Michel30ee7df2008-12-04 03:02:42 +00003053#endif
3054
Scott Michelf0569be2008-12-27 04:51:36 +00003055 return IndirectArg;
3056 } else if (isa<ConstantSDNode>(IndOp1)) {
3057 // (add (SPUindirect <arg>, <const>), <const>) ->
3058 // (SPUindirect <arg>, <const + const>)
3059 ConstantSDNode *CN1 = cast<ConstantSDNode > (IndOp1);
3060 int64_t combinedConst = CN0->getSExtValue() + CN1->getSExtValue();
3061 SDValue combinedValue = DAG.getConstant(combinedConst, Op0VT);
Scott Michel053c1da2008-01-29 02:16:57 +00003062
Scott Michelf0569be2008-12-27 04:51:36 +00003063#if !defined(NDEBUG)
3064 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
3065 cerr << "\n"
3066 << "Replace: (add (SPUindirect <arg>, " << CN1->getSExtValue()
3067 << "), " << CN0->getSExtValue() << ")\n"
3068 << "With: (SPUindirect <arg>, "
3069 << combinedConst << ")\n";
3070 }
3071#endif
Scott Michel053c1da2008-01-29 02:16:57 +00003072
Scott Michelf0569be2008-12-27 04:51:36 +00003073 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
3074 IndirectArg, combinedValue);
3075 }
Scott Michel053c1da2008-01-29 02:16:57 +00003076 }
3077 }
Scott Michela59d4692008-02-23 18:41:37 +00003078 break;
3079 }
3080 case ISD::SIGN_EXTEND:
3081 case ISD::ZERO_EXTEND:
3082 case ISD::ANY_EXTEND: {
Scott Michel1a6cdb62008-12-01 17:56:02 +00003083 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT && NodeVT == Op0VT) {
Scott Michela59d4692008-02-23 18:41:37 +00003084 // (any_extend (SPUextract_elt0 <arg>)) ->
3085 // (SPUextract_elt0 <arg>)
3086 // Types must match, however...
Scott Michel23f2ff72008-12-04 17:16:59 +00003087#if !defined(NDEBUG)
3088 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel30ee7df2008-12-04 03:02:42 +00003089 cerr << "\nReplace: ";
3090 N->dump(&DAG);
3091 cerr << "\nWith: ";
3092 Op0.getNode()->dump(&DAG);
3093 cerr << "\n";
Scott Michel23f2ff72008-12-04 17:16:59 +00003094 }
Scott Michel30ee7df2008-12-04 03:02:42 +00003095#endif
Scott Michela59d4692008-02-23 18:41:37 +00003096
3097 return Op0;
3098 }
3099 break;
3100 }
3101 case SPUISD::IndirectAddr: {
3102 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
3103 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00003104 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00003105 // (SPUindirect (SPUaform <addr>, 0), 0) ->
3106 // (SPUaform <addr>, 0)
3107
3108 DEBUG(cerr << "Replace: ");
3109 DEBUG(N->dump(&DAG));
3110 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00003111 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00003112 DEBUG(cerr << "\n");
3113
3114 return Op0;
3115 }
Scott Michelf0569be2008-12-27 04:51:36 +00003116 } else if (Op0.getOpcode() == ISD::ADD) {
3117 SDValue Op1 = N->getOperand(1);
3118 if (ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(Op1)) {
3119 // (SPUindirect (add <arg>, <arg>), 0) ->
3120 // (SPUindirect <arg>, <arg>)
3121 if (CN1->isNullValue()) {
3122
3123#if !defined(NDEBUG)
3124 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
3125 cerr << "\n"
3126 << "Replace: (SPUindirect (add <arg>, <arg>), 0)\n"
3127 << "With: (SPUindirect <arg>, <arg>)\n";
3128 }
3129#endif
3130
3131 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
3132 Op0.getOperand(0), Op0.getOperand(1));
3133 }
3134 }
Scott Michela59d4692008-02-23 18:41:37 +00003135 }
3136 break;
3137 }
3138 case SPUISD::SHLQUAD_L_BITS:
3139 case SPUISD::SHLQUAD_L_BYTES:
3140 case SPUISD::VEC_SHL:
3141 case SPUISD::VEC_SRL:
3142 case SPUISD::VEC_SRA:
3143 case SPUISD::ROTQUAD_RZ_BYTES:
Scott Michelf0569be2008-12-27 04:51:36 +00003144 case SPUISD::ROTQUAD_RZ_BITS:
3145 case SPUISD::ROTBYTES_LEFT: {
Dan Gohman475871a2008-07-27 21:46:04 +00003146 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00003147
Scott Michelf0569be2008-12-27 04:51:36 +00003148 // Kill degenerate vector shifts:
3149 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1)) {
3150 if (CN->isNullValue()) {
Scott Michela59d4692008-02-23 18:41:37 +00003151 Result = Op0;
3152 }
3153 }
3154 break;
3155 }
Scott Michelf0569be2008-12-27 04:51:36 +00003156 case SPUISD::PREFSLOT2VEC: {
Scott Michela59d4692008-02-23 18:41:37 +00003157 switch (Op0.getOpcode()) {
3158 default:
3159 break;
3160 case ISD::ANY_EXTEND:
3161 case ISD::ZERO_EXTEND:
3162 case ISD::SIGN_EXTEND: {
Scott Michel1a6cdb62008-12-01 17:56:02 +00003163 // (SPUpromote_scalar (any|zero|sign_extend (SPUvec2prefslot <arg>))) ->
Scott Michela59d4692008-02-23 18:41:37 +00003164 // <arg>
3165 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00003166 SDValue Op00 = Op0.getOperand(0);
Scott Michel104de432008-11-24 17:11:17 +00003167 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman475871a2008-07-27 21:46:04 +00003168 SDValue Op000 = Op00.getOperand(0);
Scott Michel1a6cdb62008-12-01 17:56:02 +00003169 if (Op000.getValueType() == NodeVT) {
Scott Michela59d4692008-02-23 18:41:37 +00003170 Result = Op000;
3171 }
3172 }
3173 break;
3174 }
Scott Michel104de432008-11-24 17:11:17 +00003175 case SPUISD::VEC2PREFSLOT: {
Scott Michel1a6cdb62008-12-01 17:56:02 +00003176 // (SPUpromote_scalar (SPUvec2prefslot <arg>)) ->
Scott Michela59d4692008-02-23 18:41:37 +00003177 // <arg>
3178 Result = Op0.getOperand(0);
3179 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003180 }
Scott Michela59d4692008-02-23 18:41:37 +00003181 }
3182 break;
Scott Michel053c1da2008-01-29 02:16:57 +00003183 }
3184 }
Scott Michel58c58182008-01-17 20:38:41 +00003185 // Otherwise, return unchanged.
Scott Michel1a6cdb62008-12-01 17:56:02 +00003186#ifndef NDEBUG
Gabor Greifba36cb52008-08-28 21:40:38 +00003187 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00003188 DEBUG(cerr << "\nReplace.SPU: ");
3189 DEBUG(N->dump(&DAG));
3190 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00003191 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00003192 DEBUG(cerr << "\n");
3193 }
3194#endif
3195
3196 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00003197}
3198
3199//===----------------------------------------------------------------------===//
3200// Inline Assembly Support
3201//===----------------------------------------------------------------------===//
3202
3203/// getConstraintType - Given a constraint letter, return the type of
3204/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00003205SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00003206SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
3207 if (ConstraintLetter.size() == 1) {
3208 switch (ConstraintLetter[0]) {
3209 default: break;
3210 case 'b':
3211 case 'r':
3212 case 'f':
3213 case 'v':
3214 case 'y':
3215 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003216 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003217 }
3218 return TargetLowering::getConstraintType(ConstraintLetter);
3219}
3220
Scott Michel5af8f0e2008-07-16 17:17:29 +00003221std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00003222SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00003223 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00003224{
3225 if (Constraint.size() == 1) {
3226 // GCC RS6000 Constraint Letters
3227 switch (Constraint[0]) {
3228 case 'b': // R1-R31
3229 case 'r': // R0-R31
3230 if (VT == MVT::i64)
3231 return std::make_pair(0U, SPU::R64CRegisterClass);
3232 return std::make_pair(0U, SPU::R32CRegisterClass);
3233 case 'f':
3234 if (VT == MVT::f32)
3235 return std::make_pair(0U, SPU::R32FPRegisterClass);
3236 else if (VT == MVT::f64)
3237 return std::make_pair(0U, SPU::R64FPRegisterClass);
3238 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003239 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00003240 return std::make_pair(0U, SPU::GPRCRegisterClass);
3241 }
3242 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003243
Scott Michel266bc8f2007-12-04 22:23:35 +00003244 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3245}
3246
Scott Michela59d4692008-02-23 18:41:37 +00003247//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00003248void
Dan Gohman475871a2008-07-27 21:46:04 +00003249SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00003250 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00003251 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00003252 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00003253 const SelectionDAG &DAG,
3254 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00003255#if 0
Scott Michela59d4692008-02-23 18:41:37 +00003256 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00003257#endif
Scott Michela59d4692008-02-23 18:41:37 +00003258
3259 switch (Op.getOpcode()) {
3260 default:
3261 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3262 break;
3263
3264#if 0
3265 case CALL:
3266 case SHUFB:
Scott Michel7a1c9e92008-11-22 23:50:42 +00003267 case SHUFFLE_MASK:
Scott Michela59d4692008-02-23 18:41:37 +00003268 case CNTB:
3269#endif
3270
Scott Michelf0569be2008-12-27 04:51:36 +00003271 case SPUISD::PREFSLOT2VEC: {
Dan Gohman475871a2008-07-27 21:46:04 +00003272 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00003273 MVT Op0VT = Op0.getValueType();
3274 unsigned Op0VTBits = Op0VT.getSizeInBits();
3275 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003276 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3277 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003278 break;
3279 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003280
Scott Michela59d4692008-02-23 18:41:37 +00003281 case SPUISD::LDRESULT:
Scott Michel30ee7df2008-12-04 03:02:42 +00003282 case SPUISD::VEC2PREFSLOT: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00003283 MVT OpVT = Op.getValueType();
3284 unsigned OpVTBits = OpVT.getSizeInBits();
3285 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003286 KnownZero |= APInt(OpVTBits, ~InMask, false);
3287 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003288 break;
3289 }
3290
3291#if 0
Scott Michela59d4692008-02-23 18:41:37 +00003292 case MPY:
3293 case MPYU:
3294 case MPYH:
3295 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00003296 case SPUISD::SHLQUAD_L_BITS:
3297 case SPUISD::SHLQUAD_L_BYTES:
3298 case SPUISD::VEC_SHL:
3299 case SPUISD::VEC_SRL:
3300 case SPUISD::VEC_SRA:
3301 case SPUISD::VEC_ROTL:
3302 case SPUISD::VEC_ROTR:
3303 case SPUISD::ROTQUAD_RZ_BYTES:
3304 case SPUISD::ROTQUAD_RZ_BITS:
Scott Michel203b2d62008-04-30 00:30:08 +00003305 case SPUISD::ROTBYTES_LEFT:
Scott Michel8bf61e82008-06-02 22:18:03 +00003306 case SPUISD::SELECT_MASK:
3307 case SPUISD::SELB:
3308 case SPUISD::FPInterp:
3309 case SPUISD::FPRecipEst:
3310 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003311#endif
3312 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003313}
Scott Michelf0569be2008-12-27 04:51:36 +00003314
3315unsigned
3316SPUTargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op,
3317 unsigned Depth) const {
3318 switch (Op.getOpcode()) {
3319 default:
3320 return 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00003321
Scott Michelf0569be2008-12-27 04:51:36 +00003322 case ISD::SETCC: {
3323 MVT VT = Op.getValueType();
3324
3325 if (VT != MVT::i8 && VT != MVT::i16 && VT != MVT::i32) {
3326 VT = MVT::i32;
3327 }
3328 return VT.getSizeInBits();
3329 }
3330 }
3331}
3332
Scott Michel203b2d62008-04-30 00:30:08 +00003333// LowerAsmOperandForConstraint
3334void
Dan Gohman475871a2008-07-27 21:46:04 +00003335SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003336 char ConstraintLetter,
Evan Chengda43bcf2008-09-24 00:05:32 +00003337 bool hasMemory,
Dan Gohman475871a2008-07-27 21:46:04 +00003338 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003339 SelectionDAG &DAG) const {
3340 // Default, for the time being, to the base class handler
Evan Chengda43bcf2008-09-24 00:05:32 +00003341 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3342 Ops, DAG);
Scott Michel203b2d62008-04-30 00:30:08 +00003343}
3344
Scott Michel266bc8f2007-12-04 22:23:35 +00003345/// isLegalAddressImmediate - Return true if the integer value can be used
3346/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003347bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3348 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003349 // SPU's addresses are 256K:
3350 return (V > -(1 << 18) && V < (1 << 18) - 1);
3351}
3352
3353bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003354 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003355}
Dan Gohman6520e202008-10-18 02:06:02 +00003356
3357bool
3358SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3359 // The SPU target isn't yet aware of offsets.
3360 return false;
3361}