blob: 2b35e76595e1b492c00b612b7bd18add2b342a1e [file] [log] [blame]
Scott Michel8efdca42007-12-04 22:23:35 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner081ce942007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Scott Michel8efdca42007-12-04 22:23:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SPUTargetLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPURegisterNames.h"
15#include "SPUISelLowering.h"
16#include "SPUTargetMachine.h"
Scott Michelbc5fbc12008-04-30 00:30:08 +000017#include "SPUFrameInfo.h"
Scott Michel8efdca42007-12-04 22:23:35 +000018#include "llvm/ADT/VectorExtras.h"
Scott Michel8efdca42007-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 Lattner1b989192007-12-31 04:13:23 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel8efdca42007-12-04 22:23:35 +000024#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel8efdca42007-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 Sands92c43912008-06-06 12:08:01 +000040 //! MVT mapping to useful data for Cell SPU
Scott Michel8efdca42007-12-04 22:23:35 +000041 struct valtype_map_s {
Scott Michel56a125e2008-11-22 23:50:42 +000042 const MVT valtype;
43 const int prefslot_byte;
Scott Michel8efdca42007-12-04 22:23:35 +000044 };
Scott Michel4ec722e2008-07-16 17:17:29 +000045
Scott Michel8efdca42007-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 Sands92c43912008-06-06 12:08:01 +000059 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel8efdca42007-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 Michel5a6f17b2008-01-30 02:55:46 +000064 retval = valtype_map + i;
65 break;
Scott Michel8efdca42007-12-04 22:23:35 +000066 }
67 }
68
69#ifndef NDEBUG
70 if (retval == 0) {
71 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands92c43912008-06-06 12:08:01 +000072 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +000073 << "\n";
Scott Michel8efdca42007-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 Micheldbac4cf2008-01-11 02:53:15 +000085 address, external symbol, constant pool) or an A-form
Scott Michel8efdca42007-12-04 22:23:35 +000086 address.
87 */
Dan Gohman8181bd12008-07-27 21:46:04 +000088 bool isMemoryOperand(const SDValue &Op)
Scott Michel8efdca42007-12-04 22:23:35 +000089 {
90 const unsigned Opc = Op.getOpcode();
91 return (Opc == ISD::GlobalAddress
92 || Opc == ISD::GlobalTLSAddress
Scott Michel8efdca42007-12-04 22:23:35 +000093 || Opc == ISD::JumpTable
94 || Opc == ISD::ConstantPool
Bill Wendlingfef06052008-09-16 21:48:12 +000095 || Opc == ISD::ExternalSymbol
Scott Michel8efdca42007-12-04 22:23:35 +000096 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel8efdca42007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
Bill Wendlingfef06052008-09-16 21:48:12 +0000100 || Opc == ISD::TargetExternalSymbol
Scott Micheldbac4cf2008-01-11 02:53:15 +0000101 || Opc == SPUISD::AFormAddr);
Scott Michel8efdca42007-12-04 22:23:35 +0000102 }
Scott Michel394e26d2008-01-17 20:38:41 +0000103
104 //! Predicate that returns true if the operand is an indirect target
Dan Gohman8181bd12008-07-27 21:46:04 +0000105 bool isIndirectOperand(const SDValue &Op)
Scott Michel394e26d2008-01-17 20:38:41 +0000106 {
107 const unsigned Opc = Op.getOpcode();
108 return (Opc == ISD::Register
Scott Michel5a6f17b2008-01-30 02:55:46 +0000109 || Opc == SPUISD::LDRESULT);
Scott Michel394e26d2008-01-17 20:38:41 +0000110 }
Scott Michel8efdca42007-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 Michel4ec722e2008-07-16 17:17:29 +0000123
Scott Michel8efdca42007-12-04 22:23:35 +0000124 // Set up the SPU's register classes:
Scott Michel438be252007-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 Michel8efdca42007-12-04 22:23:35 +0000131 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel4ec722e2008-07-16 17:17:29 +0000132
Scott Michelabb8ca12008-11-20 16:36:33 +0000133 // Initialize libcalls:
134 setLibcallName(RTLIB::MUL_I64, "__muldi3");
135
Scott Michel8efdca42007-12-04 22:23:35 +0000136 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng08c171a2008-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 Michel8efdca42007-12-04 22:23:35 +0000140
Evan Cheng08c171a2008-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 Michel55252632008-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 Michel4ec722e2008-07-16 17:17:29 +0000149
Evan Cheng08c171a2008-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 Michel8efdca42007-12-04 22:23:35 +0000153
Scott Michelec8c82e2008-12-02 19:53:53 +0000154 setLoadExtAction(ISD::EXTLOAD, MVT::f32, Custom);
155
Scott Michel8efdca42007-12-04 22:23:35 +0000156 // SPU constant load actions are custom lowered:
157 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begeman78125042008-02-14 18:43:04 +0000158 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000159 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
160
161 // SPU's loads and stores have to be custom lowered:
Scott Michele1006032008-11-19 17:45:08 +0000162 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel8efdca42007-12-04 22:23:35 +0000163 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000164 MVT VT = (MVT::SimpleValueType)sctype;
165
166 setOperationAction(ISD::LOAD, VT, Custom);
167 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000168 }
169
Scott Michel33d73eb2008-11-21 02:56:16 +0000170 // Custom lower BRCOND for i8 to "promote" the result to i16
Scott Michel394e26d2008-01-17 20:38:41 +0000171 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000172
173 // Expand the jumptable branches
174 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
175 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel56a125e2008-11-22 23:50:42 +0000176
177 // Custom lower SELECT_CC for most cases, but expand by default
Scott Michel4ec722e2008-07-16 17:17:29 +0000178 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel56a125e2008-11-22 23:50:42 +0000179 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
180 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
181 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
Scott Michelfa888632008-11-25 00:23:16 +0000182#if 0
Scott Michel56a125e2008-11-22 23:50:42 +0000183 setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
Scott Michelfa888632008-11-25 00:23:16 +0000184#endif
Scott Michel8efdca42007-12-04 22:23:35 +0000185
186 // SPU has no intrinsics for these particular operations:
Andrew Lenharth0531ec52008-02-16 14:46:26 +0000187 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
188
Scott Michel8efdca42007-12-04 22:23:35 +0000189 // PowerPC has no SREM/UREM instructions
190 setOperationAction(ISD::SREM, MVT::i32, Expand);
191 setOperationAction(ISD::UREM, MVT::i32, Expand);
192 setOperationAction(ISD::SREM, MVT::i64, Expand);
193 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000194
Scott Michel8efdca42007-12-04 22:23:35 +0000195 // We don't support sin/cos/sqrt/fmod
196 setOperationAction(ISD::FSIN , MVT::f64, Expand);
197 setOperationAction(ISD::FCOS , MVT::f64, Expand);
198 setOperationAction(ISD::FREM , MVT::f64, Expand);
199 setOperationAction(ISD::FSIN , MVT::f32, Expand);
200 setOperationAction(ISD::FCOS , MVT::f32, Expand);
201 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000202
Scott Michel8efdca42007-12-04 22:23:35 +0000203 // If we're enabling GP optimizations, use hardware square root
204 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
205 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000206
Scott Michel8efdca42007-12-04 22:23:35 +0000207 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
208 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
209
210 // SPU can do rotate right and left, so legalize it... but customize for i8
211 // because instructions don't exist.
Bill Wendling965299c2008-08-31 02:59:23 +0000212
213 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
214 // .td files.
215 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
216 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
217 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
218
Scott Michel8efdca42007-12-04 22:23:35 +0000219 setOperationAction(ISD::ROTL, MVT::i32, Legal);
220 setOperationAction(ISD::ROTL, MVT::i16, Legal);
221 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Michelabb8ca12008-11-20 16:36:33 +0000222
Scott Michel8efdca42007-12-04 22:23:35 +0000223 // SPU has no native version of shift left/right for i8
224 setOperationAction(ISD::SHL, MVT::i8, Custom);
225 setOperationAction(ISD::SRL, MVT::i8, Custom);
226 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel33d73eb2008-11-21 02:56:16 +0000227
228 // SPU needs custom lowering for shift left/right for i64
Scott Michel97872d32008-02-23 18:41:37 +0000229 setOperationAction(ISD::SHL, MVT::i64, Custom);
230 setOperationAction(ISD::SRL, MVT::i64, Custom);
231 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000232
Scott Michel4ec722e2008-07-16 17:17:29 +0000233 // Custom lower i8, i32 and i64 multiplications
234 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000235 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel33d73eb2008-11-21 02:56:16 +0000236 setOperationAction(ISD::MUL, MVT::i64, Expand); // libcall
237
238 // SMUL_LOHI, UMUL_LOHI
239 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
240 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
241 setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom);
242 setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000243
Scott Michel67224b22008-06-02 22:18:03 +0000244 // Need to custom handle (some) common i8, i64 math ops
245 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000246 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel67224b22008-06-02 22:18:03 +0000247 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000248
Scott Michel8efdca42007-12-04 22:23:35 +0000249 // SPU does not have BSWAP. It does have i32 support CTLZ.
250 // CTPOP has to be custom lowered.
251 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
252 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
253
254 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
255 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
256 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
257 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
258
259 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
260 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
261
262 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000263
Scott Michel67224b22008-06-02 22:18:03 +0000264 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel978b96f2008-03-10 23:49:09 +0000265 // select ought to work:
Scott Michel53ab7792008-03-10 16:58:52 +0000266 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000267 setOperationAction(ISD::SELECT, MVT::i16, Legal);
268 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000269 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000270
Scott Michel53ab7792008-03-10 16:58:52 +0000271 setOperationAction(ISD::SETCC, MVT::i8, Legal);
272 setOperationAction(ISD::SETCC, MVT::i16, Legal);
273 setOperationAction(ISD::SETCC, MVT::i32, Legal);
274 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michel6baba072008-03-05 23:02:02 +0000275
Scott Michel97872d32008-02-23 18:41:37 +0000276 // Zero extension and sign extension for i64 have to be
277 // custom legalized
278 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
279 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
280 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000281
Scott Michelec8c82e2008-12-02 19:53:53 +0000282 // Custom lower truncates
283 setOperationAction(ISD::TRUNCATE, MVT::i8, Custom);
284 setOperationAction(ISD::TRUNCATE, MVT::i16, Custom);
285 setOperationAction(ISD::TRUNCATE, MVT::i32, Custom);
286 setOperationAction(ISD::TRUNCATE, MVT::i64, Custom);
287
Scott Michel8efdca42007-12-04 22:23:35 +0000288 // SPU has a legal FP -> signed INT instruction
289 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
290 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
291 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
292 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
293
294 // FDIV on SPU requires custom lowering
295 setOperationAction(ISD::FDIV, MVT::f32, Custom);
296 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
297
298 // SPU has [U|S]INT_TO_FP
299 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
300 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
301 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
302 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
303 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
304 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
305 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
306 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
307
Scott Michel754d8662007-12-20 00:44:13 +0000308 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
309 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
310 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
311 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000312
313 // We cannot sextinreg(i1). Expand to shifts.
314 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000315
Scott Michel8efdca42007-12-04 22:23:35 +0000316 // Support label based line numbers.
Dan Gohman472d12c2008-06-30 20:59:49 +0000317 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000318 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000319
320 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel8efdca42007-12-04 22:23:35 +0000321 // appropriate instructions to materialize the address.
Scott Michel33d73eb2008-11-21 02:56:16 +0000322 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michelf9f42e62008-01-29 02:16:57 +0000323 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000324 MVT VT = (MVT::SimpleValueType)sctype;
325
326 setOperationAction(ISD::GlobalAddress, VT, Custom);
327 setOperationAction(ISD::ConstantPool, VT, Custom);
328 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michelf9f42e62008-01-29 02:16:57 +0000329 }
Scott Michel8efdca42007-12-04 22:23:35 +0000330
331 // RET must be custom lowered, to meet ABI requirements
332 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000333
Scott Michel8efdca42007-12-04 22:23:35 +0000334 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
335 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000336
Scott Michel8efdca42007-12-04 22:23:35 +0000337 // Use the default implementation.
338 setOperationAction(ISD::VAARG , MVT::Other, Expand);
339 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
340 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000341 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000342 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
343 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
344 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
345
346 // Cell SPU has instructions for converting between i64 and fp.
347 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
348 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000349
Scott Michel8efdca42007-12-04 22:23:35 +0000350 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
351 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
352
353 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
354 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
355
356 // First set operation action for all vector types to expand. Then we
357 // will selectively turn on ones that can be effectively codegen'd.
358 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
359 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
360 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
361 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
362 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
363 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
364
Duncan Sands92c43912008-06-06 12:08:01 +0000365 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
366 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
367 MVT VT = (MVT::SimpleValueType)i;
Scott Michel8efdca42007-12-04 22:23:35 +0000368
Duncan Sands92c43912008-06-06 12:08:01 +0000369 // add/sub are legal for all supported vector VT's.
370 setOperationAction(ISD::ADD , VT, Legal);
371 setOperationAction(ISD::SUB , VT, Legal);
372 // mul has to be custom lowered.
373 setOperationAction(ISD::MUL , VT, Custom);
374
375 setOperationAction(ISD::AND , VT, Legal);
376 setOperationAction(ISD::OR , VT, Legal);
377 setOperationAction(ISD::XOR , VT, Legal);
378 setOperationAction(ISD::LOAD , VT, Legal);
379 setOperationAction(ISD::SELECT, VT, Legal);
380 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000381
Scott Michel8efdca42007-12-04 22:23:35 +0000382 // These operations need to be expanded:
Duncan Sands92c43912008-06-06 12:08:01 +0000383 setOperationAction(ISD::SDIV, VT, Expand);
384 setOperationAction(ISD::SREM, VT, Expand);
385 setOperationAction(ISD::UDIV, VT, Expand);
386 setOperationAction(ISD::UREM, VT, Expand);
387 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000388
389 // Custom lower build_vector, constant pool spills, insert and
390 // extract vector elements:
Duncan Sands92c43912008-06-06 12:08:01 +0000391 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
392 setOperationAction(ISD::ConstantPool, VT, Custom);
393 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
394 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
395 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
396 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000397 }
398
399 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
400 setOperationAction(ISD::AND, MVT::v16i8, Custom);
401 setOperationAction(ISD::OR, MVT::v16i8, Custom);
402 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
403 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000404
Scott Michel8efdca42007-12-04 22:23:35 +0000405 setShiftAmountType(MVT::i32);
Duncan Sands8cf4a822008-11-23 15:47:28 +0000406 setBooleanContents(ZeroOrOneBooleanContent);
Scott Michel4ec722e2008-07-16 17:17:29 +0000407
Scott Michel8efdca42007-12-04 22:23:35 +0000408 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel4ec722e2008-07-16 17:17:29 +0000409
Scott Michel8efdca42007-12-04 22:23:35 +0000410 // We have target-specific dag combine patterns for the following nodes:
Scott Michelf9f42e62008-01-29 02:16:57 +0000411 setTargetDAGCombine(ISD::ADD);
Scott Michel97872d32008-02-23 18:41:37 +0000412 setTargetDAGCombine(ISD::ZERO_EXTEND);
413 setTargetDAGCombine(ISD::SIGN_EXTEND);
414 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel4ec722e2008-07-16 17:17:29 +0000415
Scott Michel8efdca42007-12-04 22:23:35 +0000416 computeRegisterProperties();
Scott Michel56a125e2008-11-22 23:50:42 +0000417
418 // Set other properties:
419 setSchedulingPreference(SchedulingForLatency);
Scott Michel8efdca42007-12-04 22:23:35 +0000420}
421
422const char *
423SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
424{
425 if (node_names.empty()) {
426 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
427 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
428 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
429 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Micheldbac4cf2008-01-11 02:53:15 +0000430 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michelf9f42e62008-01-29 02:16:57 +0000431 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel8efdca42007-12-04 22:23:35 +0000432 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
433 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
434 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
Scott Michel56a125e2008-11-22 23:50:42 +0000435 node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000436 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
437 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
Scott Michelc630c412008-11-24 17:11:17 +0000438 node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
Scott Michel8efdca42007-12-04 22:23:35 +0000439 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
440 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
441 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
442 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michel97872d32008-02-23 18:41:37 +0000443 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
444 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel8efdca42007-12-04 22:23:35 +0000445 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
446 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
447 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
448 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
449 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michel97872d32008-02-23 18:41:37 +0000450 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
451 "SPUISD::ROTQUAD_RZ_BYTES";
452 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
453 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel8efdca42007-12-04 22:23:35 +0000454 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
Scott Michel67224b22008-06-02 22:18:03 +0000455 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
456 "SPUISD::ROTBYTES_LEFT_BITS";
457 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000458 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel67224b22008-06-02 22:18:03 +0000459 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
460 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
461 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
462 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel8efdca42007-12-04 22:23:35 +0000463 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
464 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
465 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
466 }
467
468 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
469
470 return ((i != node_names.end()) ? i->second : 0);
471}
472
Dan Gohman8181bd12008-07-27 21:46:04 +0000473MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands92c43912008-06-06 12:08:01 +0000474 MVT VT = Op.getValueType();
Scott Michela313fb02008-10-30 01:51:48 +0000475 return (VT.isInteger() ? VT : MVT(MVT::i32));
Scott Michel53ab7792008-03-10 16:58:52 +0000476}
477
Scott Michel8efdca42007-12-04 22:23:35 +0000478//===----------------------------------------------------------------------===//
479// Calling convention code:
480//===----------------------------------------------------------------------===//
481
482#include "SPUGenCallingConv.inc"
483
484//===----------------------------------------------------------------------===//
485// LowerOperation implementation
486//===----------------------------------------------------------------------===//
487
Scott Micheldbac4cf2008-01-11 02:53:15 +0000488/// Aligned load common code for CellSPU
489/*!
490 \param[in] Op The SelectionDAG load or store operand
491 \param[in] DAG The selection DAG
492 \param[in] ST CellSPU subtarget information structure
493 \param[in,out] alignment Caller initializes this to the load or store node's
494 value from getAlignment(), may be updated while generating the aligned load
495 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
496 offset (divisible by 16, modulo 16 == 0)
497 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
498 offset of the preferred slot (modulo 16 != 0)
499 \param[in,out] VT Caller initializes this value type to the the load or store
500 node's loaded or stored value type; may be updated if an i1-extended load or
501 store.
502 \param[out] was16aligned true if the base pointer had 16-byte alignment,
503 otherwise false. Can help to determine if the chunk needs to be rotated.
504
505 Both load and store lowering load a block of data aligned on a 16-byte
506 boundary. This is the common aligned load code shared between both.
507 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000508static SDValue
509AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Micheldbac4cf2008-01-11 02:53:15 +0000510 LSBaseSDNode *LSN,
511 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands92c43912008-06-06 12:08:01 +0000512 MVT &VT, bool &was16aligned)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000513{
Duncan Sands92c43912008-06-06 12:08:01 +0000514 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000515 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman8181bd12008-07-27 21:46:04 +0000516 SDValue basePtr = LSN->getBasePtr();
517 SDValue chain = LSN->getChain();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000518
519 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greif1c80d112008-08-28 21:40:38 +0000520 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000521
Gabor Greife9f7f582008-08-31 15:37:04 +0000522 if (Op1.getOpcode() == ISD::Constant
523 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel394e26d2008-01-17 20:38:41 +0000524 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000525
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000526 alignOffs = (int) CN->getZExtValue();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000527 prefSlotOffs = (int) (alignOffs & 0xf);
528
529 // Adjust the rotation amount to ensure that the final result ends up in
530 // the preferred slot:
531 prefSlotOffs -= vtm->prefslot_byte;
532 basePtr = basePtr.getOperand(0);
533
Scott Michel394e26d2008-01-17 20:38:41 +0000534 // Loading from memory, can we adjust alignment?
535 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000536 SDValue APtr = basePtr.getOperand(0);
Scott Michel394e26d2008-01-17 20:38:41 +0000537 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
538 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
539 alignment = GSDN->getGlobal()->getAlignment();
540 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000541 }
542 } else {
543 alignOffs = 0;
544 prefSlotOffs = -vtm->prefslot_byte;
545 }
Scott Michelbc5fbc12008-04-30 00:30:08 +0000546 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
547 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
548 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
549 prefSlotOffs = (int) (alignOffs & 0xf);
550 prefSlotOffs -= vtm->prefslot_byte;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000551 } else {
552 alignOffs = 0;
553 prefSlotOffs = -vtm->prefslot_byte;
554 }
555
556 if (alignment == 16) {
557 // Realign the base pointer as a D-Form address:
558 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel394e26d2008-01-17 20:38:41 +0000559 basePtr = DAG.getNode(ISD::ADD, PtrVT,
560 basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000561 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000562 }
563
564 // Emit the vector load:
565 was16aligned = true;
566 return DAG.getLoad(MVT::v16i8, chain, basePtr,
567 LSN->getSrcValue(), LSN->getSrcValueOffset(),
568 LSN->isVolatile(), 16);
569 }
570
571 // Unaligned load or we're using the "large memory" model, which means that
572 // we have to be very pessimistic:
Scott Michel394e26d2008-01-17 20:38:41 +0000573 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greife9f7f582008-08-31 15:37:04 +0000574 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
575 DAG.getConstant(0, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000576 }
577
578 // Add the offset
Scott Michelf9f42e62008-01-29 02:16:57 +0000579 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000580 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000581 was16aligned = false;
582 return DAG.getLoad(MVT::v16i8, chain, basePtr,
583 LSN->getSrcValue(), LSN->getSrcValueOffset(),
584 LSN->isVolatile(), 16);
585}
586
Scott Michel8efdca42007-12-04 22:23:35 +0000587/// Custom lower loads for CellSPU
588/*!
589 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
590 within a 16-byte block, we have to rotate to extract the requested element.
Scott Michel6ccefab2008-12-04 03:02:42 +0000591
592 For extending loads, we also want to ensure that the following sequence is
593 emitted, e.g. for MVT::f32 extending load to MVT::f64:
594
595\verbatim
596%1 v16i8,ch = load
597%2 v16i8,ch = rotate %1
598%3 v4f8, ch = bitconvert %2
599%4 f32 = vec2perfslot %3
600%5 f64 = fp_extend %4
601\endverbatim
602*/
Dan Gohman8181bd12008-07-27 21:46:04 +0000603static SDValue
604LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000605 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000606 SDValue the_chain = LN->getChain();
Scott Michel6ccefab2008-12-04 03:02:42 +0000607 MVT InVT = LN->getMemoryVT();
608 MVT OutVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000609 ISD::LoadExtType ExtType = LN->getExtensionType();
610 unsigned alignment = LN->getAlignment();
Dan Gohman8181bd12008-07-27 21:46:04 +0000611 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +0000612
Scott Michel8efdca42007-12-04 22:23:35 +0000613 switch (LN->getAddressingMode()) {
614 case ISD::UNINDEXED: {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000615 int offset, rotamt;
616 bool was16aligned;
Dan Gohman8181bd12008-07-27 21:46:04 +0000617 SDValue result =
Scott Michel6ccefab2008-12-04 03:02:42 +0000618 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, InVT,
619 was16aligned);
Scott Michel8efdca42007-12-04 22:23:35 +0000620
Gabor Greif1c80d112008-08-28 21:40:38 +0000621 if (result.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +0000622 return result;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000623
624 the_chain = result.getValue(1);
625 // Rotate the chunk if necessary
626 if (rotamt < 0)
627 rotamt += 16;
Scott Michelabc58242008-01-11 21:01:19 +0000628 if (rotamt != 0 || !was16aligned) {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000629 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
630
Scott Michel6ccefab2008-12-04 03:02:42 +0000631 Ops[0] = result;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000632 if (was16aligned) {
Scott Michel6ccefab2008-12-04 03:02:42 +0000633 Ops[1] = DAG.getConstant(rotamt, MVT::i16);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000634 } else {
Duncan Sands92c43912008-06-06 12:08:01 +0000635 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000636 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel6ccefab2008-12-04 03:02:42 +0000637 Ops[1] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel5a6f17b2008-01-30 02:55:46 +0000638 DAG.getConstant(rotamt, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000639 }
640
Scott Michel6ccefab2008-12-04 03:02:42 +0000641 result = DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v16i8, Ops, 2);
Scott Michel8efdca42007-12-04 22:23:35 +0000642 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000643
Scott Michel6ccefab2008-12-04 03:02:42 +0000644 // Convert the loaded v16i8 vector to the appropriate vector type
645 // specified by the operand:
646 MVT vecVT = MVT::getVectorVT(InVT, (128 / InVT.getSizeInBits()));
647 result = DAG.getNode(SPUISD::VEC2PREFSLOT, InVT,
648 DAG.getNode(ISD::BIT_CONVERT, vecVT, result));
Scott Michel4ec722e2008-07-16 17:17:29 +0000649
Scott Michel6ccefab2008-12-04 03:02:42 +0000650 // Handle extending loads by extending the scalar result:
651 if (ExtType == ISD::SEXTLOAD) {
652 result = DAG.getNode(ISD::SIGN_EXTEND, OutVT, result);
653 } else if (ExtType == ISD::ZEXTLOAD) {
654 result = DAG.getNode(ISD::ZERO_EXTEND, OutVT, result);
655 } else if (ExtType == ISD::EXTLOAD) {
656 unsigned NewOpc = ISD::ANY_EXTEND;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000657
Scott Michel6ccefab2008-12-04 03:02:42 +0000658 if (OutVT.isFloatingPoint())
659 NewOpc = ISD::FP_EXTEND;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000660
Scott Michel6ccefab2008-12-04 03:02:42 +0000661 result = DAG.getNode(NewOpc, OutVT, result);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000662 }
663
Scott Michel6ccefab2008-12-04 03:02:42 +0000664 SDVTList retvts = DAG.getVTList(OutVT, MVT::Other);
Dan Gohman8181bd12008-07-27 21:46:04 +0000665 SDValue retops[2] = {
Scott Michel394e26d2008-01-17 20:38:41 +0000666 result,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000667 the_chain
Scott Michel394e26d2008-01-17 20:38:41 +0000668 };
Scott Micheldbac4cf2008-01-11 02:53:15 +0000669
Scott Michel394e26d2008-01-17 20:38:41 +0000670 result = DAG.getNode(SPUISD::LDRESULT, retvts,
671 retops, sizeof(retops) / sizeof(retops[0]));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000672 return result;
Scott Michel8efdca42007-12-04 22:23:35 +0000673 }
674 case ISD::PRE_INC:
675 case ISD::PRE_DEC:
676 case ISD::POST_INC:
677 case ISD::POST_DEC:
678 case ISD::LAST_INDEXED_MODE:
679 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
680 "UNINDEXED\n";
681 cerr << (unsigned) LN->getAddressingMode() << "\n";
682 abort();
683 /*NOTREACHED*/
684 }
685
Dan Gohman8181bd12008-07-27 21:46:04 +0000686 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000687}
688
689/// Custom lower stores for CellSPU
690/*!
691 All CellSPU stores are aligned to 16-byte boundaries, so for elements
692 within a 16-byte block, we have to generate a shuffle to insert the
693 requested element into its place, then store the resulting block.
694 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000695static SDValue
696LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000697 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000698 SDValue Value = SN->getValue();
Duncan Sands92c43912008-06-06 12:08:01 +0000699 MVT VT = Value.getValueType();
700 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
701 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000702 unsigned alignment = SN->getAlignment();
Scott Michel8efdca42007-12-04 22:23:35 +0000703
704 switch (SN->getAddressingMode()) {
705 case ISD::UNINDEXED: {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000706 int chunk_offset, slot_offset;
707 bool was16aligned;
Scott Michel8efdca42007-12-04 22:23:35 +0000708
Scott Michel33d73eb2008-11-21 02:56:16 +0000709 // The vector type we really want to load from the 16-byte chunk.
Scott Michele1006032008-11-19 17:45:08 +0000710 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
711 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +0000712
Dan Gohman8181bd12008-07-27 21:46:04 +0000713 SDValue alignLoadVec =
Scott Micheldbac4cf2008-01-11 02:53:15 +0000714 AlignedLoad(Op, DAG, ST, SN, alignment,
715 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel8efdca42007-12-04 22:23:35 +0000716
Gabor Greif1c80d112008-08-28 21:40:38 +0000717 if (alignLoadVec.getNode() == 0)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000718 return alignLoadVec;
Scott Michel8efdca42007-12-04 22:23:35 +0000719
Scott Micheldbac4cf2008-01-11 02:53:15 +0000720 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman8181bd12008-07-27 21:46:04 +0000721 SDValue basePtr = LN->getBasePtr();
722 SDValue the_chain = alignLoadVec.getValue(1);
723 SDValue theValue = SN->getValue();
724 SDValue result;
Scott Michel8efdca42007-12-04 22:23:35 +0000725
726 if (StVT != VT
Scott Michel5a6f17b2008-01-30 02:55:46 +0000727 && (theValue.getOpcode() == ISD::AssertZext
728 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel8efdca42007-12-04 22:23:35 +0000729 // Drill down and get the value for zero- and sign-extended
730 // quantities
Scott Michel4ec722e2008-07-16 17:17:29 +0000731 theValue = theValue.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000732 }
733
Scott Micheldbac4cf2008-01-11 02:53:15 +0000734 chunk_offset &= 0xf;
Scott Michel8efdca42007-12-04 22:23:35 +0000735
Dan Gohman8181bd12008-07-27 21:46:04 +0000736 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
737 SDValue insertEltPtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000738
739 // If the base pointer is already a D-form address, then just create
740 // a new D-form address with a slot offset and the orignal base pointer.
741 // Otherwise generate a D-form address with the slot offset relative
742 // to the stack pointer, which is always aligned.
Scott Michelabc58242008-01-11 21:01:19 +0000743 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greif1c80d112008-08-28 21:40:38 +0000744 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michelabc58242008-01-11 21:01:19 +0000745 DEBUG(cerr << "\n");
746
Scott Michelf9f42e62008-01-29 02:16:57 +0000747 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
748 (basePtr.getOpcode() == ISD::ADD
749 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michelabc58242008-01-11 21:01:19 +0000750 insertEltPtr = basePtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000751 } else {
Scott Michelf9f42e62008-01-29 02:16:57 +0000752 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000753 }
754
Scott Michelf65c8f02008-11-19 15:24:16 +0000755 SDValue insertEltOp =
Scott Michel0718cd82008-12-01 17:56:02 +0000756 DAG.getNode(SPUISD::SHUFFLE_MASK, vecVT, insertEltPtr);
Scott Michele1006032008-11-19 17:45:08 +0000757 SDValue vectorizeOp =
758 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michelf65c8f02008-11-19 15:24:16 +0000759
Scott Michel0718cd82008-12-01 17:56:02 +0000760 result = DAG.getNode(SPUISD::SHUFB, vecVT,
761 vectorizeOp, alignLoadVec,
762 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, insertEltOp));
Scott Michel8efdca42007-12-04 22:23:35 +0000763
Scott Micheldbac4cf2008-01-11 02:53:15 +0000764 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel8efdca42007-12-04 22:23:35 +0000765 LN->getSrcValue(), LN->getSrcValueOffset(),
766 LN->isVolatile(), LN->getAlignment());
767
Scott Michel8c2746e2008-12-04 17:16:59 +0000768#if 0 && !defined(NDEBUG)
Scott Michelf65c8f02008-11-19 15:24:16 +0000769 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
770 const SDValue &currentRoot = DAG.getRoot();
771
772 DAG.setRoot(result);
773 cerr << "------- CellSPU:LowerStore result:\n";
774 DAG.dump();
775 cerr << "-------\n";
776 DAG.setRoot(currentRoot);
777 }
778#endif
Scott Michelec8c82e2008-12-02 19:53:53 +0000779
Scott Michel8efdca42007-12-04 22:23:35 +0000780 return result;
781 /*UNREACHED*/
782 }
783 case ISD::PRE_INC:
784 case ISD::PRE_DEC:
785 case ISD::POST_INC:
786 case ISD::POST_DEC:
787 case ISD::LAST_INDEXED_MODE:
788 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
789 "UNINDEXED\n";
790 cerr << (unsigned) SN->getAddressingMode() << "\n";
791 abort();
792 /*NOTREACHED*/
793 }
794
Dan Gohman8181bd12008-07-27 21:46:04 +0000795 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000796}
797
798/// Generate the address of a constant pool entry.
Dan Gohman8181bd12008-07-27 21:46:04 +0000799static SDValue
800LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000801 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000802 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
803 Constant *C = CP->getConstVal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000804 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
805 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000806 const TargetMachine &TM = DAG.getTarget();
Scott Michel8efdca42007-12-04 22:23:35 +0000807
808 if (TM.getRelocationModel() == Reloc::Static) {
809 if (!ST->usingLargeMem()) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000810 // Just return the SDValue with the constant pool address in it.
Scott Michel394e26d2008-01-17 20:38:41 +0000811 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +0000812 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000813 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
814 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000815 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel8efdca42007-12-04 22:23:35 +0000816 }
817 }
818
819 assert(0 &&
Gabor Greife9f7f582008-08-31 15:37:04 +0000820 "LowerConstantPool: Relocation model other than static"
821 " not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000822 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000823}
824
Dan Gohman8181bd12008-07-27 21:46:04 +0000825static SDValue
826LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000827 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000828 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000829 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
830 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000831 const TargetMachine &TM = DAG.getTarget();
832
833 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel97872d32008-02-23 18:41:37 +0000834 if (!ST->usingLargeMem()) {
835 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
836 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000837 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
838 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000839 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
840 }
Scott Michel8efdca42007-12-04 22:23:35 +0000841 }
842
843 assert(0 &&
844 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000845 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000846}
847
Dan Gohman8181bd12008-07-27 21:46:04 +0000848static SDValue
849LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000850 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000851 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
852 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000853 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel8efdca42007-12-04 22:23:35 +0000854 const TargetMachine &TM = DAG.getTarget();
Dan Gohman8181bd12008-07-27 21:46:04 +0000855 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel4ec722e2008-07-16 17:17:29 +0000856
Scott Michel8efdca42007-12-04 22:23:35 +0000857 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michelf9f42e62008-01-29 02:16:57 +0000858 if (!ST->usingLargeMem()) {
859 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
860 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000861 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
862 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michelf9f42e62008-01-29 02:16:57 +0000863 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
864 }
Scott Michel8efdca42007-12-04 22:23:35 +0000865 } else {
866 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel5a6f17b2008-01-30 02:55:46 +0000867 << "supported.\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000868 abort();
869 /*NOTREACHED*/
870 }
871
Dan Gohman8181bd12008-07-27 21:46:04 +0000872 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000873}
874
875//! Custom lower i64 integer constants
876/*!
877 This code inserts all of the necessary juggling that needs to occur to load
878 a 64-bit constant into a register.
879 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000880static SDValue
881LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000882 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000883
884 if (VT == MVT::i64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000885 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
886 SDValue T = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michelc630c412008-11-24 17:11:17 +0000887 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000888 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +0000889 } else {
890 cerr << "LowerConstant: unhandled constant type "
Duncan Sands92c43912008-06-06 12:08:01 +0000891 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +0000892 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000893 abort();
894 /*NOTREACHED*/
895 }
896
Dan Gohman8181bd12008-07-27 21:46:04 +0000897 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000898}
899
Nate Begeman78125042008-02-14 18:43:04 +0000900//! Custom lower double precision floating point constants
Dan Gohman8181bd12008-07-27 21:46:04 +0000901static SDValue
902LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000903 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000904
Nate Begeman78125042008-02-14 18:43:04 +0000905 if (VT == MVT::f64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000906 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
907
908 assert((FP != 0) &&
909 "LowerConstantFP: Node is not ConstantFPSDNode");
910
Scott Michel11e88bb2007-12-19 20:15:47 +0000911 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel0718cd82008-12-01 17:56:02 +0000912 SDValue T = DAG.getConstant(dbits, MVT::i64);
913 SDValue Tvec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T);
914 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
915 DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64, Tvec));
Scott Michel8efdca42007-12-04 22:23:35 +0000916 }
917
Dan Gohman8181bd12008-07-27 21:46:04 +0000918 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000919}
920
Scott Michel33d73eb2008-11-21 02:56:16 +0000921//! Lower MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman8181bd12008-07-27 21:46:04 +0000922static SDValue
923LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel394e26d2008-01-17 20:38:41 +0000924{
Dan Gohman8181bd12008-07-27 21:46:04 +0000925 SDValue Cond = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +0000926 MVT CondVT = Cond.getValueType();
927 MVT CondNVT;
Scott Michel394e26d2008-01-17 20:38:41 +0000928
Scott Michel33d73eb2008-11-21 02:56:16 +0000929 if (CondVT == MVT::i8) {
930 CondNVT = MVT::i16;
Scott Michel394e26d2008-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 Gohman8181bd12008-07-27 21:46:04 +0000936 return SDValue(); // Unchanged
Scott Michel394e26d2008-01-17 20:38:41 +0000937}
938
Dan Gohman8181bd12008-07-27 21:46:04 +0000939static SDValue
940LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel8efdca42007-12-04 22:23:35 +0000941{
942 MachineFunction &MF = DAG.getMachineFunction();
943 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner1b989192007-12-31 04:13:23 +0000944 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michela313fb02008-10-30 01:51:48 +0000945 SmallVector<SDValue, 48> ArgValues;
Dan Gohman8181bd12008-07-27 21:46:04 +0000946 SDValue Root = Op.getOperand(0);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000947 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel8efdca42007-12-04 22:23:35 +0000948
949 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
950 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel4ec722e2008-07-16 17:17:29 +0000951
Scott Michel8efdca42007-12-04 22:23:35 +0000952 unsigned ArgOffset = SPUFrameInfo::minStackSize();
953 unsigned ArgRegIdx = 0;
954 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel4ec722e2008-07-16 17:17:29 +0000955
Duncan Sands92c43912008-06-06 12:08:01 +0000956 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +0000957
Scott Michel8efdca42007-12-04 22:23:35 +0000958 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greife9f7f582008-08-31 15:37:04 +0000959 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
960 ArgNo != e; ++ArgNo) {
Duncan Sands92c43912008-06-06 12:08:01 +0000961 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
962 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michela313fb02008-10-30 01:51:48 +0000963 SDValue ArgVal;
Scott Michel8efdca42007-12-04 22:23:35 +0000964
Scott Michela313fb02008-10-30 01:51:48 +0000965 if (ArgRegIdx < NumArgRegs) {
966 const TargetRegisterClass *ArgRegClass;
Scott Michel4ec722e2008-07-16 17:17:29 +0000967
Scott Michela313fb02008-10-30 01:51:48 +0000968 switch (ObjectVT.getSimpleVT()) {
969 default: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000970 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
971 << ObjectVT.getMVTString()
972 << "\n";
973 abort();
Scott Michela313fb02008-10-30 01:51:48 +0000974 }
975 case MVT::i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000976 ArgRegClass = &SPU::R8CRegClass;
977 break;
Scott Michela313fb02008-10-30 01:51:48 +0000978 case MVT::i16:
Scott Michel33d73eb2008-11-21 02:56:16 +0000979 ArgRegClass = &SPU::R16CRegClass;
980 break;
Scott Michela313fb02008-10-30 01:51:48 +0000981 case MVT::i32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000982 ArgRegClass = &SPU::R32CRegClass;
983 break;
Scott Michela313fb02008-10-30 01:51:48 +0000984 case MVT::i64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000985 ArgRegClass = &SPU::R64CRegClass;
986 break;
Scott Michela313fb02008-10-30 01:51:48 +0000987 case MVT::f32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000988 ArgRegClass = &SPU::R32FPRegClass;
989 break;
Scott Michela313fb02008-10-30 01:51:48 +0000990 case MVT::f64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000991 ArgRegClass = &SPU::R64FPRegClass;
992 break;
Scott Michela313fb02008-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 Michel33d73eb2008-11-21 02:56:16 +0000999 ArgRegClass = &SPU::VECREGRegClass;
1000 break;
Scott Michela313fb02008-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 Lattner60069452008-02-13 07:35:30 +00001011 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman8181bd12008-07-27 21:46:04 +00001012 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner60069452008-02-13 07:35:30 +00001013 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel8efdca42007-12-04 22:23:35 +00001014 ArgOffset += StackSlotSize;
1015 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001016
Scott Michel8efdca42007-12-04 22:23:35 +00001017 ArgValues.push_back(ArgVal);
Scott Michela313fb02008-10-30 01:51:48 +00001018 // Update the chain
1019 Root = ArgVal.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001020 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001021
Scott Michela313fb02008-10-30 01:51:48 +00001022 // vararg handling:
Scott Michel8efdca42007-12-04 22:23:35 +00001023 if (isVarArg) {
Scott Michela313fb02008-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 Michel8efdca42007-12-04 22:23:35 +00001030 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Michela313fb02008-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 Michel8efdca42007-12-04 22:23:35 +00001036 MemOps.push_back(Store);
Scott Michela313fb02008-10-30 01:51:48 +00001037
1038 // Increment address by stack slot size for the next stored argument
1039 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001040 }
1041 if (!MemOps.empty())
Scott Michela313fb02008-10-30 01:51:48 +00001042 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001043 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001044
Scott Michel8efdca42007-12-04 22:23:35 +00001045 ArgValues.push_back(Root);
Scott Michel4ec722e2008-07-16 17:17:29 +00001046
Scott Michel8efdca42007-12-04 22:23:35 +00001047 // Return the new list of results.
Duncan Sands42d7bb82008-12-01 11:41:29 +00001048 return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(),
1049 &ArgValues[0], ArgValues.size());
Scott Michel8efdca42007-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 Gohman8181bd12008-07-27 21:46:04 +00001054static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel5974f432008-11-11 03:06:06 +00001055 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel8efdca42007-12-04 22:23:35 +00001056 if (!C) return 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001057
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001058 int Addr = C->getZExtValue();
Scott Michel8efdca42007-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 Michel4ec722e2008-07-16 17:17:29 +00001062
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001063 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel8efdca42007-12-04 22:23:35 +00001064}
1065
1066static
Dan Gohman8181bd12008-07-27 21:46:04 +00001067SDValue
1068LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001069 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1070 SDValue Chain = TheCall->getChain();
Dan Gohman705e3f72008-09-13 01:54:27 +00001071 SDValue Callee = TheCall->getCallee();
1072 unsigned NumOps = TheCall->getNumArgs();
Scott Michel8efdca42007-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 Sands92c43912008-06-06 12:08:01 +00001078 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +00001079
Scott Michel8efdca42007-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 Michel4ec722e2008-07-16 17:17:29 +00001084
Scott Michel8efdca42007-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 Gohman8181bd12008-07-27 21:46:04 +00001088 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel4ec722e2008-07-16 17:17:29 +00001089
Scott Michel8efdca42007-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 Gohman8181bd12008-07-27 21:46:04 +00001096 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel8efdca42007-12-04 22:23:35 +00001097 // And the arguments passed on the stack
Dan Gohman8181bd12008-07-27 21:46:04 +00001098 SmallVector<SDValue, 8> MemOpChains;
Scott Michel8efdca42007-12-04 22:23:35 +00001099
1100 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001101 SDValue Arg = TheCall->getArg(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001102
Scott Michel8efdca42007-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 Gohman8181bd12008-07-27 21:46:04 +00001105 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel8efdca42007-12-04 22:23:35 +00001106 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1107
Duncan Sands92c43912008-06-06 12:08:01 +00001108 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-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 Michel5a6f17b2008-01-30 02:55:46 +00001117 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-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 Michel5a6f17b2008-01-30 02:55:46 +00001126 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001127 }
1128 break;
Scott Michele2641a12008-12-04 21:01:44 +00001129 case MVT::v2i64:
1130 case MVT::v2f64:
Scott Michel8efdca42007-12-04 22:23:35 +00001131 case MVT::v4f32:
1132 case MVT::v4i32:
1133 case MVT::v8i16:
1134 case MVT::v16i8:
1135 if (ArgRegIdx != NumArgRegs) {
1136 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1137 } else {
1138 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001139 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001140 }
1141 break;
1142 }
1143 }
1144
1145 // Update number of stack bytes actually used, insert a call sequence start
1146 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001147 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1148 true));
Scott Michel8efdca42007-12-04 22:23:35 +00001149
1150 if (!MemOpChains.empty()) {
1151 // Adjust the stack pointer for the stack arguments.
1152 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1153 &MemOpChains[0], MemOpChains.size());
1154 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001155
Scott Michel8efdca42007-12-04 22:23:35 +00001156 // Build a sequence of copy-to-reg nodes chained together with token chain
1157 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman8181bd12008-07-27 21:46:04 +00001158 SDValue InFlag;
Scott Michel8efdca42007-12-04 22:23:35 +00001159 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1160 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1161 InFlag);
1162 InFlag = Chain.getValue(1);
1163 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001164
Dan Gohman8181bd12008-07-27 21:46:04 +00001165 SmallVector<SDValue, 8> Ops;
Scott Michel8efdca42007-12-04 22:23:35 +00001166 unsigned CallOpc = SPUISD::CALL;
Scott Michel4ec722e2008-07-16 17:17:29 +00001167
Bill Wendlingfef06052008-09-16 21:48:12 +00001168 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1169 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1170 // node so that legalize doesn't hack it.
Scott Michel5974f432008-11-11 03:06:06 +00001171 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001172 GlobalValue *GV = G->getGlobal();
Duncan Sands92c43912008-06-06 12:08:01 +00001173 MVT CalleeVT = Callee.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001174 SDValue Zero = DAG.getConstant(0, PtrVT);
1175 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001176
Scott Micheldbac4cf2008-01-11 02:53:15 +00001177 if (!ST->usingLargeMem()) {
1178 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1179 // style calls, otherwise, external symbols are BRASL calls. This assumes
1180 // that declared/defined symbols are in the same compilation unit and can
1181 // be reached through PC-relative jumps.
1182 //
1183 // NOTE:
1184 // This may be an unsafe assumption for JIT and really large compilation
1185 // units.
1186 if (GV->isDeclaration()) {
1187 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1188 } else {
1189 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1190 }
Scott Michel8efdca42007-12-04 22:23:35 +00001191 } else {
Scott Micheldbac4cf2008-01-11 02:53:15 +00001192 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1193 // address pairs:
Scott Michelf9f42e62008-01-29 02:16:57 +00001194 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +00001195 }
Scott Michel5974f432008-11-11 03:06:06 +00001196 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendlingfef06052008-09-16 21:48:12 +00001197 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Micheldbac4cf2008-01-11 02:53:15 +00001198 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001199 // If this is an absolute destination address that appears to be a legal
1200 // local store address, use the munged value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001201 Callee = SDValue(Dest, 0);
Scott Micheldbac4cf2008-01-11 02:53:15 +00001202 }
Scott Michel8efdca42007-12-04 22:23:35 +00001203
1204 Ops.push_back(Chain);
1205 Ops.push_back(Callee);
Scott Michel4ec722e2008-07-16 17:17:29 +00001206
Scott Michel8efdca42007-12-04 22:23:35 +00001207 // Add argument registers to the end of the list so that they are known live
1208 // into the call.
1209 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel4ec722e2008-07-16 17:17:29 +00001210 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel8efdca42007-12-04 22:23:35 +00001211 RegsToPass[i].second.getValueType()));
Scott Michel4ec722e2008-07-16 17:17:29 +00001212
Gabor Greif1c80d112008-08-28 21:40:38 +00001213 if (InFlag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001214 Ops.push_back(InFlag);
Duncan Sands698842f2008-07-02 17:40:58 +00001215 // Returns a chain and a flag for retval copy to use.
1216 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1217 &Ops[0], Ops.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001218 InFlag = Chain.getValue(1);
1219
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001220 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1221 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman705e3f72008-09-13 01:54:27 +00001222 if (TheCall->getValueType(0) != MVT::Other)
Evan Cheng07322bb2008-02-05 22:44:06 +00001223 InFlag = Chain.getValue(1);
1224
Dan Gohman8181bd12008-07-27 21:46:04 +00001225 SDValue ResultVals[3];
Scott Michel8efdca42007-12-04 22:23:35 +00001226 unsigned NumResults = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001227
Scott Michel8efdca42007-12-04 22:23:35 +00001228 // If the call has results, copy the values out of the ret val registers.
Dan Gohman705e3f72008-09-13 01:54:27 +00001229 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001230 default: assert(0 && "Unexpected ret value!");
1231 case MVT::Other: break;
1232 case MVT::i32:
Dan Gohman705e3f72008-09-13 01:54:27 +00001233 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001234 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1235 ResultVals[0] = Chain.getValue(0);
1236 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1237 Chain.getValue(2)).getValue(1);
1238 ResultVals[1] = Chain.getValue(0);
1239 NumResults = 2;
Scott Michel8efdca42007-12-04 22:23:35 +00001240 } else {
1241 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1242 ResultVals[0] = Chain.getValue(0);
1243 NumResults = 1;
1244 }
Scott Michel8efdca42007-12-04 22:23:35 +00001245 break;
1246 case MVT::i64:
1247 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1248 ResultVals[0] = Chain.getValue(0);
1249 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001250 break;
1251 case MVT::f32:
1252 case MVT::f64:
Dan Gohman705e3f72008-09-13 01:54:27 +00001253 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001254 InFlag).getValue(1);
1255 ResultVals[0] = Chain.getValue(0);
1256 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001257 break;
1258 case MVT::v2f64:
Scott Michele2641a12008-12-04 21:01:44 +00001259 case MVT::v2i64:
Scott Michel8efdca42007-12-04 22:23:35 +00001260 case MVT::v4f32:
1261 case MVT::v4i32:
1262 case MVT::v8i16:
1263 case MVT::v16i8:
Dan Gohman705e3f72008-09-13 01:54:27 +00001264 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001265 InFlag).getValue(1);
1266 ResultVals[0] = Chain.getValue(0);
1267 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001268 break;
1269 }
Duncan Sands698842f2008-07-02 17:40:58 +00001270
Scott Michel8efdca42007-12-04 22:23:35 +00001271 // If the function returns void, just return the chain.
1272 if (NumResults == 0)
1273 return Chain;
Scott Michel4ec722e2008-07-16 17:17:29 +00001274
Scott Michel8efdca42007-12-04 22:23:35 +00001275 // Otherwise, merge everything together with a MERGE_VALUES node.
1276 ResultVals[NumResults++] = Chain;
Dan Gohman8181bd12008-07-27 21:46:04 +00001277 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif46bf5472008-08-26 22:36:50 +00001278 return Res.getValue(Op.getResNo());
Scott Michel8efdca42007-12-04 22:23:35 +00001279}
1280
Dan Gohman8181bd12008-07-27 21:46:04 +00001281static SDValue
1282LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel8efdca42007-12-04 22:23:35 +00001283 SmallVector<CCValAssign, 16> RVLocs;
1284 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1285 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1286 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greif1c80d112008-08-28 21:40:38 +00001287 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel4ec722e2008-07-16 17:17:29 +00001288
Scott Michel8efdca42007-12-04 22:23:35 +00001289 // If this is the first return lowered for this function, add the regs to the
1290 // liveout set for the function.
Chris Lattner1b989192007-12-31 04:13:23 +00001291 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001292 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner1b989192007-12-31 04:13:23 +00001293 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel8efdca42007-12-04 22:23:35 +00001294 }
1295
Dan Gohman8181bd12008-07-27 21:46:04 +00001296 SDValue Chain = Op.getOperand(0);
1297 SDValue Flag;
Scott Michel4ec722e2008-07-16 17:17:29 +00001298
Scott Michel8efdca42007-12-04 22:23:35 +00001299 // Copy the result values into the output registers.
1300 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1301 CCValAssign &VA = RVLocs[i];
1302 assert(VA.isRegLoc() && "Can only return in registers!");
1303 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1304 Flag = Chain.getValue(1);
1305 }
1306
Gabor Greif1c80d112008-08-28 21:40:38 +00001307 if (Flag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001308 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1309 else
1310 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1311}
1312
1313
1314//===----------------------------------------------------------------------===//
1315// Vector related lowering:
1316//===----------------------------------------------------------------------===//
1317
1318static ConstantSDNode *
1319getVecImm(SDNode *N) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001320 SDValue OpVal(0, 0);
Scott Michel4ec722e2008-07-16 17:17:29 +00001321
Scott Michel8efdca42007-12-04 22:23:35 +00001322 // Check to see if this buildvec has a single non-undef value in its elements.
1323 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1324 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greif1c80d112008-08-28 21:40:38 +00001325 if (OpVal.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +00001326 OpVal = N->getOperand(i);
1327 else if (OpVal != N->getOperand(i))
1328 return 0;
1329 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001330
Gabor Greif1c80d112008-08-28 21:40:38 +00001331 if (OpVal.getNode() != 0) {
Scott Michel5974f432008-11-11 03:06:06 +00001332 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001333 return CN;
1334 }
1335 }
1336
1337 return 0; // All UNDEF: use implicit def.; not Constant node
1338}
1339
1340/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1341/// and the value fits into an unsigned 18-bit constant, and if so, return the
1342/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001343SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001344 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001345 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001346 uint64_t Value = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001347 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001348 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001349 uint32_t upper = uint32_t(UValue >> 32);
1350 uint32_t lower = uint32_t(UValue);
1351 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001352 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001353 Value = Value >> 32;
1354 }
Scott Michel8efdca42007-12-04 22:23:35 +00001355 if (Value <= 0x3ffff)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001356 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001357 }
1358
Dan Gohman8181bd12008-07-27 21:46:04 +00001359 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001360}
1361
1362/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1363/// and the value fits into a signed 16-bit constant, and if so, return the
1364/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001365SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001366 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001367 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001368 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001369 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001370 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001371 uint32_t upper = uint32_t(UValue >> 32);
1372 uint32_t lower = uint32_t(UValue);
1373 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001374 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001375 Value = Value >> 32;
1376 }
Scott Michel6baba072008-03-05 23:02:02 +00001377 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001378 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001379 }
1380 }
1381
Dan Gohman8181bd12008-07-27 21:46:04 +00001382 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001383}
1384
1385/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1386/// and the value fits into a signed 10-bit constant, and if so, return the
1387/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001388SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001389 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001390 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001391 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001392 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001393 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001394 uint32_t upper = uint32_t(UValue >> 32);
1395 uint32_t lower = uint32_t(UValue);
1396 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001397 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001398 Value = Value >> 32;
1399 }
Scott Michel6baba072008-03-05 23:02:02 +00001400 if (isS10Constant(Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001401 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001402 }
1403
Dan Gohman8181bd12008-07-27 21:46:04 +00001404 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001405}
1406
1407/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1408/// and the value fits into a signed 8-bit constant, and if so, return the
1409/// constant.
1410///
1411/// @note: The incoming vector is v16i8 because that's the only way we can load
1412/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1413/// same value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001414SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001415 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001416 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001417 int Value = (int) CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001418 if (ValueType == MVT::i16
Scott Michel5a6f17b2008-01-30 02:55:46 +00001419 && Value <= 0xffff /* truncated from uint64_t */
1420 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001421 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001422 else if (ValueType == MVT::i8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001423 && (Value & 0xff) == Value)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001424 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001425 }
1426
Dan Gohman8181bd12008-07-27 21:46:04 +00001427 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001428}
1429
1430/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1431/// and the value fits into a signed 16-bit constant, and if so, return the
1432/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001433SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001434 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001435 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001436 uint64_t Value = CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001437 if ((ValueType == MVT::i32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001438 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1439 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001440 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001441 }
1442
Dan Gohman8181bd12008-07-27 21:46:04 +00001443 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001444}
1445
1446/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001447SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001448 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001449 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001450 }
1451
Dan Gohman8181bd12008-07-27 21:46:04 +00001452 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001453}
1454
1455/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001456SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001457 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001458 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001459 }
1460
Dan Gohman8181bd12008-07-27 21:46:04 +00001461 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001462}
1463
1464// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001465// UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001466// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1467// zero. Return true if this is not an array of constants, false if it is.
1468//
1469static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1470 uint64_t UndefBits[2]) {
1471 // Start with zero'd results.
1472 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001473
Duncan Sands92c43912008-06-06 12:08:01 +00001474 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel8efdca42007-12-04 22:23:35 +00001475 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001476 SDValue OpVal = BV->getOperand(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001477
Scott Michel8efdca42007-12-04 22:23:35 +00001478 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1479 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1480
1481 uint64_t EltBits = 0;
1482 if (OpVal.getOpcode() == ISD::UNDEF) {
1483 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1484 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1485 continue;
Scott Michel5974f432008-11-11 03:06:06 +00001486 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001487 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel5974f432008-11-11 03:06:06 +00001488 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001489 const APFloat &apf = CN->getValueAPF();
1490 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001491 ? FloatToBits(apf.convertToFloat())
1492 : DoubleToBits(apf.convertToDouble()));
Scott Michel8efdca42007-12-04 22:23:35 +00001493 } else {
1494 // Nonconstant element.
1495 return true;
1496 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001497
Scott Michel8efdca42007-12-04 22:23:35 +00001498 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1499 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001500
1501 //printf("%llx %llx %llx %llx\n",
Scott Michel8efdca42007-12-04 22:23:35 +00001502 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1503 return false;
1504}
1505
1506/// If this is a splat (repetition) of a value across the whole vector, return
1507/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel4ec722e2008-07-16 17:17:29 +00001508/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel8efdca42007-12-04 22:23:35 +00001509/// SplatSize = 1 byte.
Scott Michel4ec722e2008-07-16 17:17:29 +00001510static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel8efdca42007-12-04 22:23:35 +00001511 const uint64_t Undef128[2],
Scott Michel5a6f17b2008-01-30 02:55:46 +00001512 int MinSplatBits,
Scott Michel8efdca42007-12-04 22:23:35 +00001513 uint64_t &SplatBits, uint64_t &SplatUndef,
1514 int &SplatSize) {
1515 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1516 // the same as the lower 64-bits, ignoring undefs.
1517 uint64_t Bits64 = Bits128[0] | Bits128[1];
1518 uint64_t Undef64 = Undef128[0] & Undef128[1];
1519 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1520 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1521 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1522 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1523
1524 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1525 if (MinSplatBits < 64) {
Scott Michel4ec722e2008-07-16 17:17:29 +00001526
Scott Michel8efdca42007-12-04 22:23:35 +00001527 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1528 // undefs.
1529 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001530 if (MinSplatBits < 32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001531
Scott Michel5a6f17b2008-01-30 02:55:46 +00001532 // If the top 16-bits are different than the lower 16-bits, ignoring
1533 // undefs, we have an i32 splat.
1534 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1535 if (MinSplatBits < 16) {
1536 // If the top 8-bits are different than the lower 8-bits, ignoring
1537 // undefs, we have an i16 splat.
Gabor Greife9f7f582008-08-31 15:37:04 +00001538 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1539 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001540 // Otherwise, we have an 8-bit splat.
1541 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1542 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1543 SplatSize = 1;
1544 return true;
1545 }
1546 } else {
1547 SplatBits = Bits16;
1548 SplatUndef = Undef16;
1549 SplatSize = 2;
1550 return true;
1551 }
1552 }
1553 } else {
1554 SplatBits = Bits32;
1555 SplatUndef = Undef32;
1556 SplatSize = 4;
1557 return true;
1558 }
Scott Michel8efdca42007-12-04 22:23:35 +00001559 }
1560 } else {
1561 SplatBits = Bits128[0];
1562 SplatUndef = Undef128[0];
1563 SplatSize = 8;
1564 return true;
1565 }
1566 }
1567
1568 return false; // Can't be a splat if two pieces don't match.
1569}
1570
1571// If this is a case we can't handle, return null and let the default
1572// expansion code take care of it. If we CAN select this case, and if it
1573// selects to a single instruction, return Op. Otherwise, if we can codegen
1574// this case more efficiently than a constant pool load, lower it to the
1575// sequence of ops that should be used.
Dan Gohman8181bd12008-07-27 21:46:04 +00001576static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001577 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00001578 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001579 // UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001580 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel4ec722e2008-07-16 17:17:29 +00001581 // zero.
Scott Michel8efdca42007-12-04 22:23:35 +00001582 uint64_t VectorBits[2];
1583 uint64_t UndefBits[2];
1584 uint64_t SplatBits, SplatUndef;
1585 int SplatSize;
Gabor Greif1c80d112008-08-28 21:40:38 +00001586 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel8efdca42007-12-04 22:23:35 +00001587 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00001588 VT.getVectorElementType().getSizeInBits(),
Scott Michel8efdca42007-12-04 22:23:35 +00001589 SplatBits, SplatUndef, SplatSize))
Dan Gohman8181bd12008-07-27 21:46:04 +00001590 return SDValue(); // Not a constant vector, not a splat.
Scott Michel4ec722e2008-07-16 17:17:29 +00001591
Duncan Sands92c43912008-06-06 12:08:01 +00001592 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001593 default:
1594 case MVT::v4f32: {
1595 uint32_t Value32 = SplatBits;
1596 assert(SplatSize == 4
Scott Michel5a6f17b2008-01-30 02:55:46 +00001597 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel8efdca42007-12-04 22:23:35 +00001598 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001599 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001600 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001601 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001602 break;
1603 }
1604 case MVT::v2f64: {
1605 uint64_t f64val = SplatBits;
1606 assert(SplatSize == 8
Scott Michelc630c412008-11-24 17:11:17 +00001607 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel8efdca42007-12-04 22:23:35 +00001608 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001609 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001610 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001611 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001612 break;
1613 }
1614 case MVT::v16i8: {
1615 // 8-bit constants have to be expanded to 16-bits
1616 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman8181bd12008-07-27 21:46:04 +00001617 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001618 for (int i = 0; i < 8; ++i)
1619 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1620 return DAG.getNode(ISD::BIT_CONVERT, VT,
1621 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1622 }
1623 case MVT::v8i16: {
1624 unsigned short Value16;
Scott Michel4ec722e2008-07-16 17:17:29 +00001625 if (SplatSize == 2)
Scott Michel8efdca42007-12-04 22:23:35 +00001626 Value16 = (unsigned short) (SplatBits & 0xffff);
1627 else
1628 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman8181bd12008-07-27 21:46:04 +00001629 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1630 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001631 for (int i = 0; i < 8; ++i) Ops[i] = T;
1632 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1633 }
1634 case MVT::v4i32: {
1635 unsigned int Value = SplatBits;
Dan Gohman8181bd12008-07-27 21:46:04 +00001636 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel8efdca42007-12-04 22:23:35 +00001637 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1638 }
1639 case MVT::v2i64: {
1640 uint64_t val = SplatBits;
1641 uint32_t upper = uint32_t(val >> 32);
1642 uint32_t lower = uint32_t(val);
1643
Scott Michelbcc7b672008-03-06 04:02:54 +00001644 if (upper == lower) {
1645 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman8181bd12008-07-27 21:46:04 +00001646 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michelbcc7b672008-03-06 04:02:54 +00001647 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michel6baba072008-03-05 23:02:02 +00001648 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +00001649 SDValue LO32;
1650 SDValue HI32;
1651 SmallVector<SDValue, 16> ShufBytes;
1652 SDValue Result;
Scott Michel8efdca42007-12-04 22:23:35 +00001653 bool upper_special, lower_special;
1654
1655 // NOTE: This code creates common-case shuffle masks that can be easily
1656 // detected as common expressions. It is not attempting to create highly
1657 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1658
1659 // Detect if the upper or lower half is a special shuffle mask pattern:
Scott Michelc630c412008-11-24 17:11:17 +00001660 upper_special = (upper == 0||upper == 0xffffffff||upper == 0x80000000);
1661 lower_special = (lower == 0||lower == 0xffffffff||lower == 0x80000000);
Scott Michel8efdca42007-12-04 22:23:35 +00001662
1663 // Create lower vector if not a special pattern
1664 if (!lower_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001665 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001666 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1667 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1668 LO32C, LO32C, LO32C, LO32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001669 }
1670
1671 // Create upper vector if not a special pattern
1672 if (!upper_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001673 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001674 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1675 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1676 HI32C, HI32C, HI32C, HI32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001677 }
1678
1679 // If either upper or lower are special, then the two input operands are
1680 // the same (basically, one of them is a "don't care")
1681 if (lower_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001682 LO32 = HI32;
Scott Michel8efdca42007-12-04 22:23:35 +00001683 if (upper_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001684 HI32 = LO32;
Scott Michel8efdca42007-12-04 22:23:35 +00001685 if (lower_special && upper_special) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001686 // Unhappy situation... both upper and lower are special, so punt with
1687 // a target constant:
Dan Gohman8181bd12008-07-27 21:46:04 +00001688 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001689 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel8efdca42007-12-04 22:23:35 +00001690 Zero, Zero);
1691 }
1692
1693 for (int i = 0; i < 4; ++i) {
Scott Michel67224b22008-06-02 22:18:03 +00001694 uint64_t val = 0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001695 for (int j = 0; j < 4; ++j) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001696 SDValue V;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001697 bool process_upper, process_lower;
Scott Michel67224b22008-06-02 22:18:03 +00001698 val <<= 8;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001699 process_upper = (upper_special && (i & 1) == 0);
1700 process_lower = (lower_special && (i & 1) == 1);
Scott Michel8efdca42007-12-04 22:23:35 +00001701
Scott Michel5a6f17b2008-01-30 02:55:46 +00001702 if (process_upper || process_lower) {
1703 if ((process_upper && upper == 0)
1704 || (process_lower && lower == 0))
Scott Michel67224b22008-06-02 22:18:03 +00001705 val |= 0x80;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001706 else if ((process_upper && upper == 0xffffffff)
1707 || (process_lower && lower == 0xffffffff))
Scott Michel67224b22008-06-02 22:18:03 +00001708 val |= 0xc0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001709 else if ((process_upper && upper == 0x80000000)
1710 || (process_lower && lower == 0x80000000))
Scott Michel67224b22008-06-02 22:18:03 +00001711 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001712 } else
Scott Michel67224b22008-06-02 22:18:03 +00001713 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001714 }
Scott Michel67224b22008-06-02 22:18:03 +00001715
1716 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001717 }
1718
1719 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel67224b22008-06-02 22:18:03 +00001720 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001721 &ShufBytes[0], ShufBytes.size()));
Scott Michel8efdca42007-12-04 22:23:35 +00001722 }
1723 }
1724 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001725
Dan Gohman8181bd12008-07-27 21:46:04 +00001726 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001727}
1728
1729/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1730/// which the Cell can operate. The code inspects V3 to ascertain whether the
1731/// permutation vector, V3, is monotonically increasing with one "exception"
1732/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel56a125e2008-11-22 23:50:42 +00001733/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel8efdca42007-12-04 22:23:35 +00001734/// In either case, the net result is going to eventually invoke SHUFB to
1735/// permute/shuffle the bytes from V1 and V2.
1736/// \note
Scott Michel56a125e2008-11-22 23:50:42 +00001737/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel8efdca42007-12-04 22:23:35 +00001738/// control word for byte/halfword/word insertion. This takes care of a single
1739/// element move from V2 into V1.
1740/// \note
1741/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman8181bd12008-07-27 21:46:04 +00001742static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1743 SDValue V1 = Op.getOperand(0);
1744 SDValue V2 = Op.getOperand(1);
1745 SDValue PermMask = Op.getOperand(2);
Scott Michel4ec722e2008-07-16 17:17:29 +00001746
Scott Michel8efdca42007-12-04 22:23:35 +00001747 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel4ec722e2008-07-16 17:17:29 +00001748
Scott Michel8efdca42007-12-04 22:23:35 +00001749 // If we have a single element being moved from V1 to V2, this can be handled
1750 // using the C*[DX] compute mask instructions, but the vector elements have
1751 // to be monotonically increasing with one exception element.
Scott Michele2641a12008-12-04 21:01:44 +00001752 MVT VecVT = V1.getValueType();
1753 MVT EltVT = VecVT.getVectorElementType();
Scott Michel8efdca42007-12-04 22:23:35 +00001754 unsigned EltsFromV2 = 0;
1755 unsigned V2Elt = 0;
1756 unsigned V2EltIdx0 = 0;
1757 unsigned CurrElt = 0;
Scott Michele2641a12008-12-04 21:01:44 +00001758 unsigned MaxElts = VecVT.getVectorNumElements();
1759 unsigned PrevElt = 0;
1760 unsigned V0Elt = 0;
Scott Michel8efdca42007-12-04 22:23:35 +00001761 bool monotonic = true;
Scott Michele2641a12008-12-04 21:01:44 +00001762 bool rotate = true;
1763
1764 if (EltVT == MVT::i8) {
Scott Michel8efdca42007-12-04 22:23:35 +00001765 V2EltIdx0 = 16;
Scott Michele2641a12008-12-04 21:01:44 +00001766 } else if (EltVT == MVT::i16) {
Scott Michel8efdca42007-12-04 22:23:35 +00001767 V2EltIdx0 = 8;
Scott Michele2641a12008-12-04 21:01:44 +00001768 } else if (EltVT == MVT::i32 || EltVT == MVT::f32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001769 V2EltIdx0 = 4;
Scott Michele2641a12008-12-04 21:01:44 +00001770 } else if (EltVT == MVT::i64 || EltVT == MVT::f64) {
1771 V2EltIdx0 = 2;
1772 } else
Scott Michel8efdca42007-12-04 22:23:35 +00001773 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1774
Scott Michele2641a12008-12-04 21:01:44 +00001775 for (unsigned i = 0; i != PermMask.getNumOperands(); ++i) {
1776 if (PermMask.getOperand(i).getOpcode() != ISD::UNDEF) {
1777 unsigned SrcElt = cast<ConstantSDNode > (PermMask.getOperand(i))->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001778
Scott Michele2641a12008-12-04 21:01:44 +00001779 if (monotonic) {
1780 if (SrcElt >= V2EltIdx0) {
1781 if (1 >= (++EltsFromV2)) {
1782 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1783 }
1784 } else if (CurrElt != SrcElt) {
1785 monotonic = false;
1786 }
1787
1788 ++CurrElt;
1789 }
1790
1791 if (rotate) {
1792 if (PrevElt > 0 && SrcElt < MaxElts) {
1793 if ((PrevElt == SrcElt - 1)
1794 || (PrevElt == MaxElts - 1 && SrcElt == 0)) {
1795 PrevElt = SrcElt;
1796 if (SrcElt == 0)
1797 V0Elt = i;
1798 } else {
1799 rotate = false;
1800 }
1801 } else if (PrevElt == 0) {
1802 // First time through, need to keep track of previous element
1803 PrevElt = SrcElt;
1804 } else {
1805 // This isn't a rotation, takes elements from vector 2
1806 rotate = false;
1807 }
1808 }
Scott Michel8efdca42007-12-04 22:23:35 +00001809 }
Scott Michel8efdca42007-12-04 22:23:35 +00001810 }
1811
1812 if (EltsFromV2 == 1 && monotonic) {
1813 // Compute mask and shuffle
1814 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001815 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1816 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands92c43912008-06-06 12:08:01 +00001817 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00001818 // Initialize temporary register to 0
Dan Gohman8181bd12008-07-27 21:46:04 +00001819 SDValue InitTempReg =
Scott Michel8efdca42007-12-04 22:23:35 +00001820 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel56a125e2008-11-22 23:50:42 +00001821 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman8181bd12008-07-27 21:46:04 +00001822 SDValue ShufMaskOp =
Scott Michel0718cd82008-12-01 17:56:02 +00001823 DAG.getNode(SPUISD::SHUFFLE_MASK, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001824 DAG.getTargetConstant(V2Elt, MVT::i32),
1825 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +00001826 // Use shuffle mask in SHUFB synthetic instruction:
1827 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
Scott Michele2641a12008-12-04 21:01:44 +00001828 } else if (rotate) {
1829 int rotamt = (MaxElts - V0Elt) * EltVT.getSizeInBits()/8;
1830
1831 return DAG.getNode(SPUISD::ROTBYTES_LEFT, V1.getValueType(),
1832 V1, DAG.getConstant(rotamt, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001833 } else {
Gabor Greife9f7f582008-08-31 15:37:04 +00001834 // Convert the SHUFFLE_VECTOR mask's input element units to the
1835 // actual bytes.
Duncan Sands92c43912008-06-06 12:08:01 +00001836 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel4ec722e2008-07-16 17:17:29 +00001837
Dan Gohman8181bd12008-07-27 21:46:04 +00001838 SmallVector<SDValue, 16> ResultMask;
Scott Michel8efdca42007-12-04 22:23:35 +00001839 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1840 unsigned SrcElt;
1841 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001842 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001843 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001844 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel4ec722e2008-07-16 17:17:29 +00001845
Scott Michel97872d32008-02-23 18:41:37 +00001846 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001847 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1848 MVT::i8));
Scott Michel8efdca42007-12-04 22:23:35 +00001849 }
1850 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001851
Dan Gohman8181bd12008-07-27 21:46:04 +00001852 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel0718cd82008-12-01 17:56:02 +00001853 &ResultMask[0], ResultMask.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001854 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1855 }
1856}
1857
Dan Gohman8181bd12008-07-27 21:46:04 +00001858static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1859 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel8efdca42007-12-04 22:23:35 +00001860
Gabor Greif1c80d112008-08-28 21:40:38 +00001861 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel8efdca42007-12-04 22:23:35 +00001862 // For a constant, build the appropriate constant vector, which will
1863 // eventually simplify to a vector register load.
1864
Gabor Greif1c80d112008-08-28 21:40:38 +00001865 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman8181bd12008-07-27 21:46:04 +00001866 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands92c43912008-06-06 12:08:01 +00001867 MVT VT;
Scott Michel8efdca42007-12-04 22:23:35 +00001868 size_t n_copies;
1869
1870 // Create a constant vector:
Duncan Sands92c43912008-06-06 12:08:01 +00001871 switch (Op.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001872 default: assert(0 && "Unexpected constant value type in "
Scott Michel5a6f17b2008-01-30 02:55:46 +00001873 "LowerSCALAR_TO_VECTOR");
Scott Michel8efdca42007-12-04 22:23:35 +00001874 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1875 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1876 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1877 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1878 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1879 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1880 }
1881
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001882 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel8efdca42007-12-04 22:23:35 +00001883 for (size_t j = 0; j < n_copies; ++j)
1884 ConstVecValues.push_back(CValue);
1885
1886 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001887 &ConstVecValues[0], ConstVecValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001888 } else {
1889 // Otherwise, copy the value from one register to another:
Duncan Sands92c43912008-06-06 12:08:01 +00001890 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001891 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1892 case MVT::i8:
1893 case MVT::i16:
1894 case MVT::i32:
1895 case MVT::i64:
1896 case MVT::f32:
1897 case MVT::f64:
1898 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1899 }
1900 }
1901
Dan Gohman8181bd12008-07-27 21:46:04 +00001902 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001903}
1904
Dan Gohman8181bd12008-07-27 21:46:04 +00001905static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001906 switch (Op.getValueType().getSimpleVT()) {
1907 default:
1908 cerr << "CellSPU: Unknown vector multiplication, got "
1909 << Op.getValueType().getMVTString()
1910 << "\n";
1911 abort();
1912 /*NOTREACHED*/
1913
Scott Michel8efdca42007-12-04 22:23:35 +00001914 case MVT::v4i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001915 SDValue rA = Op.getOperand(0);
1916 SDValue rB = Op.getOperand(1);
1917 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1918 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1919 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1920 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel8efdca42007-12-04 22:23:35 +00001921
1922 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1923 break;
1924 }
1925
1926 // Multiply two v8i16 vectors (pipeline friendly version):
1927 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1928 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1929 // c) Use SELB to select upper and lower halves from the intermediate results
1930 //
Scott Michel67224b22008-06-02 22:18:03 +00001931 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel8efdca42007-12-04 22:23:35 +00001932 // dual-issue. This code does manage to do this, even if it's a little on
1933 // the wacky side
1934 case MVT::v8i16: {
1935 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001936 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman8181bd12008-07-27 21:46:04 +00001937 SDValue Chain = Op.getOperand(0);
1938 SDValue rA = Op.getOperand(0);
1939 SDValue rB = Op.getOperand(1);
Chris Lattner1b989192007-12-31 04:13:23 +00001940 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1941 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00001942
Dan Gohman8181bd12008-07-27 21:46:04 +00001943 SDValue FSMBOp =
Scott Michel8efdca42007-12-04 22:23:35 +00001944 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel67224b22008-06-02 22:18:03 +00001945 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001946 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel8efdca42007-12-04 22:23:35 +00001947
Dan Gohman8181bd12008-07-27 21:46:04 +00001948 SDValue HHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001949 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001950 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001951
Dan Gohman8181bd12008-07-27 21:46:04 +00001952 SDValue HHProd_v4i32 =
Scott Michel8efdca42007-12-04 22:23:35 +00001953 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001954 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001955
1956 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001957 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1958 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1959 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1960 HHProd_v4i32,
1961 DAG.getConstant(16, MVT::i16))),
1962 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001963 }
1964
1965 // This M00sE is N@stI! (apologies to Monty Python)
1966 //
1967 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1968 // is to break it all apart, sign extend, and reassemble the various
1969 // intermediate products.
1970 case MVT::v16i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001971 SDValue rA = Op.getOperand(0);
1972 SDValue rB = Op.getOperand(1);
1973 SDValue c8 = DAG.getConstant(8, MVT::i32);
1974 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001975
Dan Gohman8181bd12008-07-27 21:46:04 +00001976 SDValue LLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001977 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001978 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1979 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001980
Dan Gohman8181bd12008-07-27 21:46:04 +00001981 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001982
Dan Gohman8181bd12008-07-27 21:46:04 +00001983 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001984
Dan Gohman8181bd12008-07-27 21:46:04 +00001985 SDValue LHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001986 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001987 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001988
Dan Gohman8181bd12008-07-27 21:46:04 +00001989 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001990 DAG.getConstant(0x2222, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001991
Dan Gohman8181bd12008-07-27 21:46:04 +00001992 SDValue LoProdParts =
Scott Michel97872d32008-02-23 18:41:37 +00001993 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1994 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1995 LLProd, LHProd, FSMBmask));
Scott Michel8efdca42007-12-04 22:23:35 +00001996
Dan Gohman8181bd12008-07-27 21:46:04 +00001997 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001998
Dan Gohman8181bd12008-07-27 21:46:04 +00001999 SDValue LoProd =
Scott Michel8efdca42007-12-04 22:23:35 +00002000 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michel97872d32008-02-23 18:41:37 +00002001 LoProdParts,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002002 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2003 LoProdMask, LoProdMask,
2004 LoProdMask, LoProdMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002005
Dan Gohman8181bd12008-07-27 21:46:04 +00002006 SDValue rAH =
Scott Michel8efdca42007-12-04 22:23:35 +00002007 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002008 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002009
Dan Gohman8181bd12008-07-27 21:46:04 +00002010 SDValue rBH =
Scott Michel8efdca42007-12-04 22:23:35 +00002011 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002012 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002013
Dan Gohman8181bd12008-07-27 21:46:04 +00002014 SDValue HLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00002015 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002016 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2017 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel8efdca42007-12-04 22:23:35 +00002018
Dan Gohman8181bd12008-07-27 21:46:04 +00002019 SDValue HHProd_1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002020 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002021 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00002022 DAG.getNode(SPUISD::VEC_SRA,
2023 MVT::v4i32, rAH, c8)),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002024 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00002025 DAG.getNode(SPUISD::VEC_SRA,
2026 MVT::v4i32, rBH, c8)));
Scott Michel8efdca42007-12-04 22:23:35 +00002027
Dan Gohman8181bd12008-07-27 21:46:04 +00002028 SDValue HHProd =
Scott Michel97872d32008-02-23 18:41:37 +00002029 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2030 HLProd,
2031 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2032 FSMBmask);
Scott Michel8efdca42007-12-04 22:23:35 +00002033
Dan Gohman8181bd12008-07-27 21:46:04 +00002034 SDValue HiProd =
Scott Michel97872d32008-02-23 18:41:37 +00002035 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002036
2037 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002038 DAG.getNode(ISD::OR, MVT::v4i32,
2039 LoProd, HiProd));
Scott Michel8efdca42007-12-04 22:23:35 +00002040 }
Scott Michel8efdca42007-12-04 22:23:35 +00002041 }
2042
Dan Gohman8181bd12008-07-27 21:46:04 +00002043 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002044}
2045
Dan Gohman8181bd12008-07-27 21:46:04 +00002046static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00002047 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002048 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002049
Dan Gohman8181bd12008-07-27 21:46:04 +00002050 SDValue A = Op.getOperand(0);
2051 SDValue B = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002052 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002053
2054 unsigned VRegBR, VRegC;
2055
2056 if (VT == MVT::f32) {
Chris Lattner1b989192007-12-31 04:13:23 +00002057 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2058 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002059 } else {
Chris Lattner1b989192007-12-31 04:13:23 +00002060 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2061 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002062 }
2063 // TODO: make sure we're feeding FPInterp the right arguments
2064 // Right now: fi B, frest(B)
2065
2066 // Computes BRcpl =
2067 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman8181bd12008-07-27 21:46:04 +00002068 SDValue BRcpl =
Scott Michel4ec722e2008-07-16 17:17:29 +00002069 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2070 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002071 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002072
Scott Michel8efdca42007-12-04 22:23:35 +00002073 // Computes A * BRcpl and stores in a temporary register
Dan Gohman8181bd12008-07-27 21:46:04 +00002074 SDValue AxBRcpl =
Scott Michel8efdca42007-12-04 22:23:35 +00002075 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel4ec722e2008-07-16 17:17:29 +00002076 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002077 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel8efdca42007-12-04 22:23:35 +00002078 // What's the Chain variable do? It's magic!
2079 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel4ec722e2008-07-16 17:17:29 +00002080
2081 return DAG.getNode(ISD::FADD, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002082 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel4ec722e2008-07-16 17:17:29 +00002083 DAG.getNode(ISD::FMUL, VT,
2084 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002085 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel4ec722e2008-07-16 17:17:29 +00002086 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002087 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel8efdca42007-12-04 22:23:35 +00002088}
2089
Dan Gohman8181bd12008-07-27 21:46:04 +00002090static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002091 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002092 SDValue N = Op.getOperand(0);
2093 SDValue Elt = Op.getOperand(1);
Scott Michel56a125e2008-11-22 23:50:42 +00002094 SDValue retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002095
Scott Michel56a125e2008-11-22 23:50:42 +00002096 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
2097 // Constant argument:
2098 int EltNo = (int) C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002099
Scott Michel56a125e2008-11-22 23:50:42 +00002100 // sanity checks:
2101 if (VT == MVT::i8 && EltNo >= 16)
2102 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2103 else if (VT == MVT::i16 && EltNo >= 8)
2104 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2105 else if (VT == MVT::i32 && EltNo >= 4)
2106 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2107 else if (VT == MVT::i64 && EltNo >= 2)
2108 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel8efdca42007-12-04 22:23:35 +00002109
Scott Michel56a125e2008-11-22 23:50:42 +00002110 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2111 // i32 and i64: Element 0 is the preferred slot
Scott Michelc630c412008-11-24 17:11:17 +00002112 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel56a125e2008-11-22 23:50:42 +00002113 }
Scott Michel8efdca42007-12-04 22:23:35 +00002114
Scott Michel56a125e2008-11-22 23:50:42 +00002115 // Need to generate shuffle mask and extract:
2116 int prefslot_begin = -1, prefslot_end = -1;
2117 int elt_byte = EltNo * VT.getSizeInBits() / 8;
2118
2119 switch (VT.getSimpleVT()) {
2120 default:
2121 assert(false && "Invalid value type!");
2122 case MVT::i8: {
2123 prefslot_begin = prefslot_end = 3;
2124 break;
2125 }
2126 case MVT::i16: {
2127 prefslot_begin = 2; prefslot_end = 3;
2128 break;
2129 }
2130 case MVT::i32:
2131 case MVT::f32: {
2132 prefslot_begin = 0; prefslot_end = 3;
2133 break;
2134 }
2135 case MVT::i64:
2136 case MVT::f64: {
2137 prefslot_begin = 0; prefslot_end = 7;
2138 break;
2139 }
2140 }
2141
2142 assert(prefslot_begin != -1 && prefslot_end != -1 &&
2143 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
2144
2145 unsigned int ShufBytes[16];
2146 for (int i = 0; i < 16; ++i) {
2147 // zero fill uppper part of preferred slot, don't care about the
2148 // other slots:
2149 unsigned int mask_val;
2150 if (i <= prefslot_end) {
2151 mask_val =
2152 ((i < prefslot_begin)
2153 ? 0x80
2154 : elt_byte + (i - prefslot_begin));
2155
2156 ShufBytes[i] = mask_val;
2157 } else
2158 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
2159 }
2160
2161 SDValue ShufMask[4];
2162 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
Scott Michele2641a12008-12-04 21:01:44 +00002163 unsigned bidx = i * 4;
Scott Michel56a125e2008-11-22 23:50:42 +00002164 unsigned int bits = ((ShufBytes[bidx] << 24) |
2165 (ShufBytes[bidx+1] << 16) |
2166 (ShufBytes[bidx+2] << 8) |
2167 ShufBytes[bidx+3]);
2168 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
2169 }
2170
2171 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2172 &ShufMask[0],
2173 sizeof(ShufMask) / sizeof(ShufMask[0]));
2174
Scott Michelc630c412008-11-24 17:11:17 +00002175 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel56a125e2008-11-22 23:50:42 +00002176 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2177 N, N, ShufMaskVec));
2178 } else {
2179 // Variable index: Rotate the requested element into slot 0, then replicate
2180 // slot 0 across the vector
2181 MVT VecVT = N.getValueType();
2182 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2183 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2184 abort();
2185 }
2186
2187 // Make life easier by making sure the index is zero-extended to i32
2188 if (Elt.getValueType() != MVT::i32)
2189 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2190
2191 // Scale the index to a bit/byte shift quantity
2192 APInt scaleFactor =
Scott Michelc630c412008-11-24 17:11:17 +00002193 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2194 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel56a125e2008-11-22 23:50:42 +00002195 SDValue vecShift;
Scott Michel56a125e2008-11-22 23:50:42 +00002196
Scott Michelc630c412008-11-24 17:11:17 +00002197 if (scaleShift > 0) {
2198 // Scale the shift factor:
Scott Michel56a125e2008-11-22 23:50:42 +00002199 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel0718cd82008-12-01 17:56:02 +00002200 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel56a125e2008-11-22 23:50:42 +00002201 }
2202
Scott Michelc630c412008-11-24 17:11:17 +00002203 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2204
2205 // Replicate the bytes starting at byte 0 across the entire vector (for
2206 // consistency with the notion of a unified register set)
Scott Michel56a125e2008-11-22 23:50:42 +00002207 SDValue replicate;
2208
2209 switch (VT.getSimpleVT()) {
2210 default:
2211 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2212 abort();
2213 /*NOTREACHED*/
2214 case MVT::i8: {
Scott Michelc630c412008-11-24 17:11:17 +00002215 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002216 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2217 factor, factor);
2218 break;
2219 }
2220 case MVT::i16: {
Scott Michelc630c412008-11-24 17:11:17 +00002221 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002222 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2223 factor, factor);
2224 break;
2225 }
2226 case MVT::i32:
2227 case MVT::f32: {
2228 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2229 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2230 factor, factor);
2231 break;
2232 }
2233 case MVT::i64:
2234 case MVT::f64: {
2235 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2236 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2237 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2238 loFactor, hiFactor);
2239 break;
2240 }
2241 }
2242
Scott Michelc630c412008-11-24 17:11:17 +00002243 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel0718cd82008-12-01 17:56:02 +00002244 DAG.getNode(SPUISD::SHUFB, VecVT,
2245 vecShift, vecShift, replicate));
Scott Michel8efdca42007-12-04 22:23:35 +00002246 }
2247
Scott Michel56a125e2008-11-22 23:50:42 +00002248 return retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002249}
2250
Dan Gohman8181bd12008-07-27 21:46:04 +00002251static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2252 SDValue VecOp = Op.getOperand(0);
2253 SDValue ValOp = Op.getOperand(1);
2254 SDValue IdxOp = Op.getOperand(2);
Duncan Sands92c43912008-06-06 12:08:01 +00002255 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002256
2257 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2258 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2259
Duncan Sands92c43912008-06-06 12:08:01 +00002260 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel0718cd82008-12-01 17:56:02 +00002261 // Use $sp ($1) because it's always 16-byte aligned and it's available:
2262 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
2263 DAG.getRegister(SPU::R1, PtrVT),
2264 DAG.getConstant(CN->getSExtValue(), PtrVT));
2265 SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, VT, Pointer);
Scott Michel8efdca42007-12-04 22:23:35 +00002266
Dan Gohman8181bd12008-07-27 21:46:04 +00002267 SDValue result =
Scott Michel8efdca42007-12-04 22:23:35 +00002268 DAG.getNode(SPUISD::SHUFB, VT,
2269 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
Scott Michel0718cd82008-12-01 17:56:02 +00002270 VecOp,
2271 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, ShufMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002272
2273 return result;
2274}
2275
Dan Gohman8181bd12008-07-27 21:46:04 +00002276static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002277{
Dan Gohman8181bd12008-07-27 21:46:04 +00002278 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel8efdca42007-12-04 22:23:35 +00002279
2280 assert(Op.getValueType() == MVT::i8);
2281 switch (Opc) {
2282 default:
2283 assert(0 && "Unhandled i8 math operator");
2284 /*NOTREACHED*/
2285 break;
2286 case ISD::SUB: {
2287 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2288 // the result:
Dan Gohman8181bd12008-07-27 21:46:04 +00002289 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002290 N0 = (N0.getOpcode() != ISD::Constant
2291 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002292 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2293 MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00002294 N1 = (N1.getOpcode() != ISD::Constant
2295 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002296 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2297 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002298 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002299 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel4ec722e2008-07-16 17:17:29 +00002300 }
Scott Michel8efdca42007-12-04 22:23:35 +00002301 case ISD::ROTR:
2302 case ISD::ROTL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002303 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002304 unsigned N1Opc;
2305 N0 = (N0.getOpcode() != ISD::Constant
2306 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002307 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2308 MVT::i16));
Duncan Sands7aef60d2008-10-30 19:24:28 +00002309 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greife9f7f582008-08-31 15:37:04 +00002310 ? ISD::ZERO_EXTEND
2311 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002312 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sands7aef60d2008-10-30 19:24:28 +00002313 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002314 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sands7aef60d2008-10-30 19:24:28 +00002315 MVT::i32));
Dan Gohman8181bd12008-07-27 21:46:04 +00002316 SDValue ExpandArg =
Scott Michel8efdca42007-12-04 22:23:35 +00002317 DAG.getNode(ISD::OR, MVT::i16, N0,
2318 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sands7aef60d2008-10-30 19:24:28 +00002319 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002320 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002321 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2322 }
2323 case ISD::SRL:
2324 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002325 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002326 unsigned N1Opc;
2327 N0 = (N0.getOpcode() != ISD::Constant
2328 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002329 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2330 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002331 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2332 ? ISD::ZERO_EXTEND
2333 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002334 N1 = (N1.getOpcode() != ISD::Constant
2335 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002336 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2337 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002338 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002339 DAG.getNode(Opc, MVT::i16, N0, N1));
2340 }
2341 case ISD::SRA: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002342 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002343 unsigned N1Opc;
2344 N0 = (N0.getOpcode() != ISD::Constant
2345 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002346 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2347 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002348 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2349 ? ISD::SIGN_EXTEND
2350 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002351 N1 = (N1.getOpcode() != ISD::Constant
2352 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002353 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2354 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002355 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002356 DAG.getNode(Opc, MVT::i16, N0, N1));
2357 }
2358 case ISD::MUL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002359 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002360 unsigned N1Opc;
2361 N0 = (N0.getOpcode() != ISD::Constant
2362 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002363 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2364 MVT::i16));
Duncan Sandsec142ee2008-06-08 20:54:56 +00002365 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002366 N1 = (N1.getOpcode() != ISD::Constant
2367 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002368 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2369 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002370 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002371 DAG.getNode(Opc, MVT::i16, N0, N1));
2372 break;
2373 }
2374 }
2375
Dan Gohman8181bd12008-07-27 21:46:04 +00002376 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002377}
2378
Dan Gohman8181bd12008-07-27 21:46:04 +00002379static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002380{
Duncan Sands92c43912008-06-06 12:08:01 +00002381 MVT VT = Op.getValueType();
2382 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002383
Dan Gohman8181bd12008-07-27 21:46:04 +00002384 SDValue Op0 = Op.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002385
2386 switch (Opc) {
2387 case ISD::ZERO_EXTEND:
2388 case ISD::SIGN_EXTEND:
2389 case ISD::ANY_EXTEND: {
Duncan Sands92c43912008-06-06 12:08:01 +00002390 MVT Op0VT = Op0.getValueType();
2391 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002392
2393 assert(Op0VT == MVT::i32
2394 && "CellSPU: Zero/sign extending something other than i32");
2395
Scott Michelc630c412008-11-24 17:11:17 +00002396 DEBUG(cerr << "CellSPU.LowerI64Math: lowering zero/sign/any extend\n");
2397
Dan Gohman8181bd12008-07-27 21:46:04 +00002398 SDValue PromoteScalar =
Scott Michelc630c412008-11-24 17:11:17 +00002399 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
Scott Michel97872d32008-02-23 18:41:37 +00002400
Scott Michelc630c412008-11-24 17:11:17 +00002401 if (Opc != ISD::SIGN_EXTEND) {
Scott Michelf2df6cb2008-11-24 18:20:46 +00002402 // Use a shuffle to zero extend the i32 to i64 directly:
2403 SDValue shufMask =
2404 DAG.getNode(ISD::BUILD_VECTOR, Op0VecVT,
2405 DAG.getConstant(0x80808080, MVT::i32),
2406 DAG.getConstant(0x00010203, MVT::i32),
2407 DAG.getConstant(0x80808080, MVT::i32),
2408 DAG.getConstant(0x08090a0b, MVT::i32));
2409 SDValue zextShuffle =
2410 DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2411 PromoteScalar, PromoteScalar, shufMask);
2412
Scott Michelc630c412008-11-24 17:11:17 +00002413 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michelf2df6cb2008-11-24 18:20:46 +00002414 DAG.getNode(ISD::BIT_CONVERT, VecVT, zextShuffle));
Scott Michelc630c412008-11-24 17:11:17 +00002415 } else {
2416 // SPU has no "rotate quadword and replicate bit 0" (i.e. rotate/shift
2417 // right and propagate the sign bit) instruction.
Scott Michelf2df6cb2008-11-24 18:20:46 +00002418 SDValue RotQuad =
2419 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, Op0VecVT,
2420 PromoteScalar, DAG.getConstant(4, MVT::i32));
Scott Michelc630c412008-11-24 17:11:17 +00002421 SDValue SignQuad =
2422 DAG.getNode(SPUISD::VEC_SRA, Op0VecVT,
2423 PromoteScalar, DAG.getConstant(32, MVT::i32));
2424 SDValue SelMask =
2425 DAG.getNode(SPUISD::SELECT_MASK, Op0VecVT,
2426 DAG.getConstant(0xf0f0, MVT::i16));
2427 SDValue CombineQuad =
2428 DAG.getNode(SPUISD::SELB, Op0VecVT,
2429 SignQuad, RotQuad, SelMask);
2430
2431 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2432 DAG.getNode(ISD::BIT_CONVERT, VecVT, CombineQuad));
2433 }
Scott Michel97872d32008-02-23 18:41:37 +00002434 }
2435
Scott Michel67224b22008-06-02 22:18:03 +00002436 case ISD::ADD: {
2437 // Turn operands into vectors to satisfy type checking (shufb works on
2438 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002439 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002440 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002441 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002442 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002443 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002444
2445 // Create the shuffle mask for "rotating" the borrow up one register slot
2446 // once the borrow is generated.
2447 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2448 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2449 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2450 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2451
Dan Gohman8181bd12008-07-27 21:46:04 +00002452 SDValue CarryGen =
Scott Michel67224b22008-06-02 22:18:03 +00002453 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002454 SDValue ShiftedCarry =
Scott Michel67224b22008-06-02 22:18:03 +00002455 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2456 CarryGen, CarryGen,
2457 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2458 &ShufBytes[0], ShufBytes.size()));
2459
Scott Michelc630c412008-11-24 17:11:17 +00002460 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002461 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2462 Op0, Op1, ShiftedCarry));
2463 }
2464
2465 case ISD::SUB: {
2466 // Turn operands into vectors to satisfy type checking (shufb works on
2467 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002468 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002469 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002470 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002471 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002472 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002473
2474 // Create the shuffle mask for "rotating" the borrow up one register slot
2475 // once the borrow is generated.
2476 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2477 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2478 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2479 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2480
Dan Gohman8181bd12008-07-27 21:46:04 +00002481 SDValue BorrowGen =
Scott Michel67224b22008-06-02 22:18:03 +00002482 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002483 SDValue ShiftedBorrow =
Scott Michel67224b22008-06-02 22:18:03 +00002484 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2485 BorrowGen, BorrowGen,
2486 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2487 &ShufBytes[0], ShufBytes.size()));
2488
Scott Michelc630c412008-11-24 17:11:17 +00002489 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002490 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2491 Op0, Op1, ShiftedBorrow));
2492 }
2493
Scott Michel97872d32008-02-23 18:41:37 +00002494 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002495 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002496 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002497 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2498 SDValue MaskLower =
Scott Michel97872d32008-02-23 18:41:37 +00002499 DAG.getNode(SPUISD::SELB, VecVT,
2500 Op0Vec,
2501 DAG.getConstant(0, VecVT),
Scott Michel67224b22008-06-02 22:18:03 +00002502 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michel97872d32008-02-23 18:41:37 +00002503 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman8181bd12008-07-27 21:46:04 +00002504 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002505 DAG.getNode(ISD::SRL, ShiftAmtVT,
2506 ShiftAmt,
2507 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002508 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002509 DAG.getNode(ISD::AND, ShiftAmtVT,
2510 ShiftAmt,
2511 DAG.getConstant(7, ShiftAmtVT));
2512
Scott Michelc630c412008-11-24 17:11:17 +00002513 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel97872d32008-02-23 18:41:37 +00002514 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2515 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2516 MaskLower, ShiftAmtBytes),
2517 ShiftAmtBits));
2518 }
2519
2520 case ISD::SRL: {
Duncan Sands92c43912008-06-06 12:08:01 +00002521 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002522 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002523 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002524 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002525 DAG.getNode(ISD::SRL, ShiftAmtVT,
2526 ShiftAmt,
2527 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002528 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002529 DAG.getNode(ISD::AND, ShiftAmtVT,
2530 ShiftAmt,
2531 DAG.getConstant(7, ShiftAmtVT));
2532
2533 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2534 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2535 Op0, ShiftAmtBytes),
2536 ShiftAmtBits);
2537 }
Scott Michel67224b22008-06-02 22:18:03 +00002538
2539 case ISD::SRA: {
2540 // Promote Op0 to vector
Dan Gohman8181bd12008-07-27 21:46:04 +00002541 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002542 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002543 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002544 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel67224b22008-06-02 22:18:03 +00002545
2546 // Negate variable shift amounts
2547 if (!isa<ConstantSDNode>(ShiftAmt)) {
2548 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2549 DAG.getConstant(0, ShiftVT), ShiftAmt);
2550 }
2551
Dan Gohman8181bd12008-07-27 21:46:04 +00002552 SDValue UpperHalfSign =
Scott Michelc630c412008-11-24 17:11:17 +00002553 DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i32,
Scott Michel67224b22008-06-02 22:18:03 +00002554 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2555 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2556 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman8181bd12008-07-27 21:46:04 +00002557 SDValue UpperHalfSignMask =
Scott Michel67224b22008-06-02 22:18:03 +00002558 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman8181bd12008-07-27 21:46:04 +00002559 SDValue UpperLowerMask =
Scott Michel67224b22008-06-02 22:18:03 +00002560 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2561 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman8181bd12008-07-27 21:46:04 +00002562 SDValue UpperLowerSelect =
Scott Michel67224b22008-06-02 22:18:03 +00002563 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2564 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman8181bd12008-07-27 21:46:04 +00002565 SDValue RotateLeftBytes =
Scott Michel67224b22008-06-02 22:18:03 +00002566 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2567 UpperLowerSelect, ShiftAmt);
Dan Gohman8181bd12008-07-27 21:46:04 +00002568 SDValue RotateLeftBits =
Scott Michel67224b22008-06-02 22:18:03 +00002569 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2570 RotateLeftBytes, ShiftAmt);
2571
Scott Michelc630c412008-11-24 17:11:17 +00002572 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002573 RotateLeftBits);
2574 }
Scott Michel97872d32008-02-23 18:41:37 +00002575 }
2576
Dan Gohman8181bd12008-07-27 21:46:04 +00002577 return SDValue();
Scott Michel97872d32008-02-23 18:41:37 +00002578}
2579
Scott Michel8efdca42007-12-04 22:23:35 +00002580//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman8181bd12008-07-27 21:46:04 +00002581static SDValue
2582LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2583 SDValue ConstVec;
2584 SDValue Arg;
Duncan Sands92c43912008-06-06 12:08:01 +00002585 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002586
2587 ConstVec = Op.getOperand(0);
2588 Arg = Op.getOperand(1);
Gabor Greif1c80d112008-08-28 21:40:38 +00002589 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2590 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel8efdca42007-12-04 22:23:35 +00002591 ConstVec = ConstVec.getOperand(0);
2592 } else {
2593 ConstVec = Op.getOperand(1);
2594 Arg = Op.getOperand(0);
Gabor Greif1c80d112008-08-28 21:40:38 +00002595 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00002596 ConstVec = ConstVec.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00002597 }
2598 }
2599 }
2600
Gabor Greif1c80d112008-08-28 21:40:38 +00002601 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel8efdca42007-12-04 22:23:35 +00002602 uint64_t VectorBits[2];
2603 uint64_t UndefBits[2];
2604 uint64_t SplatBits, SplatUndef;
2605 int SplatSize;
2606
Gabor Greif1c80d112008-08-28 21:40:38 +00002607 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002608 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00002609 VT.getVectorElementType().getSizeInBits(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002610 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002611 SDValue tcVec[16];
2612 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel8efdca42007-12-04 22:23:35 +00002613 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2614
2615 // Turn the BUILD_VECTOR into a set of target constants:
2616 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002617 tcVec[i] = tc;
Scott Michel8efdca42007-12-04 22:23:35 +00002618
Gabor Greif1c80d112008-08-28 21:40:38 +00002619 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002620 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel8efdca42007-12-04 22:23:35 +00002621 }
2622 }
Nate Begeman7569e762008-07-29 19:07:27 +00002623 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2624 // lowered. Return the operation, rather than a null SDValue.
2625 return Op;
Scott Michel8efdca42007-12-04 22:23:35 +00002626}
2627
2628//! Lower i32 multiplication
Dan Gohman8181bd12008-07-27 21:46:04 +00002629static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel8efdca42007-12-04 22:23:35 +00002630 unsigned Opc) {
Duncan Sands92c43912008-06-06 12:08:01 +00002631 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00002632 default:
2633 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands92c43912008-06-06 12:08:01 +00002634 << Op.getValueType().getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +00002635 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +00002636 abort();
2637 /*NOTREACHED*/
2638
2639 case MVT::i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002640 SDValue rA = Op.getOperand(0);
2641 SDValue rB = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002642
2643 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002644 DAG.getNode(ISD::ADD, MVT::i32,
2645 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2646 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2647 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00002648 }
2649 }
2650
Dan Gohman8181bd12008-07-27 21:46:04 +00002651 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002652}
2653
2654//! Custom lowering for CTPOP (count population)
2655/*!
2656 Custom lowering code that counts the number ones in the input
2657 operand. SPU has such an instruction, but it counts the number of
2658 ones per byte, which then have to be accumulated.
2659*/
Dan Gohman8181bd12008-07-27 21:46:04 +00002660static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002661 MVT VT = Op.getValueType();
2662 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +00002663
Duncan Sands92c43912008-06-06 12:08:01 +00002664 switch (VT.getSimpleVT()) {
2665 default:
2666 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002667 case MVT::i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002668 SDValue N = Op.getOperand(0);
2669 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002670
Dan Gohman8181bd12008-07-27 21:46:04 +00002671 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2672 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002673
2674 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2675 }
2676
2677 case MVT::i16: {
2678 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002679 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002680
Chris Lattner1b989192007-12-31 04:13:23 +00002681 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002682
Dan Gohman8181bd12008-07-27 21:46:04 +00002683 SDValue N = Op.getOperand(0);
2684 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2685 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sands7aef60d2008-10-30 19:24:28 +00002686 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002687
Dan Gohman8181bd12008-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 Michel8efdca42007-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 Gohman8181bd12008-07-27 21:46:04 +00002693 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002694 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002695
Dan Gohman8181bd12008-07-27 21:46:04 +00002696 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002697 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2698
Dan Gohman8181bd12008-07-27 21:46:04 +00002699 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002700
2701 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002702 DAG.getNode(ISD::ADD, MVT::i16,
2703 DAG.getNode(ISD::SRL, MVT::i16,
2704 Tmp1, Shift1),
2705 Tmp1),
2706 Mask0);
Scott Michel8efdca42007-12-04 22:23:35 +00002707 }
2708
2709 case MVT::i32: {
2710 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002711 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002712
Chris Lattner1b989192007-12-31 04:13:23 +00002713 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2714 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002715
Dan Gohman8181bd12008-07-27 21:46:04 +00002716 SDValue N = Op.getOperand(0);
2717 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2718 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2719 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2720 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002721
Dan Gohman8181bd12008-07-27 21:46:04 +00002722 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2723 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002724
2725 // CNTB_result becomes the chain to which all of the virtual registers
2726 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002727 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002728 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002729
Dan Gohman8181bd12008-07-27 21:46:04 +00002730 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002731 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2732
Dan Gohman8181bd12008-07-27 21:46:04 +00002733 SDValue Comp1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002734 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002735 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel8efdca42007-12-04 22:23:35 +00002736
Dan Gohman8181bd12008-07-27 21:46:04 +00002737 SDValue Sum1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002738 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002739 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002740
Dan Gohman8181bd12008-07-27 21:46:04 +00002741 SDValue Sum1_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002742 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2743
Dan Gohman8181bd12008-07-27 21:46:04 +00002744 SDValue Comp2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002745 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002746 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2747 Shift2);
Dan Gohman8181bd12008-07-27 21:46:04 +00002748 SDValue Sum2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002749 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002750 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002751
2752 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2753 }
2754
2755 case MVT::i64:
2756 break;
2757 }
2758
Dan Gohman8181bd12008-07-27 21:46:04 +00002759 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002760}
2761
Scott Michel56a125e2008-11-22 23:50:42 +00002762//! Lower ISD::SELECT_CC
2763/*!
2764 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2765 SELB instruction.
2766
2767 \note Need to revisit this in the future: if the code path through the true
2768 and false value computations is longer than the latency of a branch (6
2769 cycles), then it would be more advantageous to branch and insert a new basic
2770 block and branch on the condition. However, this code does not make that
2771 assumption, given the simplisitc uses so far.
2772 */
2773
2774static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
2775 MVT VT = Op.getValueType();
2776 SDValue lhs = Op.getOperand(0);
2777 SDValue rhs = Op.getOperand(1);
2778 SDValue trueval = Op.getOperand(2);
2779 SDValue falseval = Op.getOperand(3);
2780 SDValue condition = Op.getOperand(4);
2781
2782 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2783 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2784 // with another "cannot select select_cc" assert:
2785
2786 SDValue compare = DAG.getNode(ISD::SETCC, VT, lhs, rhs, condition);
2787 return DAG.getNode(SPUISD::SELB, VT, trueval, falseval, compare);
2788}
2789
Scott Michelec8c82e2008-12-02 19:53:53 +00002790//! Custom lower ISD::TRUNCATE
2791static SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG)
2792{
2793 MVT VT = Op.getValueType();
2794 MVT::SimpleValueType simpleVT = VT.getSimpleVT();
2795 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
2796
2797 SDValue Op0 = Op.getOperand(0);
2798 MVT Op0VT = Op0.getValueType();
2799 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
2800
2801 SDValue PromoteScalar = DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2802
2803 unsigned maskLow;
2804 unsigned maskHigh;
2805
2806 // Create shuffle mask
2807 switch (Op0VT.getSimpleVT()) {
2808 case MVT::i128:
2809 switch (simpleVT) {
2810 case MVT::i64:
2811 // least significant doubleword of quadword
2812 maskHigh = 0x08090a0b;
2813 maskLow = 0x0c0d0e0f;
2814 break;
2815 case MVT::i32:
2816 // least significant word of quadword
2817 maskHigh = maskLow = 0x0c0d0e0f;
2818 break;
2819 case MVT::i16:
2820 // least significant halfword of quadword
2821 maskHigh = maskLow = 0x0e0f0e0f;
2822 break;
2823 case MVT::i8:
2824 // least significant byte of quadword
2825 maskHigh = maskLow = 0x0f0f0f0f;
2826 break;
2827 default:
2828 cerr << "Truncation to illegal type!";
2829 abort();
2830 }
2831 break;
2832 case MVT::i64:
2833 switch (simpleVT) {
2834 case MVT::i32:
2835 // least significant word of doubleword
2836 maskHigh = maskLow = 0x04050607;
2837 break;
2838 case MVT::i16:
2839 // least significant halfword of doubleword
2840 maskHigh = maskLow = 0x06070607;
2841 break;
2842 case MVT::i8:
2843 // least significant byte of doubleword
2844 maskHigh = maskLow = 0x07070707;
2845 break;
2846 default:
2847 cerr << "Truncation to illegal type!";
2848 abort();
2849 }
2850 break;
2851 case MVT::i32:
2852 case MVT::i16:
2853 switch (simpleVT) {
2854 case MVT::i16:
2855 // least significant halfword of word
2856 maskHigh = maskLow = 0x02030203;
2857 break;
2858 case MVT::i8:
2859 // least significant byte of word/halfword
2860 maskHigh = maskLow = 0x03030303;
2861 break;
2862 default:
2863 cerr << "Truncation to illegal type!";
2864 abort();
2865 }
2866 break;
2867 default:
2868 cerr << "Trying to lower truncation from illegal type!";
2869 abort();
2870 }
2871
2872 // Use a shuffle to perform the truncation
2873 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2874 DAG.getConstant(maskHigh, MVT::i32),
2875 DAG.getConstant(maskLow, MVT::i32),
2876 DAG.getConstant(maskHigh, MVT::i32),
2877 DAG.getConstant(maskLow, MVT::i32));
2878
2879 SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2880 PromoteScalar, PromoteScalar, shufMask);
2881
2882 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2883 DAG.getNode(ISD::BIT_CONVERT, VecVT, truncShuffle));
2884}
2885
Scott Michel56a125e2008-11-22 23:50:42 +00002886//! Custom (target-specific) lowering entry point
2887/*!
2888 This is where LLVM's DAG selection process calls to do target-specific
2889 lowering of nodes.
2890 */
Dan Gohman8181bd12008-07-27 21:46:04 +00002891SDValue
2892SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel8efdca42007-12-04 22:23:35 +00002893{
Scott Michel97872d32008-02-23 18:41:37 +00002894 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands92c43912008-06-06 12:08:01 +00002895 MVT VT = Op.getValueType();
Scott Michel97872d32008-02-23 18:41:37 +00002896
2897 switch (Opc) {
Scott Michel8efdca42007-12-04 22:23:35 +00002898 default: {
2899 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michel97872d32008-02-23 18:41:37 +00002900 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greif1c80d112008-08-28 21:40:38 +00002901 cerr << "*Op.getNode():\n";
2902 Op.getNode()->dump();
Scott Michel8efdca42007-12-04 22:23:35 +00002903 abort();
2904 }
2905 case ISD::LOAD:
Scott Michelec8c82e2008-12-02 19:53:53 +00002906 case ISD::EXTLOAD:
Scott Michel8efdca42007-12-04 22:23:35 +00002907 case ISD::SEXTLOAD:
2908 case ISD::ZEXTLOAD:
2909 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2910 case ISD::STORE:
2911 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2912 case ISD::ConstantPool:
2913 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2914 case ISD::GlobalAddress:
2915 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2916 case ISD::JumpTable:
2917 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2918 case ISD::Constant:
2919 return LowerConstant(Op, DAG);
2920 case ISD::ConstantFP:
2921 return LowerConstantFP(Op, DAG);
Scott Michel394e26d2008-01-17 20:38:41 +00002922 case ISD::BRCOND:
2923 return LowerBRCOND(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002924 case ISD::FORMAL_ARGUMENTS:
Scott Michel394e26d2008-01-17 20:38:41 +00002925 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel8efdca42007-12-04 22:23:35 +00002926 case ISD::CALL:
Scott Micheldbac4cf2008-01-11 02:53:15 +00002927 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel8efdca42007-12-04 22:23:35 +00002928 case ISD::RET:
2929 return LowerRET(Op, DAG, getTargetMachine());
2930
Scott Michel97872d32008-02-23 18:41:37 +00002931
2932 // i8, i64 math ops:
2933 case ISD::ZERO_EXTEND:
2934 case ISD::SIGN_EXTEND:
2935 case ISD::ANY_EXTEND:
Scott Michel67224b22008-06-02 22:18:03 +00002936 case ISD::ADD:
Scott Michel8efdca42007-12-04 22:23:35 +00002937 case ISD::SUB:
2938 case ISD::ROTR:
2939 case ISD::ROTL:
2940 case ISD::SRL:
2941 case ISD::SHL:
Scott Michel67224b22008-06-02 22:18:03 +00002942 case ISD::SRA: {
Scott Michel97872d32008-02-23 18:41:37 +00002943 if (VT == MVT::i8)
2944 return LowerI8Math(Op, DAG, Opc);
2945 else if (VT == MVT::i64)
2946 return LowerI64Math(Op, DAG, Opc);
2947 break;
Scott Michel67224b22008-06-02 22:18:03 +00002948 }
Scott Michel8efdca42007-12-04 22:23:35 +00002949
2950 // Vector-related lowering.
2951 case ISD::BUILD_VECTOR:
2952 return LowerBUILD_VECTOR(Op, DAG);
2953 case ISD::SCALAR_TO_VECTOR:
2954 return LowerSCALAR_TO_VECTOR(Op, DAG);
2955 case ISD::VECTOR_SHUFFLE:
2956 return LowerVECTOR_SHUFFLE(Op, DAG);
2957 case ISD::EXTRACT_VECTOR_ELT:
2958 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2959 case ISD::INSERT_VECTOR_ELT:
2960 return LowerINSERT_VECTOR_ELT(Op, DAG);
2961
2962 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2963 case ISD::AND:
2964 case ISD::OR:
2965 case ISD::XOR:
2966 return LowerByteImmed(Op, DAG);
2967
2968 // Vector and i8 multiply:
2969 case ISD::MUL:
Duncan Sands92c43912008-06-06 12:08:01 +00002970 if (VT.isVector())
Scott Michel8efdca42007-12-04 22:23:35 +00002971 return LowerVectorMUL(Op, DAG);
Scott Michel97872d32008-02-23 18:41:37 +00002972 else if (VT == MVT::i8)
2973 return LowerI8Math(Op, DAG, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002974 else
Scott Michel97872d32008-02-23 18:41:37 +00002975 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002976
2977 case ISD::FDIV:
Scott Michel97872d32008-02-23 18:41:37 +00002978 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel8efdca42007-12-04 22:23:35 +00002979 return LowerFDIVf32(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002980#if 0
2981 // This is probably a libcall
2982 else if (Op.getValueType() == MVT::f64)
2983 return LowerFDIVf64(Op, DAG);
2984#endif
Scott Michel8efdca42007-12-04 22:23:35 +00002985 else
2986 assert(0 && "Calling FDIV on unsupported MVT");
2987
2988 case ISD::CTPOP:
2989 return LowerCTPOP(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002990
2991 case ISD::SELECT_CC:
2992 return LowerSELECT_CC(Op, DAG);
Scott Michelec8c82e2008-12-02 19:53:53 +00002993
2994 case ISD::TRUNCATE:
2995 return LowerTRUNCATE(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002996 }
2997
Dan Gohman8181bd12008-07-27 21:46:04 +00002998 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002999}
3000
Duncan Sands7d9834b2008-12-01 11:39:25 +00003001void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
3002 SmallVectorImpl<SDValue>&Results,
3003 SelectionDAG &DAG)
Scott Michel6e2d68b2008-11-10 23:43:06 +00003004{
3005#if 0
3006 unsigned Opc = (unsigned) N->getOpcode();
3007 MVT OpVT = N->getValueType(0);
3008
3009 switch (Opc) {
3010 default: {
3011 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
3012 cerr << "Op.getOpcode() = " << Opc << "\n";
3013 cerr << "*Op.getNode():\n";
3014 N->dump();
3015 abort();
3016 /*NOTREACHED*/
3017 }
3018 }
3019#endif
3020
3021 /* Otherwise, return unchanged */
Scott Michel6e2d68b2008-11-10 23:43:06 +00003022}
3023
Scott Michel8efdca42007-12-04 22:23:35 +00003024//===----------------------------------------------------------------------===//
Scott Michel8efdca42007-12-04 22:23:35 +00003025// Target Optimization Hooks
3026//===----------------------------------------------------------------------===//
3027
Dan Gohman8181bd12008-07-27 21:46:04 +00003028SDValue
Scott Michel8efdca42007-12-04 22:23:35 +00003029SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
3030{
3031#if 0
3032 TargetMachine &TM = getTargetMachine();
Scott Michelf9f42e62008-01-29 02:16:57 +00003033#endif
3034 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel8efdca42007-12-04 22:23:35 +00003035 SelectionDAG &DAG = DCI.DAG;
Scott Michel0718cd82008-12-01 17:56:02 +00003036 SDValue Op0 = N->getOperand(0); // everything has at least one operand
3037 MVT NodeVT = N->getValueType(0); // The node's value type
3038 MVT Op0VT = Op0.getValueType(); // The first operand's result
3039 SDValue Result; // Initially, empty result
Scott Michel8efdca42007-12-04 22:23:35 +00003040
3041 switch (N->getOpcode()) {
3042 default: break;
Scott Michelf9f42e62008-01-29 02:16:57 +00003043 case ISD::ADD: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003044 SDValue Op1 = N->getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003045
Scott Michel67224b22008-06-02 22:18:03 +00003046 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003047 SDValue Op01 = Op0.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003048 if (Op01.getOpcode() == ISD::Constant
3049 || Op01.getOpcode() == ISD::TargetConstant) {
3050 // (add <const>, (SPUindirect <arg>, <const>)) ->
3051 // (SPUindirect <arg>, <const + const>)
3052 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
3053 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman8181bd12008-07-27 21:46:04 +00003054 SDValue combinedConst =
Scott Michel0718cd82008-12-01 17:56:02 +00003055 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(), Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00003056
Scott Michel8c2746e2008-12-04 17:16:59 +00003057#if !defined(NDEBUG)
Scott Michel6ccefab2008-12-04 03:02:42 +00003058 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
3059 cerr << "\n"
3060 << "Replace: (add " << CN0->getZExtValue() << ", "
3061 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n"
3062 << "With: (SPUindirect <arg>, "
3063 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n";
3064 }
3065#endif
3066
Scott Michel0718cd82008-12-01 17:56:02 +00003067 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
Scott Michelf9f42e62008-01-29 02:16:57 +00003068 Op0.getOperand(0), combinedConst);
3069 }
Scott Michel67224b22008-06-02 22:18:03 +00003070 } else if (isa<ConstantSDNode>(Op0)
Scott Michelf9f42e62008-01-29 02:16:57 +00003071 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003072 SDValue Op11 = Op1.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003073 if (Op11.getOpcode() == ISD::Constant
3074 || Op11.getOpcode() == ISD::TargetConstant) {
3075 // (add (SPUindirect <arg>, <const>), <const>) ->
3076 // (SPUindirect <arg>, <const + const>)
3077 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
3078 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman8181bd12008-07-27 21:46:04 +00003079 SDValue combinedConst =
Scott Michel0718cd82008-12-01 17:56:02 +00003080 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(), Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00003081
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003082 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
3083 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00003084 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003085 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00003086
3087 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
3088 Op1.getOperand(0), combinedConst);
3089 }
3090 }
Scott Michel97872d32008-02-23 18:41:37 +00003091 break;
3092 }
3093 case ISD::SIGN_EXTEND:
3094 case ISD::ZERO_EXTEND:
3095 case ISD::ANY_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00003096 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT && NodeVT == Op0VT) {
Scott Michel97872d32008-02-23 18:41:37 +00003097 // (any_extend (SPUextract_elt0 <arg>)) ->
3098 // (SPUextract_elt0 <arg>)
3099 // Types must match, however...
Scott Michel8c2746e2008-12-04 17:16:59 +00003100#if !defined(NDEBUG)
3101 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel6ccefab2008-12-04 03:02:42 +00003102 cerr << "\nReplace: ";
3103 N->dump(&DAG);
3104 cerr << "\nWith: ";
3105 Op0.getNode()->dump(&DAG);
3106 cerr << "\n";
Scott Michel8c2746e2008-12-04 17:16:59 +00003107 }
Scott Michel6ccefab2008-12-04 03:02:42 +00003108#endif
Scott Michel97872d32008-02-23 18:41:37 +00003109
3110 return Op0;
3111 }
3112 break;
3113 }
3114 case SPUISD::IndirectAddr: {
3115 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
3116 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003117 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00003118 // (SPUindirect (SPUaform <addr>, 0), 0) ->
3119 // (SPUaform <addr>, 0)
3120
3121 DEBUG(cerr << "Replace: ");
3122 DEBUG(N->dump(&DAG));
3123 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00003124 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00003125 DEBUG(cerr << "\n");
3126
3127 return Op0;
3128 }
3129 }
3130 break;
3131 }
3132 case SPUISD::SHLQUAD_L_BITS:
3133 case SPUISD::SHLQUAD_L_BYTES:
3134 case SPUISD::VEC_SHL:
3135 case SPUISD::VEC_SRL:
3136 case SPUISD::VEC_SRA:
3137 case SPUISD::ROTQUAD_RZ_BYTES:
3138 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003139 SDValue Op1 = N->getOperand(1);
Scott Michel97872d32008-02-23 18:41:37 +00003140
3141 if (isa<ConstantSDNode>(Op1)) {
3142 // Kill degenerate vector shifts:
3143 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003144 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00003145 Result = Op0;
3146 }
3147 }
3148 break;
3149 }
3150 case SPUISD::PROMOTE_SCALAR: {
3151 switch (Op0.getOpcode()) {
3152 default:
3153 break;
3154 case ISD::ANY_EXTEND:
3155 case ISD::ZERO_EXTEND:
3156 case ISD::SIGN_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00003157 // (SPUpromote_scalar (any|zero|sign_extend (SPUvec2prefslot <arg>))) ->
Scott Michel97872d32008-02-23 18:41:37 +00003158 // <arg>
3159 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman8181bd12008-07-27 21:46:04 +00003160 SDValue Op00 = Op0.getOperand(0);
Scott Michelc630c412008-11-24 17:11:17 +00003161 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003162 SDValue Op000 = Op00.getOperand(0);
Scott Michel0718cd82008-12-01 17:56:02 +00003163 if (Op000.getValueType() == NodeVT) {
Scott Michel97872d32008-02-23 18:41:37 +00003164 Result = Op000;
3165 }
3166 }
3167 break;
3168 }
Scott Michelc630c412008-11-24 17:11:17 +00003169 case SPUISD::VEC2PREFSLOT: {
Scott Michel0718cd82008-12-01 17:56:02 +00003170 // (SPUpromote_scalar (SPUvec2prefslot <arg>)) ->
Scott Michel97872d32008-02-23 18:41:37 +00003171 // <arg>
3172 Result = Op0.getOperand(0);
3173 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00003174 }
Scott Michel97872d32008-02-23 18:41:37 +00003175 }
3176 break;
Scott Michelf9f42e62008-01-29 02:16:57 +00003177 }
3178 }
Scott Michel394e26d2008-01-17 20:38:41 +00003179 // Otherwise, return unchanged.
Scott Michel0718cd82008-12-01 17:56:02 +00003180#ifndef NDEBUG
Gabor Greif1c80d112008-08-28 21:40:38 +00003181 if (Result.getNode()) {
Scott Michel97872d32008-02-23 18:41:37 +00003182 DEBUG(cerr << "\nReplace.SPU: ");
3183 DEBUG(N->dump(&DAG));
3184 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00003185 DEBUG(Result.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00003186 DEBUG(cerr << "\n");
3187 }
3188#endif
3189
3190 return Result;
Scott Michel8efdca42007-12-04 22:23:35 +00003191}
3192
3193//===----------------------------------------------------------------------===//
3194// Inline Assembly Support
3195//===----------------------------------------------------------------------===//
3196
3197/// getConstraintType - Given a constraint letter, return the type of
3198/// constraint it is for this target.
Scott Michel4ec722e2008-07-16 17:17:29 +00003199SPUTargetLowering::ConstraintType
Scott Michel8efdca42007-12-04 22:23:35 +00003200SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
3201 if (ConstraintLetter.size() == 1) {
3202 switch (ConstraintLetter[0]) {
3203 default: break;
3204 case 'b':
3205 case 'r':
3206 case 'f':
3207 case 'v':
3208 case 'y':
3209 return C_RegisterClass;
Scott Michel4ec722e2008-07-16 17:17:29 +00003210 }
Scott Michel8efdca42007-12-04 22:23:35 +00003211 }
3212 return TargetLowering::getConstraintType(ConstraintLetter);
3213}
3214
Scott Michel4ec722e2008-07-16 17:17:29 +00003215std::pair<unsigned, const TargetRegisterClass*>
Scott Michel8efdca42007-12-04 22:23:35 +00003216SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands92c43912008-06-06 12:08:01 +00003217 MVT VT) const
Scott Michel8efdca42007-12-04 22:23:35 +00003218{
3219 if (Constraint.size() == 1) {
3220 // GCC RS6000 Constraint Letters
3221 switch (Constraint[0]) {
3222 case 'b': // R1-R31
3223 case 'r': // R0-R31
3224 if (VT == MVT::i64)
3225 return std::make_pair(0U, SPU::R64CRegisterClass);
3226 return std::make_pair(0U, SPU::R32CRegisterClass);
3227 case 'f':
3228 if (VT == MVT::f32)
3229 return std::make_pair(0U, SPU::R32FPRegisterClass);
3230 else if (VT == MVT::f64)
3231 return std::make_pair(0U, SPU::R64FPRegisterClass);
3232 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00003233 case 'v':
Scott Michel8efdca42007-12-04 22:23:35 +00003234 return std::make_pair(0U, SPU::GPRCRegisterClass);
3235 }
3236 }
Scott Michel4ec722e2008-07-16 17:17:29 +00003237
Scott Michel8efdca42007-12-04 22:23:35 +00003238 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3239}
3240
Scott Michel97872d32008-02-23 18:41:37 +00003241//! Compute used/known bits for a SPU operand
Scott Michel8efdca42007-12-04 22:23:35 +00003242void
Dan Gohman8181bd12008-07-27 21:46:04 +00003243SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohmand0dfc772008-02-13 22:28:48 +00003244 const APInt &Mask,
Scott Michel4ec722e2008-07-16 17:17:29 +00003245 APInt &KnownZero,
Dan Gohman229fa052008-02-13 00:35:47 +00003246 APInt &KnownOne,
Scott Michel5a6f17b2008-01-30 02:55:46 +00003247 const SelectionDAG &DAG,
3248 unsigned Depth ) const {
Scott Michelbc5fbc12008-04-30 00:30:08 +00003249#if 0
Scott Michel97872d32008-02-23 18:41:37 +00003250 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michelbc5fbc12008-04-30 00:30:08 +00003251#endif
Scott Michel97872d32008-02-23 18:41:37 +00003252
3253 switch (Op.getOpcode()) {
3254 default:
3255 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3256 break;
3257
3258#if 0
3259 case CALL:
3260 case SHUFB:
Scott Michel56a125e2008-11-22 23:50:42 +00003261 case SHUFFLE_MASK:
Scott Michel97872d32008-02-23 18:41:37 +00003262 case CNTB:
3263#endif
3264
3265 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003266 SDValue Op0 = Op.getOperand(0);
Duncan Sands92c43912008-06-06 12:08:01 +00003267 MVT Op0VT = Op0.getValueType();
3268 unsigned Op0VTBits = Op0VT.getSizeInBits();
3269 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003270 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3271 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003272 break;
3273 }
Scott Michel4ec722e2008-07-16 17:17:29 +00003274
Scott Michel97872d32008-02-23 18:41:37 +00003275 case SPUISD::LDRESULT:
Scott Michel6ccefab2008-12-04 03:02:42 +00003276 case SPUISD::VEC2PREFSLOT: {
Duncan Sands92c43912008-06-06 12:08:01 +00003277 MVT OpVT = Op.getValueType();
3278 unsigned OpVTBits = OpVT.getSizeInBits();
3279 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003280 KnownZero |= APInt(OpVTBits, ~InMask, false);
3281 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003282 break;
3283 }
3284
3285#if 0
Scott Michel97872d32008-02-23 18:41:37 +00003286 case MPY:
3287 case MPYU:
3288 case MPYH:
3289 case MPYHH:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003290 case SPUISD::SHLQUAD_L_BITS:
3291 case SPUISD::SHLQUAD_L_BYTES:
3292 case SPUISD::VEC_SHL:
3293 case SPUISD::VEC_SRL:
3294 case SPUISD::VEC_SRA:
3295 case SPUISD::VEC_ROTL:
3296 case SPUISD::VEC_ROTR:
3297 case SPUISD::ROTQUAD_RZ_BYTES:
3298 case SPUISD::ROTQUAD_RZ_BITS:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003299 case SPUISD::ROTBYTES_LEFT:
Scott Michel67224b22008-06-02 22:18:03 +00003300 case SPUISD::SELECT_MASK:
3301 case SPUISD::SELB:
3302 case SPUISD::FPInterp:
3303 case SPUISD::FPRecipEst:
3304 case SPUISD::SEXT32TO64:
Scott Michel97872d32008-02-23 18:41:37 +00003305#endif
3306 }
Scott Michel8efdca42007-12-04 22:23:35 +00003307}
3308
Scott Michelbc5fbc12008-04-30 00:30:08 +00003309// LowerAsmOperandForConstraint
3310void
Dan Gohman8181bd12008-07-27 21:46:04 +00003311SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003312 char ConstraintLetter,
Evan Cheng7f250d62008-09-24 00:05:32 +00003313 bool hasMemory,
Dan Gohman8181bd12008-07-27 21:46:04 +00003314 std::vector<SDValue> &Ops,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003315 SelectionDAG &DAG) const {
3316 // Default, for the time being, to the base class handler
Evan Cheng7f250d62008-09-24 00:05:32 +00003317 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3318 Ops, DAG);
Scott Michelbc5fbc12008-04-30 00:30:08 +00003319}
3320
Scott Michel8efdca42007-12-04 22:23:35 +00003321/// isLegalAddressImmediate - Return true if the integer value can be used
3322/// as the offset of the target addressing mode.
Gabor Greife9f7f582008-08-31 15:37:04 +00003323bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3324 const Type *Ty) const {
Scott Michel8efdca42007-12-04 22:23:35 +00003325 // SPU's addresses are 256K:
3326 return (V > -(1 << 18) && V < (1 << 18) - 1);
3327}
3328
3329bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel4ec722e2008-07-16 17:17:29 +00003330 return false;
Scott Michel8efdca42007-12-04 22:23:35 +00003331}
Dan Gohman36322c72008-10-18 02:06:02 +00003332
3333bool
3334SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3335 // The SPU target isn't yet aware of offsets.
3336 return false;
3337}