blob: 0b954743984694a09fcd6f2d83640541d4289383 [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";
Scott Michel104de432008-11-24 17:11:17 +0000428 node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
429 node_names[(unsigned) SPUISD::VEC2PREFSLOT_CHAINED]
430 = "SPUISD::VEC2PREFSLOT_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_LEFT] = "SPUISD::ROTBYTES_LEFT";
451 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
452 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel8bf61e82008-06-02 22:18:03 +0000453 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
454 "SPUISD::ROTBYTES_LEFT_BITS";
455 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000456 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel8bf61e82008-06-02 22:18:03 +0000457 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
458 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
459 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
460 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel266bc8f2007-12-04 22:23:35 +0000461 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
462 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
463 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
464 }
465
466 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
467
468 return ((i != node_names.end()) ? i->second : 0);
469}
470
Dan Gohman475871a2008-07-27 21:46:04 +0000471MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000472 MVT VT = Op.getValueType();
Scott Micheld976c212008-10-30 01:51:48 +0000473 return (VT.isInteger() ? VT : MVT(MVT::i32));
Scott Michel78c47fa2008-03-10 16:58:52 +0000474}
475
Scott Michel266bc8f2007-12-04 22:23:35 +0000476//===----------------------------------------------------------------------===//
477// Calling convention code:
478//===----------------------------------------------------------------------===//
479
480#include "SPUGenCallingConv.inc"
481
482//===----------------------------------------------------------------------===//
483// LowerOperation implementation
484//===----------------------------------------------------------------------===//
485
Scott Michel9de5d0d2008-01-11 02:53:15 +0000486/// Aligned load common code for CellSPU
487/*!
488 \param[in] Op The SelectionDAG load or store operand
489 \param[in] DAG The selection DAG
490 \param[in] ST CellSPU subtarget information structure
491 \param[in,out] alignment Caller initializes this to the load or store node's
492 value from getAlignment(), may be updated while generating the aligned load
493 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
494 offset (divisible by 16, modulo 16 == 0)
495 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
496 offset of the preferred slot (modulo 16 != 0)
497 \param[in,out] VT Caller initializes this value type to the the load or store
498 node's loaded or stored value type; may be updated if an i1-extended load or
499 store.
500 \param[out] was16aligned true if the base pointer had 16-byte alignment,
501 otherwise false. Can help to determine if the chunk needs to be rotated.
502
503 Both load and store lowering load a block of data aligned on a 16-byte
504 boundary. This is the common aligned load code shared between both.
505 */
Dan Gohman475871a2008-07-27 21:46:04 +0000506static SDValue
507AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Michel9de5d0d2008-01-11 02:53:15 +0000508 LSBaseSDNode *LSN,
509 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000510 MVT &VT, bool &was16aligned)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000511{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000512 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000513 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman475871a2008-07-27 21:46:04 +0000514 SDValue basePtr = LSN->getBasePtr();
515 SDValue chain = LSN->getChain();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000516
517 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000518 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000519
Gabor Greif93c53e52008-08-31 15:37:04 +0000520 if (Op1.getOpcode() == ISD::Constant
521 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel58c58182008-01-17 20:38:41 +0000522 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000523
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000524 alignOffs = (int) CN->getZExtValue();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000525 prefSlotOffs = (int) (alignOffs & 0xf);
526
527 // Adjust the rotation amount to ensure that the final result ends up in
528 // the preferred slot:
529 prefSlotOffs -= vtm->prefslot_byte;
530 basePtr = basePtr.getOperand(0);
531
Scott Michel58c58182008-01-17 20:38:41 +0000532 // Loading from memory, can we adjust alignment?
533 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +0000534 SDValue APtr = basePtr.getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000535 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
536 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
537 alignment = GSDN->getGlobal()->getAlignment();
538 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000539 }
540 } else {
541 alignOffs = 0;
542 prefSlotOffs = -vtm->prefslot_byte;
543 }
Scott Michel203b2d62008-04-30 00:30:08 +0000544 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
545 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
546 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
547 prefSlotOffs = (int) (alignOffs & 0xf);
548 prefSlotOffs -= vtm->prefslot_byte;
549 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000550 } else {
551 alignOffs = 0;
552 prefSlotOffs = -vtm->prefslot_byte;
553 }
554
555 if (alignment == 16) {
556 // Realign the base pointer as a D-Form address:
557 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel58c58182008-01-17 20:38:41 +0000558 basePtr = DAG.getNode(ISD::ADD, PtrVT,
559 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000560 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000561 }
562
563 // Emit the vector load:
564 was16aligned = true;
565 return DAG.getLoad(MVT::v16i8, chain, basePtr,
566 LSN->getSrcValue(), LSN->getSrcValueOffset(),
567 LSN->isVolatile(), 16);
568 }
569
570 // Unaligned load or we're using the "large memory" model, which means that
571 // we have to be very pessimistic:
Scott Michel58c58182008-01-17 20:38:41 +0000572 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greif93c53e52008-08-31 15:37:04 +0000573 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
574 DAG.getConstant(0, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000575 }
576
577 // Add the offset
Scott Michel053c1da2008-01-29 02:16:57 +0000578 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000579 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000580 was16aligned = false;
581 return DAG.getLoad(MVT::v16i8, chain, basePtr,
582 LSN->getSrcValue(), LSN->getSrcValueOffset(),
583 LSN->isVolatile(), 16);
584}
585
Scott Michel266bc8f2007-12-04 22:23:35 +0000586/// Custom lower loads for CellSPU
587/*!
588 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
589 within a 16-byte block, we have to rotate to extract the requested element.
590 */
Dan Gohman475871a2008-07-27 21:46:04 +0000591static SDValue
592LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000593 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000594 SDValue the_chain = LN->getChain();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000595 MVT VT = LN->getMemoryVT();
Gabor Greifba36cb52008-08-28 21:40:38 +0000596 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000597 ISD::LoadExtType ExtType = LN->getExtensionType();
598 unsigned alignment = LN->getAlignment();
Dan Gohman475871a2008-07-27 21:46:04 +0000599 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000600
Scott Michel266bc8f2007-12-04 22:23:35 +0000601 switch (LN->getAddressingMode()) {
602 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000603 int offset, rotamt;
604 bool was16aligned;
Dan Gohman475871a2008-07-27 21:46:04 +0000605 SDValue result =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000606 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000607
Gabor Greifba36cb52008-08-28 21:40:38 +0000608 if (result.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +0000609 return result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000610
611 the_chain = result.getValue(1);
612 // Rotate the chunk if necessary
613 if (rotamt < 0)
614 rotamt += 16;
Scott Michel497e8882008-01-11 21:01:19 +0000615 if (rotamt != 0 || !was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000616 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
617
Scott Michel58c58182008-01-17 20:38:41 +0000618 Ops[0] = the_chain;
619 Ops[1] = result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000620 if (was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000621 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
622 } else {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000623 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000624 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel497e8882008-01-11 21:01:19 +0000625 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000626 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000627 }
628
629 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
630 the_chain = result.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000631 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000632
633 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
634 SDVTList scalarvts;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000635 MVT vecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000636
Scott Michel9de5d0d2008-01-11 02:53:15 +0000637 // Convert the loaded v16i8 vector to the appropriate vector type
638 // specified by the operand:
639 if (OpVT == VT) {
640 if (VT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000641 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000642 } else
Duncan Sands83ec4b62008-06-06 12:08:01 +0000643 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000644
645 Ops[0] = the_chain;
646 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
647 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
Scott Michel104de432008-11-24 17:11:17 +0000648 result = DAG.getNode(SPUISD::VEC2PREFSLOT_CHAINED, scalarvts, Ops, 2);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000649 the_chain = result.getValue(1);
650 } else {
651 // Handle the sign and zero-extending loads for i1 and i8:
652 unsigned NewOpC;
653
654 if (ExtType == ISD::SEXTLOAD) {
655 NewOpC = (OpVT == MVT::i1
656 ? SPUISD::EXTRACT_I1_SEXT
657 : SPUISD::EXTRACT_I8_SEXT);
658 } else {
659 assert(ExtType == ISD::ZEXTLOAD);
660 NewOpC = (OpVT == MVT::i1
661 ? SPUISD::EXTRACT_I1_ZEXT
662 : SPUISD::EXTRACT_I8_ZEXT);
663 }
664
665 result = DAG.getNode(NewOpC, OpVT, result);
666 }
667
668 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000669 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000670 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000671 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000672 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000673
Scott Michel58c58182008-01-17 20:38:41 +0000674 result = DAG.getNode(SPUISD::LDRESULT, retvts,
675 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000676 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000677 }
678 case ISD::PRE_INC:
679 case ISD::PRE_DEC:
680 case ISD::POST_INC:
681 case ISD::POST_DEC:
682 case ISD::LAST_INDEXED_MODE:
683 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
684 "UNINDEXED\n";
685 cerr << (unsigned) LN->getAddressingMode() << "\n";
686 abort();
687 /*NOTREACHED*/
688 }
689
Dan Gohman475871a2008-07-27 21:46:04 +0000690 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000691}
692
693/// Custom lower stores for CellSPU
694/*!
695 All CellSPU stores are aligned to 16-byte boundaries, so for elements
696 within a 16-byte block, we have to generate a shuffle to insert the
697 requested element into its place, then store the resulting block.
698 */
Dan Gohman475871a2008-07-27 21:46:04 +0000699static SDValue
700LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000701 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000702 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000703 MVT VT = Value.getValueType();
704 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
705 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000706 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000707
708 switch (SN->getAddressingMode()) {
709 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000710 int chunk_offset, slot_offset;
711 bool was16aligned;
Scott Michel266bc8f2007-12-04 22:23:35 +0000712
Scott Michel9c0c6b22008-11-21 02:56:16 +0000713 // The vector type we really want to load from the 16-byte chunk.
Scott Michel719b0e12008-11-19 17:45:08 +0000714 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
715 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000716
Dan Gohman475871a2008-07-27 21:46:04 +0000717 SDValue alignLoadVec =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000718 AlignedLoad(Op, DAG, ST, SN, alignment,
719 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000720
Gabor Greifba36cb52008-08-28 21:40:38 +0000721 if (alignLoadVec.getNode() == 0)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000722 return alignLoadVec;
Scott Michel266bc8f2007-12-04 22:23:35 +0000723
Scott Michel9de5d0d2008-01-11 02:53:15 +0000724 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000725 SDValue basePtr = LN->getBasePtr();
726 SDValue the_chain = alignLoadVec.getValue(1);
727 SDValue theValue = SN->getValue();
728 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000729
730 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000731 && (theValue.getOpcode() == ISD::AssertZext
732 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000733 // Drill down and get the value for zero- and sign-extended
734 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000735 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000736 }
737
Scott Michel9de5d0d2008-01-11 02:53:15 +0000738 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000739
Dan Gohman475871a2008-07-27 21:46:04 +0000740 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
741 SDValue insertEltPtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000742
743 // If the base pointer is already a D-form address, then just create
744 // a new D-form address with a slot offset and the orignal base pointer.
745 // Otherwise generate a D-form address with the slot offset relative
746 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000747 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greifba36cb52008-08-28 21:40:38 +0000748 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michel497e8882008-01-11 21:01:19 +0000749 DEBUG(cerr << "\n");
750
Scott Michel053c1da2008-01-29 02:16:57 +0000751 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
752 (basePtr.getOpcode() == ISD::ADD
753 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000754 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000755 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000756 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000757 }
758
Scott Michel430a5552008-11-19 15:24:16 +0000759 SDValue insertEltOp =
Scott Michel7a1c9e92008-11-22 23:50:42 +0000760 DAG.getNode(SPUISD::SHUFFLE_MASK, stVecVT, insertEltPtr);
Scott Michel719b0e12008-11-19 17:45:08 +0000761 SDValue vectorizeOp =
762 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michel430a5552008-11-19 15:24:16 +0000763
764 result = DAG.getNode(SPUISD::SHUFB, vecVT, vectorizeOp, alignLoadVec,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000765 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000766
Scott Michel9de5d0d2008-01-11 02:53:15 +0000767 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000768 LN->getSrcValue(), LN->getSrcValueOffset(),
769 LN->isVolatile(), LN->getAlignment());
770
Scott Michel719b0e12008-11-19 17:45:08 +0000771#if 0 && defined(NDEBUG)
Scott Michel430a5552008-11-19 15:24:16 +0000772 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
773 const SDValue &currentRoot = DAG.getRoot();
774
775 DAG.setRoot(result);
776 cerr << "------- CellSPU:LowerStore result:\n";
777 DAG.dump();
778 cerr << "-------\n";
779 DAG.setRoot(currentRoot);
780 }
781#endif
782
Scott Michel266bc8f2007-12-04 22:23:35 +0000783 return result;
784 /*UNREACHED*/
785 }
786 case ISD::PRE_INC:
787 case ISD::PRE_DEC:
788 case ISD::POST_INC:
789 case ISD::POST_DEC:
790 case ISD::LAST_INDEXED_MODE:
791 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
792 "UNINDEXED\n";
793 cerr << (unsigned) SN->getAddressingMode() << "\n";
794 abort();
795 /*NOTREACHED*/
796 }
797
Dan Gohman475871a2008-07-27 21:46:04 +0000798 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000799}
800
801/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000802static SDValue
803LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000804 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000805 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
806 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000807 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
808 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000809 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000810
811 if (TM.getRelocationModel() == Reloc::Static) {
812 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000813 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000814 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000815 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000816 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
817 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000818 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000819 }
820 }
821
822 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000823 "LowerConstantPool: Relocation model other than static"
824 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000825 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000826}
827
Dan Gohman475871a2008-07-27 21:46:04 +0000828static SDValue
829LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000830 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000831 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000832 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
833 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000834 const TargetMachine &TM = DAG.getTarget();
835
836 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000837 if (!ST->usingLargeMem()) {
838 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
839 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000840 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
841 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000842 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
843 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000844 }
845
846 assert(0 &&
847 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000848 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000849}
850
Dan Gohman475871a2008-07-27 21:46:04 +0000851static SDValue
852LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000853 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000854 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
855 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000856 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000857 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000858 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000859
Scott Michel266bc8f2007-12-04 22:23:35 +0000860 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000861 if (!ST->usingLargeMem()) {
862 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
863 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000864 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
865 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000866 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
867 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000868 } else {
869 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000870 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000871 abort();
872 /*NOTREACHED*/
873 }
874
Dan Gohman475871a2008-07-27 21:46:04 +0000875 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000876}
877
878//! Custom lower i64 integer constants
879/*!
880 This code inserts all of the necessary juggling that needs to occur to load
881 a 64-bit constant into a register.
882 */
Dan Gohman475871a2008-07-27 21:46:04 +0000883static SDValue
884LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000885 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000886 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000887
888 if (VT == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000889 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel104de432008-11-24 17:11:17 +0000890 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000891 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000892 } else {
893 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000894 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000895 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000896 abort();
897 /*NOTREACHED*/
898 }
899
Dan Gohman475871a2008-07-27 21:46:04 +0000900 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000901}
902
Nate Begemanccef5802008-02-14 18:43:04 +0000903//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000904static SDValue
905LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000906 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000907 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000908
909 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000910 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000911
Nate Begemanccef5802008-02-14 18:43:04 +0000912 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000913 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000914 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000915 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000916 }
917
Dan Gohman475871a2008-07-27 21:46:04 +0000918 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000919}
920
Scott Michel9c0c6b22008-11-21 02:56:16 +0000921//! Lower MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman475871a2008-07-27 21:46:04 +0000922static SDValue
923LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel58c58182008-01-17 20:38:41 +0000924{
Dan Gohman475871a2008-07-27 21:46:04 +0000925 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000926 MVT CondVT = Cond.getValueType();
927 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000928
Scott Michel9c0c6b22008-11-21 02:56:16 +0000929 if (CondVT == MVT::i8) {
930 CondNVT = MVT::i16;
Scott Michel58c58182008-01-17 20:38:41 +0000931 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
932 Op.getOperand(0),
933 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
934 Op.getOperand(2));
935 } else
Dan Gohman475871a2008-07-27 21:46:04 +0000936 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000937}
938
Dan Gohman475871a2008-07-27 21:46:04 +0000939static SDValue
940LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000941{
942 MachineFunction &MF = DAG.getMachineFunction();
943 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000944 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Micheld976c212008-10-30 01:51:48 +0000945 SmallVector<SDValue, 48> ArgValues;
Dan Gohman475871a2008-07-27 21:46:04 +0000946 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000947 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000948
949 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
950 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000951
Scott Michel266bc8f2007-12-04 22:23:35 +0000952 unsigned ArgOffset = SPUFrameInfo::minStackSize();
953 unsigned ArgRegIdx = 0;
954 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000955
Duncan Sands83ec4b62008-06-06 12:08:01 +0000956 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000957
Scott Michel266bc8f2007-12-04 22:23:35 +0000958 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000959 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
960 ArgNo != e; ++ArgNo) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000961 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
962 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Micheld976c212008-10-30 01:51:48 +0000963 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000964
Scott Micheld976c212008-10-30 01:51:48 +0000965 if (ArgRegIdx < NumArgRegs) {
966 const TargetRegisterClass *ArgRegClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000967
Scott Micheld976c212008-10-30 01:51:48 +0000968 switch (ObjectVT.getSimpleVT()) {
969 default: {
Scott Michel9c0c6b22008-11-21 02:56:16 +0000970 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
971 << ObjectVT.getMVTString()
972 << "\n";
973 abort();
Scott Micheld976c212008-10-30 01:51:48 +0000974 }
975 case MVT::i8:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000976 ArgRegClass = &SPU::R8CRegClass;
977 break;
Scott Micheld976c212008-10-30 01:51:48 +0000978 case MVT::i16:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000979 ArgRegClass = &SPU::R16CRegClass;
980 break;
Scott Micheld976c212008-10-30 01:51:48 +0000981 case MVT::i32:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000982 ArgRegClass = &SPU::R32CRegClass;
983 break;
Scott Micheld976c212008-10-30 01:51:48 +0000984 case MVT::i64:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000985 ArgRegClass = &SPU::R64CRegClass;
986 break;
Scott Micheld976c212008-10-30 01:51:48 +0000987 case MVT::f32:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000988 ArgRegClass = &SPU::R32FPRegClass;
989 break;
Scott Micheld976c212008-10-30 01:51:48 +0000990 case MVT::f64:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000991 ArgRegClass = &SPU::R64FPRegClass;
992 break;
Scott Micheld976c212008-10-30 01:51:48 +0000993 case MVT::v2f64:
994 case MVT::v4f32:
995 case MVT::v2i64:
996 case MVT::v4i32:
997 case MVT::v8i16:
998 case MVT::v16i8:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000999 ArgRegClass = &SPU::VECREGRegClass;
1000 break;
Scott Micheld976c212008-10-30 01:51:48 +00001001 }
1002
1003 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
1004 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
1005 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1006 ++ArgRegIdx;
1007 } else {
1008 // We need to load the argument to a virtual register if we determined
1009 // above that we ran out of physical registers of the appropriate type
1010 // or we're forced to do vararg
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001011 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001012 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001013 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001014 ArgOffset += StackSlotSize;
1015 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001016
Scott Michel266bc8f2007-12-04 22:23:35 +00001017 ArgValues.push_back(ArgVal);
Scott Micheld976c212008-10-30 01:51:48 +00001018 // Update the chain
1019 Root = ArgVal.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001020 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001021
Scott Micheld976c212008-10-30 01:51:48 +00001022 // vararg handling:
Scott Michel266bc8f2007-12-04 22:23:35 +00001023 if (isVarArg) {
Scott Micheld976c212008-10-30 01:51:48 +00001024 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1025 // We will spill (79-3)+1 registers to the stack
1026 SmallVector<SDValue, 79-3+1> MemOps;
1027
1028 // Create the frame slot
1029
Scott Michel266bc8f2007-12-04 22:23:35 +00001030 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Micheld976c212008-10-30 01:51:48 +00001031 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1032 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1033 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1034 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1035 Root = Store.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001036 MemOps.push_back(Store);
Scott Micheld976c212008-10-30 01:51:48 +00001037
1038 // Increment address by stack slot size for the next stored argument
1039 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001040 }
1041 if (!MemOps.empty())
Scott Micheld976c212008-10-30 01:51:48 +00001042 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001043 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001044
Scott Michel266bc8f2007-12-04 22:23:35 +00001045 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001046
Scott Michel266bc8f2007-12-04 22:23:35 +00001047 // Return the new list of results.
Gabor Greifba36cb52008-08-28 21:40:38 +00001048 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf9516202008-06-30 10:19:09 +00001049 ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001050}
1051
1052/// isLSAAddress - Return the immediate to use if the specified
1053/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001054static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001055 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel266bc8f2007-12-04 22:23:35 +00001056 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001057
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001058 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001059 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1060 (Addr << 14 >> 14) != Addr)
1061 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001062
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001063 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001064}
1065
1066static
Dan Gohman475871a2008-07-27 21:46:04 +00001067SDValue
1068LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman095cc292008-09-13 01:54:27 +00001069 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1070 SDValue Chain = TheCall->getChain();
Dan Gohman095cc292008-09-13 01:54:27 +00001071 SDValue Callee = TheCall->getCallee();
1072 unsigned NumOps = TheCall->getNumArgs();
Scott Michel266bc8f2007-12-04 22:23:35 +00001073 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1074 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1075 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1076
1077 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001078 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001079
Scott Michel266bc8f2007-12-04 22:23:35 +00001080 // Accumulate how many bytes are to be pushed on the stack, including the
1081 // linkage area, and parameter passing area. According to the SPU ABI,
1082 // we minimally need space for [LR] and [SP]
1083 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001084
Scott Michel266bc8f2007-12-04 22:23:35 +00001085 // Set up a copy of the stack pointer for use loading and storing any
1086 // arguments that may not fit in the registers available for argument
1087 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001088 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001089
Scott Michel266bc8f2007-12-04 22:23:35 +00001090 // Figure out which arguments are going to go in registers, and which in
1091 // memory.
1092 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1093 unsigned ArgRegIdx = 0;
1094
1095 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001096 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001097 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001098 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001099
1100 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman095cc292008-09-13 01:54:27 +00001101 SDValue Arg = TheCall->getArg(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001102
Scott Michel266bc8f2007-12-04 22:23:35 +00001103 // PtrOff will be used to store the current argument to the stack if a
1104 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001105 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001106 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1107
Duncan Sands83ec4b62008-06-06 12:08:01 +00001108 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001109 default: assert(0 && "Unexpected ValueType for argument!");
1110 case MVT::i32:
1111 case MVT::i64:
1112 case MVT::i128:
1113 if (ArgRegIdx != NumArgRegs) {
1114 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1115 } else {
1116 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001117 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001118 }
1119 break;
1120 case MVT::f32:
1121 case MVT::f64:
1122 if (ArgRegIdx != NumArgRegs) {
1123 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1124 } else {
1125 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001126 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001127 }
1128 break;
1129 case MVT::v4f32:
1130 case MVT::v4i32:
1131 case MVT::v8i16:
1132 case MVT::v16i8:
1133 if (ArgRegIdx != NumArgRegs) {
1134 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1135 } else {
1136 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001137 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001138 }
1139 break;
1140 }
1141 }
1142
1143 // Update number of stack bytes actually used, insert a call sequence start
1144 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnere563bbc2008-10-11 22:08:30 +00001145 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1146 true));
Scott Michel266bc8f2007-12-04 22:23:35 +00001147
1148 if (!MemOpChains.empty()) {
1149 // Adjust the stack pointer for the stack arguments.
1150 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1151 &MemOpChains[0], MemOpChains.size());
1152 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001153
Scott Michel266bc8f2007-12-04 22:23:35 +00001154 // Build a sequence of copy-to-reg nodes chained together with token chain
1155 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001156 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001157 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1158 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1159 InFlag);
1160 InFlag = Chain.getValue(1);
1161 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001162
Dan Gohman475871a2008-07-27 21:46:04 +00001163 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001164 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001165
Bill Wendling056292f2008-09-16 21:48:12 +00001166 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1167 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1168 // node so that legalize doesn't hack it.
Scott Michel19fd42a2008-11-11 03:06:06 +00001169 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001170 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001171 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001172 SDValue Zero = DAG.getConstant(0, PtrVT);
1173 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001174
Scott Michel9de5d0d2008-01-11 02:53:15 +00001175 if (!ST->usingLargeMem()) {
1176 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1177 // style calls, otherwise, external symbols are BRASL calls. This assumes
1178 // that declared/defined symbols are in the same compilation unit and can
1179 // be reached through PC-relative jumps.
1180 //
1181 // NOTE:
1182 // This may be an unsafe assumption for JIT and really large compilation
1183 // units.
1184 if (GV->isDeclaration()) {
1185 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1186 } else {
1187 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1188 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001189 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001190 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1191 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001192 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001193 }
Scott Michel19fd42a2008-11-11 03:06:06 +00001194 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendling056292f2008-09-16 21:48:12 +00001195 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001196 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001197 // If this is an absolute destination address that appears to be a legal
1198 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001199 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001200 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001201
1202 Ops.push_back(Chain);
1203 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001204
Scott Michel266bc8f2007-12-04 22:23:35 +00001205 // Add argument registers to the end of the list so that they are known live
1206 // into the call.
1207 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001208 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001209 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001210
Gabor Greifba36cb52008-08-28 21:40:38 +00001211 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001212 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001213 // Returns a chain and a flag for retval copy to use.
1214 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1215 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001216 InFlag = Chain.getValue(1);
1217
Chris Lattnere563bbc2008-10-11 22:08:30 +00001218 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1219 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001220 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001221 InFlag = Chain.getValue(1);
1222
Dan Gohman475871a2008-07-27 21:46:04 +00001223 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001224 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001225
Scott Michel266bc8f2007-12-04 22:23:35 +00001226 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001227 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001228 default: assert(0 && "Unexpected ret value!");
1229 case MVT::Other: break;
1230 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001231 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001232 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1233 ResultVals[0] = Chain.getValue(0);
1234 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1235 Chain.getValue(2)).getValue(1);
1236 ResultVals[1] = Chain.getValue(0);
1237 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001238 } else {
1239 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1240 ResultVals[0] = Chain.getValue(0);
1241 NumResults = 1;
1242 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001243 break;
1244 case MVT::i64:
1245 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1246 ResultVals[0] = Chain.getValue(0);
1247 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001248 break;
1249 case MVT::f32:
1250 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001251 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001252 InFlag).getValue(1);
1253 ResultVals[0] = Chain.getValue(0);
1254 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001255 break;
1256 case MVT::v2f64:
1257 case MVT::v4f32:
1258 case MVT::v4i32:
1259 case MVT::v8i16:
1260 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001261 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001262 InFlag).getValue(1);
1263 ResultVals[0] = Chain.getValue(0);
1264 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001265 break;
1266 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001267
Scott Michel266bc8f2007-12-04 22:23:35 +00001268 // If the function returns void, just return the chain.
1269 if (NumResults == 0)
1270 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001271
Scott Michel266bc8f2007-12-04 22:23:35 +00001272 // Otherwise, merge everything together with a MERGE_VALUES node.
1273 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001274 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001275 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001276}
1277
Dan Gohman475871a2008-07-27 21:46:04 +00001278static SDValue
1279LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001280 SmallVector<CCValAssign, 16> RVLocs;
1281 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1282 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1283 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001284 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001285
Scott Michel266bc8f2007-12-04 22:23:35 +00001286 // If this is the first return lowered for this function, add the regs to the
1287 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001288 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001289 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001290 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001291 }
1292
Dan Gohman475871a2008-07-27 21:46:04 +00001293 SDValue Chain = Op.getOperand(0);
1294 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001295
Scott Michel266bc8f2007-12-04 22:23:35 +00001296 // Copy the result values into the output registers.
1297 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1298 CCValAssign &VA = RVLocs[i];
1299 assert(VA.isRegLoc() && "Can only return in registers!");
1300 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1301 Flag = Chain.getValue(1);
1302 }
1303
Gabor Greifba36cb52008-08-28 21:40:38 +00001304 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001305 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1306 else
1307 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1308}
1309
1310
1311//===----------------------------------------------------------------------===//
1312// Vector related lowering:
1313//===----------------------------------------------------------------------===//
1314
1315static ConstantSDNode *
1316getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001317 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001318
Scott Michel266bc8f2007-12-04 22:23:35 +00001319 // Check to see if this buildvec has a single non-undef value in its elements.
1320 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1321 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001322 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001323 OpVal = N->getOperand(i);
1324 else if (OpVal != N->getOperand(i))
1325 return 0;
1326 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001327
Gabor Greifba36cb52008-08-28 21:40:38 +00001328 if (OpVal.getNode() != 0) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001329 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001330 return CN;
1331 }
1332 }
1333
1334 return 0; // All UNDEF: use implicit def.; not Constant node
1335}
1336
1337/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1338/// and the value fits into an unsigned 18-bit constant, and if so, return the
1339/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001340SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001341 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001342 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001343 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001344 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001345 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001346 uint32_t upper = uint32_t(UValue >> 32);
1347 uint32_t lower = uint32_t(UValue);
1348 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001349 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001350 Value = Value >> 32;
1351 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001352 if (Value <= 0x3ffff)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001353 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001354 }
1355
Dan Gohman475871a2008-07-27 21:46:04 +00001356 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001357}
1358
1359/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1360/// and the value fits into a signed 16-bit constant, and if so, return the
1361/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001362SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001363 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001364 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001365 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001366 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001367 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001368 uint32_t upper = uint32_t(UValue >> 32);
1369 uint32_t lower = uint32_t(UValue);
1370 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001371 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001372 Value = Value >> 32;
1373 }
Scott Michelad2715e2008-03-05 23:02:02 +00001374 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001375 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001376 }
1377 }
1378
Dan Gohman475871a2008-07-27 21:46:04 +00001379 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001380}
1381
1382/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1383/// and the value fits into a signed 10-bit constant, and if so, return the
1384/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001385SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001386 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001387 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001388 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001389 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001390 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001391 uint32_t upper = uint32_t(UValue >> 32);
1392 uint32_t lower = uint32_t(UValue);
1393 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001394 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001395 Value = Value >> 32;
1396 }
Scott Michelad2715e2008-03-05 23:02:02 +00001397 if (isS10Constant(Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001398 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001399 }
1400
Dan Gohman475871a2008-07-27 21:46:04 +00001401 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001402}
1403
1404/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1405/// and the value fits into a signed 8-bit constant, and if so, return the
1406/// constant.
1407///
1408/// @note: The incoming vector is v16i8 because that's the only way we can load
1409/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1410/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001411SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001412 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001413 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001414 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001415 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001416 && Value <= 0xffff /* truncated from uint64_t */
1417 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001418 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001419 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001420 && (Value & 0xff) == Value)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001421 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001422 }
1423
Dan Gohman475871a2008-07-27 21:46:04 +00001424 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001425}
1426
1427/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1428/// and the value fits into a signed 16-bit constant, and if so, return the
1429/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001430SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001431 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001432 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001433 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001434 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001435 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1436 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001437 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001438 }
1439
Dan Gohman475871a2008-07-27 21:46:04 +00001440 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001441}
1442
1443/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001444SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001445 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001446 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001447 }
1448
Dan Gohman475871a2008-07-27 21:46:04 +00001449 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001450}
1451
1452/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001453SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001454 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001455 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001456 }
1457
Dan Gohman475871a2008-07-27 21:46:04 +00001458 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001459}
1460
1461// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001462// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001463// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1464// zero. Return true if this is not an array of constants, false if it is.
1465//
1466static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1467 uint64_t UndefBits[2]) {
1468 // Start with zero'd results.
1469 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001470
Duncan Sands83ec4b62008-06-06 12:08:01 +00001471 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001472 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001473 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001474
Scott Michel266bc8f2007-12-04 22:23:35 +00001475 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1476 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1477
1478 uint64_t EltBits = 0;
1479 if (OpVal.getOpcode() == ISD::UNDEF) {
1480 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1481 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1482 continue;
Scott Michel19fd42a2008-11-11 03:06:06 +00001483 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001484 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel19fd42a2008-11-11 03:06:06 +00001485 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001486 const APFloat &apf = CN->getValueAPF();
1487 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001488 ? FloatToBits(apf.convertToFloat())
1489 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001490 } else {
1491 // Nonconstant element.
1492 return true;
1493 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001494
Scott Michel266bc8f2007-12-04 22:23:35 +00001495 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1496 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001497
1498 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001499 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1500 return false;
1501}
1502
1503/// If this is a splat (repetition) of a value across the whole vector, return
1504/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001505/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001506/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001507static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001508 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001509 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001510 uint64_t &SplatBits, uint64_t &SplatUndef,
1511 int &SplatSize) {
1512 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1513 // the same as the lower 64-bits, ignoring undefs.
1514 uint64_t Bits64 = Bits128[0] | Bits128[1];
1515 uint64_t Undef64 = Undef128[0] & Undef128[1];
1516 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1517 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1518 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1519 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1520
1521 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1522 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001523
Scott Michel266bc8f2007-12-04 22:23:35 +00001524 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1525 // undefs.
1526 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001527 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001528
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001529 // If the top 16-bits are different than the lower 16-bits, ignoring
1530 // undefs, we have an i32 splat.
1531 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1532 if (MinSplatBits < 16) {
1533 // If the top 8-bits are different than the lower 8-bits, ignoring
1534 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001535 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1536 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001537 // Otherwise, we have an 8-bit splat.
1538 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1539 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1540 SplatSize = 1;
1541 return true;
1542 }
1543 } else {
1544 SplatBits = Bits16;
1545 SplatUndef = Undef16;
1546 SplatSize = 2;
1547 return true;
1548 }
1549 }
1550 } else {
1551 SplatBits = Bits32;
1552 SplatUndef = Undef32;
1553 SplatSize = 4;
1554 return true;
1555 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001556 }
1557 } else {
1558 SplatBits = Bits128[0];
1559 SplatUndef = Undef128[0];
1560 SplatSize = 8;
1561 return true;
1562 }
1563 }
1564
1565 return false; // Can't be a splat if two pieces don't match.
1566}
1567
1568// If this is a case we can't handle, return null and let the default
1569// expansion code take care of it. If we CAN select this case, and if it
1570// selects to a single instruction, return Op. Otherwise, if we can codegen
1571// this case more efficiently than a constant pool load, lower it to the
1572// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001573static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001574 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001575 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001576 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001577 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001578 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001579 uint64_t VectorBits[2];
1580 uint64_t UndefBits[2];
1581 uint64_t SplatBits, SplatUndef;
1582 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001583 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001584 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001585 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001586 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001587 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001588
Duncan Sands83ec4b62008-06-06 12:08:01 +00001589 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001590 default:
1591 case MVT::v4f32: {
1592 uint32_t Value32 = SplatBits;
1593 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001594 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001595 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001596 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001597 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001598 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001599 break;
1600 }
1601 case MVT::v2f64: {
1602 uint64_t f64val = SplatBits;
1603 assert(SplatSize == 8
Scott Michel104de432008-11-24 17:11:17 +00001604 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001605 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001606 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001607 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001608 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001609 break;
1610 }
1611 case MVT::v16i8: {
1612 // 8-bit constants have to be expanded to 16-bits
1613 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001614 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001615 for (int i = 0; i < 8; ++i)
1616 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1617 return DAG.getNode(ISD::BIT_CONVERT, VT,
1618 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1619 }
1620 case MVT::v8i16: {
1621 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001622 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001623 Value16 = (unsigned short) (SplatBits & 0xffff);
1624 else
1625 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001626 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1627 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001628 for (int i = 0; i < 8; ++i) Ops[i] = T;
1629 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1630 }
1631 case MVT::v4i32: {
1632 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001633 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001634 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1635 }
1636 case MVT::v2i64: {
1637 uint64_t val = SplatBits;
1638 uint32_t upper = uint32_t(val >> 32);
1639 uint32_t lower = uint32_t(val);
1640
Scott Michel4cb8bd82008-03-06 04:02:54 +00001641 if (upper == lower) {
1642 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001643 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001644 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001645 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001646 SDValue LO32;
1647 SDValue HI32;
1648 SmallVector<SDValue, 16> ShufBytes;
1649 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001650 bool upper_special, lower_special;
1651
1652 // NOTE: This code creates common-case shuffle masks that can be easily
1653 // detected as common expressions. It is not attempting to create highly
1654 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1655
1656 // Detect if the upper or lower half is a special shuffle mask pattern:
Scott Michel104de432008-11-24 17:11:17 +00001657 upper_special = (upper == 0||upper == 0xffffffff||upper == 0x80000000);
1658 lower_special = (lower == 0||lower == 0xffffffff||lower == 0x80000000);
Scott Michel266bc8f2007-12-04 22:23:35 +00001659
1660 // Create lower vector if not a special pattern
1661 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001662 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001663 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1664 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1665 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001666 }
1667
1668 // Create upper vector if not a special pattern
1669 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001670 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001671 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1672 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1673 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001674 }
1675
1676 // If either upper or lower are special, then the two input operands are
1677 // the same (basically, one of them is a "don't care")
1678 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001679 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001680 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001681 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001682 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001683 // Unhappy situation... both upper and lower are special, so punt with
1684 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001685 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001686 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001687 Zero, Zero);
1688 }
1689
1690 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001691 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001692 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001693 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001694 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001695 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001696 process_upper = (upper_special && (i & 1) == 0);
1697 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001698
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001699 if (process_upper || process_lower) {
1700 if ((process_upper && upper == 0)
1701 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001702 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001703 else if ((process_upper && upper == 0xffffffff)
1704 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001705 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001706 else if ((process_upper && upper == 0x80000000)
1707 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001708 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001709 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001710 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001711 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001712
1713 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001714 }
1715
1716 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001717 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001718 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001719 }
1720 }
1721 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001722
Dan Gohman475871a2008-07-27 21:46:04 +00001723 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001724}
1725
1726/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1727/// which the Cell can operate. The code inspects V3 to ascertain whether the
1728/// permutation vector, V3, is monotonically increasing with one "exception"
1729/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel7a1c9e92008-11-22 23:50:42 +00001730/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel266bc8f2007-12-04 22:23:35 +00001731/// In either case, the net result is going to eventually invoke SHUFB to
1732/// permute/shuffle the bytes from V1 and V2.
1733/// \note
Scott Michel7a1c9e92008-11-22 23:50:42 +00001734/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel266bc8f2007-12-04 22:23:35 +00001735/// control word for byte/halfword/word insertion. This takes care of a single
1736/// element move from V2 into V1.
1737/// \note
1738/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001739static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1740 SDValue V1 = Op.getOperand(0);
1741 SDValue V2 = Op.getOperand(1);
1742 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001743
Scott Michel266bc8f2007-12-04 22:23:35 +00001744 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001745
Scott Michel266bc8f2007-12-04 22:23:35 +00001746 // If we have a single element being moved from V1 to V2, this can be handled
1747 // using the C*[DX] compute mask instructions, but the vector elements have
1748 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001749 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001750 unsigned EltsFromV2 = 0;
1751 unsigned V2Elt = 0;
1752 unsigned V2EltIdx0 = 0;
1753 unsigned CurrElt = 0;
1754 bool monotonic = true;
1755 if (EltVT == MVT::i8)
1756 V2EltIdx0 = 16;
1757 else if (EltVT == MVT::i16)
1758 V2EltIdx0 = 8;
1759 else if (EltVT == MVT::i32)
1760 V2EltIdx0 = 4;
1761 else
1762 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1763
1764 for (unsigned i = 0, e = PermMask.getNumOperands();
1765 EltsFromV2 <= 1 && monotonic && i != e;
1766 ++i) {
1767 unsigned SrcElt;
1768 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1769 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001770 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001771 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001772
1773 if (SrcElt >= V2EltIdx0) {
1774 ++EltsFromV2;
1775 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1776 } else if (CurrElt != SrcElt) {
1777 monotonic = false;
1778 }
1779
1780 ++CurrElt;
1781 }
1782
1783 if (EltsFromV2 == 1 && monotonic) {
1784 // Compute mask and shuffle
1785 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001786 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1787 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001788 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001789 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001790 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001791 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel7a1c9e92008-11-22 23:50:42 +00001792 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001793 SDValue ShufMaskOp =
Scott Michel7a1c9e92008-11-22 23:50:42 +00001794 DAG.getNode(SPUISD::SHUFFLE_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001795 DAG.getTargetConstant(V2Elt, MVT::i32),
1796 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001797 // Use shuffle mask in SHUFB synthetic instruction:
1798 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1799 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001800 // Convert the SHUFFLE_VECTOR mask's input element units to the
1801 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001802 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001803
Dan Gohman475871a2008-07-27 21:46:04 +00001804 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001805 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1806 unsigned SrcElt;
1807 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001808 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001809 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001810 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001811
Scott Michela59d4692008-02-23 18:41:37 +00001812 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001813 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1814 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001815 }
1816 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001817
Dan Gohman475871a2008-07-27 21:46:04 +00001818 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001819 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001820 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1821 }
1822}
1823
Dan Gohman475871a2008-07-27 21:46:04 +00001824static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1825 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001826
Gabor Greifba36cb52008-08-28 21:40:38 +00001827 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001828 // For a constant, build the appropriate constant vector, which will
1829 // eventually simplify to a vector register load.
1830
Gabor Greifba36cb52008-08-28 21:40:38 +00001831 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001832 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001833 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001834 size_t n_copies;
1835
1836 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001837 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001838 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001839 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001840 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1841 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1842 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1843 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1844 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1845 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1846 }
1847
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001848 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001849 for (size_t j = 0; j < n_copies; ++j)
1850 ConstVecValues.push_back(CValue);
1851
1852 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001853 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001854 } else {
1855 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001856 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001857 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1858 case MVT::i8:
1859 case MVT::i16:
1860 case MVT::i32:
1861 case MVT::i64:
1862 case MVT::f32:
1863 case MVT::f64:
1864 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1865 }
1866 }
1867
Dan Gohman475871a2008-07-27 21:46:04 +00001868 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001869}
1870
Dan Gohman475871a2008-07-27 21:46:04 +00001871static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001872 switch (Op.getValueType().getSimpleVT()) {
1873 default:
1874 cerr << "CellSPU: Unknown vector multiplication, got "
1875 << Op.getValueType().getMVTString()
1876 << "\n";
1877 abort();
1878 /*NOTREACHED*/
1879
Scott Michel266bc8f2007-12-04 22:23:35 +00001880 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001881 SDValue rA = Op.getOperand(0);
1882 SDValue rB = Op.getOperand(1);
1883 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1884 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1885 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1886 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001887
1888 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1889 break;
1890 }
1891
1892 // Multiply two v8i16 vectors (pipeline friendly version):
1893 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1894 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1895 // c) Use SELB to select upper and lower halves from the intermediate results
1896 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001897 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001898 // dual-issue. This code does manage to do this, even if it's a little on
1899 // the wacky side
1900 case MVT::v8i16: {
1901 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001902 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001903 SDValue Chain = Op.getOperand(0);
1904 SDValue rA = Op.getOperand(0);
1905 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001906 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1907 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001908
Dan Gohman475871a2008-07-27 21:46:04 +00001909 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001910 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001911 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001912 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001913
Dan Gohman475871a2008-07-27 21:46:04 +00001914 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001915 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001916 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001917
Dan Gohman475871a2008-07-27 21:46:04 +00001918 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001919 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001920 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001921
1922 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001923 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1924 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1925 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1926 HHProd_v4i32,
1927 DAG.getConstant(16, MVT::i16))),
1928 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001929 }
1930
1931 // This M00sE is N@stI! (apologies to Monty Python)
1932 //
1933 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1934 // is to break it all apart, sign extend, and reassemble the various
1935 // intermediate products.
1936 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001937 SDValue rA = Op.getOperand(0);
1938 SDValue rB = Op.getOperand(1);
1939 SDValue c8 = DAG.getConstant(8, MVT::i32);
1940 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001941
Dan Gohman475871a2008-07-27 21:46:04 +00001942 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001943 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001944 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1945 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001946
Dan Gohman475871a2008-07-27 21:46:04 +00001947 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001948
Dan Gohman475871a2008-07-27 21:46:04 +00001949 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001950
Dan Gohman475871a2008-07-27 21:46:04 +00001951 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001952 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001953 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001954
Dan Gohman475871a2008-07-27 21:46:04 +00001955 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001956 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001957
Dan Gohman475871a2008-07-27 21:46:04 +00001958 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001959 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1960 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1961 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001962
Dan Gohman475871a2008-07-27 21:46:04 +00001963 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001964
Dan Gohman475871a2008-07-27 21:46:04 +00001965 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001966 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00001967 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001968 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1969 LoProdMask, LoProdMask,
1970 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001971
Dan Gohman475871a2008-07-27 21:46:04 +00001972 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001973 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001974 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001975
Dan Gohman475871a2008-07-27 21:46:04 +00001976 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001977 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001978 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001979
Dan Gohman475871a2008-07-27 21:46:04 +00001980 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001981 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001982 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
1983 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00001984
Dan Gohman475871a2008-07-27 21:46:04 +00001985 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001986 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001987 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00001988 DAG.getNode(SPUISD::VEC_SRA,
1989 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001990 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00001991 DAG.getNode(SPUISD::VEC_SRA,
1992 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001993
Dan Gohman475871a2008-07-27 21:46:04 +00001994 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00001995 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1996 HLProd,
1997 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
1998 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00001999
Dan Gohman475871a2008-07-27 21:46:04 +00002000 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002001 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002002
2003 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002004 DAG.getNode(ISD::OR, MVT::v4i32,
2005 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002006 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002007 }
2008
Dan Gohman475871a2008-07-27 21:46:04 +00002009 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002010}
2011
Dan Gohman475871a2008-07-27 21:46:04 +00002012static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002013 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002014 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002015
Dan Gohman475871a2008-07-27 21:46:04 +00002016 SDValue A = Op.getOperand(0);
2017 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002018 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002019
2020 unsigned VRegBR, VRegC;
2021
2022 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002023 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2024 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002025 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002026 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2027 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002028 }
2029 // TODO: make sure we're feeding FPInterp the right arguments
2030 // Right now: fi B, frest(B)
2031
2032 // Computes BRcpl =
2033 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002034 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002035 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2036 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002037 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002038
Scott Michel266bc8f2007-12-04 22:23:35 +00002039 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002040 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002041 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002042 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002043 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002044 // What's the Chain variable do? It's magic!
2045 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002046
2047 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002048 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002049 DAG.getNode(ISD::FMUL, VT,
2050 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002051 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002052 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002053 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002054}
2055
Dan Gohman475871a2008-07-27 21:46:04 +00002056static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002057 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002058 SDValue N = Op.getOperand(0);
2059 SDValue Elt = Op.getOperand(1);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002060 SDValue retval;
Scott Michel266bc8f2007-12-04 22:23:35 +00002061
Scott Michel7a1c9e92008-11-22 23:50:42 +00002062 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
2063 // Constant argument:
2064 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002065
Scott Michel7a1c9e92008-11-22 23:50:42 +00002066 // sanity checks:
2067 if (VT == MVT::i8 && EltNo >= 16)
2068 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2069 else if (VT == MVT::i16 && EltNo >= 8)
2070 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2071 else if (VT == MVT::i32 && EltNo >= 4)
2072 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2073 else if (VT == MVT::i64 && EltNo >= 2)
2074 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel266bc8f2007-12-04 22:23:35 +00002075
Scott Michel7a1c9e92008-11-22 23:50:42 +00002076 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2077 // i32 and i64: Element 0 is the preferred slot
Scott Michel104de432008-11-24 17:11:17 +00002078 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002079 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002080
Scott Michel7a1c9e92008-11-22 23:50:42 +00002081 // Need to generate shuffle mask and extract:
2082 int prefslot_begin = -1, prefslot_end = -1;
2083 int elt_byte = EltNo * VT.getSizeInBits() / 8;
2084
2085 switch (VT.getSimpleVT()) {
2086 default:
2087 assert(false && "Invalid value type!");
2088 case MVT::i8: {
2089 prefslot_begin = prefslot_end = 3;
2090 break;
2091 }
2092 case MVT::i16: {
2093 prefslot_begin = 2; prefslot_end = 3;
2094 break;
2095 }
2096 case MVT::i32:
2097 case MVT::f32: {
2098 prefslot_begin = 0; prefslot_end = 3;
2099 break;
2100 }
2101 case MVT::i64:
2102 case MVT::f64: {
2103 prefslot_begin = 0; prefslot_end = 7;
2104 break;
2105 }
2106 }
2107
2108 assert(prefslot_begin != -1 && prefslot_end != -1 &&
2109 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
2110
2111 unsigned int ShufBytes[16];
2112 for (int i = 0; i < 16; ++i) {
2113 // zero fill uppper part of preferred slot, don't care about the
2114 // other slots:
2115 unsigned int mask_val;
2116 if (i <= prefslot_end) {
2117 mask_val =
2118 ((i < prefslot_begin)
2119 ? 0x80
2120 : elt_byte + (i - prefslot_begin));
2121
2122 ShufBytes[i] = mask_val;
2123 } else
2124 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
2125 }
2126
2127 SDValue ShufMask[4];
2128 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
2129 unsigned bidx = i / 4;
2130 unsigned int bits = ((ShufBytes[bidx] << 24) |
2131 (ShufBytes[bidx+1] << 16) |
2132 (ShufBytes[bidx+2] << 8) |
2133 ShufBytes[bidx+3]);
2134 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
2135 }
2136
2137 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2138 &ShufMask[0],
2139 sizeof(ShufMask) / sizeof(ShufMask[0]));
2140
Scott Michel104de432008-11-24 17:11:17 +00002141 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel7a1c9e92008-11-22 23:50:42 +00002142 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2143 N, N, ShufMaskVec));
2144 } else {
2145 // Variable index: Rotate the requested element into slot 0, then replicate
2146 // slot 0 across the vector
2147 MVT VecVT = N.getValueType();
2148 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2149 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2150 abort();
2151 }
2152
2153 // Make life easier by making sure the index is zero-extended to i32
2154 if (Elt.getValueType() != MVT::i32)
2155 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2156
2157 // Scale the index to a bit/byte shift quantity
2158 APInt scaleFactor =
Scott Michel104de432008-11-24 17:11:17 +00002159 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2160 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel7a1c9e92008-11-22 23:50:42 +00002161 SDValue vecShift;
Scott Michel7a1c9e92008-11-22 23:50:42 +00002162
Scott Michel104de432008-11-24 17:11:17 +00002163 if (scaleShift > 0) {
2164 // Scale the shift factor:
Scott Michel7a1c9e92008-11-22 23:50:42 +00002165 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel104de432008-11-24 17:11:17 +00002166 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel7a1c9e92008-11-22 23:50:42 +00002167 }
2168
Scott Michel104de432008-11-24 17:11:17 +00002169 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2170
2171 // Replicate the bytes starting at byte 0 across the entire vector (for
2172 // consistency with the notion of a unified register set)
Scott Michel7a1c9e92008-11-22 23:50:42 +00002173 SDValue replicate;
2174
2175 switch (VT.getSimpleVT()) {
2176 default:
2177 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2178 abort();
2179 /*NOTREACHED*/
2180 case MVT::i8: {
Scott Michel104de432008-11-24 17:11:17 +00002181 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002182 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2183 factor, factor);
2184 break;
2185 }
2186 case MVT::i16: {
Scott Michel104de432008-11-24 17:11:17 +00002187 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002188 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2189 factor, factor);
2190 break;
2191 }
2192 case MVT::i32:
2193 case MVT::f32: {
2194 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2195 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2196 factor, factor);
2197 break;
2198 }
2199 case MVT::i64:
2200 case MVT::f64: {
2201 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2202 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2203 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2204 loFactor, hiFactor);
2205 break;
2206 }
2207 }
2208
Scott Michel104de432008-11-24 17:11:17 +00002209 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel7a1c9e92008-11-22 23:50:42 +00002210 DAG.getNode(SPUISD::SHUFB, VecVT, vecShift, vecShift, replicate));
Scott Michel266bc8f2007-12-04 22:23:35 +00002211 }
2212
Scott Michel7a1c9e92008-11-22 23:50:42 +00002213 return retval;
Scott Michel266bc8f2007-12-04 22:23:35 +00002214}
2215
Dan Gohman475871a2008-07-27 21:46:04 +00002216static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2217 SDValue VecOp = Op.getOperand(0);
2218 SDValue ValOp = Op.getOperand(1);
2219 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002220 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002221
2222 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2223 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2224
Duncan Sands83ec4b62008-06-06 12:08:01 +00002225 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002226 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002227 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002228
Dan Gohman475871a2008-07-27 21:46:04 +00002229 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002230 DAG.getNode(SPUISD::SHUFB, VT,
2231 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2232 VecOp,
Scott Michel7a1c9e92008-11-22 23:50:42 +00002233 DAG.getNode(SPUISD::SHUFFLE_MASK, VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002234 DAG.getNode(ISD::ADD, PtrVT,
2235 PtrBase,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002236 DAG.getConstant(CN->getZExtValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002237 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002238
2239 return result;
2240}
2241
Dan Gohman475871a2008-07-27 21:46:04 +00002242static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002243{
Dan Gohman475871a2008-07-27 21:46:04 +00002244 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002245
2246 assert(Op.getValueType() == MVT::i8);
2247 switch (Opc) {
2248 default:
2249 assert(0 && "Unhandled i8 math operator");
2250 /*NOTREACHED*/
2251 break;
2252 case ISD::SUB: {
2253 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2254 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002255 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002256 N0 = (N0.getOpcode() != ISD::Constant
2257 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002258 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2259 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002260 N1 = (N1.getOpcode() != ISD::Constant
2261 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002262 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2263 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002264 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002265 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002266 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002267 case ISD::ROTR:
2268 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002269 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002270 unsigned N1Opc;
2271 N0 = (N0.getOpcode() != ISD::Constant
2272 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002273 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2274 MVT::i16));
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002275 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greif93c53e52008-08-31 15:37:04 +00002276 ? ISD::ZERO_EXTEND
2277 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002278 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002279 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002280 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002281 MVT::i32));
Dan Gohman475871a2008-07-27 21:46:04 +00002282 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002283 DAG.getNode(ISD::OR, MVT::i16, N0,
2284 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002285 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002286 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002287 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2288 }
2289 case ISD::SRL:
2290 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002291 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002292 unsigned N1Opc;
2293 N0 = (N0.getOpcode() != ISD::Constant
2294 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002295 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2296 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002297 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2298 ? ISD::ZERO_EXTEND
2299 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002300 N1 = (N1.getOpcode() != ISD::Constant
2301 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002302 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2303 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002304 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002305 DAG.getNode(Opc, MVT::i16, N0, N1));
2306 }
2307 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002308 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002309 unsigned N1Opc;
2310 N0 = (N0.getOpcode() != ISD::Constant
2311 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002312 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2313 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002314 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2315 ? ISD::SIGN_EXTEND
2316 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002317 N1 = (N1.getOpcode() != ISD::Constant
2318 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002319 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2320 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002321 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002322 DAG.getNode(Opc, MVT::i16, N0, N1));
2323 }
2324 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002325 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002326 unsigned N1Opc;
2327 N0 = (N0.getOpcode() != ISD::Constant
2328 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002329 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2330 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002331 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002332 N1 = (N1.getOpcode() != ISD::Constant
2333 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002334 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2335 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002336 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002337 DAG.getNode(Opc, MVT::i16, N0, N1));
2338 break;
2339 }
2340 }
2341
Dan Gohman475871a2008-07-27 21:46:04 +00002342 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002343}
2344
Dan Gohman475871a2008-07-27 21:46:04 +00002345static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002346{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002347 MVT VT = Op.getValueType();
2348 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002349
Dan Gohman475871a2008-07-27 21:46:04 +00002350 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002351
2352 switch (Opc) {
2353 case ISD::ZERO_EXTEND:
2354 case ISD::SIGN_EXTEND:
2355 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002356 MVT Op0VT = Op0.getValueType();
2357 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002358
2359 assert(Op0VT == MVT::i32
2360 && "CellSPU: Zero/sign extending something other than i32");
2361
Scott Michel104de432008-11-24 17:11:17 +00002362 DEBUG(cerr << "CellSPU.LowerI64Math: lowering zero/sign/any extend\n");
2363
Dan Gohman475871a2008-07-27 21:46:04 +00002364 SDValue PromoteScalar =
Scott Michel104de432008-11-24 17:11:17 +00002365 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
Scott Michela59d4692008-02-23 18:41:37 +00002366
Scott Michel104de432008-11-24 17:11:17 +00002367 if (Opc != ISD::SIGN_EXTEND) {
Scott Michel045a1452008-11-24 18:20:46 +00002368 // Use a shuffle to zero extend the i32 to i64 directly:
2369 SDValue shufMask =
2370 DAG.getNode(ISD::BUILD_VECTOR, Op0VecVT,
2371 DAG.getConstant(0x80808080, MVT::i32),
2372 DAG.getConstant(0x00010203, MVT::i32),
2373 DAG.getConstant(0x80808080, MVT::i32),
2374 DAG.getConstant(0x08090a0b, MVT::i32));
2375 SDValue zextShuffle =
2376 DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2377 PromoteScalar, PromoteScalar, shufMask);
2378
Scott Michel104de432008-11-24 17:11:17 +00002379 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel045a1452008-11-24 18:20:46 +00002380 DAG.getNode(ISD::BIT_CONVERT, VecVT, zextShuffle));
Scott Michel104de432008-11-24 17:11:17 +00002381 } else {
2382 // SPU has no "rotate quadword and replicate bit 0" (i.e. rotate/shift
2383 // right and propagate the sign bit) instruction.
Scott Michel045a1452008-11-24 18:20:46 +00002384 SDValue RotQuad =
2385 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, Op0VecVT,
2386 PromoteScalar, DAG.getConstant(4, MVT::i32));
Scott Michel104de432008-11-24 17:11:17 +00002387 SDValue SignQuad =
2388 DAG.getNode(SPUISD::VEC_SRA, Op0VecVT,
2389 PromoteScalar, DAG.getConstant(32, MVT::i32));
2390 SDValue SelMask =
2391 DAG.getNode(SPUISD::SELECT_MASK, Op0VecVT,
2392 DAG.getConstant(0xf0f0, MVT::i16));
2393 SDValue CombineQuad =
2394 DAG.getNode(SPUISD::SELB, Op0VecVT,
2395 SignQuad, RotQuad, SelMask);
2396
2397 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2398 DAG.getNode(ISD::BIT_CONVERT, VecVT, CombineQuad));
2399 }
Scott Michela59d4692008-02-23 18:41:37 +00002400 }
2401
Scott Michel8bf61e82008-06-02 22:18:03 +00002402 case ISD::ADD: {
2403 // Turn operands into vectors to satisfy type checking (shufb works on
2404 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002405 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002406 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002407 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002408 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002409 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002410
2411 // Create the shuffle mask for "rotating" the borrow up one register slot
2412 // once the borrow is generated.
2413 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2414 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2415 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2416 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2417
Dan Gohman475871a2008-07-27 21:46:04 +00002418 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002419 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002420 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002421 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2422 CarryGen, CarryGen,
2423 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2424 &ShufBytes[0], ShufBytes.size()));
2425
Scott Michel104de432008-11-24 17:11:17 +00002426 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel8bf61e82008-06-02 22:18:03 +00002427 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2428 Op0, Op1, ShiftedCarry));
2429 }
2430
2431 case ISD::SUB: {
2432 // Turn operands into vectors to satisfy type checking (shufb works on
2433 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002434 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002435 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002436 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002437 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002438 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002439
2440 // Create the shuffle mask for "rotating" the borrow up one register slot
2441 // once the borrow is generated.
2442 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2443 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2444 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2445 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2446
Dan Gohman475871a2008-07-27 21:46:04 +00002447 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002448 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002449 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002450 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2451 BorrowGen, BorrowGen,
2452 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2453 &ShufBytes[0], ShufBytes.size()));
2454
Scott Michel104de432008-11-24 17:11:17 +00002455 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel8bf61e82008-06-02 22:18:03 +00002456 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2457 Op0, Op1, ShiftedBorrow));
2458 }
2459
Scott Michela59d4692008-02-23 18:41:37 +00002460 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002461 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002462 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002463 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2464 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002465 DAG.getNode(SPUISD::SELB, VecVT,
2466 Op0Vec,
2467 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002468 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002469 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002470 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002471 DAG.getNode(ISD::SRL, ShiftAmtVT,
2472 ShiftAmt,
2473 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002474 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002475 DAG.getNode(ISD::AND, ShiftAmtVT,
2476 ShiftAmt,
2477 DAG.getConstant(7, ShiftAmtVT));
2478
Scott Michel104de432008-11-24 17:11:17 +00002479 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michela59d4692008-02-23 18:41:37 +00002480 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2481 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2482 MaskLower, ShiftAmtBytes),
2483 ShiftAmtBits));
2484 }
2485
2486 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002487 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002488 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002489 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002490 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002491 DAG.getNode(ISD::SRL, ShiftAmtVT,
2492 ShiftAmt,
2493 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002494 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002495 DAG.getNode(ISD::AND, ShiftAmtVT,
2496 ShiftAmt,
2497 DAG.getConstant(7, ShiftAmtVT));
2498
2499 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2500 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2501 Op0, ShiftAmtBytes),
2502 ShiftAmtBits);
2503 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002504
2505 case ISD::SRA: {
2506 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002507 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002508 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002509 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002510 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002511
2512 // Negate variable shift amounts
2513 if (!isa<ConstantSDNode>(ShiftAmt)) {
2514 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2515 DAG.getConstant(0, ShiftVT), ShiftAmt);
2516 }
2517
Dan Gohman475871a2008-07-27 21:46:04 +00002518 SDValue UpperHalfSign =
Scott Michel104de432008-11-24 17:11:17 +00002519 DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i32,
Scott Michel8bf61e82008-06-02 22:18:03 +00002520 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2521 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2522 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002523 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002524 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002525 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002526 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2527 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002528 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002529 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2530 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002531 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002532 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2533 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002534 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002535 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2536 RotateLeftBytes, ShiftAmt);
2537
Scott Michel104de432008-11-24 17:11:17 +00002538 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel8bf61e82008-06-02 22:18:03 +00002539 RotateLeftBits);
2540 }
Scott Michela59d4692008-02-23 18:41:37 +00002541 }
2542
Dan Gohman475871a2008-07-27 21:46:04 +00002543 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002544}
2545
Scott Michel266bc8f2007-12-04 22:23:35 +00002546//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002547static SDValue
2548LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2549 SDValue ConstVec;
2550 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002551 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002552
2553 ConstVec = Op.getOperand(0);
2554 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002555 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2556 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002557 ConstVec = ConstVec.getOperand(0);
2558 } else {
2559 ConstVec = Op.getOperand(1);
2560 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002561 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002562 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002563 }
2564 }
2565 }
2566
Gabor Greifba36cb52008-08-28 21:40:38 +00002567 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002568 uint64_t VectorBits[2];
2569 uint64_t UndefBits[2];
2570 uint64_t SplatBits, SplatUndef;
2571 int SplatSize;
2572
Gabor Greifba36cb52008-08-28 21:40:38 +00002573 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002574 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002575 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002576 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002577 SDValue tcVec[16];
2578 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002579 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2580
2581 // Turn the BUILD_VECTOR into a set of target constants:
2582 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002583 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002584
Gabor Greifba36cb52008-08-28 21:40:38 +00002585 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002586 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002587 }
2588 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002589 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2590 // lowered. Return the operation, rather than a null SDValue.
2591 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002592}
2593
2594//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002595static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002596 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002597 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002598 default:
2599 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002600 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002601 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002602 abort();
2603 /*NOTREACHED*/
2604
2605 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002606 SDValue rA = Op.getOperand(0);
2607 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002608
2609 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002610 DAG.getNode(ISD::ADD, MVT::i32,
2611 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2612 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2613 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002614 }
2615 }
2616
Dan Gohman475871a2008-07-27 21:46:04 +00002617 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002618}
2619
2620//! Custom lowering for CTPOP (count population)
2621/*!
2622 Custom lowering code that counts the number ones in the input
2623 operand. SPU has such an instruction, but it counts the number of
2624 ones per byte, which then have to be accumulated.
2625*/
Dan Gohman475871a2008-07-27 21:46:04 +00002626static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002627 MVT VT = Op.getValueType();
2628 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002629
Duncan Sands83ec4b62008-06-06 12:08:01 +00002630 switch (VT.getSimpleVT()) {
2631 default:
2632 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002633 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002634 SDValue N = Op.getOperand(0);
2635 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002636
Dan Gohman475871a2008-07-27 21:46:04 +00002637 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2638 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002639
2640 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2641 }
2642
2643 case MVT::i16: {
2644 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002645 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002646
Chris Lattner84bc5422007-12-31 04:13:23 +00002647 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002648
Dan Gohman475871a2008-07-27 21:46:04 +00002649 SDValue N = Op.getOperand(0);
2650 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2651 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002652 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002653
Dan Gohman475871a2008-07-27 21:46:04 +00002654 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2655 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002656
2657 // CNTB_result becomes the chain to which all of the virtual registers
2658 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002659 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002660 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002661
Dan Gohman475871a2008-07-27 21:46:04 +00002662 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002663 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2664
Dan Gohman475871a2008-07-27 21:46:04 +00002665 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002666
2667 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002668 DAG.getNode(ISD::ADD, MVT::i16,
2669 DAG.getNode(ISD::SRL, MVT::i16,
2670 Tmp1, Shift1),
2671 Tmp1),
2672 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002673 }
2674
2675 case MVT::i32: {
2676 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002677 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002678
Chris Lattner84bc5422007-12-31 04:13:23 +00002679 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2680 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002681
Dan Gohman475871a2008-07-27 21:46:04 +00002682 SDValue N = Op.getOperand(0);
2683 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2684 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2685 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2686 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002687
Dan Gohman475871a2008-07-27 21:46:04 +00002688 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2689 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002690
2691 // CNTB_result becomes the chain to which all of the virtual registers
2692 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002693 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002694 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002695
Dan Gohman475871a2008-07-27 21:46:04 +00002696 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002697 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2698
Dan Gohman475871a2008-07-27 21:46:04 +00002699 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002700 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002701 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002702
Dan Gohman475871a2008-07-27 21:46:04 +00002703 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002704 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002705 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002706
Dan Gohman475871a2008-07-27 21:46:04 +00002707 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002708 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2709
Dan Gohman475871a2008-07-27 21:46:04 +00002710 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002711 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002712 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2713 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002714 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002715 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002716 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002717
2718 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2719 }
2720
2721 case MVT::i64:
2722 break;
2723 }
2724
Dan Gohman475871a2008-07-27 21:46:04 +00002725 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002726}
2727
Scott Michel7a1c9e92008-11-22 23:50:42 +00002728//! Lower ISD::SELECT_CC
2729/*!
2730 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2731 SELB instruction.
2732
2733 \note Need to revisit this in the future: if the code path through the true
2734 and false value computations is longer than the latency of a branch (6
2735 cycles), then it would be more advantageous to branch and insert a new basic
2736 block and branch on the condition. However, this code does not make that
2737 assumption, given the simplisitc uses so far.
2738 */
2739
2740static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
2741 MVT VT = Op.getValueType();
2742 SDValue lhs = Op.getOperand(0);
2743 SDValue rhs = Op.getOperand(1);
2744 SDValue trueval = Op.getOperand(2);
2745 SDValue falseval = Op.getOperand(3);
2746 SDValue condition = Op.getOperand(4);
2747
2748 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2749 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2750 // with another "cannot select select_cc" assert:
2751
2752 SDValue compare = DAG.getNode(ISD::SETCC, VT, lhs, rhs, condition);
2753 return DAG.getNode(SPUISD::SELB, VT, trueval, falseval, compare);
2754}
2755
2756//! Custom (target-specific) lowering entry point
2757/*!
2758 This is where LLVM's DAG selection process calls to do target-specific
2759 lowering of nodes.
2760 */
Dan Gohman475871a2008-07-27 21:46:04 +00002761SDValue
2762SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002763{
Scott Michela59d4692008-02-23 18:41:37 +00002764 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002765 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002766
2767 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002768 default: {
2769 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002770 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002771 cerr << "*Op.getNode():\n";
2772 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002773 abort();
2774 }
2775 case ISD::LOAD:
2776 case ISD::SEXTLOAD:
2777 case ISD::ZEXTLOAD:
2778 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2779 case ISD::STORE:
2780 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2781 case ISD::ConstantPool:
2782 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2783 case ISD::GlobalAddress:
2784 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2785 case ISD::JumpTable:
2786 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2787 case ISD::Constant:
2788 return LowerConstant(Op, DAG);
2789 case ISD::ConstantFP:
2790 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002791 case ISD::BRCOND:
2792 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002793 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002794 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002795 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002796 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002797 case ISD::RET:
2798 return LowerRET(Op, DAG, getTargetMachine());
2799
Scott Michela59d4692008-02-23 18:41:37 +00002800
2801 // i8, i64 math ops:
2802 case ISD::ZERO_EXTEND:
2803 case ISD::SIGN_EXTEND:
2804 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002805 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002806 case ISD::SUB:
2807 case ISD::ROTR:
2808 case ISD::ROTL:
2809 case ISD::SRL:
2810 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002811 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002812 if (VT == MVT::i8)
2813 return LowerI8Math(Op, DAG, Opc);
2814 else if (VT == MVT::i64)
2815 return LowerI64Math(Op, DAG, Opc);
2816 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002817 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002818
2819 // Vector-related lowering.
2820 case ISD::BUILD_VECTOR:
2821 return LowerBUILD_VECTOR(Op, DAG);
2822 case ISD::SCALAR_TO_VECTOR:
2823 return LowerSCALAR_TO_VECTOR(Op, DAG);
2824 case ISD::VECTOR_SHUFFLE:
2825 return LowerVECTOR_SHUFFLE(Op, DAG);
2826 case ISD::EXTRACT_VECTOR_ELT:
2827 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2828 case ISD::INSERT_VECTOR_ELT:
2829 return LowerINSERT_VECTOR_ELT(Op, DAG);
2830
2831 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2832 case ISD::AND:
2833 case ISD::OR:
2834 case ISD::XOR:
2835 return LowerByteImmed(Op, DAG);
2836
2837 // Vector and i8 multiply:
2838 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002839 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002840 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002841 else if (VT == MVT::i8)
2842 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002843 else
Scott Michela59d4692008-02-23 18:41:37 +00002844 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002845
2846 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002847 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002848 return LowerFDIVf32(Op, DAG);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002849#if 0
2850 // This is probably a libcall
2851 else if (Op.getValueType() == MVT::f64)
2852 return LowerFDIVf64(Op, DAG);
2853#endif
Scott Michel266bc8f2007-12-04 22:23:35 +00002854 else
2855 assert(0 && "Calling FDIV on unsupported MVT");
2856
2857 case ISD::CTPOP:
2858 return LowerCTPOP(Op, DAG);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002859
2860 case ISD::SELECT_CC:
2861 return LowerSELECT_CC(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002862 }
2863
Dan Gohman475871a2008-07-27 21:46:04 +00002864 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002865}
2866
Scott Michel73ce1c52008-11-10 23:43:06 +00002867SDNode *SPUTargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG)
2868{
2869#if 0
2870 unsigned Opc = (unsigned) N->getOpcode();
2871 MVT OpVT = N->getValueType(0);
2872
2873 switch (Opc) {
2874 default: {
2875 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2876 cerr << "Op.getOpcode() = " << Opc << "\n";
2877 cerr << "*Op.getNode():\n";
2878 N->dump();
2879 abort();
2880 /*NOTREACHED*/
2881 }
2882 }
2883#endif
2884
2885 /* Otherwise, return unchanged */
2886 return 0;
2887}
2888
Scott Michel266bc8f2007-12-04 22:23:35 +00002889//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002890// Target Optimization Hooks
2891//===----------------------------------------------------------------------===//
2892
Dan Gohman475871a2008-07-27 21:46:04 +00002893SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002894SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2895{
2896#if 0
2897 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002898#endif
2899 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002900 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002901 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2902 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002903
2904 switch (N->getOpcode()) {
2905 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002906 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002907 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002908
Scott Michel8bf61e82008-06-02 22:18:03 +00002909 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002910 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002911 if (Op01.getOpcode() == ISD::Constant
2912 || Op01.getOpcode() == ISD::TargetConstant) {
2913 // (add <const>, (SPUindirect <arg>, <const>)) ->
2914 // (SPUindirect <arg>, <const + const>)
2915 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2916 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002917 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002918 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002919 Op0.getValueType());
2920
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002921 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2922 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002923 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002924 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002925 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2926 Op0.getOperand(0), combinedConst);
2927 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002928 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002929 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002930 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002931 if (Op11.getOpcode() == ISD::Constant
2932 || Op11.getOpcode() == ISD::TargetConstant) {
2933 // (add (SPUindirect <arg>, <const>), <const>) ->
2934 // (SPUindirect <arg>, <const + const>)
2935 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2936 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002937 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002938 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002939 Op0.getValueType());
2940
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002941 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2942 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002943 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002944 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002945
2946 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2947 Op1.getOperand(0), combinedConst);
2948 }
2949 }
Scott Michela59d4692008-02-23 18:41:37 +00002950 break;
2951 }
2952 case ISD::SIGN_EXTEND:
2953 case ISD::ZERO_EXTEND:
2954 case ISD::ANY_EXTEND: {
Scott Michel104de432008-11-24 17:11:17 +00002955 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT &&
Scott Michela59d4692008-02-23 18:41:37 +00002956 N->getValueType(0) == Op0.getValueType()) {
2957 // (any_extend (SPUextract_elt0 <arg>)) ->
2958 // (SPUextract_elt0 <arg>)
2959 // Types must match, however...
2960 DEBUG(cerr << "Replace: ");
2961 DEBUG(N->dump(&DAG));
2962 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002963 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002964 DEBUG(cerr << "\n");
2965
2966 return Op0;
2967 }
2968 break;
2969 }
2970 case SPUISD::IndirectAddr: {
2971 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2972 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002973 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002974 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2975 // (SPUaform <addr>, 0)
2976
2977 DEBUG(cerr << "Replace: ");
2978 DEBUG(N->dump(&DAG));
2979 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002980 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002981 DEBUG(cerr << "\n");
2982
2983 return Op0;
2984 }
2985 }
2986 break;
2987 }
2988 case SPUISD::SHLQUAD_L_BITS:
2989 case SPUISD::SHLQUAD_L_BYTES:
2990 case SPUISD::VEC_SHL:
2991 case SPUISD::VEC_SRL:
2992 case SPUISD::VEC_SRA:
2993 case SPUISD::ROTQUAD_RZ_BYTES:
2994 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002995 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002996
2997 if (isa<ConstantSDNode>(Op1)) {
2998 // Kill degenerate vector shifts:
2999 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
3000
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00003001 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00003002 Result = Op0;
3003 }
3004 }
3005 break;
3006 }
3007 case SPUISD::PROMOTE_SCALAR: {
3008 switch (Op0.getOpcode()) {
3009 default:
3010 break;
3011 case ISD::ANY_EXTEND:
3012 case ISD::ZERO_EXTEND:
3013 case ISD::SIGN_EXTEND: {
3014 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
3015 // <arg>
3016 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00003017 SDValue Op00 = Op0.getOperand(0);
Scott Michel104de432008-11-24 17:11:17 +00003018 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman475871a2008-07-27 21:46:04 +00003019 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00003020 if (Op000.getValueType() == N->getValueType(0)) {
3021 Result = Op000;
3022 }
3023 }
3024 break;
3025 }
Scott Michel104de432008-11-24 17:11:17 +00003026 case SPUISD::VEC2PREFSLOT: {
Scott Michela59d4692008-02-23 18:41:37 +00003027 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
3028 // <arg>
3029 Result = Op0.getOperand(0);
3030 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003031 }
Scott Michela59d4692008-02-23 18:41:37 +00003032 }
3033 break;
Scott Michel053c1da2008-01-29 02:16:57 +00003034 }
3035 }
Scott Michel58c58182008-01-17 20:38:41 +00003036 // Otherwise, return unchanged.
Scott Michel9c0c6b22008-11-21 02:56:16 +00003037#ifdef NDEBUG
Gabor Greifba36cb52008-08-28 21:40:38 +00003038 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00003039 DEBUG(cerr << "\nReplace.SPU: ");
3040 DEBUG(N->dump(&DAG));
3041 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00003042 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00003043 DEBUG(cerr << "\n");
3044 }
3045#endif
3046
3047 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00003048}
3049
3050//===----------------------------------------------------------------------===//
3051// Inline Assembly Support
3052//===----------------------------------------------------------------------===//
3053
3054/// getConstraintType - Given a constraint letter, return the type of
3055/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00003056SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00003057SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
3058 if (ConstraintLetter.size() == 1) {
3059 switch (ConstraintLetter[0]) {
3060 default: break;
3061 case 'b':
3062 case 'r':
3063 case 'f':
3064 case 'v':
3065 case 'y':
3066 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003067 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003068 }
3069 return TargetLowering::getConstraintType(ConstraintLetter);
3070}
3071
Scott Michel5af8f0e2008-07-16 17:17:29 +00003072std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00003073SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00003074 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00003075{
3076 if (Constraint.size() == 1) {
3077 // GCC RS6000 Constraint Letters
3078 switch (Constraint[0]) {
3079 case 'b': // R1-R31
3080 case 'r': // R0-R31
3081 if (VT == MVT::i64)
3082 return std::make_pair(0U, SPU::R64CRegisterClass);
3083 return std::make_pair(0U, SPU::R32CRegisterClass);
3084 case 'f':
3085 if (VT == MVT::f32)
3086 return std::make_pair(0U, SPU::R32FPRegisterClass);
3087 else if (VT == MVT::f64)
3088 return std::make_pair(0U, SPU::R64FPRegisterClass);
3089 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003090 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00003091 return std::make_pair(0U, SPU::GPRCRegisterClass);
3092 }
3093 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003094
Scott Michel266bc8f2007-12-04 22:23:35 +00003095 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3096}
3097
Scott Michela59d4692008-02-23 18:41:37 +00003098//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00003099void
Dan Gohman475871a2008-07-27 21:46:04 +00003100SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00003101 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00003102 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00003103 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00003104 const SelectionDAG &DAG,
3105 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00003106#if 0
Scott Michela59d4692008-02-23 18:41:37 +00003107 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00003108#endif
Scott Michela59d4692008-02-23 18:41:37 +00003109
3110 switch (Op.getOpcode()) {
3111 default:
3112 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3113 break;
3114
3115#if 0
3116 case CALL:
3117 case SHUFB:
Scott Michel7a1c9e92008-11-22 23:50:42 +00003118 case SHUFFLE_MASK:
Scott Michela59d4692008-02-23 18:41:37 +00003119 case CNTB:
3120#endif
3121
3122 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00003123 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00003124 MVT Op0VT = Op0.getValueType();
3125 unsigned Op0VTBits = Op0VT.getSizeInBits();
3126 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003127 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3128 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003129 break;
3130 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003131
Scott Michela59d4692008-02-23 18:41:37 +00003132 case SPUISD::LDRESULT:
Scott Michel104de432008-11-24 17:11:17 +00003133 case SPUISD::VEC2PREFSLOT:
3134 case SPUISD::VEC2PREFSLOT_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00003135 MVT OpVT = Op.getValueType();
3136 unsigned OpVTBits = OpVT.getSizeInBits();
3137 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003138 KnownZero |= APInt(OpVTBits, ~InMask, false);
3139 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003140 break;
3141 }
3142
3143#if 0
3144 case EXTRACT_I1_ZEXT:
3145 case EXTRACT_I1_SEXT:
3146 case EXTRACT_I8_ZEXT:
3147 case EXTRACT_I8_SEXT:
3148 case MPY:
3149 case MPYU:
3150 case MPYH:
3151 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00003152 case SPUISD::SHLQUAD_L_BITS:
3153 case SPUISD::SHLQUAD_L_BYTES:
3154 case SPUISD::VEC_SHL:
3155 case SPUISD::VEC_SRL:
3156 case SPUISD::VEC_SRA:
3157 case SPUISD::VEC_ROTL:
3158 case SPUISD::VEC_ROTR:
3159 case SPUISD::ROTQUAD_RZ_BYTES:
3160 case SPUISD::ROTQUAD_RZ_BITS:
Scott Michel203b2d62008-04-30 00:30:08 +00003161 case SPUISD::ROTBYTES_LEFT:
3162 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00003163 case SPUISD::SELECT_MASK:
3164 case SPUISD::SELB:
3165 case SPUISD::FPInterp:
3166 case SPUISD::FPRecipEst:
3167 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003168#endif
3169 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003170}
3171
Scott Michel203b2d62008-04-30 00:30:08 +00003172// LowerAsmOperandForConstraint
3173void
Dan Gohman475871a2008-07-27 21:46:04 +00003174SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003175 char ConstraintLetter,
Evan Chengda43bcf2008-09-24 00:05:32 +00003176 bool hasMemory,
Dan Gohman475871a2008-07-27 21:46:04 +00003177 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003178 SelectionDAG &DAG) const {
3179 // Default, for the time being, to the base class handler
Evan Chengda43bcf2008-09-24 00:05:32 +00003180 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3181 Ops, DAG);
Scott Michel203b2d62008-04-30 00:30:08 +00003182}
3183
Scott Michel266bc8f2007-12-04 22:23:35 +00003184/// isLegalAddressImmediate - Return true if the integer value can be used
3185/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003186bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3187 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003188 // SPU's addresses are 256K:
3189 return (V > -(1 << 18) && V < (1 << 18) - 1);
3190}
3191
3192bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003193 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003194}
Dan Gohman6520e202008-10-18 02:06:02 +00003195
3196bool
3197SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3198 // The SPU target isn't yet aware of offsets.
3199 return false;
3200}