blob: 033b8a7338cf5c95c02076c3ac033be68a0d5763 [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 Michel266bc8f2007-12-04 22:23:35 +000018#include "llvm/ADT/VectorExtras.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000019#include "llvm/CodeGen/CallingConvLower.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner84bc5422007-12-31 04:13:23 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000024#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000025#include "llvm/Constants.h"
26#include "llvm/Function.h"
27#include "llvm/Intrinsics.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/MathExtras.h"
30#include "llvm/Target/TargetOptions.h"
31
32#include <map>
33
34using namespace llvm;
35
36// Used in getTargetNodeName() below
37namespace {
38 std::map<unsigned, const char *> node_names;
39
Duncan Sands83ec4b62008-06-06 12:08:01 +000040 //! MVT mapping to useful data for Cell SPU
Scott Michel266bc8f2007-12-04 22:23:35 +000041 struct valtype_map_s {
Scott Michel7a1c9e92008-11-22 23:50:42 +000042 const MVT valtype;
43 const int prefslot_byte;
Scott Michel266bc8f2007-12-04 22:23:35 +000044 };
Scott Michel5af8f0e2008-07-16 17:17:29 +000045
Scott Michel266bc8f2007-12-04 22:23:35 +000046 const valtype_map_s valtype_map[] = {
47 { MVT::i1, 3 },
48 { MVT::i8, 3 },
49 { MVT::i16, 2 },
50 { MVT::i32, 0 },
51 { MVT::f32, 0 },
52 { MVT::i64, 0 },
53 { MVT::f64, 0 },
54 { MVT::i128, 0 }
55 };
56
57 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
58
Duncan Sands83ec4b62008-06-06 12:08:01 +000059 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel266bc8f2007-12-04 22:23:35 +000060 const valtype_map_s *retval = 0;
61
62 for (size_t i = 0; i < n_valtype_map; ++i) {
63 if (valtype_map[i].valtype == VT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +000064 retval = valtype_map + i;
65 break;
Scott Michel266bc8f2007-12-04 22:23:35 +000066 }
67 }
68
69#ifndef NDEBUG
70 if (retval == 0) {
71 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands83ec4b62008-06-06 12:08:01 +000072 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +000073 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +000074 abort();
75 }
76#endif
77
78 return retval;
79 }
80
81 //! Predicate that returns true if operand is a memory target
82 /*!
83 \arg Op Operand to test
84 \return true if the operand is a memory target (i.e., global
Scott Michel9de5d0d2008-01-11 02:53:15 +000085 address, external symbol, constant pool) or an A-form
Scott Michel266bc8f2007-12-04 22:23:35 +000086 address.
87 */
Dan Gohman475871a2008-07-27 21:46:04 +000088 bool isMemoryOperand(const SDValue &Op)
Scott Michel266bc8f2007-12-04 22:23:35 +000089 {
90 const unsigned Opc = Op.getOpcode();
91 return (Opc == ISD::GlobalAddress
92 || Opc == ISD::GlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000093 || Opc == ISD::JumpTable
94 || Opc == ISD::ConstantPool
Bill Wendling056292f2008-09-16 21:48:12 +000095 || Opc == ISD::ExternalSymbol
Scott Michel266bc8f2007-12-04 22:23:35 +000096 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
Bill Wendling056292f2008-09-16 21:48:12 +0000100 || Opc == ISD::TargetExternalSymbol
Scott Michel9de5d0d2008-01-11 02:53:15 +0000101 || Opc == SPUISD::AFormAddr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000102 }
Scott Michel58c58182008-01-17 20:38:41 +0000103
104 //! Predicate that returns true if the operand is an indirect target
Dan Gohman475871a2008-07-27 21:46:04 +0000105 bool isIndirectOperand(const SDValue &Op)
Scott Michel58c58182008-01-17 20:38:41 +0000106 {
107 const unsigned Opc = Op.getOpcode();
108 return (Opc == ISD::Register
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000109 || Opc == SPUISD::LDRESULT);
Scott Michel58c58182008-01-17 20:38:41 +0000110 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000111}
112
113SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
114 : TargetLowering(TM),
115 SPUTM(TM)
116{
117 // Fold away setcc operations if possible.
118 setPow2DivIsCheap();
119
120 // Use _setjmp/_longjmp instead of setjmp/longjmp.
121 setUseUnderscoreSetJmp(true);
122 setUseUnderscoreLongJmp(true);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000123
Scott Michel266bc8f2007-12-04 22:23:35 +0000124 // Set up the SPU's register classes:
Scott Michel504c3692007-12-17 22:32:34 +0000125 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
126 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
127 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
128 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
129 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
130 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
Scott Michel266bc8f2007-12-04 22:23:35 +0000131 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000132
Scott Micheldc91bea2008-11-20 16:36:33 +0000133 // Initialize libcalls:
134 setLibcallName(RTLIB::MUL_I64, "__muldi3");
135
Scott Michel266bc8f2007-12-04 22:23:35 +0000136 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng03294662008-10-14 21:26:46 +0000137 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
138 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
139 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +0000140
Evan Cheng03294662008-10-14 21:26:46 +0000141 setLoadExtAction(ISD::EXTLOAD, MVT::i8, Custom);
142 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Custom);
143 setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Scott Michela0e57692008-11-20 04:26:21 +0000144 setTruncStoreAction(MVT::i8, MVT::i8, Custom);
145 setTruncStoreAction(MVT::i16, MVT::i8, Custom);
146 setTruncStoreAction(MVT::i32, MVT::i8, Custom);
147 setTruncStoreAction(MVT::i64, MVT::i8, Custom);
148 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000149
Evan Cheng03294662008-10-14 21:26:46 +0000150 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Custom);
151 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Custom);
152 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000153
154 // SPU constant load actions are custom lowered:
155 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begemanccef5802008-02-14 18:43:04 +0000156 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000157 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
158
159 // SPU's loads and stores have to be custom lowered:
Scott Michel719b0e12008-11-19 17:45:08 +0000160 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel266bc8f2007-12-04 22:23:35 +0000161 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000162 MVT VT = (MVT::SimpleValueType)sctype;
163
164 setOperationAction(ISD::LOAD, VT, Custom);
165 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000166 }
167
Scott Michel9c0c6b22008-11-21 02:56:16 +0000168 // Custom lower BRCOND for i8 to "promote" the result to i16
Scott Michel58c58182008-01-17 20:38:41 +0000169 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000170
171 // Expand the jumptable branches
172 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
173 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel7a1c9e92008-11-22 23:50:42 +0000174
175 // Custom lower SELECT_CC for most cases, but expand by default
Scott Michel5af8f0e2008-07-16 17:17:29 +0000176 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel7a1c9e92008-11-22 23:50:42 +0000177 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
178 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
179 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
180 setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000181
182 // SPU has no intrinsics for these particular operations:
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000183 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
184
Scott Michel266bc8f2007-12-04 22:23:35 +0000185 // PowerPC has no SREM/UREM instructions
186 setOperationAction(ISD::SREM, MVT::i32, Expand);
187 setOperationAction(ISD::UREM, MVT::i32, Expand);
188 setOperationAction(ISD::SREM, MVT::i64, Expand);
189 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000190
Scott Michel266bc8f2007-12-04 22:23:35 +0000191 // We don't support sin/cos/sqrt/fmod
192 setOperationAction(ISD::FSIN , MVT::f64, Expand);
193 setOperationAction(ISD::FCOS , MVT::f64, Expand);
194 setOperationAction(ISD::FREM , MVT::f64, Expand);
195 setOperationAction(ISD::FSIN , MVT::f32, Expand);
196 setOperationAction(ISD::FCOS , MVT::f32, Expand);
197 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000198
Scott Michel266bc8f2007-12-04 22:23:35 +0000199 // If we're enabling GP optimizations, use hardware square root
200 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
201 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000202
Scott Michel266bc8f2007-12-04 22:23:35 +0000203 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
204 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
205
206 // SPU can do rotate right and left, so legalize it... but customize for i8
207 // because instructions don't exist.
Bill Wendling9440e352008-08-31 02:59:23 +0000208
209 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
210 // .td files.
211 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
212 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
213 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
214
Scott Michel266bc8f2007-12-04 22:23:35 +0000215 setOperationAction(ISD::ROTL, MVT::i32, Legal);
216 setOperationAction(ISD::ROTL, MVT::i16, Legal);
217 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Micheldc91bea2008-11-20 16:36:33 +0000218
Scott Michel266bc8f2007-12-04 22:23:35 +0000219 // SPU has no native version of shift left/right for i8
220 setOperationAction(ISD::SHL, MVT::i8, Custom);
221 setOperationAction(ISD::SRL, MVT::i8, Custom);
222 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel9c0c6b22008-11-21 02:56:16 +0000223
224 // SPU needs custom lowering for shift left/right for i64
Scott Michela59d4692008-02-23 18:41:37 +0000225 setOperationAction(ISD::SHL, MVT::i64, Custom);
226 setOperationAction(ISD::SRL, MVT::i64, Custom);
227 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000228
Scott Michel5af8f0e2008-07-16 17:17:29 +0000229 // Custom lower i8, i32 and i64 multiplications
230 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000231 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel9c0c6b22008-11-21 02:56:16 +0000232 setOperationAction(ISD::MUL, MVT::i64, Expand); // libcall
233
234 // SMUL_LOHI, UMUL_LOHI
235 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
236 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
237 setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom);
238 setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000239
Scott Michel8bf61e82008-06-02 22:18:03 +0000240 // Need to custom handle (some) common i8, i64 math ops
241 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000242 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel8bf61e82008-06-02 22:18:03 +0000243 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000244
Scott Michel266bc8f2007-12-04 22:23:35 +0000245 // SPU does not have BSWAP. It does have i32 support CTLZ.
246 // CTPOP has to be custom lowered.
247 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
248 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
249
250 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
251 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
252 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
253 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
254
255 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
256 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
257
258 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000259
Scott Michel8bf61e82008-06-02 22:18:03 +0000260 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000261 // select ought to work:
Scott Michel78c47fa2008-03-10 16:58:52 +0000262 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michelad2715e2008-03-05 23:02:02 +0000263 setOperationAction(ISD::SELECT, MVT::i16, Legal);
264 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000265 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000266
Scott Michel78c47fa2008-03-10 16:58:52 +0000267 setOperationAction(ISD::SETCC, MVT::i8, Legal);
268 setOperationAction(ISD::SETCC, MVT::i16, Legal);
269 setOperationAction(ISD::SETCC, MVT::i32, Legal);
270 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michelad2715e2008-03-05 23:02:02 +0000271
Scott Michela59d4692008-02-23 18:41:37 +0000272 // Zero extension and sign extension for i64 have to be
273 // custom legalized
274 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
275 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
276 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000277
Scott Michel266bc8f2007-12-04 22:23:35 +0000278 // SPU has a legal FP -> signed INT instruction
279 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
280 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
281 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
282 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
283
284 // FDIV on SPU requires custom lowering
285 setOperationAction(ISD::FDIV, MVT::f32, Custom);
286 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
287
288 // SPU has [U|S]INT_TO_FP
289 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
290 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
291 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
292 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
293 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
294 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
295 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
296 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
297
Scott Michel86c041f2007-12-20 00:44:13 +0000298 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
299 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
300 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
301 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000302
303 // We cannot sextinreg(i1). Expand to shifts.
304 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000305
Scott Michel266bc8f2007-12-04 22:23:35 +0000306 // Support label based line numbers.
Dan Gohman7f460202008-06-30 20:59:49 +0000307 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000308 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000309
310 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000311 // appropriate instructions to materialize the address.
Scott Michel9c0c6b22008-11-21 02:56:16 +0000312 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel053c1da2008-01-29 02:16:57 +0000313 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000314 MVT VT = (MVT::SimpleValueType)sctype;
315
316 setOperationAction(ISD::GlobalAddress, VT, Custom);
317 setOperationAction(ISD::ConstantPool, VT, Custom);
318 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000319 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000320
321 // RET must be custom lowered, to meet ABI requirements
322 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000323
Scott Michel266bc8f2007-12-04 22:23:35 +0000324 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
325 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000326
Scott Michel266bc8f2007-12-04 22:23:35 +0000327 // Use the default implementation.
328 setOperationAction(ISD::VAARG , MVT::Other, Expand);
329 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
330 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000331 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000332 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
333 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
334 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
335
336 // Cell SPU has instructions for converting between i64 and fp.
337 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
338 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000339
Scott Michel266bc8f2007-12-04 22:23:35 +0000340 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
341 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
342
343 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
344 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
345
346 // First set operation action for all vector types to expand. Then we
347 // will selectively turn on ones that can be effectively codegen'd.
348 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
349 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
350 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
351 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
352 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
353 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
354
Duncan Sands83ec4b62008-06-06 12:08:01 +0000355 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
356 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
357 MVT VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000358
Duncan Sands83ec4b62008-06-06 12:08:01 +0000359 // add/sub are legal for all supported vector VT's.
360 setOperationAction(ISD::ADD , VT, Legal);
361 setOperationAction(ISD::SUB , VT, Legal);
362 // mul has to be custom lowered.
363 setOperationAction(ISD::MUL , VT, Custom);
364
365 setOperationAction(ISD::AND , VT, Legal);
366 setOperationAction(ISD::OR , VT, Legal);
367 setOperationAction(ISD::XOR , VT, Legal);
368 setOperationAction(ISD::LOAD , VT, Legal);
369 setOperationAction(ISD::SELECT, VT, Legal);
370 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000371
Scott Michel266bc8f2007-12-04 22:23:35 +0000372 // These operations need to be expanded:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000373 setOperationAction(ISD::SDIV, VT, Expand);
374 setOperationAction(ISD::SREM, VT, Expand);
375 setOperationAction(ISD::UDIV, VT, Expand);
376 setOperationAction(ISD::UREM, VT, Expand);
377 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000378
379 // Custom lower build_vector, constant pool spills, insert and
380 // extract vector elements:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000381 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
382 setOperationAction(ISD::ConstantPool, VT, Custom);
383 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
384 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
385 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
386 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000387 }
388
389 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
390 setOperationAction(ISD::AND, MVT::v16i8, Custom);
391 setOperationAction(ISD::OR, MVT::v16i8, Custom);
392 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
393 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000394
Scott Michel266bc8f2007-12-04 22:23:35 +0000395 setShiftAmountType(MVT::i32);
Duncan Sands03228082008-11-23 15:47:28 +0000396 setBooleanContents(ZeroOrOneBooleanContent);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000397
Scott Michel266bc8f2007-12-04 22:23:35 +0000398 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000399
Scott Michel266bc8f2007-12-04 22:23:35 +0000400 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000401 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000402 setTargetDAGCombine(ISD::ZERO_EXTEND);
403 setTargetDAGCombine(ISD::SIGN_EXTEND);
404 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000405
Scott Michel266bc8f2007-12-04 22:23:35 +0000406 computeRegisterProperties();
Scott Michel7a1c9e92008-11-22 23:50:42 +0000407
408 // Set other properties:
409 setSchedulingPreference(SchedulingForLatency);
Scott Michel266bc8f2007-12-04 22:23:35 +0000410}
411
412const char *
413SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
414{
415 if (node_names.empty()) {
416 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
417 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
418 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
419 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000420 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000421 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000422 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
423 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
424 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
Scott Michel7a1c9e92008-11-22 23:50:42 +0000425 node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000426 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
427 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
428 node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
Gabor Greif93c53e52008-08-31 15:37:04 +0000429 node_names[(unsigned) SPUISD::EXTRACT_ELT0_CHAINED]
430 = "SPUISD::EXTRACT_ELT0_CHAINED";
Scott Michel266bc8f2007-12-04 22:23:35 +0000431 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
432 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
433 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
434 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
435 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
436 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
437 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
438 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michela59d4692008-02-23 18:41:37 +0000439 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
440 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000441 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
442 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
443 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
444 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
445 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michela59d4692008-02-23 18:41:37 +0000446 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
447 "SPUISD::ROTQUAD_RZ_BYTES";
448 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
449 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel266bc8f2007-12-04 22:23:35 +0000450 node_names[(unsigned) SPUISD::ROTBYTES_RIGHT_S] =
451 "SPUISD::ROTBYTES_RIGHT_S";
452 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
453 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
454 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel8bf61e82008-06-02 22:18:03 +0000455 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
456 "SPUISD::ROTBYTES_LEFT_BITS";
457 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000458 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel8bf61e82008-06-02 22:18:03 +0000459 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
460 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
461 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
462 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel266bc8f2007-12-04 22:23:35 +0000463 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
464 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
465 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
466 }
467
468 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
469
470 return ((i != node_names.end()) ? i->second : 0);
471}
472
Dan Gohman475871a2008-07-27 21:46:04 +0000473MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000474 MVT VT = Op.getValueType();
Scott Micheld976c212008-10-30 01:51:48 +0000475 return (VT.isInteger() ? VT : MVT(MVT::i32));
Scott Michel78c47fa2008-03-10 16:58:52 +0000476}
477
Scott Michel266bc8f2007-12-04 22:23:35 +0000478//===----------------------------------------------------------------------===//
479// Calling convention code:
480//===----------------------------------------------------------------------===//
481
482#include "SPUGenCallingConv.inc"
483
484//===----------------------------------------------------------------------===//
485// LowerOperation implementation
486//===----------------------------------------------------------------------===//
487
Scott Michel9de5d0d2008-01-11 02:53:15 +0000488/// Aligned load common code for CellSPU
489/*!
490 \param[in] Op The SelectionDAG load or store operand
491 \param[in] DAG The selection DAG
492 \param[in] ST CellSPU subtarget information structure
493 \param[in,out] alignment Caller initializes this to the load or store node's
494 value from getAlignment(), may be updated while generating the aligned load
495 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
496 offset (divisible by 16, modulo 16 == 0)
497 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
498 offset of the preferred slot (modulo 16 != 0)
499 \param[in,out] VT Caller initializes this value type to the the load or store
500 node's loaded or stored value type; may be updated if an i1-extended load or
501 store.
502 \param[out] was16aligned true if the base pointer had 16-byte alignment,
503 otherwise false. Can help to determine if the chunk needs to be rotated.
504
505 Both load and store lowering load a block of data aligned on a 16-byte
506 boundary. This is the common aligned load code shared between both.
507 */
Dan Gohman475871a2008-07-27 21:46:04 +0000508static SDValue
509AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Michel9de5d0d2008-01-11 02:53:15 +0000510 LSBaseSDNode *LSN,
511 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000512 MVT &VT, bool &was16aligned)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000513{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000514 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000515 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman475871a2008-07-27 21:46:04 +0000516 SDValue basePtr = LSN->getBasePtr();
517 SDValue chain = LSN->getChain();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000518
519 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000520 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000521
Gabor Greif93c53e52008-08-31 15:37:04 +0000522 if (Op1.getOpcode() == ISD::Constant
523 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel58c58182008-01-17 20:38:41 +0000524 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000525
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000526 alignOffs = (int) CN->getZExtValue();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000527 prefSlotOffs = (int) (alignOffs & 0xf);
528
529 // Adjust the rotation amount to ensure that the final result ends up in
530 // the preferred slot:
531 prefSlotOffs -= vtm->prefslot_byte;
532 basePtr = basePtr.getOperand(0);
533
Scott Michel58c58182008-01-17 20:38:41 +0000534 // Loading from memory, can we adjust alignment?
535 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +0000536 SDValue APtr = basePtr.getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000537 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
538 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
539 alignment = GSDN->getGlobal()->getAlignment();
540 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000541 }
542 } else {
543 alignOffs = 0;
544 prefSlotOffs = -vtm->prefslot_byte;
545 }
Scott Michel203b2d62008-04-30 00:30:08 +0000546 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
547 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
548 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
549 prefSlotOffs = (int) (alignOffs & 0xf);
550 prefSlotOffs -= vtm->prefslot_byte;
551 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000552 } else {
553 alignOffs = 0;
554 prefSlotOffs = -vtm->prefslot_byte;
555 }
556
557 if (alignment == 16) {
558 // Realign the base pointer as a D-Form address:
559 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel58c58182008-01-17 20:38:41 +0000560 basePtr = DAG.getNode(ISD::ADD, PtrVT,
561 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000562 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000563 }
564
565 // Emit the vector load:
566 was16aligned = true;
567 return DAG.getLoad(MVT::v16i8, chain, basePtr,
568 LSN->getSrcValue(), LSN->getSrcValueOffset(),
569 LSN->isVolatile(), 16);
570 }
571
572 // Unaligned load or we're using the "large memory" model, which means that
573 // we have to be very pessimistic:
Scott Michel58c58182008-01-17 20:38:41 +0000574 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greif93c53e52008-08-31 15:37:04 +0000575 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
576 DAG.getConstant(0, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000577 }
578
579 // Add the offset
Scott Michel053c1da2008-01-29 02:16:57 +0000580 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000581 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000582 was16aligned = false;
583 return DAG.getLoad(MVT::v16i8, chain, basePtr,
584 LSN->getSrcValue(), LSN->getSrcValueOffset(),
585 LSN->isVolatile(), 16);
586}
587
Scott Michel266bc8f2007-12-04 22:23:35 +0000588/// Custom lower loads for CellSPU
589/*!
590 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
591 within a 16-byte block, we have to rotate to extract the requested element.
592 */
Dan Gohman475871a2008-07-27 21:46:04 +0000593static SDValue
594LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000595 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000596 SDValue the_chain = LN->getChain();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000597 MVT VT = LN->getMemoryVT();
Gabor Greifba36cb52008-08-28 21:40:38 +0000598 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000599 ISD::LoadExtType ExtType = LN->getExtensionType();
600 unsigned alignment = LN->getAlignment();
Dan Gohman475871a2008-07-27 21:46:04 +0000601 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000602
Scott Michel266bc8f2007-12-04 22:23:35 +0000603 switch (LN->getAddressingMode()) {
604 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000605 int offset, rotamt;
606 bool was16aligned;
Dan Gohman475871a2008-07-27 21:46:04 +0000607 SDValue result =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000608 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000609
Gabor Greifba36cb52008-08-28 21:40:38 +0000610 if (result.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +0000611 return result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000612
613 the_chain = result.getValue(1);
614 // Rotate the chunk if necessary
615 if (rotamt < 0)
616 rotamt += 16;
Scott Michel497e8882008-01-11 21:01:19 +0000617 if (rotamt != 0 || !was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000618 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
619
Scott Michel58c58182008-01-17 20:38:41 +0000620 Ops[0] = the_chain;
621 Ops[1] = result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000622 if (was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000623 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
624 } else {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000625 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000626 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel497e8882008-01-11 21:01:19 +0000627 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000628 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000629 }
630
631 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
632 the_chain = result.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000633 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000634
635 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
636 SDVTList scalarvts;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000637 MVT vecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000638
Scott Michel9de5d0d2008-01-11 02:53:15 +0000639 // Convert the loaded v16i8 vector to the appropriate vector type
640 // specified by the operand:
641 if (OpVT == VT) {
642 if (VT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000643 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000644 } else
Duncan Sands83ec4b62008-06-06 12:08:01 +0000645 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000646
647 Ops[0] = the_chain;
648 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
649 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
650 result = DAG.getNode(SPUISD::EXTRACT_ELT0_CHAINED, scalarvts, Ops, 2);
651 the_chain = result.getValue(1);
652 } else {
653 // Handle the sign and zero-extending loads for i1 and i8:
654 unsigned NewOpC;
655
656 if (ExtType == ISD::SEXTLOAD) {
657 NewOpC = (OpVT == MVT::i1
658 ? SPUISD::EXTRACT_I1_SEXT
659 : SPUISD::EXTRACT_I8_SEXT);
660 } else {
661 assert(ExtType == ISD::ZEXTLOAD);
662 NewOpC = (OpVT == MVT::i1
663 ? SPUISD::EXTRACT_I1_ZEXT
664 : SPUISD::EXTRACT_I8_ZEXT);
665 }
666
667 result = DAG.getNode(NewOpC, OpVT, result);
668 }
669
670 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000671 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000672 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000673 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000674 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000675
Scott Michel58c58182008-01-17 20:38:41 +0000676 result = DAG.getNode(SPUISD::LDRESULT, retvts,
677 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000678 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000679 }
680 case ISD::PRE_INC:
681 case ISD::PRE_DEC:
682 case ISD::POST_INC:
683 case ISD::POST_DEC:
684 case ISD::LAST_INDEXED_MODE:
685 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
686 "UNINDEXED\n";
687 cerr << (unsigned) LN->getAddressingMode() << "\n";
688 abort();
689 /*NOTREACHED*/
690 }
691
Dan Gohman475871a2008-07-27 21:46:04 +0000692 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000693}
694
695/// Custom lower stores for CellSPU
696/*!
697 All CellSPU stores are aligned to 16-byte boundaries, so for elements
698 within a 16-byte block, we have to generate a shuffle to insert the
699 requested element into its place, then store the resulting block.
700 */
Dan Gohman475871a2008-07-27 21:46:04 +0000701static SDValue
702LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000703 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000704 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000705 MVT VT = Value.getValueType();
706 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
707 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000708 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000709
710 switch (SN->getAddressingMode()) {
711 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000712 int chunk_offset, slot_offset;
713 bool was16aligned;
Scott Michel266bc8f2007-12-04 22:23:35 +0000714
Scott Michel9c0c6b22008-11-21 02:56:16 +0000715 // The vector type we really want to load from the 16-byte chunk.
Scott Michel719b0e12008-11-19 17:45:08 +0000716 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
717 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000718
Dan Gohman475871a2008-07-27 21:46:04 +0000719 SDValue alignLoadVec =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000720 AlignedLoad(Op, DAG, ST, SN, alignment,
721 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000722
Gabor Greifba36cb52008-08-28 21:40:38 +0000723 if (alignLoadVec.getNode() == 0)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000724 return alignLoadVec;
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 basePtr = LN->getBasePtr();
728 SDValue the_chain = alignLoadVec.getValue(1);
729 SDValue theValue = SN->getValue();
730 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000731
732 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000733 && (theValue.getOpcode() == ISD::AssertZext
734 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000735 // Drill down and get the value for zero- and sign-extended
736 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000737 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000738 }
739
Scott Michel9de5d0d2008-01-11 02:53:15 +0000740 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000741
Dan Gohman475871a2008-07-27 21:46:04 +0000742 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
743 SDValue insertEltPtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000744
745 // If the base pointer is already a D-form address, then just create
746 // a new D-form address with a slot offset and the orignal base pointer.
747 // Otherwise generate a D-form address with the slot offset relative
748 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000749 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greifba36cb52008-08-28 21:40:38 +0000750 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michel497e8882008-01-11 21:01:19 +0000751 DEBUG(cerr << "\n");
752
Scott Michel053c1da2008-01-29 02:16:57 +0000753 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
754 (basePtr.getOpcode() == ISD::ADD
755 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000756 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000757 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000758 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000759 }
760
Scott Michel430a5552008-11-19 15:24:16 +0000761 SDValue insertEltOp =
Scott Michel7a1c9e92008-11-22 23:50:42 +0000762 DAG.getNode(SPUISD::SHUFFLE_MASK, stVecVT, insertEltPtr);
Scott Michel719b0e12008-11-19 17:45:08 +0000763 SDValue vectorizeOp =
764 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michel430a5552008-11-19 15:24:16 +0000765
766 result = DAG.getNode(SPUISD::SHUFB, vecVT, vectorizeOp, alignLoadVec,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000767 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000768
Scott Michel9de5d0d2008-01-11 02:53:15 +0000769 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000770 LN->getSrcValue(), LN->getSrcValueOffset(),
771 LN->isVolatile(), LN->getAlignment());
772
Scott Michel719b0e12008-11-19 17:45:08 +0000773#if 0 && defined(NDEBUG)
Scott Michel430a5552008-11-19 15:24:16 +0000774 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
775 const SDValue &currentRoot = DAG.getRoot();
776
777 DAG.setRoot(result);
778 cerr << "------- CellSPU:LowerStore result:\n";
779 DAG.dump();
780 cerr << "-------\n";
781 DAG.setRoot(currentRoot);
782 }
783#endif
784
Scott Michel266bc8f2007-12-04 22:23:35 +0000785 return result;
786 /*UNREACHED*/
787 }
788 case ISD::PRE_INC:
789 case ISD::PRE_DEC:
790 case ISD::POST_INC:
791 case ISD::POST_DEC:
792 case ISD::LAST_INDEXED_MODE:
793 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
794 "UNINDEXED\n";
795 cerr << (unsigned) SN->getAddressingMode() << "\n";
796 abort();
797 /*NOTREACHED*/
798 }
799
Dan Gohman475871a2008-07-27 21:46:04 +0000800 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000801}
802
803/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000804static SDValue
805LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000806 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000807 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
808 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000809 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
810 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000811 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000812
813 if (TM.getRelocationModel() == Reloc::Static) {
814 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000815 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000816 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000817 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000818 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
819 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000820 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000821 }
822 }
823
824 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000825 "LowerConstantPool: Relocation model other than static"
826 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000827 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000828}
829
Dan Gohman475871a2008-07-27 21:46:04 +0000830static SDValue
831LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000832 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000833 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000834 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
835 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000836 const TargetMachine &TM = DAG.getTarget();
837
838 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000839 if (!ST->usingLargeMem()) {
840 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
841 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000842 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
843 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000844 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
845 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000846 }
847
848 assert(0 &&
849 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000850 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000851}
852
Dan Gohman475871a2008-07-27 21:46:04 +0000853static SDValue
854LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000855 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000856 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
857 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000858 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000859 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000860 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000861
Scott Michel266bc8f2007-12-04 22:23:35 +0000862 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000863 if (!ST->usingLargeMem()) {
864 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
865 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000866 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
867 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000868 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
869 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000870 } else {
871 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000872 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000873 abort();
874 /*NOTREACHED*/
875 }
876
Dan Gohman475871a2008-07-27 21:46:04 +0000877 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000878}
879
880//! Custom lower i64 integer constants
881/*!
882 This code inserts all of the necessary juggling that needs to occur to load
883 a 64-bit constant into a register.
884 */
Dan Gohman475871a2008-07-27 21:46:04 +0000885static SDValue
886LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000887 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000888 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000889
890 if (VT == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000891 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +0000892 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000893 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000894 } else {
895 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000896 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000897 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000898 abort();
899 /*NOTREACHED*/
900 }
901
Dan Gohman475871a2008-07-27 21:46:04 +0000902 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000903}
904
Nate Begemanccef5802008-02-14 18:43:04 +0000905//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000906static SDValue
907LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000908 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000909 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000910
911 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000912 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000913
Nate Begemanccef5802008-02-14 18:43:04 +0000914 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000915 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000916 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000917 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000918 }
919
Dan Gohman475871a2008-07-27 21:46:04 +0000920 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000921}
922
Scott Michel9c0c6b22008-11-21 02:56:16 +0000923//! Lower MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman475871a2008-07-27 21:46:04 +0000924static SDValue
925LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel58c58182008-01-17 20:38:41 +0000926{
Dan Gohman475871a2008-07-27 21:46:04 +0000927 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000928 MVT CondVT = Cond.getValueType();
929 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000930
Scott Michel9c0c6b22008-11-21 02:56:16 +0000931 if (CondVT == MVT::i8) {
932 CondNVT = MVT::i16;
Scott Michel58c58182008-01-17 20:38:41 +0000933 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
934 Op.getOperand(0),
935 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
936 Op.getOperand(2));
937 } else
Dan Gohman475871a2008-07-27 21:46:04 +0000938 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000939}
940
Dan Gohman475871a2008-07-27 21:46:04 +0000941static SDValue
942LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000943{
944 MachineFunction &MF = DAG.getMachineFunction();
945 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000946 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Micheld976c212008-10-30 01:51:48 +0000947 SmallVector<SDValue, 48> ArgValues;
Dan Gohman475871a2008-07-27 21:46:04 +0000948 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000949 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000950
951 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
952 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000953
Scott Michel266bc8f2007-12-04 22:23:35 +0000954 unsigned ArgOffset = SPUFrameInfo::minStackSize();
955 unsigned ArgRegIdx = 0;
956 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000957
Duncan Sands83ec4b62008-06-06 12:08:01 +0000958 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000959
Scott Michel266bc8f2007-12-04 22:23:35 +0000960 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000961 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
962 ArgNo != e; ++ArgNo) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000963 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
964 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Micheld976c212008-10-30 01:51:48 +0000965 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000966
Scott Micheld976c212008-10-30 01:51:48 +0000967 if (ArgRegIdx < NumArgRegs) {
968 const TargetRegisterClass *ArgRegClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000969
Scott Micheld976c212008-10-30 01:51:48 +0000970 switch (ObjectVT.getSimpleVT()) {
971 default: {
Scott Michel9c0c6b22008-11-21 02:56:16 +0000972 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
973 << ObjectVT.getMVTString()
974 << "\n";
975 abort();
Scott Micheld976c212008-10-30 01:51:48 +0000976 }
977 case MVT::i8:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000978 ArgRegClass = &SPU::R8CRegClass;
979 break;
Scott Micheld976c212008-10-30 01:51:48 +0000980 case MVT::i16:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000981 ArgRegClass = &SPU::R16CRegClass;
982 break;
Scott Micheld976c212008-10-30 01:51:48 +0000983 case MVT::i32:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000984 ArgRegClass = &SPU::R32CRegClass;
985 break;
Scott Micheld976c212008-10-30 01:51:48 +0000986 case MVT::i64:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000987 ArgRegClass = &SPU::R64CRegClass;
988 break;
Scott Micheld976c212008-10-30 01:51:48 +0000989 case MVT::f32:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000990 ArgRegClass = &SPU::R32FPRegClass;
991 break;
Scott Micheld976c212008-10-30 01:51:48 +0000992 case MVT::f64:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000993 ArgRegClass = &SPU::R64FPRegClass;
994 break;
Scott Micheld976c212008-10-30 01:51:48 +0000995 case MVT::v2f64:
996 case MVT::v4f32:
997 case MVT::v2i64:
998 case MVT::v4i32:
999 case MVT::v8i16:
1000 case MVT::v16i8:
Scott Michel9c0c6b22008-11-21 02:56:16 +00001001 ArgRegClass = &SPU::VECREGRegClass;
1002 break;
Scott Micheld976c212008-10-30 01:51:48 +00001003 }
1004
1005 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
1006 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
1007 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1008 ++ArgRegIdx;
1009 } else {
1010 // We need to load the argument to a virtual register if we determined
1011 // above that we ran out of physical registers of the appropriate type
1012 // or we're forced to do vararg
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001013 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001014 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001015 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001016 ArgOffset += StackSlotSize;
1017 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001018
Scott Michel266bc8f2007-12-04 22:23:35 +00001019 ArgValues.push_back(ArgVal);
Scott Micheld976c212008-10-30 01:51:48 +00001020 // Update the chain
1021 Root = ArgVal.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001022 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001023
Scott Micheld976c212008-10-30 01:51:48 +00001024 // vararg handling:
Scott Michel266bc8f2007-12-04 22:23:35 +00001025 if (isVarArg) {
Scott Micheld976c212008-10-30 01:51:48 +00001026 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1027 // We will spill (79-3)+1 registers to the stack
1028 SmallVector<SDValue, 79-3+1> MemOps;
1029
1030 // Create the frame slot
1031
Scott Michel266bc8f2007-12-04 22:23:35 +00001032 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Micheld976c212008-10-30 01:51:48 +00001033 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1034 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1035 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1036 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1037 Root = Store.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001038 MemOps.push_back(Store);
Scott Micheld976c212008-10-30 01:51:48 +00001039
1040 // Increment address by stack slot size for the next stored argument
1041 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001042 }
1043 if (!MemOps.empty())
Scott Micheld976c212008-10-30 01:51:48 +00001044 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001045 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001046
Scott Michel266bc8f2007-12-04 22:23:35 +00001047 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001048
Scott Michel266bc8f2007-12-04 22:23:35 +00001049 // Return the new list of results.
Gabor Greifba36cb52008-08-28 21:40:38 +00001050 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf9516202008-06-30 10:19:09 +00001051 ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001052}
1053
1054/// isLSAAddress - Return the immediate to use if the specified
1055/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001056static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001057 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel266bc8f2007-12-04 22:23:35 +00001058 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001059
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001060 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001061 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1062 (Addr << 14 >> 14) != Addr)
1063 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001064
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001065 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001066}
1067
1068static
Dan Gohman475871a2008-07-27 21:46:04 +00001069SDValue
1070LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman095cc292008-09-13 01:54:27 +00001071 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1072 SDValue Chain = TheCall->getChain();
Dan Gohman095cc292008-09-13 01:54:27 +00001073 SDValue Callee = TheCall->getCallee();
1074 unsigned NumOps = TheCall->getNumArgs();
Scott Michel266bc8f2007-12-04 22:23:35 +00001075 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1076 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1077 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1078
1079 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001080 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001081
Scott Michel266bc8f2007-12-04 22:23:35 +00001082 // Accumulate how many bytes are to be pushed on the stack, including the
1083 // linkage area, and parameter passing area. According to the SPU ABI,
1084 // we minimally need space for [LR] and [SP]
1085 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001086
Scott Michel266bc8f2007-12-04 22:23:35 +00001087 // Set up a copy of the stack pointer for use loading and storing any
1088 // arguments that may not fit in the registers available for argument
1089 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001090 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001091
Scott Michel266bc8f2007-12-04 22:23:35 +00001092 // Figure out which arguments are going to go in registers, and which in
1093 // memory.
1094 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1095 unsigned ArgRegIdx = 0;
1096
1097 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001098 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001099 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001100 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001101
1102 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman095cc292008-09-13 01:54:27 +00001103 SDValue Arg = TheCall->getArg(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001104
Scott Michel266bc8f2007-12-04 22:23:35 +00001105 // PtrOff will be used to store the current argument to the stack if a
1106 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001107 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001108 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1109
Duncan Sands83ec4b62008-06-06 12:08:01 +00001110 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001111 default: assert(0 && "Unexpected ValueType for argument!");
1112 case MVT::i32:
1113 case MVT::i64:
1114 case MVT::i128:
1115 if (ArgRegIdx != NumArgRegs) {
1116 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1117 } else {
1118 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001119 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001120 }
1121 break;
1122 case MVT::f32:
1123 case MVT::f64:
1124 if (ArgRegIdx != NumArgRegs) {
1125 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1126 } else {
1127 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001128 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001129 }
1130 break;
1131 case MVT::v4f32:
1132 case MVT::v4i32:
1133 case MVT::v8i16:
1134 case MVT::v16i8:
1135 if (ArgRegIdx != NumArgRegs) {
1136 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1137 } else {
1138 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001139 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001140 }
1141 break;
1142 }
1143 }
1144
1145 // Update number of stack bytes actually used, insert a call sequence start
1146 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnere563bbc2008-10-11 22:08:30 +00001147 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1148 true));
Scott Michel266bc8f2007-12-04 22:23:35 +00001149
1150 if (!MemOpChains.empty()) {
1151 // Adjust the stack pointer for the stack arguments.
1152 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1153 &MemOpChains[0], MemOpChains.size());
1154 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001155
Scott Michel266bc8f2007-12-04 22:23:35 +00001156 // Build a sequence of copy-to-reg nodes chained together with token chain
1157 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001158 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001159 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1160 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1161 InFlag);
1162 InFlag = Chain.getValue(1);
1163 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001164
Dan Gohman475871a2008-07-27 21:46:04 +00001165 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001166 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001167
Bill Wendling056292f2008-09-16 21:48:12 +00001168 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1169 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1170 // node so that legalize doesn't hack it.
Scott Michel19fd42a2008-11-11 03:06:06 +00001171 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001172 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001173 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001174 SDValue Zero = DAG.getConstant(0, PtrVT);
1175 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001176
Scott Michel9de5d0d2008-01-11 02:53:15 +00001177 if (!ST->usingLargeMem()) {
1178 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1179 // style calls, otherwise, external symbols are BRASL calls. This assumes
1180 // that declared/defined symbols are in the same compilation unit and can
1181 // be reached through PC-relative jumps.
1182 //
1183 // NOTE:
1184 // This may be an unsafe assumption for JIT and really large compilation
1185 // units.
1186 if (GV->isDeclaration()) {
1187 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1188 } else {
1189 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1190 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001191 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001192 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1193 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001194 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001195 }
Scott Michel19fd42a2008-11-11 03:06:06 +00001196 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendling056292f2008-09-16 21:48:12 +00001197 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001198 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001199 // If this is an absolute destination address that appears to be a legal
1200 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001201 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001202 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001203
1204 Ops.push_back(Chain);
1205 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001206
Scott Michel266bc8f2007-12-04 22:23:35 +00001207 // Add argument registers to the end of the list so that they are known live
1208 // into the call.
1209 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001210 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001211 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001212
Gabor Greifba36cb52008-08-28 21:40:38 +00001213 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001214 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001215 // Returns a chain and a flag for retval copy to use.
1216 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1217 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001218 InFlag = Chain.getValue(1);
1219
Chris Lattnere563bbc2008-10-11 22:08:30 +00001220 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1221 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001222 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001223 InFlag = Chain.getValue(1);
1224
Dan Gohman475871a2008-07-27 21:46:04 +00001225 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001226 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001227
Scott Michel266bc8f2007-12-04 22:23:35 +00001228 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001229 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001230 default: assert(0 && "Unexpected ret value!");
1231 case MVT::Other: break;
1232 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001233 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001234 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1235 ResultVals[0] = Chain.getValue(0);
1236 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1237 Chain.getValue(2)).getValue(1);
1238 ResultVals[1] = Chain.getValue(0);
1239 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001240 } else {
1241 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1242 ResultVals[0] = Chain.getValue(0);
1243 NumResults = 1;
1244 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001245 break;
1246 case MVT::i64:
1247 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1248 ResultVals[0] = Chain.getValue(0);
1249 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001250 break;
1251 case MVT::f32:
1252 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001253 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001254 InFlag).getValue(1);
1255 ResultVals[0] = Chain.getValue(0);
1256 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001257 break;
1258 case MVT::v2f64:
1259 case MVT::v4f32:
1260 case MVT::v4i32:
1261 case MVT::v8i16:
1262 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001263 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001264 InFlag).getValue(1);
1265 ResultVals[0] = Chain.getValue(0);
1266 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001267 break;
1268 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001269
Scott Michel266bc8f2007-12-04 22:23:35 +00001270 // If the function returns void, just return the chain.
1271 if (NumResults == 0)
1272 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001273
Scott Michel266bc8f2007-12-04 22:23:35 +00001274 // Otherwise, merge everything together with a MERGE_VALUES node.
1275 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001276 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001277 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001278}
1279
Dan Gohman475871a2008-07-27 21:46:04 +00001280static SDValue
1281LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001282 SmallVector<CCValAssign, 16> RVLocs;
1283 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1284 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1285 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001286 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001287
Scott Michel266bc8f2007-12-04 22:23:35 +00001288 // If this is the first return lowered for this function, add the regs to the
1289 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001290 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001291 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001292 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001293 }
1294
Dan Gohman475871a2008-07-27 21:46:04 +00001295 SDValue Chain = Op.getOperand(0);
1296 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001297
Scott Michel266bc8f2007-12-04 22:23:35 +00001298 // Copy the result values into the output registers.
1299 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1300 CCValAssign &VA = RVLocs[i];
1301 assert(VA.isRegLoc() && "Can only return in registers!");
1302 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1303 Flag = Chain.getValue(1);
1304 }
1305
Gabor Greifba36cb52008-08-28 21:40:38 +00001306 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001307 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1308 else
1309 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1310}
1311
1312
1313//===----------------------------------------------------------------------===//
1314// Vector related lowering:
1315//===----------------------------------------------------------------------===//
1316
1317static ConstantSDNode *
1318getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001319 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001320
Scott Michel266bc8f2007-12-04 22:23:35 +00001321 // Check to see if this buildvec has a single non-undef value in its elements.
1322 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1323 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001324 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001325 OpVal = N->getOperand(i);
1326 else if (OpVal != N->getOperand(i))
1327 return 0;
1328 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001329
Gabor Greifba36cb52008-08-28 21:40:38 +00001330 if (OpVal.getNode() != 0) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001331 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001332 return CN;
1333 }
1334 }
1335
1336 return 0; // All UNDEF: use implicit def.; not Constant node
1337}
1338
1339/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1340/// and the value fits into an unsigned 18-bit constant, and if so, return the
1341/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001342SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001343 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001344 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001345 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001346 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001347 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001348 uint32_t upper = uint32_t(UValue >> 32);
1349 uint32_t lower = uint32_t(UValue);
1350 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001351 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001352 Value = Value >> 32;
1353 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001354 if (Value <= 0x3ffff)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001355 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001356 }
1357
Dan Gohman475871a2008-07-27 21:46:04 +00001358 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001359}
1360
1361/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1362/// and the value fits into a signed 16-bit constant, and if so, return the
1363/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001364SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001365 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001366 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001367 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001368 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001369 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001370 uint32_t upper = uint32_t(UValue >> 32);
1371 uint32_t lower = uint32_t(UValue);
1372 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001373 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001374 Value = Value >> 32;
1375 }
Scott Michelad2715e2008-03-05 23:02:02 +00001376 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001377 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001378 }
1379 }
1380
Dan Gohman475871a2008-07-27 21:46:04 +00001381 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001382}
1383
1384/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1385/// and the value fits into a signed 10-bit constant, and if so, return the
1386/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001387SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001388 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001389 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001390 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001391 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001392 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001393 uint32_t upper = uint32_t(UValue >> 32);
1394 uint32_t lower = uint32_t(UValue);
1395 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001396 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001397 Value = Value >> 32;
1398 }
Scott Michelad2715e2008-03-05 23:02:02 +00001399 if (isS10Constant(Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001400 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001401 }
1402
Dan Gohman475871a2008-07-27 21:46:04 +00001403 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001404}
1405
1406/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1407/// and the value fits into a signed 8-bit constant, and if so, return the
1408/// constant.
1409///
1410/// @note: The incoming vector is v16i8 because that's the only way we can load
1411/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1412/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001413SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001414 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001415 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001416 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001417 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001418 && Value <= 0xffff /* truncated from uint64_t */
1419 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001420 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001421 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001422 && (Value & 0xff) == Value)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001423 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001424 }
1425
Dan Gohman475871a2008-07-27 21:46:04 +00001426 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001427}
1428
1429/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1430/// and the value fits into a signed 16-bit constant, and if so, return the
1431/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001432SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001433 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001434 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001435 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001436 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001437 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1438 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001439 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001440 }
1441
Dan Gohman475871a2008-07-27 21:46:04 +00001442 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001443}
1444
1445/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001446SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001447 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001448 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001449 }
1450
Dan Gohman475871a2008-07-27 21:46:04 +00001451 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001452}
1453
1454/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001455SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001456 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001457 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001458 }
1459
Dan Gohman475871a2008-07-27 21:46:04 +00001460 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001461}
1462
1463// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001464// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001465// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1466// zero. Return true if this is not an array of constants, false if it is.
1467//
1468static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1469 uint64_t UndefBits[2]) {
1470 // Start with zero'd results.
1471 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001472
Duncan Sands83ec4b62008-06-06 12:08:01 +00001473 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001474 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001475 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001476
Scott Michel266bc8f2007-12-04 22:23:35 +00001477 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1478 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1479
1480 uint64_t EltBits = 0;
1481 if (OpVal.getOpcode() == ISD::UNDEF) {
1482 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1483 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1484 continue;
Scott Michel19fd42a2008-11-11 03:06:06 +00001485 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001486 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel19fd42a2008-11-11 03:06:06 +00001487 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001488 const APFloat &apf = CN->getValueAPF();
1489 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001490 ? FloatToBits(apf.convertToFloat())
1491 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001492 } else {
1493 // Nonconstant element.
1494 return true;
1495 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001496
Scott Michel266bc8f2007-12-04 22:23:35 +00001497 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1498 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001499
1500 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001501 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1502 return false;
1503}
1504
1505/// If this is a splat (repetition) of a value across the whole vector, return
1506/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001507/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001508/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001509static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001510 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001511 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001512 uint64_t &SplatBits, uint64_t &SplatUndef,
1513 int &SplatSize) {
1514 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1515 // the same as the lower 64-bits, ignoring undefs.
1516 uint64_t Bits64 = Bits128[0] | Bits128[1];
1517 uint64_t Undef64 = Undef128[0] & Undef128[1];
1518 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1519 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1520 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1521 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1522
1523 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1524 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001525
Scott Michel266bc8f2007-12-04 22:23:35 +00001526 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1527 // undefs.
1528 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001529 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001530
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001531 // If the top 16-bits are different than the lower 16-bits, ignoring
1532 // undefs, we have an i32 splat.
1533 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1534 if (MinSplatBits < 16) {
1535 // If the top 8-bits are different than the lower 8-bits, ignoring
1536 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001537 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1538 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001539 // Otherwise, we have an 8-bit splat.
1540 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1541 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1542 SplatSize = 1;
1543 return true;
1544 }
1545 } else {
1546 SplatBits = Bits16;
1547 SplatUndef = Undef16;
1548 SplatSize = 2;
1549 return true;
1550 }
1551 }
1552 } else {
1553 SplatBits = Bits32;
1554 SplatUndef = Undef32;
1555 SplatSize = 4;
1556 return true;
1557 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001558 }
1559 } else {
1560 SplatBits = Bits128[0];
1561 SplatUndef = Undef128[0];
1562 SplatSize = 8;
1563 return true;
1564 }
1565 }
1566
1567 return false; // Can't be a splat if two pieces don't match.
1568}
1569
1570// If this is a case we can't handle, return null and let the default
1571// expansion code take care of it. If we CAN select this case, and if it
1572// selects to a single instruction, return Op. Otherwise, if we can codegen
1573// this case more efficiently than a constant pool load, lower it to the
1574// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001575static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001576 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001577 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001578 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001579 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001580 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001581 uint64_t VectorBits[2];
1582 uint64_t UndefBits[2];
1583 uint64_t SplatBits, SplatUndef;
1584 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001585 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001586 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001587 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001588 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001589 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001590
Duncan Sands83ec4b62008-06-06 12:08:01 +00001591 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001592 default:
1593 case MVT::v4f32: {
1594 uint32_t Value32 = SplatBits;
1595 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001596 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001597 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001598 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001599 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001600 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001601 break;
1602 }
1603 case MVT::v2f64: {
1604 uint64_t f64val = SplatBits;
1605 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001606 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001607 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001608 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001609 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001610 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001611 break;
1612 }
1613 case MVT::v16i8: {
1614 // 8-bit constants have to be expanded to 16-bits
1615 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001616 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001617 for (int i = 0; i < 8; ++i)
1618 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1619 return DAG.getNode(ISD::BIT_CONVERT, VT,
1620 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1621 }
1622 case MVT::v8i16: {
1623 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001624 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001625 Value16 = (unsigned short) (SplatBits & 0xffff);
1626 else
1627 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001628 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1629 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001630 for (int i = 0; i < 8; ++i) Ops[i] = T;
1631 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1632 }
1633 case MVT::v4i32: {
1634 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001635 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001636 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1637 }
1638 case MVT::v2i64: {
1639 uint64_t val = SplatBits;
1640 uint32_t upper = uint32_t(val >> 32);
1641 uint32_t lower = uint32_t(val);
1642
Scott Michel4cb8bd82008-03-06 04:02:54 +00001643 if (upper == lower) {
1644 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001645 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001646 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001647 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001648 SDValue LO32;
1649 SDValue HI32;
1650 SmallVector<SDValue, 16> ShufBytes;
1651 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001652 bool upper_special, lower_special;
1653
1654 // NOTE: This code creates common-case shuffle masks that can be easily
1655 // detected as common expressions. It is not attempting to create highly
1656 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1657
1658 // Detect if the upper or lower half is a special shuffle mask pattern:
1659 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1660 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1661
1662 // Create lower vector if not a special pattern
1663 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001664 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001665 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1666 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1667 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001668 }
1669
1670 // Create upper vector if not a special pattern
1671 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001672 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001673 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1674 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1675 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001676 }
1677
1678 // If either upper or lower are special, then the two input operands are
1679 // the same (basically, one of them is a "don't care")
1680 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001681 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001682 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001683 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001684 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001685 // Unhappy situation... both upper and lower are special, so punt with
1686 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001687 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001688 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001689 Zero, Zero);
1690 }
1691
1692 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001693 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001694 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001695 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001696 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001697 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001698 process_upper = (upper_special && (i & 1) == 0);
1699 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001700
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001701 if (process_upper || process_lower) {
1702 if ((process_upper && upper == 0)
1703 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001704 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001705 else if ((process_upper && upper == 0xffffffff)
1706 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001707 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001708 else if ((process_upper && upper == 0x80000000)
1709 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001710 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001711 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001712 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001713 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001714
1715 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001716 }
1717
1718 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001719 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001720 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001721 }
1722 }
1723 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001724
Dan Gohman475871a2008-07-27 21:46:04 +00001725 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001726}
1727
1728/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1729/// which the Cell can operate. The code inspects V3 to ascertain whether the
1730/// permutation vector, V3, is monotonically increasing with one "exception"
1731/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel7a1c9e92008-11-22 23:50:42 +00001732/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel266bc8f2007-12-04 22:23:35 +00001733/// In either case, the net result is going to eventually invoke SHUFB to
1734/// permute/shuffle the bytes from V1 and V2.
1735/// \note
Scott Michel7a1c9e92008-11-22 23:50:42 +00001736/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel266bc8f2007-12-04 22:23:35 +00001737/// control word for byte/halfword/word insertion. This takes care of a single
1738/// element move from V2 into V1.
1739/// \note
1740/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001741static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1742 SDValue V1 = Op.getOperand(0);
1743 SDValue V2 = Op.getOperand(1);
1744 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001745
Scott Michel266bc8f2007-12-04 22:23:35 +00001746 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001747
Scott Michel266bc8f2007-12-04 22:23:35 +00001748 // If we have a single element being moved from V1 to V2, this can be handled
1749 // using the C*[DX] compute mask instructions, but the vector elements have
1750 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001751 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001752 unsigned EltsFromV2 = 0;
1753 unsigned V2Elt = 0;
1754 unsigned V2EltIdx0 = 0;
1755 unsigned CurrElt = 0;
1756 bool monotonic = true;
1757 if (EltVT == MVT::i8)
1758 V2EltIdx0 = 16;
1759 else if (EltVT == MVT::i16)
1760 V2EltIdx0 = 8;
1761 else if (EltVT == MVT::i32)
1762 V2EltIdx0 = 4;
1763 else
1764 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1765
1766 for (unsigned i = 0, e = PermMask.getNumOperands();
1767 EltsFromV2 <= 1 && monotonic && i != e;
1768 ++i) {
1769 unsigned SrcElt;
1770 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1771 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001772 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001773 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001774
1775 if (SrcElt >= V2EltIdx0) {
1776 ++EltsFromV2;
1777 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1778 } else if (CurrElt != SrcElt) {
1779 monotonic = false;
1780 }
1781
1782 ++CurrElt;
1783 }
1784
1785 if (EltsFromV2 == 1 && monotonic) {
1786 // Compute mask and shuffle
1787 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001788 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1789 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001790 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001791 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001792 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001793 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel7a1c9e92008-11-22 23:50:42 +00001794 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001795 SDValue ShufMaskOp =
Scott Michel7a1c9e92008-11-22 23:50:42 +00001796 DAG.getNode(SPUISD::SHUFFLE_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001797 DAG.getTargetConstant(V2Elt, MVT::i32),
1798 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001799 // Use shuffle mask in SHUFB synthetic instruction:
1800 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1801 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001802 // Convert the SHUFFLE_VECTOR mask's input element units to the
1803 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001804 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001805
Dan Gohman475871a2008-07-27 21:46:04 +00001806 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001807 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1808 unsigned SrcElt;
1809 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001810 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001811 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001812 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001813
Scott Michela59d4692008-02-23 18:41:37 +00001814 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001815 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1816 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001817 }
1818 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001819
Dan Gohman475871a2008-07-27 21:46:04 +00001820 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001821 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001822 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1823 }
1824}
1825
Dan Gohman475871a2008-07-27 21:46:04 +00001826static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1827 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001828
Gabor Greifba36cb52008-08-28 21:40:38 +00001829 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001830 // For a constant, build the appropriate constant vector, which will
1831 // eventually simplify to a vector register load.
1832
Gabor Greifba36cb52008-08-28 21:40:38 +00001833 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001834 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001835 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001836 size_t n_copies;
1837
1838 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001839 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001840 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001841 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001842 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1843 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1844 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1845 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1846 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1847 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1848 }
1849
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001850 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001851 for (size_t j = 0; j < n_copies; ++j)
1852 ConstVecValues.push_back(CValue);
1853
1854 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001855 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001856 } else {
1857 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001858 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001859 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1860 case MVT::i8:
1861 case MVT::i16:
1862 case MVT::i32:
1863 case MVT::i64:
1864 case MVT::f32:
1865 case MVT::f64:
1866 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1867 }
1868 }
1869
Dan Gohman475871a2008-07-27 21:46:04 +00001870 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001871}
1872
Dan Gohman475871a2008-07-27 21:46:04 +00001873static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001874 switch (Op.getValueType().getSimpleVT()) {
1875 default:
1876 cerr << "CellSPU: Unknown vector multiplication, got "
1877 << Op.getValueType().getMVTString()
1878 << "\n";
1879 abort();
1880 /*NOTREACHED*/
1881
Scott Michel266bc8f2007-12-04 22:23:35 +00001882 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001883 SDValue rA = Op.getOperand(0);
1884 SDValue rB = Op.getOperand(1);
1885 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1886 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1887 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1888 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001889
1890 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1891 break;
1892 }
1893
1894 // Multiply two v8i16 vectors (pipeline friendly version):
1895 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1896 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1897 // c) Use SELB to select upper and lower halves from the intermediate results
1898 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001899 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001900 // dual-issue. This code does manage to do this, even if it's a little on
1901 // the wacky side
1902 case MVT::v8i16: {
1903 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001904 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001905 SDValue Chain = Op.getOperand(0);
1906 SDValue rA = Op.getOperand(0);
1907 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001908 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1909 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001910
Dan Gohman475871a2008-07-27 21:46:04 +00001911 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001912 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001913 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001914 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001915
Dan Gohman475871a2008-07-27 21:46:04 +00001916 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001917 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001918 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001919
Dan Gohman475871a2008-07-27 21:46:04 +00001920 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001921 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001922 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001923
1924 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001925 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1926 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1927 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1928 HHProd_v4i32,
1929 DAG.getConstant(16, MVT::i16))),
1930 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001931 }
1932
1933 // This M00sE is N@stI! (apologies to Monty Python)
1934 //
1935 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1936 // is to break it all apart, sign extend, and reassemble the various
1937 // intermediate products.
1938 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001939 SDValue rA = Op.getOperand(0);
1940 SDValue rB = Op.getOperand(1);
1941 SDValue c8 = DAG.getConstant(8, MVT::i32);
1942 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001943
Dan Gohman475871a2008-07-27 21:46:04 +00001944 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001945 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001946 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1947 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001948
Dan Gohman475871a2008-07-27 21:46:04 +00001949 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001950
Dan Gohman475871a2008-07-27 21:46:04 +00001951 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001952
Dan Gohman475871a2008-07-27 21:46:04 +00001953 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001954 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001955 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001956
Dan Gohman475871a2008-07-27 21:46:04 +00001957 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001958 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001959
Dan Gohman475871a2008-07-27 21:46:04 +00001960 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001961 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1962 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1963 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001964
Dan Gohman475871a2008-07-27 21:46:04 +00001965 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001966
Dan Gohman475871a2008-07-27 21:46:04 +00001967 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001968 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00001969 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001970 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1971 LoProdMask, LoProdMask,
1972 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001973
Dan Gohman475871a2008-07-27 21:46:04 +00001974 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001975 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001976 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001977
Dan Gohman475871a2008-07-27 21:46:04 +00001978 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001979 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001980 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001981
Dan Gohman475871a2008-07-27 21:46:04 +00001982 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001983 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001984 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
1985 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00001986
Dan Gohman475871a2008-07-27 21:46:04 +00001987 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001988 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001989 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00001990 DAG.getNode(SPUISD::VEC_SRA,
1991 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001992 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00001993 DAG.getNode(SPUISD::VEC_SRA,
1994 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001995
Dan Gohman475871a2008-07-27 21:46:04 +00001996 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00001997 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1998 HLProd,
1999 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2000 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00002001
Dan Gohman475871a2008-07-27 21:46:04 +00002002 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002003 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002004
2005 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002006 DAG.getNode(ISD::OR, MVT::v4i32,
2007 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002008 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002009 }
2010
Dan Gohman475871a2008-07-27 21:46:04 +00002011 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002012}
2013
Dan Gohman475871a2008-07-27 21:46:04 +00002014static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002015 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002016 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002017
Dan Gohman475871a2008-07-27 21:46:04 +00002018 SDValue A = Op.getOperand(0);
2019 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002020 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002021
2022 unsigned VRegBR, VRegC;
2023
2024 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002025 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2026 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002027 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002028 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2029 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002030 }
2031 // TODO: make sure we're feeding FPInterp the right arguments
2032 // Right now: fi B, frest(B)
2033
2034 // Computes BRcpl =
2035 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002036 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002037 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2038 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002039 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002040
Scott Michel266bc8f2007-12-04 22:23:35 +00002041 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002042 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002043 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002044 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002045 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002046 // What's the Chain variable do? It's magic!
2047 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002048
2049 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002050 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002051 DAG.getNode(ISD::FMUL, VT,
2052 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002053 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002054 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002055 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002056}
2057
Dan Gohman475871a2008-07-27 21:46:04 +00002058static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002059 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002060 SDValue N = Op.getOperand(0);
2061 SDValue Elt = Op.getOperand(1);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002062 SDValue retval;
Scott Michel266bc8f2007-12-04 22:23:35 +00002063
Scott Michel7a1c9e92008-11-22 23:50:42 +00002064 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
2065 // Constant argument:
2066 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002067
Scott Michel7a1c9e92008-11-22 23:50:42 +00002068 // sanity checks:
2069 if (VT == MVT::i8 && EltNo >= 16)
2070 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2071 else if (VT == MVT::i16 && EltNo >= 8)
2072 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2073 else if (VT == MVT::i32 && EltNo >= 4)
2074 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2075 else if (VT == MVT::i64 && EltNo >= 2)
2076 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel266bc8f2007-12-04 22:23:35 +00002077
Scott Michel7a1c9e92008-11-22 23:50:42 +00002078 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2079 // i32 and i64: Element 0 is the preferred slot
2080 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2081 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002082
Scott Michel7a1c9e92008-11-22 23:50:42 +00002083 // Need to generate shuffle mask and extract:
2084 int prefslot_begin = -1, prefslot_end = -1;
2085 int elt_byte = EltNo * VT.getSizeInBits() / 8;
2086
2087 switch (VT.getSimpleVT()) {
2088 default:
2089 assert(false && "Invalid value type!");
2090 case MVT::i8: {
2091 prefslot_begin = prefslot_end = 3;
2092 break;
2093 }
2094 case MVT::i16: {
2095 prefslot_begin = 2; prefslot_end = 3;
2096 break;
2097 }
2098 case MVT::i32:
2099 case MVT::f32: {
2100 prefslot_begin = 0; prefslot_end = 3;
2101 break;
2102 }
2103 case MVT::i64:
2104 case MVT::f64: {
2105 prefslot_begin = 0; prefslot_end = 7;
2106 break;
2107 }
2108 }
2109
2110 assert(prefslot_begin != -1 && prefslot_end != -1 &&
2111 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
2112
2113 unsigned int ShufBytes[16];
2114 for (int i = 0; i < 16; ++i) {
2115 // zero fill uppper part of preferred slot, don't care about the
2116 // other slots:
2117 unsigned int mask_val;
2118 if (i <= prefslot_end) {
2119 mask_val =
2120 ((i < prefslot_begin)
2121 ? 0x80
2122 : elt_byte + (i - prefslot_begin));
2123
2124 ShufBytes[i] = mask_val;
2125 } else
2126 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
2127 }
2128
2129 SDValue ShufMask[4];
2130 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
2131 unsigned bidx = i / 4;
2132 unsigned int bits = ((ShufBytes[bidx] << 24) |
2133 (ShufBytes[bidx+1] << 16) |
2134 (ShufBytes[bidx+2] << 8) |
2135 ShufBytes[bidx+3]);
2136 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
2137 }
2138
2139 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2140 &ShufMask[0],
2141 sizeof(ShufMask) / sizeof(ShufMask[0]));
2142
2143 retval = DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2144 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2145 N, N, ShufMaskVec));
2146 } else {
2147 // Variable index: Rotate the requested element into slot 0, then replicate
2148 // slot 0 across the vector
2149 MVT VecVT = N.getValueType();
2150 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2151 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2152 abort();
2153 }
2154
2155 // Make life easier by making sure the index is zero-extended to i32
2156 if (Elt.getValueType() != MVT::i32)
2157 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2158
2159 // Scale the index to a bit/byte shift quantity
2160 APInt scaleFactor =
2161 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2162 SDValue vecShift;
2163
2164 switch (VT.getSimpleVT()) {
2165 default:
2166 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2167 abort();
2168 /*NOTREACHED*/
2169 case MVT::i8: {
2170 // Don't need to scale, but we do need to correct for where bytes go in
2171 // slot 0:
2172 SDValue prefSlot = DAG.getNode(ISD::SUB, MVT::i32,
2173 Elt, DAG.getConstant(3, MVT::i32));
2174 SDValue corrected = DAG.getNode(ISD::ADD, MVT::i32, prefSlot,
2175 DAG.getConstant(16, MVT::i32));
2176
2177 SDValue shiftAmt = DAG.getNode(ISD::SELECT_CC, MVT::i32,
2178 prefSlot, DAG.getConstant(0, MVT::i32),
2179 prefSlot, // trueval
2180 corrected, // falseval
2181 DAG.getCondCode(ISD::SETGT));
2182 vecShift = DAG.getNode(SPUISD::ROTBYTES_LEFT, VecVT, N, shiftAmt);
2183 break;
2184 }
2185 case MVT::i16: {
2186 // Scale the index to bytes, subtract for preferred slot:
2187 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
2188 DAG.getConstant(scaleFactor.logBase2(), MVT::i32));
2189 SDValue prefSlot = DAG.getNode(ISD::SUB, MVT::i32,
2190 Elt, DAG.getConstant(2, MVT::i32));
2191 SDValue corrected = DAG.getNode(ISD::ADD, MVT::i32, prefSlot,
2192 DAG.getConstant(16, MVT::i32));
2193
2194 SDValue shiftAmt = DAG.getNode(ISD::SELECT_CC, MVT::i32,
2195 prefSlot, DAG.getConstant(0, MVT::i32),
2196 prefSlot, // trueval
2197 corrected, // falseval
2198 DAG.getCondCode(ISD::SETGT));
2199 vecShift = DAG.getNode(SPUISD::ROTBYTES_LEFT, VecVT, N, shiftAmt);
2200 break;
2201 }
2202 case MVT::i32:
2203 case MVT::f32:
2204 case MVT::i64:
2205 case MVT::f64:
2206 // Simple left shift to slot 0
2207 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
2208 DAG.getConstant(scaleFactor.logBase2(), MVT::i32));
2209 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2210 break;
2211 }
2212
2213 // Replicate slot 0 across the entire vector (for consistency with the
2214 // notion of a unified register set)
2215 SDValue replicate;
2216
2217 switch (VT.getSimpleVT()) {
2218 default:
2219 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2220 abort();
2221 /*NOTREACHED*/
2222 case MVT::i8: {
2223 SDValue factor = DAG.getConstant(0x03030303, MVT::i32);
2224 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2225 factor, factor);
2226 break;
2227 }
2228 case MVT::i16: {
2229 SDValue factor = DAG.getConstant(0x02030203, MVT::i32);
2230 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2231 factor, factor);
2232 break;
2233 }
2234 case MVT::i32:
2235 case MVT::f32: {
2236 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2237 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2238 factor, factor);
2239 break;
2240 }
2241 case MVT::i64:
2242 case MVT::f64: {
2243 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2244 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2245 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2246 loFactor, hiFactor);
2247 break;
2248 }
2249 }
2250
2251 retval = DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2252 DAG.getNode(SPUISD::SHUFB, VecVT, vecShift, vecShift, replicate));
Scott Michel266bc8f2007-12-04 22:23:35 +00002253 }
2254
Scott Michel7a1c9e92008-11-22 23:50:42 +00002255 return retval;
Scott Michel266bc8f2007-12-04 22:23:35 +00002256}
2257
Dan Gohman475871a2008-07-27 21:46:04 +00002258static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2259 SDValue VecOp = Op.getOperand(0);
2260 SDValue ValOp = Op.getOperand(1);
2261 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002262 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002263
2264 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2265 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2266
Duncan Sands83ec4b62008-06-06 12:08:01 +00002267 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002268 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002269 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
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),
2274 VecOp,
Scott Michel7a1c9e92008-11-22 23:50:42 +00002275 DAG.getNode(SPUISD::SHUFFLE_MASK, VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002276 DAG.getNode(ISD::ADD, PtrVT,
2277 PtrBase,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002278 DAG.getConstant(CN->getZExtValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002279 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002280
2281 return result;
2282}
2283
Dan Gohman475871a2008-07-27 21:46:04 +00002284static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002285{
Dan Gohman475871a2008-07-27 21:46:04 +00002286 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002287
2288 assert(Op.getValueType() == MVT::i8);
2289 switch (Opc) {
2290 default:
2291 assert(0 && "Unhandled i8 math operator");
2292 /*NOTREACHED*/
2293 break;
2294 case ISD::SUB: {
2295 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2296 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002297 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002298 N0 = (N0.getOpcode() != ISD::Constant
2299 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002300 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2301 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002302 N1 = (N1.getOpcode() != ISD::Constant
2303 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002304 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2305 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002306 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002307 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002308 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002309 case ISD::ROTR:
2310 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002311 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002312 unsigned N1Opc;
2313 N0 = (N0.getOpcode() != ISD::Constant
2314 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002315 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2316 MVT::i16));
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002317 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greif93c53e52008-08-31 15:37:04 +00002318 ? ISD::ZERO_EXTEND
2319 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002320 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002321 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002322 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002323 MVT::i32));
Dan Gohman475871a2008-07-27 21:46:04 +00002324 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002325 DAG.getNode(ISD::OR, MVT::i16, N0,
2326 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002327 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002328 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002329 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2330 }
2331 case ISD::SRL:
2332 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002333 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002334 unsigned N1Opc;
2335 N0 = (N0.getOpcode() != ISD::Constant
2336 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002337 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2338 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002339 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2340 ? ISD::ZERO_EXTEND
2341 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002342 N1 = (N1.getOpcode() != ISD::Constant
2343 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002344 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2345 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002346 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002347 DAG.getNode(Opc, MVT::i16, N0, N1));
2348 }
2349 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002350 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002351 unsigned N1Opc;
2352 N0 = (N0.getOpcode() != ISD::Constant
2353 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002354 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2355 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002356 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2357 ? ISD::SIGN_EXTEND
2358 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002359 N1 = (N1.getOpcode() != ISD::Constant
2360 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002361 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2362 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002363 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002364 DAG.getNode(Opc, MVT::i16, N0, N1));
2365 }
2366 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002367 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002368 unsigned N1Opc;
2369 N0 = (N0.getOpcode() != ISD::Constant
2370 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002371 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2372 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002373 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002374 N1 = (N1.getOpcode() != ISD::Constant
2375 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002376 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2377 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002378 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002379 DAG.getNode(Opc, MVT::i16, N0, N1));
2380 break;
2381 }
2382 }
2383
Dan Gohman475871a2008-07-27 21:46:04 +00002384 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002385}
2386
Dan Gohman475871a2008-07-27 21:46:04 +00002387static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002388{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002389 MVT VT = Op.getValueType();
2390 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002391
Dan Gohman475871a2008-07-27 21:46:04 +00002392 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002393
2394 switch (Opc) {
2395 case ISD::ZERO_EXTEND:
2396 case ISD::SIGN_EXTEND:
2397 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002398 MVT Op0VT = Op0.getValueType();
2399 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002400
2401 assert(Op0VT == MVT::i32
2402 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002403 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002404
2405 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2406 ? SPUISD::ROTBYTES_RIGHT_S
2407 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman475871a2008-07-27 21:46:04 +00002408 SDValue PromoteScalar =
Scott Michela59d4692008-02-23 18:41:37 +00002409 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2410
2411 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2412 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2413 DAG.getNode(NewOpc, Op0VecVT,
2414 PromoteScalar,
2415 DAG.getConstant(4, MVT::i32))));
2416 }
2417
Scott Michel8bf61e82008-06-02 22:18:03 +00002418 case ISD::ADD: {
2419 // Turn operands into vectors to satisfy type checking (shufb works on
2420 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002421 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002422 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002423 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002424 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002425 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002426
2427 // Create the shuffle mask for "rotating" the borrow up one register slot
2428 // once the borrow is generated.
2429 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2430 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2431 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2432 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2433
Dan Gohman475871a2008-07-27 21:46:04 +00002434 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002435 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002436 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002437 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2438 CarryGen, CarryGen,
2439 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2440 &ShufBytes[0], ShufBytes.size()));
2441
2442 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2443 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2444 Op0, Op1, ShiftedCarry));
2445 }
2446
2447 case ISD::SUB: {
2448 // Turn operands into vectors to satisfy type checking (shufb works on
2449 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002450 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002451 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002452 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002453 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002454 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002455
2456 // Create the shuffle mask for "rotating" the borrow up one register slot
2457 // once the borrow is generated.
2458 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2459 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2460 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2461 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2462
Dan Gohman475871a2008-07-27 21:46:04 +00002463 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002464 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002465 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002466 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2467 BorrowGen, BorrowGen,
2468 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2469 &ShufBytes[0], ShufBytes.size()));
2470
2471 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2472 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2473 Op0, Op1, ShiftedBorrow));
2474 }
2475
Scott Michela59d4692008-02-23 18:41:37 +00002476 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002477 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002478 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002479 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2480 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002481 DAG.getNode(SPUISD::SELB, VecVT,
2482 Op0Vec,
2483 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002484 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002485 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002486 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002487 DAG.getNode(ISD::SRL, ShiftAmtVT,
2488 ShiftAmt,
2489 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002490 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002491 DAG.getNode(ISD::AND, ShiftAmtVT,
2492 ShiftAmt,
2493 DAG.getConstant(7, ShiftAmtVT));
2494
2495 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2496 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2497 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2498 MaskLower, ShiftAmtBytes),
2499 ShiftAmtBits));
2500 }
2501
2502 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002503 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002504 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002505 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002506 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002507 DAG.getNode(ISD::SRL, ShiftAmtVT,
2508 ShiftAmt,
2509 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002510 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002511 DAG.getNode(ISD::AND, ShiftAmtVT,
2512 ShiftAmt,
2513 DAG.getConstant(7, ShiftAmtVT));
2514
2515 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2516 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2517 Op0, ShiftAmtBytes),
2518 ShiftAmtBits);
2519 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002520
2521 case ISD::SRA: {
2522 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002523 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002524 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002525 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002526 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002527
2528 // Negate variable shift amounts
2529 if (!isa<ConstantSDNode>(ShiftAmt)) {
2530 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2531 DAG.getConstant(0, ShiftVT), ShiftAmt);
2532 }
2533
Dan Gohman475871a2008-07-27 21:46:04 +00002534 SDValue UpperHalfSign =
Scott Michel8bf61e82008-06-02 22:18:03 +00002535 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2536 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2537 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2538 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002539 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002540 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002541 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002542 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2543 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002544 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002545 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2546 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002547 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002548 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2549 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002550 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002551 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2552 RotateLeftBytes, ShiftAmt);
2553
2554 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2555 RotateLeftBits);
2556 }
Scott Michela59d4692008-02-23 18:41:37 +00002557 }
2558
Dan Gohman475871a2008-07-27 21:46:04 +00002559 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002560}
2561
Scott Michel266bc8f2007-12-04 22:23:35 +00002562//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002563static SDValue
2564LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2565 SDValue ConstVec;
2566 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002567 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002568
2569 ConstVec = Op.getOperand(0);
2570 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002571 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2572 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002573 ConstVec = ConstVec.getOperand(0);
2574 } else {
2575 ConstVec = Op.getOperand(1);
2576 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002577 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002578 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002579 }
2580 }
2581 }
2582
Gabor Greifba36cb52008-08-28 21:40:38 +00002583 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002584 uint64_t VectorBits[2];
2585 uint64_t UndefBits[2];
2586 uint64_t SplatBits, SplatUndef;
2587 int SplatSize;
2588
Gabor Greifba36cb52008-08-28 21:40:38 +00002589 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002590 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002591 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002592 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002593 SDValue tcVec[16];
2594 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002595 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2596
2597 // Turn the BUILD_VECTOR into a set of target constants:
2598 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002599 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002600
Gabor Greifba36cb52008-08-28 21:40:38 +00002601 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002602 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002603 }
2604 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002605 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2606 // lowered. Return the operation, rather than a null SDValue.
2607 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002608}
2609
2610//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002611static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002612 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002613 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002614 default:
2615 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002616 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002617 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002618 abort();
2619 /*NOTREACHED*/
2620
2621 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002622 SDValue rA = Op.getOperand(0);
2623 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002624
2625 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002626 DAG.getNode(ISD::ADD, MVT::i32,
2627 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2628 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2629 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002630 }
2631 }
2632
Dan Gohman475871a2008-07-27 21:46:04 +00002633 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002634}
2635
2636//! Custom lowering for CTPOP (count population)
2637/*!
2638 Custom lowering code that counts the number ones in the input
2639 operand. SPU has such an instruction, but it counts the number of
2640 ones per byte, which then have to be accumulated.
2641*/
Dan Gohman475871a2008-07-27 21:46:04 +00002642static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002643 MVT VT = Op.getValueType();
2644 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002645
Duncan Sands83ec4b62008-06-06 12:08:01 +00002646 switch (VT.getSimpleVT()) {
2647 default:
2648 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002649 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002650 SDValue N = Op.getOperand(0);
2651 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002652
Dan Gohman475871a2008-07-27 21:46:04 +00002653 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2654 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002655
2656 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2657 }
2658
2659 case MVT::i16: {
2660 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002661 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002662
Chris Lattner84bc5422007-12-31 04:13:23 +00002663 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002664
Dan Gohman475871a2008-07-27 21:46:04 +00002665 SDValue N = Op.getOperand(0);
2666 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2667 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002668 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002669
Dan Gohman475871a2008-07-27 21:46:04 +00002670 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2671 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002672
2673 // CNTB_result becomes the chain to which all of the virtual registers
2674 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002675 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002676 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002677
Dan Gohman475871a2008-07-27 21:46:04 +00002678 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002679 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2680
Dan Gohman475871a2008-07-27 21:46:04 +00002681 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002682
2683 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002684 DAG.getNode(ISD::ADD, MVT::i16,
2685 DAG.getNode(ISD::SRL, MVT::i16,
2686 Tmp1, Shift1),
2687 Tmp1),
2688 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002689 }
2690
2691 case MVT::i32: {
2692 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002693 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002694
Chris Lattner84bc5422007-12-31 04:13:23 +00002695 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2696 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002697
Dan Gohman475871a2008-07-27 21:46:04 +00002698 SDValue N = Op.getOperand(0);
2699 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2700 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2701 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2702 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002703
Dan Gohman475871a2008-07-27 21:46:04 +00002704 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2705 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002706
2707 // CNTB_result becomes the chain to which all of the virtual registers
2708 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002709 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002710 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002711
Dan Gohman475871a2008-07-27 21:46:04 +00002712 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002713 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2714
Dan Gohman475871a2008-07-27 21:46:04 +00002715 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002716 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002717 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002718
Dan Gohman475871a2008-07-27 21:46:04 +00002719 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002720 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002721 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002722
Dan Gohman475871a2008-07-27 21:46:04 +00002723 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002724 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2725
Dan Gohman475871a2008-07-27 21:46:04 +00002726 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002727 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002728 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2729 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002730 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002731 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002732 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002733
2734 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2735 }
2736
2737 case MVT::i64:
2738 break;
2739 }
2740
Dan Gohman475871a2008-07-27 21:46:04 +00002741 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002742}
2743
Scott Michel7a1c9e92008-11-22 23:50:42 +00002744//! Lower ISD::SELECT_CC
2745/*!
2746 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2747 SELB instruction.
2748
2749 \note Need to revisit this in the future: if the code path through the true
2750 and false value computations is longer than the latency of a branch (6
2751 cycles), then it would be more advantageous to branch and insert a new basic
2752 block and branch on the condition. However, this code does not make that
2753 assumption, given the simplisitc uses so far.
2754 */
2755
2756static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
2757 MVT VT = Op.getValueType();
2758 SDValue lhs = Op.getOperand(0);
2759 SDValue rhs = Op.getOperand(1);
2760 SDValue trueval = Op.getOperand(2);
2761 SDValue falseval = Op.getOperand(3);
2762 SDValue condition = Op.getOperand(4);
2763
2764 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2765 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2766 // with another "cannot select select_cc" assert:
2767
2768 SDValue compare = DAG.getNode(ISD::SETCC, VT, lhs, rhs, condition);
2769 return DAG.getNode(SPUISD::SELB, VT, trueval, falseval, compare);
2770}
2771
2772//! Custom (target-specific) lowering entry point
2773/*!
2774 This is where LLVM's DAG selection process calls to do target-specific
2775 lowering of nodes.
2776 */
Dan Gohman475871a2008-07-27 21:46:04 +00002777SDValue
2778SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002779{
Scott Michela59d4692008-02-23 18:41:37 +00002780 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002781 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002782
2783 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002784 default: {
2785 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002786 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002787 cerr << "*Op.getNode():\n";
2788 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002789 abort();
2790 }
2791 case ISD::LOAD:
2792 case ISD::SEXTLOAD:
2793 case ISD::ZEXTLOAD:
2794 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2795 case ISD::STORE:
2796 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2797 case ISD::ConstantPool:
2798 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2799 case ISD::GlobalAddress:
2800 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2801 case ISD::JumpTable:
2802 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2803 case ISD::Constant:
2804 return LowerConstant(Op, DAG);
2805 case ISD::ConstantFP:
2806 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002807 case ISD::BRCOND:
2808 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002809 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002810 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002811 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002812 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002813 case ISD::RET:
2814 return LowerRET(Op, DAG, getTargetMachine());
2815
Scott Michela59d4692008-02-23 18:41:37 +00002816
2817 // i8, i64 math ops:
2818 case ISD::ZERO_EXTEND:
2819 case ISD::SIGN_EXTEND:
2820 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002821 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002822 case ISD::SUB:
2823 case ISD::ROTR:
2824 case ISD::ROTL:
2825 case ISD::SRL:
2826 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002827 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002828 if (VT == MVT::i8)
2829 return LowerI8Math(Op, DAG, Opc);
2830 else if (VT == MVT::i64)
2831 return LowerI64Math(Op, DAG, Opc);
2832 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002833 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002834
2835 // Vector-related lowering.
2836 case ISD::BUILD_VECTOR:
2837 return LowerBUILD_VECTOR(Op, DAG);
2838 case ISD::SCALAR_TO_VECTOR:
2839 return LowerSCALAR_TO_VECTOR(Op, DAG);
2840 case ISD::VECTOR_SHUFFLE:
2841 return LowerVECTOR_SHUFFLE(Op, DAG);
2842 case ISD::EXTRACT_VECTOR_ELT:
2843 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2844 case ISD::INSERT_VECTOR_ELT:
2845 return LowerINSERT_VECTOR_ELT(Op, DAG);
2846
2847 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2848 case ISD::AND:
2849 case ISD::OR:
2850 case ISD::XOR:
2851 return LowerByteImmed(Op, DAG);
2852
2853 // Vector and i8 multiply:
2854 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002855 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002856 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002857 else if (VT == MVT::i8)
2858 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002859 else
Scott Michela59d4692008-02-23 18:41:37 +00002860 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002861
2862 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002863 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002864 return LowerFDIVf32(Op, DAG);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002865#if 0
2866 // This is probably a libcall
2867 else if (Op.getValueType() == MVT::f64)
2868 return LowerFDIVf64(Op, DAG);
2869#endif
Scott Michel266bc8f2007-12-04 22:23:35 +00002870 else
2871 assert(0 && "Calling FDIV on unsupported MVT");
2872
2873 case ISD::CTPOP:
2874 return LowerCTPOP(Op, DAG);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002875
2876 case ISD::SELECT_CC:
2877 return LowerSELECT_CC(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002878 }
2879
Dan Gohman475871a2008-07-27 21:46:04 +00002880 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002881}
2882
Scott Michel73ce1c52008-11-10 23:43:06 +00002883SDNode *SPUTargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG)
2884{
2885#if 0
2886 unsigned Opc = (unsigned) N->getOpcode();
2887 MVT OpVT = N->getValueType(0);
2888
2889 switch (Opc) {
2890 default: {
2891 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2892 cerr << "Op.getOpcode() = " << Opc << "\n";
2893 cerr << "*Op.getNode():\n";
2894 N->dump();
2895 abort();
2896 /*NOTREACHED*/
2897 }
2898 }
2899#endif
2900
2901 /* Otherwise, return unchanged */
2902 return 0;
2903}
2904
Scott Michel266bc8f2007-12-04 22:23:35 +00002905//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002906// Target Optimization Hooks
2907//===----------------------------------------------------------------------===//
2908
Dan Gohman475871a2008-07-27 21:46:04 +00002909SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002910SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2911{
2912#if 0
2913 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002914#endif
2915 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002916 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002917 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2918 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002919
2920 switch (N->getOpcode()) {
2921 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002922 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002923 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002924
Scott Michel8bf61e82008-06-02 22:18:03 +00002925 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002926 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002927 if (Op01.getOpcode() == ISD::Constant
2928 || Op01.getOpcode() == ISD::TargetConstant) {
2929 // (add <const>, (SPUindirect <arg>, <const>)) ->
2930 // (SPUindirect <arg>, <const + const>)
2931 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2932 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002933 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002934 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002935 Op0.getValueType());
2936
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002937 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2938 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002939 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002940 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002941 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2942 Op0.getOperand(0), combinedConst);
2943 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002944 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002945 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002946 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002947 if (Op11.getOpcode() == ISD::Constant
2948 || Op11.getOpcode() == ISD::TargetConstant) {
2949 // (add (SPUindirect <arg>, <const>), <const>) ->
2950 // (SPUindirect <arg>, <const + const>)
2951 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2952 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002953 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002954 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002955 Op0.getValueType());
2956
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002957 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2958 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002959 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002960 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002961
2962 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2963 Op1.getOperand(0), combinedConst);
2964 }
2965 }
Scott Michela59d4692008-02-23 18:41:37 +00002966 break;
2967 }
2968 case ISD::SIGN_EXTEND:
2969 case ISD::ZERO_EXTEND:
2970 case ISD::ANY_EXTEND: {
2971 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2972 N->getValueType(0) == Op0.getValueType()) {
2973 // (any_extend (SPUextract_elt0 <arg>)) ->
2974 // (SPUextract_elt0 <arg>)
2975 // Types must match, however...
2976 DEBUG(cerr << "Replace: ");
2977 DEBUG(N->dump(&DAG));
2978 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002979 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002980 DEBUG(cerr << "\n");
2981
2982 return Op0;
2983 }
2984 break;
2985 }
2986 case SPUISD::IndirectAddr: {
2987 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2988 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002989 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002990 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2991 // (SPUaform <addr>, 0)
2992
2993 DEBUG(cerr << "Replace: ");
2994 DEBUG(N->dump(&DAG));
2995 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002996 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002997 DEBUG(cerr << "\n");
2998
2999 return Op0;
3000 }
3001 }
3002 break;
3003 }
3004 case SPUISD::SHLQUAD_L_BITS:
3005 case SPUISD::SHLQUAD_L_BYTES:
3006 case SPUISD::VEC_SHL:
3007 case SPUISD::VEC_SRL:
3008 case SPUISD::VEC_SRA:
3009 case SPUISD::ROTQUAD_RZ_BYTES:
3010 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00003011 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00003012
3013 if (isa<ConstantSDNode>(Op1)) {
3014 // Kill degenerate vector shifts:
3015 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
3016
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00003017 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00003018 Result = Op0;
3019 }
3020 }
3021 break;
3022 }
3023 case SPUISD::PROMOTE_SCALAR: {
3024 switch (Op0.getOpcode()) {
3025 default:
3026 break;
3027 case ISD::ANY_EXTEND:
3028 case ISD::ZERO_EXTEND:
3029 case ISD::SIGN_EXTEND: {
3030 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
3031 // <arg>
3032 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00003033 SDValue Op00 = Op0.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00003034 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman475871a2008-07-27 21:46:04 +00003035 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00003036 if (Op000.getValueType() == N->getValueType(0)) {
3037 Result = Op000;
3038 }
3039 }
3040 break;
3041 }
3042 case SPUISD::EXTRACT_ELT0: {
3043 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
3044 // <arg>
3045 Result = Op0.getOperand(0);
3046 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003047 }
Scott Michela59d4692008-02-23 18:41:37 +00003048 }
3049 break;
Scott Michel053c1da2008-01-29 02:16:57 +00003050 }
3051 }
Scott Michel58c58182008-01-17 20:38:41 +00003052 // Otherwise, return unchanged.
Scott Michel9c0c6b22008-11-21 02:56:16 +00003053#ifdef NDEBUG
Gabor Greifba36cb52008-08-28 21:40:38 +00003054 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00003055 DEBUG(cerr << "\nReplace.SPU: ");
3056 DEBUG(N->dump(&DAG));
3057 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00003058 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00003059 DEBUG(cerr << "\n");
3060 }
3061#endif
3062
3063 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00003064}
3065
3066//===----------------------------------------------------------------------===//
3067// Inline Assembly Support
3068//===----------------------------------------------------------------------===//
3069
3070/// getConstraintType - Given a constraint letter, return the type of
3071/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00003072SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00003073SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
3074 if (ConstraintLetter.size() == 1) {
3075 switch (ConstraintLetter[0]) {
3076 default: break;
3077 case 'b':
3078 case 'r':
3079 case 'f':
3080 case 'v':
3081 case 'y':
3082 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003083 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003084 }
3085 return TargetLowering::getConstraintType(ConstraintLetter);
3086}
3087
Scott Michel5af8f0e2008-07-16 17:17:29 +00003088std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00003089SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00003090 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00003091{
3092 if (Constraint.size() == 1) {
3093 // GCC RS6000 Constraint Letters
3094 switch (Constraint[0]) {
3095 case 'b': // R1-R31
3096 case 'r': // R0-R31
3097 if (VT == MVT::i64)
3098 return std::make_pair(0U, SPU::R64CRegisterClass);
3099 return std::make_pair(0U, SPU::R32CRegisterClass);
3100 case 'f':
3101 if (VT == MVT::f32)
3102 return std::make_pair(0U, SPU::R32FPRegisterClass);
3103 else if (VT == MVT::f64)
3104 return std::make_pair(0U, SPU::R64FPRegisterClass);
3105 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003106 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00003107 return std::make_pair(0U, SPU::GPRCRegisterClass);
3108 }
3109 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003110
Scott Michel266bc8f2007-12-04 22:23:35 +00003111 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3112}
3113
Scott Michela59d4692008-02-23 18:41:37 +00003114//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00003115void
Dan Gohman475871a2008-07-27 21:46:04 +00003116SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00003117 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00003118 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00003119 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00003120 const SelectionDAG &DAG,
3121 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00003122#if 0
Scott Michela59d4692008-02-23 18:41:37 +00003123 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00003124#endif
Scott Michela59d4692008-02-23 18:41:37 +00003125
3126 switch (Op.getOpcode()) {
3127 default:
3128 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3129 break;
3130
3131#if 0
3132 case CALL:
3133 case SHUFB:
Scott Michel7a1c9e92008-11-22 23:50:42 +00003134 case SHUFFLE_MASK:
Scott Michela59d4692008-02-23 18:41:37 +00003135 case CNTB:
3136#endif
3137
3138 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00003139 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00003140 MVT Op0VT = Op0.getValueType();
3141 unsigned Op0VTBits = Op0VT.getSizeInBits();
3142 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003143 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3144 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003145 break;
3146 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003147
Scott Michela59d4692008-02-23 18:41:37 +00003148 case SPUISD::LDRESULT:
3149 case SPUISD::EXTRACT_ELT0:
3150 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00003151 MVT OpVT = Op.getValueType();
3152 unsigned OpVTBits = OpVT.getSizeInBits();
3153 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003154 KnownZero |= APInt(OpVTBits, ~InMask, false);
3155 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003156 break;
3157 }
3158
3159#if 0
3160 case EXTRACT_I1_ZEXT:
3161 case EXTRACT_I1_SEXT:
3162 case EXTRACT_I8_ZEXT:
3163 case EXTRACT_I8_SEXT:
3164 case MPY:
3165 case MPYU:
3166 case MPYH:
3167 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00003168 case SPUISD::SHLQUAD_L_BITS:
3169 case SPUISD::SHLQUAD_L_BYTES:
3170 case SPUISD::VEC_SHL:
3171 case SPUISD::VEC_SRL:
3172 case SPUISD::VEC_SRA:
3173 case SPUISD::VEC_ROTL:
3174 case SPUISD::VEC_ROTR:
3175 case SPUISD::ROTQUAD_RZ_BYTES:
3176 case SPUISD::ROTQUAD_RZ_BITS:
3177 case SPUISD::ROTBYTES_RIGHT_S:
3178 case SPUISD::ROTBYTES_LEFT:
3179 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00003180 case SPUISD::SELECT_MASK:
3181 case SPUISD::SELB:
3182 case SPUISD::FPInterp:
3183 case SPUISD::FPRecipEst:
3184 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003185#endif
3186 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003187}
3188
Scott Michel203b2d62008-04-30 00:30:08 +00003189// LowerAsmOperandForConstraint
3190void
Dan Gohman475871a2008-07-27 21:46:04 +00003191SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003192 char ConstraintLetter,
Evan Chengda43bcf2008-09-24 00:05:32 +00003193 bool hasMemory,
Dan Gohman475871a2008-07-27 21:46:04 +00003194 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003195 SelectionDAG &DAG) const {
3196 // Default, for the time being, to the base class handler
Evan Chengda43bcf2008-09-24 00:05:32 +00003197 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3198 Ops, DAG);
Scott Michel203b2d62008-04-30 00:30:08 +00003199}
3200
Scott Michel266bc8f2007-12-04 22:23:35 +00003201/// isLegalAddressImmediate - Return true if the integer value can be used
3202/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003203bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3204 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003205 // SPU's addresses are 256K:
3206 return (V > -(1 << 18) && V < (1 << 18) - 1);
3207}
3208
3209bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003210 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003211}
Dan Gohman6520e202008-10-18 02:06:02 +00003212
3213bool
3214SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3215 // The SPU target isn't yet aware of offsets.
3216 return false;
3217}